/vm/class.go

http://github.com/feyeleanor/RubyGoLightly · Go · 202 lines · 175 code · 23 blank · 4 comment · 30 complexity · bb1c6b5ab5b0af552f1b390101fa08ab MD5 · raw file

  1. import (
  2. "tr";
  3. )
  4. type Method struct {
  5. type TR_T;
  6. class *RubyObject;
  7. ivars map[string] RubyObject;
  8. func *TrFunc;
  9. data *RubyObject;
  10. name *RubyObject;
  11. arity int;
  12. }
  13. type Module struct {
  14. type TR_T;
  15. class *RubyObject;
  16. ivars map[string] RubyObject;
  17. name *RubyObject;
  18. super *RubyObject;
  19. methods map[string] RubyObject;
  20. meta bool;
  21. }
  22. func (vm *RubyVM) newModule(name *RubyObject) RubyObject {
  23. return Module{type: TR_T_Module, class: vm.classes[TR_T_Module], ivars: make(map[string] RubyObject), name: name, methods: make(map[string] RubyObject)};
  24. }
  25. func (vm *RubyVM) newIncludedModule(module, super *RubyObject) RubyObject {
  26. if !module.(Class) && !module.(Module) {
  27. vm.throw_reason = TR_THROW_EXCEPTION;
  28. vm.throw_value = TrException_new(vm, vm.cTypeError, TrString_new2(vm, "Expected " + module));
  29. return TR_UNDEF;
  30. }
  31. m := Class *(module);
  32. return Module{type: TR_T_Module, class: vm.classes[TR_T_Module], ivars: make(map[string] RubyObject), name: m.name, methods: m.methods, super: super};
  33. }
  34. type Class struct {
  35. module Module;
  36. }
  37. func (self *Module) instance_method(vm *RubyVM, name *RubyObject) RubyObject {
  38. if !self.(Class) && !self.(Module) {
  39. vm.throw_reason = TR_THROW_EXCEPTION;
  40. vm.throw_value = TrException_new(vm, vm.cTypeError, TrString_new2(vm, "Expected " + self));
  41. return TR_UNDEF;
  42. }
  43. class := Class *(self);
  44. while (class) {
  45. if method := class.methods[name] { return method; }
  46. class = Class *(class).super;
  47. }
  48. return TR_NIL;
  49. }
  50. func (self *Module) add_method(vm *RubyVM, name, method *RubyObject) RubyObject {
  51. if !self.(Class) && !self.(Module) {
  52. vm.throw_reason = TR_THROW_EXCEPTION;
  53. vm.throw_value = TrException_new(vm, vm.cTypeError, TrString_new2(vm, "Expected " + self));
  54. return TR_UNDEF;
  55. }
  56. m := Class *(self);
  57. m.methods[name] = method;
  58. method.name = name;
  59. return method;
  60. }
  61. func (self *Module) alias_method(vm *RubyVM, new_name, old_name *RubyObject) RubyObject {
  62. return self.instance_method(vm, old_name).add_method(vm, self, new_name);
  63. }
  64. func (self *Module) include(vm *RubyVM, module *RubyObject) RubyObject {
  65. if !self.(Class) && !self.(Module) {
  66. vm.throw_reason = TR_THROW_EXCEPTION;
  67. vm.throw_value = TrException_new(vm, vm.cTypeError, TrString_new2(vm, "Expected " + self));
  68. return TR_UNDEF;
  69. }
  70. class := Class *(self);
  71. class.super = vm.newIncludedModule(module, class.super);
  72. return module;
  73. }
  74. func (self *Module) name(vm *RubyVM) RubyObject {
  75. if !self.(Class) && !self.(Module) {
  76. vm.throw_reason = TR_THROW_EXCEPTION;
  77. vm.throw_value = TrException_new(vm, vm.cTypeError, TrString_new2(vm, "Expected " + self));
  78. return TR_UNDEF;
  79. }
  80. return Class *(self).name;
  81. }
  82. func TrModule_init(vm *RubyVM) {
  83. c := vm.classes[TR_T_Module] = Object_const_set(vm, vm.self, TrSymbol_new(vm, Module), newClass(vm, TrSymbol_new(vm, Module), vm.classes[TR_T_Object]));
  84. c.add_method(vm, TrSymbol_new(vm, "name"), newMethod(vm, (TrFunc *)TrModule_name, TR_NIL, 0));
  85. c.add_method(vm, TrSymbol_new(vm, "include"), newMethod(vm, (TrFunc *)TrModule_include, TR_NIL, 1));
  86. c.add_method(vm, TrSymbol_new(vm, "instance_method"), newMethod(vm, (TrFunc *)TrModule_instance_method, TR_NIL, 1));
  87. c.add_method(vm, TrSymbol_new(vm, "alias_method"), newMethod(vm, (TrFunc *)TrModule_instance_method, TR_NIL, 2));
  88. c.add_method(vm, TrSymbol_new(vm, "to_s"), newMethod(vm, (TrFunc *)TrModule_name, TR_NIL, 0));
  89. }
  90. /* class */
  91. func newClass(vm *RubyVM, name, super *RubyObject) RubyObject {
  92. c := Class{type: TR_T_Class, class: vm.classes[TR_T_Class], ivars: make(map[string] RubyObject), name: name, methods: make(map[string] RubyObject), meta: false};
  93. if !super.(Class) && !super.(Module) {
  94. vm.throw_reason = TR_THROW_EXCEPTION;
  95. vm.throw_value = TrException_new(vm, vm.cTypeError, TrString_new2(vm, "Expected " + super));
  96. return TR_UNDEF;
  97. }
  98. // if VM is booting, those might not be set
  99. if (super && Class *(super).class) { c.class = newMetaClass(vm, Class *(super).class); }
  100. c.super = super
  101. return c;
  102. }
  103. func (self *Class) allocate(vm *RubyVM) RubyObject {
  104. return Object{type: TR_T_Object, class: vm.classes[TR_T_Object], ivars: make(map[string] RubyObject), class: self};
  105. }
  106. func (self *Class) superclass(vm *RubyVM) RubyObject {
  107. if !self.(Class) && !self.(Module) {
  108. vm.throw_reason = TR_THROW_EXCEPTION;
  109. vm.throw_value = TrException_new(vm, vm.cTypeError, TrString_new2(vm, "Expected " + self));
  110. return TR_UNDEF;
  111. }
  112. super := Class *(self).super;
  113. while (super && !super.(Class)) {
  114. if !super.(Module) {
  115. vm.throw_reason = TR_THROW_EXCEPTION;
  116. vm.throw_value = TrException_new(vm, vm.cTypeError, TrString_new2(vm, "Expected " + super));
  117. return TR_UNDEF;
  118. }
  119. super = Class *(super).super;
  120. }
  121. return super;
  122. }
  123. func TrClass_init(vm *RubyVM) {
  124. c := vm.classes[TR_T_Class] = Object_const_set(vm, vm.self, TrSymbol_new(vm, Class), newClass(vm, TrSymbol_new(vm, Class), vm.classes[TR_T_Module]));
  125. c.add_method(vm, TrSymbol_new(vm, "superclass"), newMethod(vm, (TrFunc *)TrClass_superclass, TR_NIL, 0));
  126. c.add_method(vm, TrSymbol_new(vm, "allocate"), newMethod(vm, (TrFunc *)TrClass_allocate, TR_NIL, 0));
  127. }
  128. /* metaclass */
  129. func newMetaClass(vm *RubyVM, super *RubyObject) RubyObject {
  130. if !super.(Class) && !super.(Module) {
  131. vm.throw_reason = TR_THROW_EXCEPTION;
  132. vm.throw_value = TrException_new(vm, vm.cTypeError, TrString_new2(vm, "Expected " + super));
  133. return TR_UNDEF;
  134. }
  135. class := Class *(super);
  136. if !class.name.(String) && !class.name.(Symbol) {
  137. vm.throw_reason = TR_THROW_EXCEPTION;
  138. vm.throw_value = TrException_new(vm, vm.cTypeError, TrString_new2(vm, "Expected " + class.name));
  139. return TR_UNDEF;
  140. }
  141. name := tr_sprintf(vm, "Class:%s", class.name.ptr);
  142. if !name.(String) && !name.(Symbol) {
  143. vm.throw_reason = TR_THROW_EXCEPTION;
  144. vm.throw_value = TrException_new(vm, vm.cTypeError, TrString_new2(vm, "Expected " + name));
  145. return TR_UNDEF;
  146. }
  147. name := TrSymbol_new(vm, name.ptr); /* symbolize */
  148. mc = newClass(vm, name, 0);
  149. mc.super = super;
  150. mc.meta = 1;
  151. return mc;
  152. }
  153. /* method */
  154. func newMethod(vm *RubyVM, function *TrFunc, data *RubyObject, arity int) RubyObject {
  155. return Method{type: TR_T_Method, class: vm.classes[TR_T_Method], ivars: make(map[string] RubyObject), func: function, data: data, arity: arity};
  156. }
  157. func (self *Method) name(vm *RubyVM) RubyObject { return ((Method *) self).name; }
  158. func (self *Method) arity(vm *RubyVM) RubyObject { return TR_INT2FIX(((Method *) self).arity); }
  159. func (self *Method) dump(vm *RubyVM) RubyObject {
  160. m := (Method *) self;
  161. if !m.name.(String) && !m.name.(Symbol) {
  162. vm.throw_reason = TR_THROW_EXCEPTION;
  163. vm.throw_value = TrException_new(vm, vm.cTypeError, TrString_new2(vm, "Expected " + m.name));
  164. return TR_UNDEF;
  165. }
  166. if m.name { println("<Method '%s':%p>", m.name.ptr, m); }
  167. if m.data {
  168. Block *(m.data).dump(vm, 0);
  169. } else {
  170. fmt.Println("<CFunction:%p>", m.func);
  171. }
  172. return TR_NIL;
  173. }
  174. func TrMethod_init(vm *RubyVM) {
  175. c := vm.classes[TR_T_Method] = Object_const_set(vm, vm.self, TrSymbol_new(vm, Method), newClass(vm, TrSymbol_new(vm, Method), vm.classes[TR_T_Object]));
  176. c.add_method(vm, TrSymbol_new(vm, "name"), newMethod(vm, (TrFunc *)TrMethod_name, TR_NIL, 0));
  177. c.add_method(vm, TrSymbol_new(vm, "arity"), newMethod(vm, (TrFunc *)TrMethod_arity, TR_NIL, 0));
  178. c.add_method(vm, TrSymbol_new(vm, "dump"), newMethod(vm, (TrFunc *)TrMethod_dump, TR_NIL, 0));
  179. }