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