PageRenderTime 70ms CodeModel.GetById 15ms app.highlight 50ms RepoModel.GetById 1ms app.codeStats 1ms

/vm/class.go

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