示例#1
0
文件: method.c 项目: chasonr/mruby
static mrb_value
method_call(mrb_state *mrb, mrb_value self)
{
  mrb_value proc = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "proc"));
  mrb_value name = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@name"));
  mrb_value recv = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@recv"));
  struct RClass *owner = mrb_class_ptr(mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@owner")));
  mrb_int argc;
  mrb_value *argv, ret, block;
  mrb_sym orig_mid;

  mrb_get_args(mrb, "*&", &argv, &argc, &block);
  orig_mid = mrb->c->ci->mid;
  mrb->c->ci->mid = mrb_symbol(name);
  if (mrb_nil_p(proc)) {
    mrb_value missing_argv = mrb_ary_new_from_values(mrb, argc, argv);
    mrb_ary_unshift(mrb, missing_argv, name);
    ret = mrb_funcall_argv(mrb, recv, mrb_intern_lit(mrb, "method_missing"), argc + 1, RARRAY_PTR(missing_argv));
  }
  else if (!mrb_nil_p(block)) {
    /*
      workaround since `mrb_yield_with_class` does not support passing block as parameter
      need new API that initializes `mrb->c->stack[argc+1]` with block passed by argument
    */
    ret = mrb_funcall_with_block(mrb, recv, mrb_symbol(name), argc, argv, block);
  }
  else {
    ret = mrb_yield_with_class(mrb, proc, argc, argv, recv, owner);
  }
  mrb->c->ci->mid = orig_mid;
  return ret;
}
示例#2
0
static void*
mrb_thread_func(void* data) {
  mrb_thread_context* context = (mrb_thread_context*) data;
  mrb_state* mrb = context->mrb;
  context->result = mrb_yield_with_class(mrb, mrb_obj_value(context->proc),
                                         context->argc, context->argv, mrb_nil_value(), mrb->object_class);
  context->alive = FALSE;
  return NULL;
}
示例#3
0
文件: struct.c 项目: nyanp/mruby
/*
 *  call-seq:
 *     Struct.new( [aString] [, aSym]+> )    -> StructClass
 *     StructClass.new(arg, ...)             -> obj
 *     StructClass[arg, ...]                 -> obj
 *
 *  Creates a new class, named by <i>aString</i>, containing accessor
 *  methods for the given symbols. If the name <i>aString</i> is
 *  omitted, an anonymous structure class will be created. Otherwise,
 *  the name of this struct will appear as a constant in class
 *  <code>Struct</code>, so it must be unique for all
 *  <code>Struct</code>s in the system and should start with a capital
 *  letter. Assigning a structure class to a constant effectively gives
 *  the class the name of the constant.
 *
 *  <code>Struct::new</code> returns a new <code>Class</code> object,
 *  which can then be used to create specific instances of the new
 *  structure. The number of actual parameters must be
 *  less than or equal to the number of attributes defined for this
 *  class; unset parameters default to <code>nil</code>.  Passing too many
 *  parameters will raise an <code>ArgumentError</code>.
 *
 *  The remaining methods listed in this section (class and instance)
 *  are defined for this generated class.
 *
 *     # Create a structure with a name in Struct
 *     Struct.new("Customer", :name, :address)    #=> Struct::Customer
 *     Struct::Customer.new("Dave", "123 Main")   #=> #<struct Struct::Customer name="Dave", address="123 Main">
 *
 *     # Create a structure named by its constant
 *     Customer = Struct.new(:name, :address)     #=> Customer
 *     Customer.new("Dave", "123 Main")           #=> #<struct Customer name="Dave", address="123 Main">
 */
static mrb_value
mrb_struct_s_def(mrb_state *mrb, mrb_value klass)
{
  mrb_value name, rest;
  mrb_value *pargv;
  int argcnt;
  mrb_int i;
  mrb_value b, st;
  mrb_sym id;
  mrb_value *argv;
  int argc;

  name = mrb_nil_value();
  rest = mrb_nil_value();
  mrb_get_args(mrb, "*&", &argv, &argc, &b);
  if (argc == 0) { /* special case to avoid crash */
    rest = mrb_ary_new(mrb);
  }
  else {
    if (argc > 0) name = argv[0];
    if (argc > 1) rest = argv[1];
    if (mrb_array_p(rest)) {
      if (!mrb_nil_p(name) && mrb_symbol_p(name)) {
        /* 1stArgument:symbol -> name=nil rest=argv[0]-[n] */
        mrb_ary_unshift(mrb, rest, name);
        name = mrb_nil_value();
      }
    }
    else {
      pargv = &argv[1];
      argcnt = argc-1;
      if (!mrb_nil_p(name) && mrb_symbol_p(name)) {
        /* 1stArgument:symbol -> name=nil rest=argv[0]-[n] */
        name = mrb_nil_value();
        pargv = &argv[0];
        argcnt++;
      }
      rest = mrb_ary_new_from_values(mrb, argcnt, pargv);
    }
    for (i=0; i<RARRAY_LEN(rest); i++) {
      id = mrb_obj_to_sym(mrb, RARRAY_PTR(rest)[i]);
      RARRAY_PTR(rest)[i] = mrb_symbol_value(id);
    }
  }
  st = make_struct(mrb, name, rest, struct_class(mrb));
  if (!mrb_nil_p(b)) {
    mrb_yield_with_class(mrb, b, 1, &st, st, mrb_class_ptr(klass));
  }

  return st;
}
示例#4
0
static void
load_mrb_file(mrb_state *mrb, mrb_value filepath)
{
  char *fpath = RSTRING_PTR(filepath);
  int arena_idx;
  FILE *fp;
  mrb_irep *irep;

  {
    FILE *fp = fopen(fpath, "rb");
    if (fp == NULL) {
      mrb_load_fail(
        mrb,
        mrb_str_new_cstr(mrb, fpath),
        "cannot load such file"
      );
      return;
    }
    fclose(fp);
  }

  arena_idx = mrb_gc_arena_save(mrb);

  fp = fopen(fpath, "rb");
  irep = mrb_read_irep_file(mrb, fp);
  fclose(fp);

  mrb_gc_arena_restore(mrb, arena_idx);

  if (irep) {
    struct RProc *proc;
    /*
    size_t i;
    for (i = sirep; i < mrb->irep_len; i++) {
      mrb->irep[i]->filename = mrb_string_value_ptr(mrb, filepath);
    }
    */

    replace_stop_with_return(mrb, irep);
    proc = mrb_proc_new(mrb, irep);
    proc->target_class = mrb->object_class;

    arena_idx = mrb_gc_arena_save(mrb);
    mrb_yield_with_class(mrb, mrb_obj_value(proc), 0, NULL, mrb_top_self(mrb), mrb->object_class);
    mrb_gc_arena_restore(mrb, arena_idx);
  } else if (mrb->exc) {
    // fail to load
    longjmp(*(jmp_buf*)mrb->jmp, 1);
  }
}
示例#5
0
static void
load_mrb_file(mrb_state *mrb, mrb_value filepath)
{
  char *fpath = RSTRING_PTR(filepath);
  int ai;
  FILE *fp;
  mrb_irep *irep;

  fp = fopen(fpath, "rb");
  if (fp == NULL) {
    mrb_load_fail(
      mrb,
      mrb_str_new_cstr(mrb, fpath),
      "cannot load such file"
    );
    return;
  }

  ai = mrb_gc_arena_save(mrb);

  irep = mrb_read_irep_file(mrb, fp);
  fclose(fp);

  mrb_gc_arena_restore(mrb, ai);

  if (irep) {
    struct RProc *proc;
    /*
    size_t i;
    for (i = sirep; i < mrb->irep_len; i++) {
      mrb->irep[i]->filename = mrb_string_value_ptr(mrb, filepath);
    }
    */

#ifdef USE_MRUBY_OLD_BYTE_CODE
    replace_stop_with_return(mrb, irep);
#endif
    proc = mrb_proc_new(mrb, irep);
    MRB_PROC_SET_TARGET_CLASS(proc, mrb->object_class);

    ai = mrb_gc_arena_save(mrb);
    mrb_yield_with_class(mrb, mrb_obj_value(proc), 0, NULL, mrb_top_self(mrb), mrb->object_class);
    mrb_gc_arena_restore(mrb, ai);
  } else if (mrb->exc) {
    // fail to load
    longjmp(*(jmp_buf*)mrb->jmp, 1);
  }
}
示例#6
0
static void*
mrb_future_func(void* data) {
  mrb_value result;

  mrb_future_context *context = (mrb_future_context *) data;
  struct mrb_state *mrb = context->mrb;
  struct mrb_state *oldmrb = context->oldmrb;
  mrb_value self = context->self;

  result = mrb_yield_with_class(mrb, mrb_obj_value(context->proc), context->argc, context->argv, context->self, mrb_class(mrb, context->self));

  mrb_iv_set(oldmrb, self, mrb_intern_cstr(oldmrb, "value"), result);
  mrb_iv_set(oldmrb, self, mrb_intern_cstr(oldmrb, "_state"), mrb_fixnum_value(FUTURE_FINISH));

  return NULL;
}
示例#7
0
static void
mrb_load_irep_data(mrb_state* mrb, const uint8_t* data)
{
  int ai = mrb_gc_arena_save(mrb);
  mrb_irep *irep = mrb_read_irep(mrb,data);
  mrb_gc_arena_restore(mrb,ai);

  if (irep) {
    int ai;
    struct RProc *proc;

    replace_stop_with_return(mrb, irep);
    proc = mrb_proc_new(mrb, irep);
    proc->target_class = mrb->object_class;

    ai = mrb_gc_arena_save(mrb);
    mrb_yield_with_class(mrb, mrb_obj_value(proc), 0, NULL, mrb_top_self(mrb), mrb->object_class);
    mrb_gc_arena_restore(mrb, ai);
  } else if (mrb->exc) {
    // fail to load
    longjmp(*(jmp_buf*)mrb->jmp, 1);
  }
}
示例#8
0
文件: kernel.c 项目: takeru/mruby
/*
 *  call-seq:
 *     obj.instance_eval {| | block }                       -> obj
 *
 *  Evaluates the given block,within  the context of the receiver (_obj_).
 *  In order to set the context, the variable +self+ is set to _obj_ while
 *  the code is executing, giving the code access to _obj_'s
 *  instance variables. In the version of <code>instance_eval</code>
 *  that takes a +String+, the optional second and third
 *  parameters supply a filename and starting line number that are used
 *  when reporting compilation errors.
 *
 *     class KlassWithSecret
 *       def initialize
 *         @secret = 99
 *       end
 *     end
 *     k = KlassWithSecret.new
 *     k.instance_eval { @secret }   #=> 99
 */
static mrb_value
mrb_obj_instance_eval(mrb_state *mrb, mrb_value self)
{
    mrb_value a, b;
    mrb_value cv;
    struct RClass *c;

    if (mrb_get_args(mrb, "|S&", &a, &b) == 1) {
        mrb_raise(mrb, E_NOTIMP_ERROR, "instance_eval with string not implemented");
    }
    switch (mrb_type(self)) {
    case MRB_TT_SYMBOL:
    case MRB_TT_FIXNUM:
    case MRB_TT_FLOAT:
        c = 0;
        break;
    default:
        cv = mrb_singleton_class(mrb, self);
        c = mrb_class_ptr(cv);
        break;
    }
    return mrb_yield_with_class(mrb, b, 0, 0, self, c);
}