PageRenderTime 24ms CodeModel.GetById 11ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/vm/tinyrb/object.c

http://github.com/feyeleanor/RubyGoLightly
C | 110 lines | 94 code | 14 blank | 2 comment | 18 complexity | a4d78c8e080514709261a476951af390 MD5 | raw file
  1#include "tr.h"
  2#include "internal.h"
  3#include "call.h"
  4
  5OBJ TrObject_alloc(VM, OBJ class) {
  6  TrObject *o = TR_INIT_CORE_OBJECT(Object);
  7  if (class) o->class = class;
  8  return (OBJ) o;
  9}
 10
 11int TrObject_type(VM, OBJ obj) {
 12  UNUSED(vm);
 13  switch (obj) {
 14    case TR_NIL: return TR_T_NilClass;
 15    case TR_TRUE: return TR_T_TrueClass;
 16    case TR_FALSE: return TR_T_FalseClass;
 17  }
 18  if (TR_IS_FIX(obj)) return TR_T_Fixnum;
 19  return TR_COBJECT(obj)->type;
 20}
 21
 22OBJ TrObject_method(VM, OBJ self, OBJ name) {
 23  return TrModule_instance_method(vm, TR_CLASS(self), name);
 24}
 25
 26OBJ TrObject_method_missing(VM, OBJ self, int argc, OBJ argv[]) {
 27  UNUSED(self);
 28  assert(argc > 0);
 29  tr_raise(NoMethodError, "Method not found: `%s'", TR_STR_PTR(argv[0]));
 30}
 31
 32OBJ TrObject_send(VM, OBJ self, int argc, OBJ argv[]) {
 33  if (unlikely(argc == 0))
 34    tr_raise(ArgumentError, "wrong number of arguments (%d for 1)", argc);
 35  OBJ method = TrObject_method(vm, self, argv[0]);
 36  if (unlikely(method == TR_NIL)) {
 37    method = TrObject_method(vm, self, tr_intern("method_missing"));
 38    return TrMethod_call(vm, method, self, argc, argv, 0, 0);
 39  } else {
 40    return TrMethod_call(vm, method, self, argc-1, argv+1, 0, 0);
 41  }
 42}
 43
 44/* TODO respect namespace */
 45OBJ TrObject_const_get(VM, OBJ self, OBJ name) {
 46  UNUSED(self);
 47  khiter_t k = kh_get(OBJ, vm->consts, name);
 48  if (k != kh_end(vm->consts)) return kh_value(vm->consts, k);
 49  return TR_NIL;
 50}
 51
 52OBJ TrObject_const_set(VM, OBJ self, OBJ name, OBJ value) {
 53  UNUSED(self);
 54  int ret;
 55  khiter_t k = kh_put(OBJ, vm->consts, name, &ret);
 56  if (!ret) kh_del(OBJ, vm->consts, k);
 57  kh_value(vm->consts, k) = value;
 58  return value;
 59}
 60
 61OBJ TrObject_add_singleton_method(VM, OBJ self, OBJ name, OBJ method) {
 62  TrObject *o = TR_COBJECT(self);
 63  if (!TR_CCLASS(o->class)->meta)
 64    o->class = TrMetaClass_new(vm, o->class);
 65  assert(TR_CCLASS(o->class)->meta && "first class must be the metaclass");
 66  TrModule_add_method(vm, o->class, name, method);
 67  return method;
 68}
 69
 70static OBJ TrObject_class(VM, OBJ self) {
 71  OBJ class = TR_CLASS(self);
 72  /* find the first non-metaclass */
 73  while (class && (!TR_IS_A(class, Class) || TR_CCLASS(class)->meta))
 74    class = TR_CCLASS(class)->super;
 75  assert(class && "classless object");
 76  return class;
 77}
 78
 79static OBJ TrObject_object_id(VM, OBJ self) {
 80  UNUSED(vm);
 81  return TR_INT2FIX((int)&self);
 82}
 83
 84static OBJ TrObject_instance_eval(VM, OBJ self, OBJ code) {
 85  TrBlock *b = TrBlock_compile(vm, TR_STR_PTR(code), "<eval>", 0);
 86  if (!b) return TR_UNDEF;
 87  return TrVM_run(vm, b, self, TR_COBJECT(self)->class, 0, 0);
 88}
 89
 90static OBJ TrObject_inspect(VM, OBJ self) {
 91  const char *name;
 92  name = TR_STR_PTR(tr_send2(tr_send2(self, "class"), "name"));
 93  return tr_sprintf(vm, "#<%s:%p>", name, (void*)self);
 94}
 95
 96void TrObject_preinit(VM) {
 97  TR_INIT_CORE_CLASS(Object, /* ignored */ Object);
 98}
 99
100void TrObject_init(VM) {
101  OBJ c = TR_CORE_CLASS(Object);
102  tr_def(c, "class", TrObject_class, 0);
103  tr_def(c, "method", TrObject_method, 1);
104  tr_def(c, "method_missing", TrObject_method_missing, -1);
105  tr_def(c, "send", TrObject_send, -1);
106  tr_def(c, "object_id", TrObject_object_id, 0);
107  tr_def(c, "instance_eval", TrObject_instance_eval, 1);
108  tr_def(c, "to_s", TrObject_inspect, 0);
109  tr_def(c, "inspect", TrObject_inspect, 0);
110}