示例#1
0
文件: struct.c 项目: akuroda/mruby
static mrb_value
mrb_struct_initialize_withArg(mrb_state *mrb, int argc, mrb_value *argv, mrb_value self)
{
  struct RClass *klass = mrb_obj_class(mrb, self);
  long n;
  struct RStruct *st;

  mrb_struct_modify(self);
  n = num_members(mrb, klass);
  if (n < argc) {
    mrb_raise(mrb, E_ARGUMENT_ERROR, "struct size differs");
  }
  st = RSTRUCT(self);
  st->ptr = mrb_calloc(mrb, sizeof(mrb_value), n);
  st->len = n;
  memcpy(st->ptr, argv, sizeof(mrb_value)*argc);

  return self;
}
示例#2
0
文件: proc.c 项目: Epictetus/mruby
void
mrb_init_proc(mrb_state *mrb)
{
  struct RProc *m;
  mrb_code *call_iseq = mrb_malloc(mrb, sizeof(mrb_code));
  mrb_irep *call_irep = mrb_calloc(mrb, sizeof(mrb_irep), 1);

  if ( call_iseq == NULL || call_irep == NULL )
    return;

  *call_iseq = MKOP_A(OP_CALL, 0);
  call_irep->idx = -1;
  call_irep->flags = MRB_IREP_NOFREE;
  call_irep->iseq = call_iseq;
  call_irep->ilen = 1;

  mrb->proc_class = mrb_define_class(mrb, "Proc", mrb->object_class);

  m = mrb_proc_new(mrb, call_irep);
  mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern(mrb, "call"), m);
  mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern(mrb, "[]"), m);
}
示例#3
0
文件: fiber.c 项目: ASnow/mruby
/*
 *  call-seq:
 *     Fiber.new{...} -> obj
 *
 *  Creates a fiber, whose execution is suspend until it is explicitly
 *  resumed using <code>Fiber#resume</code> method.
 *  The code running inside the fiber can give up control by calling
 *  <code>Fiber.yield</code> in which case it yields control back to caller
 *  (the caller of the <code>Fiber#resume</code>).
 *
 *  Upon yielding or termination the Fiber returns the value of the last
 *  executed expression
 *
 *  For instance:
 *
 *    fiber = Fiber.new do
 *      Fiber.yield 1
 *      2
 *    end
 *
 *    puts fiber.resume
 *    puts fiber.resume
 *    puts fiber.resume
 *
 *  <em>produces</em>
 *
 *    1
 *    2
 *    resuming dead fiber (FiberError)
 *
 *  The <code>Fiber#resume</code> method accepts an arbitrary number of
 *  parameters, if it is the first call to <code>resume</code> then they
 *  will be passed as block arguments. Otherwise they will be the return
 *  value of the call to <code>Fiber.yield</code>
 *
 *  Example:
 *
 *    fiber = Fiber.new do |first|
 *      second = Fiber.yield first + 2
 *    end
 *
 *    puts fiber.resume 10
 *    puts fiber.resume 14
 *    puts fiber.resume 18
 *
 *  <em>produces</em>
 *
 *    12
 *    14
 *    resuming dead fiber (FiberError)
 *
 */
static mrb_value
fiber_init(mrb_state *mrb, mrb_value self)
{
  static const struct mrb_context mrb_context_zero = { 0 };
  struct RFiber *f = fiber_ptr(self);
  struct mrb_context *c;
  struct RProc *p;
  mrb_callinfo *ci;
  mrb_value blk;
  size_t slen;

  mrb_get_args(mrb, "&", &blk);

  if (mrb_nil_p(blk)) {
    mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Fiber object without a block");
  }
  p = mrb_proc_ptr(blk);
  if (MRB_PROC_CFUNC_P(p)) {
    mrb_raise(mrb, E_FIBER_ERROR, "tried to create Fiber from C defined method");
  }

  f->cxt = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context));
  *f->cxt = mrb_context_zero;
  c = f->cxt;

  /* initialize VM stack */
  slen = FIBER_STACK_INIT_SIZE;
  if (p->body.irep->nregs > slen) {
    slen += p->body.irep->nregs;
  }
  c->stbase = (mrb_value *)mrb_malloc(mrb, slen*sizeof(mrb_value));
  c->stend = c->stbase + slen;
  c->stack = c->stbase;

#ifdef MRB_NAN_BOXING
  {
    mrb_value *p = c->stbase;
    mrb_value *pend = c->stend;

    while (p < pend) {
      SET_NIL_VALUE(*p);
      p++;
    }
  }
#else
  memset(c->stbase, 0, slen * sizeof(mrb_value));
#endif

  /* copy receiver from a block */
  c->stack[0] = mrb->c->stack[0];

  /* initialize callinfo stack */
  c->cibase = (mrb_callinfo *)mrb_calloc(mrb, FIBER_CI_INIT_SIZE, sizeof(mrb_callinfo));
  c->ciend = c->cibase + FIBER_CI_INIT_SIZE;
  c->ci = c->cibase;
  c->ci->stackent = c->stack;

  /* adjust return callinfo */
  ci = c->ci;
  ci->target_class = p->target_class;
  ci->proc = p;
  ci->pc = p->body.irep->iseq;
  ci->nregs = p->body.irep->nregs;
  ci[1] = ci[0];
  c->ci++;                      /* push dummy callinfo */

  c->fib = f;
  c->status = MRB_FIBER_CREATED;

  return self;
}
示例#4
0
static mrb_value
mrb_future_init(mrb_state *oldmrb, mrb_value self)
{
  static const struct mrb_context mrb_context_zero = { 0 };
  mrb_state *mrb = mrb_open();
  mrb_future_context *context = (mrb_future_context *) malloc(sizeof(mrb_future_context));
  struct mrb_context *c;
  struct RProc *p;
  mrb_callinfo *ci;
  mrb_value blk;
  size_t slen;
  int argc;
  mrb_value* argv;

  *mrb = *oldmrb;
  mrb_get_args(mrb, "*&", &argv, &argc, &blk);

  p = mrb_proc_ptr(blk);

  c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context));
  *c = mrb_context_zero;
  mrb->c = c;
  context->mrb = mrb;
  context->oldmrb = oldmrb;
  context->proc = mrb_proc_ptr(blk);
  context->argc = argc;
  context->argv = argv;
  context->self = self;

  /* initialize VM stack */
  slen = FIBER_STACK_INIT_SIZE;
  if (!MRB_PROC_CFUNC_P(p) && p->body.irep->nregs > slen) {
    slen += p->body.irep->nregs;
  }
  c->stbase = (mrb_value *)mrb_malloc(mrb, slen*sizeof(mrb_value));
  c->stend = c->stbase + slen;
  c->stack = c->stbase;

#ifdef MRB_NAN_BOXING
  {
    mrb_value *p = c->stbase;
    mrb_value *pend = c->stend;
    
    while (p < pend) {
      SET_NIL_VALUE(*p);
      p++;
    }
  }
#else
  memset(c->stbase, 0, slen * sizeof(mrb_value));
#endif

  /* copy future object(self) from a block */
  c->stack[0] = self;

  /* initialize callinfo stack */
  c->cibase = (mrb_callinfo *)mrb_calloc(mrb, FIBER_CI_INIT_SIZE, sizeof(mrb_callinfo));
  c->ciend = c->cibase + FIBER_CI_INIT_SIZE;
  c->ci = c->cibase;
  c->ci->stackent = c->stack;

  /* adjust return callinfo */
  ci = c->ci;
  ci->target_class = p->target_class;
  ci->proc = p;
  if (!MRB_PROC_CFUNC_P(p)) {
    ci->pc = p->body.irep->iseq;
    ci->nregs = p->body.irep->nregs;
  }
  ci[1] = ci[0];
  c->ci++;                      /* push dummy callinfo */

  mrb_iv_set(oldmrb, self, mrb_intern_cstr(oldmrb, "_context"), mrb_cptr_value(oldmrb, context));
  mrb_iv_set(oldmrb, self, mrb_intern_cstr(oldmrb, "_state"), mrb_fixnum_value(FUTURE_RUNNING));

  pthread_create(&context->thread, NULL, &mrb_future_func, (void *)context);

  return self;
}