PageRenderTime 22ms CodeModel.GetById 10ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/vm/tinyrb/call.h

http://github.com/feyeleanor/RubyGoLightly
C++ Header | 68 lines | 59 code | 7 blank | 2 comment | 10 complexity | df44f35e73021df159526cbba455ac52 MD5 | raw file
 1/* Inlined functions frequently used in the method calling process. */
 2
 3#include <alloca.h>
 4
 5#define TR_WITH_FRAME(SELF,CLASS,CLOS,BODY) ({ \
 6  /* push a frame */ \
 7  if (unlikely(++vm->cf >= TR_MAX_FRAMES)) tr_raise(SystemStackError, "Stack overflow"); \
 8  TrFrame __f; \
 9  register TrFrame *__fp = &__f; \
10  __f.previous = vm->frame; \
11  if (vm->cf == 0) vm->top_frame = __fp; \
12  vm->frame = __fp; \
13  vm->throw_reason = vm->throw_value = 0; \
14  __f.method = NULL; \
15  __f.filename = __f.line = 0; \
16  __f.self = SELF; \
17  __f.class = CLASS; \
18  __f.closure = CLOS; \
19  /* execute BODY inside the frame */ \
20  BODY \
21  /* pop the frame */ \
22  vm->cf--; \
23  vm->frame = vm->frame->previous; \
24})
25
26static inline OBJ TrMethod_call(VM, OBJ self, OBJ receiver, int argc, OBJ *args, int splat, TrClosure *cl) {
27  OBJ ret = TR_NIL;
28  TrFrame *f = NULL;
29
30  TR_WITH_FRAME(receiver, TR_CLASS(receiver), cl, {
31    f = vm->frame;
32    TrMethod *m = f->method = TR_CMETHOD(self);
33    TrFunc *func = f->method->func;
34
35    /* splat last arg is needed */
36    if (unlikely(splat)) {
37      OBJ splated = args[argc-1];
38      int splatedn = TR_ARRAY_SIZE(splated);
39      OBJ *new_args = TR_ALLOC_N(OBJ, argc);
40      TR_MEMCPY_N(new_args, args, OBJ, argc-1);
41      TR_MEMCPY_N(new_args + argc-1, &TR_ARRAY_AT(splated, 0), OBJ, splatedn);
42      argc += splatedn-1;
43      args = new_args;
44    }
45  
46    if (m->arity == -1) {
47      ret = func(vm, receiver, argc, args);
48    } else {
49      if (m->arity != argc) tr_raise(ArgumentError, "Expected %d arguments, got %d.", f->method->arity, argc);
50      switch (argc) {
51        case 0:  ret = func(vm, receiver); break;
52        case 1:  ret = func(vm, receiver, args[0]); break;
53        case 2:  ret = func(vm, receiver, args[0], args[1]); break;
54        case 3:  ret = func(vm, receiver, args[0], args[1], args[2]); break;
55        case 4:  ret = func(vm, receiver, args[0], args[1], args[2], args[3]); break;
56        case 5:  ret = func(vm, receiver, args[0], args[1], args[2], args[3], args[4]); break;
57        case 6:  ret = func(vm, receiver, args[0], args[1], args[2], args[3], args[4], args[5]); break;
58        case 7:  ret = func(vm, receiver, args[0], args[1], args[2], args[3], args[4], args[5], args[6]); break;
59        case 8:  ret = func(vm, receiver, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); break;
60        case 9:  ret = func(vm, receiver, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); break;
61        case 10: ret = func(vm, receiver, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]); break;
62        default: tr_raise(ArgumentError, "Too much arguments: %d, max is %d for now.", argc, 10);
63      }
64    }
65  });
66  
67  return ret;
68}