[macruby-changes] [1858] MacRuby/branches/experimental

source_changes at macosforge.org source_changes at macosforge.org
Sun Jun 14 21:43:56 PDT 2009


Revision: 1858
          http://trac.macosforge.org/projects/ruby/changeset/1858
Author:   lsansonetti at apple.com
Date:     2009-06-14 21:43:56 -0700 (Sun, 14 Jun 2009)
Log Message:
-----------
a quick implementation for #define_method (not yet 100% complete)

Modified Paths:
--------------
    MacRuby/branches/experimental/class.c
    MacRuby/branches/experimental/compiler.cpp
    MacRuby/branches/experimental/compiler.h
    MacRuby/branches/experimental/proc.c
    MacRuby/branches/experimental/vm.cpp
    MacRuby/branches/experimental/vm.h

Modified: MacRuby/branches/experimental/class.c
===================================================================
--- MacRuby/branches/experimental/class.c	2009-06-14 19:01:51 UTC (rev 1857)
+++ MacRuby/branches/experimental/class.c	2009-06-15 04:43:56 UTC (rev 1858)
@@ -940,8 +940,7 @@
 	assert(name[strlen(name) - 1] != ':');
     }
 
-    NODE *node = NEW_CFUNC(imp, arity);
-    NODE *body = NEW_FBODY(NEW_METHOD(node, klass, noex), 0);
+    NODE *body = rb_vm_cfunc_node_from_imp((Class)klass, arity, (IMP)imp, noex);
     rb_objc_retain(body);
 
     rb_vm_define_method((Class)klass, name_to_sel(name, arity), (IMP)imp,

Modified: MacRuby/branches/experimental/compiler.cpp
===================================================================
--- MacRuby/branches/experimental/compiler.cpp	2009-06-14 19:01:51 UTC (rev 1857)
+++ MacRuby/branches/experimental/compiler.cpp	2009-06-15 04:43:56 UTC (rev 1858)
@@ -101,6 +101,7 @@
     masgnGetSplatFunc = NULL;
     newStringFunc = NULL;
     yieldFunc = NULL;
+    blockEvalFunc = NULL;
     gvarSetFunc = NULL;
     gvarGetFunc = NULL;
     cvarSetFunc = NULL;
@@ -5352,6 +5353,43 @@
 }
 
 Function *
+RoxorCompiler::compile_block_caller(rb_vm_block_t *block)
+{
+    // VALUE foo(VALUE rcv, SEL sel, int argc, VALUE *argv)
+    // {
+    //     return rb_vm_block_eval2(block, rcv, argc, argv);
+    // }
+    Function *f = cast<Function>(module->getOrInsertFunction("",
+		RubyObjTy, RubyObjTy, PtrTy, Type::Int32Ty, RubyObjPtrTy,
+		NULL));
+    Function::arg_iterator arg = f->arg_begin();
+    Value *rcv = arg++;
+    arg++; // sel
+    Value *argc = arg++;
+    Value *argv = arg++;
+
+    bb = BasicBlock::Create("EntryBlock", f);
+
+    if (blockEvalFunc == NULL) {
+	blockEvalFunc = cast<Function>(module->getOrInsertFunction(
+		    "rb_vm_block_eval2",
+		    RubyObjTy, PtrTy, RubyObjTy, Type::Int32Ty, RubyObjPtrTy,
+		    NULL));
+    }
+    std::vector<Value *> params;
+    params.push_back(compile_const_pointer(block));
+    params.push_back(rcv);
+    params.push_back(argc);
+    params.push_back(argv);
+
+    Value *retval = compile_protected_call(blockEvalFunc, params);
+
+    ReturnInst::Create(retval, bb);
+
+    return f;
+}
+
+Function *
 RoxorCompiler::compile_to_rval_convertor(const char *type)
 {
     // VALUE foo(void *ocval);

Modified: MacRuby/branches/experimental/compiler.h
===================================================================
--- MacRuby/branches/experimental/compiler.h	2009-06-14 19:01:51 UTC (rev 1857)
+++ MacRuby/branches/experimental/compiler.h	2009-06-15 04:43:56 UTC (rev 1858)
@@ -46,6 +46,7 @@
 	Function *compile_to_rval_convertor(const char *type);
 	Function *compile_to_ocval_convertor(const char *type);
 	Function *compile_objc_stub(Function *ruby_func, const char *types);
+	Function *compile_block_caller(rb_vm_block_t *block);
 
 	const Type *convert_type(const char *type);
 
@@ -131,6 +132,7 @@
 	Function *masgnGetSplatFunc;
 	Function *newStringFunc;
 	Function *yieldFunc;
+	Function *blockEvalFunc;
 	Function *gvarSetFunc;
 	Function *gvarGetFunc;
 	Function *cvarSetFunc;

Modified: MacRuby/branches/experimental/proc.c
===================================================================
--- MacRuby/branches/experimental/proc.c	2009-06-14 19:01:51 UTC (rev 1857)
+++ MacRuby/branches/experimental/proc.c	2009-06-15 04:43:56 UTC (rev 1858)
@@ -48,16 +48,18 @@
     return obj;
 }
 
-VALUE
-rb_obj_is_proc(VALUE proc)
+static inline bool
+rb_obj_is_proc(VALUE obj)
 {
-    if (TYPE(proc) == T_DATA) {
-	// TODO check if it's really a rb_cProc
-	return Qtrue;
-    }
-    return Qfalse;
+    return CLASS_OF(obj) == rb_cProc;
 }
 
+static inline bool
+rb_obj_is_method(VALUE obj)
+{
+    return CLASS_OF(obj) == rb_cMethod;
+}
+
 static VALUE
 proc_dup(VALUE self, SEL sel)
 {
@@ -944,11 +946,8 @@
 static VALUE
 rb_mod_define_method(VALUE mod, SEL sel, int argc, VALUE *argv)
 {
-#if 0 // TODO
     ID id;
     VALUE body;
-    NODE *node;
-    int noex = NOEX_PUBLIC;
 
     if (argc == 1) {
 	id = rb_to_id(argv[0]);
@@ -967,7 +966,11 @@
 	rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
     }
 
-    if (true/*RDATA(body)->dmark == (RUBY_DATA_FUNC) bm_mark*/) {
+    SEL method_sel = sel_registerName(rb_id2name(id));
+    if (rb_obj_is_method(body)) {
+	// TODO
+	abort();
+#if 0
 	struct METHOD *method = (struct METHOD *)DATA_PTR(body);
 	VALUE rclass = method->rclass;
 	if (rclass != mod) {
@@ -982,32 +985,15 @@
 	    }
 	}
 	node = method->body;
+#endif
     }
-#if 0 // TODO
-    else if (rb_obj_is_proc(body)) {
-	rb_proc_t *proc;
-	body = proc_dup(body, 0);
+    else {
+	rb_vm_block_t *proc;
 	GetProcPtr(body, proc);
-	if (BUILTIN_TYPE(proc->block.iseq) != T_NODE) {
-	    proc->block.iseq->defined_method_id = id;
-	    proc->block.iseq->klass = mod;
-	    proc->is_lambda = Qtrue;
-	    proc->is_from_method = Qtrue;
-	}
-	node = NEW_BMETHOD(body);
+	rb_vm_define_method3((Class)mod, method_sel, proc);
     }
-#endif
-    else {
-	/* type error */
-	rb_raise(rb_eTypeError, "wrong argument type (expected Proc/Method)");
-    }
 
-    /* TODO: visibility */
-
-    rb_add_method(mod, id, node, noex);
     return body;
-#endif
-    return Qnil;
 }
 
 static VALUE

Modified: MacRuby/branches/experimental/vm.cpp
===================================================================
--- MacRuby/branches/experimental/vm.cpp	2009-06-14 19:01:51 UTC (rev 1857)
+++ MacRuby/branches/experimental/vm.cpp	2009-06-15 04:43:56 UTC (rev 1858)
@@ -510,7 +510,7 @@
     abort();
 }
 
-void
+rb_vm_method_node_t *
 RoxorVM::add_method(Class klass, SEL sel, IMP imp, IMP ruby_imp,
 		    const rb_vm_arity_t &arity, int flags, const char *types)
 {
@@ -608,6 +608,8 @@
 	    }
 	}
     }
+
+    return node;
 }
 
 void
@@ -1343,15 +1345,16 @@
     }
 }
 
-static void __rb_vm_define_method(Class klass, SEL sel, IMP imp,
-	const rb_vm_arity_t &arity, int flags, bool direct);
+static void __rb_vm_define_method(Class klass, SEL sel, IMP objc_imp,
+	IMP ruby_imp, const rb_vm_arity_t &arity, int flags, bool direct);
 
 extern "C"
 void
 rb_vm_prepare_method2(Class klass, SEL sel, IMP imp, rb_vm_arity_t arity,
 		      int flags)
 {
-    __rb_vm_define_method(klass, sel, imp, arity, flags, false);
+    // TODO: create objc_imp
+    __rb_vm_define_method(klass, sel, imp, imp, arity, flags, false);
 }
 
 #define VISI(x) ((x)&NOEX_MASK)
@@ -1616,18 +1619,15 @@
 }
 
 static void
-__rb_vm_define_method(Class klass, SEL sel, IMP imp,
+__rb_vm_define_method(Class klass, SEL sel, IMP objc_imp, IMP ruby_imp,
 		      const rb_vm_arity_t &arity, int flags, bool direct)
 {
     assert(klass != NULL);
 
     const char *sel_name = sel_getName(sel);
     const bool genuine_selector = sel_name[strlen(sel_name) - 1] == ':';
-
     int oc_arity = genuine_selector ? arity.real : 0;
     bool redefined = direct;
-    rb_vm_method_node_t *node = GET_VM()->method_node_get(imp);
-    IMP ruby_imp = node == NULL ? imp : node->ruby_imp;
 
 define_method:
     Method method = class_getInstanceMethod(klass, sel);
@@ -1635,7 +1635,7 @@
     char types[100];
     resolve_method_type(types, sizeof types, klass, method, sel, oc_arity);
 
-    GET_VM()->add_method(klass, sel, imp, ruby_imp, arity, flags, types);
+    GET_VM()->add_method(klass, sel, objc_imp, ruby_imp, arity, flags, types);
 
     if (!redefined) {
 	if (!genuine_selector && arity.max != arity.min) {
@@ -1666,7 +1666,8 @@
 {
     assert(node != NULL);
 
-    __rb_vm_define_method(klass, sel, imp, rb_vm_node_arity(node),
+    // TODO: create objc_imp
+    __rb_vm_define_method(klass, sel, imp, imp, rb_vm_node_arity(node),
 	    rb_vm_node_flags(node), direct);
 }
 
@@ -1677,12 +1678,27 @@
 {
     assert(node != NULL);
 
-    __rb_vm_define_method(klass, sel, node->objc_imp, node->arity,
-	    node->flags, direct);
+    __rb_vm_define_method(klass, sel, node->objc_imp, node->ruby_imp,
+	    node->arity, node->flags, direct);
 }
 
 extern "C"
 void
+rb_vm_define_method3(Class klass, SEL sel, rb_vm_block_t *block)
+{
+    assert(block != NULL);
+
+    Function *func = RoxorCompiler::shared->compile_block_caller(block);
+    IMP imp = GET_VM()->compile(func);
+    NODE *body = rb_vm_cfunc_node_from_imp(klass, -1, imp, 0);
+    rb_objc_retain(body);
+    rb_objc_retain(block);
+
+    rb_vm_define_method(klass, sel, imp, body, false);
+}
+
+extern "C"
+void
 rb_vm_undef_method(Class klass, const char *name, bool must_exist)
 {
     rb_vm_method_node_t *node = NULL;
@@ -3133,7 +3149,7 @@
 }
 
 static inline VALUE
-rb_vm_block_eval0(rb_vm_block_t *b, int argc, const VALUE *argv)
+rb_vm_block_eval0(rb_vm_block_t *b, VALUE self, int argc, const VALUE *argv)
 {
     if (b->node != NULL) {
 	if (nd_type(b->node) == NODE_IFUNC) {
@@ -3205,7 +3221,7 @@
 		    m->sel, argc, argv);
 	}
 	else {
-	    v = __rb_vm_bcall(b->self, (VALUE)b->dvars, b, b->imp, b->arity,
+	    v = __rb_vm_bcall(self, (VALUE)b->dvars, b, b->imp, b->arity,
 		    argc, argv);
 	}
     }
@@ -3222,9 +3238,17 @@
 VALUE
 rb_vm_block_eval(rb_vm_block_t *b, int argc, const VALUE *argv)
 {
-    return rb_vm_block_eval0(b, argc, argv);
+    return rb_vm_block_eval0(b, b->self, argc, argv);
 }
 
+extern "C"
+VALUE
+rb_vm_block_eval2(rb_vm_block_t *b, VALUE self, int argc, const VALUE *argv)
+{
+    // TODO check given arity and raise exception
+    return rb_vm_block_eval0(b, self, argc, argv);
+}
+
 static inline VALUE
 rb_vm_yield0(int argc, const VALUE *argv)
 {
@@ -3237,7 +3261,7 @@
 
     VALUE retval = Qnil;
     try {
-	retval = rb_vm_block_eval0(b, argc, argv);
+	retval = rb_vm_block_eval0(b, b->self, argc, argv);
     }
     catch (...) {
 	GET_VM()->add_current_block(b);
@@ -3270,7 +3294,7 @@
 
     VALUE retval = Qnil;
     try {
-	retval = rb_vm_block_eval0(b, argc, argv);
+	retval = rb_vm_block_eval0(b, b->self, argc, argv);
     }
     catch (...) {
 	b->self = old_self;

Modified: MacRuby/branches/experimental/vm.h
===================================================================
--- MacRuby/branches/experimental/vm.h	2009-06-14 19:01:51 UTC (rev 1857)
+++ MacRuby/branches/experimental/vm.h	2009-06-15 04:43:56 UTC (rev 1858)
@@ -191,6 +191,13 @@
     return 0;
 }
 
+static inline NODE *
+rb_vm_cfunc_node_from_imp(Class klass, int arity, IMP imp, int noex)
+{
+    NODE *node = NEW_CFUNC(imp, arity);
+    return NEW_FBODY(NEW_METHOD(node, klass, noex), 0);
+}
+
 VALUE rb_vm_run(const char *fname, NODE *node, rb_vm_binding_t *binding,
 		bool try_interpreter);
 VALUE rb_vm_run_under(VALUE klass, VALUE self, const char *fname, NODE *node,
@@ -217,6 +224,7 @@
 	bool direct);
 void rb_vm_define_method2(Class klass, SEL sel, rb_vm_method_node_t *node,
 	bool direct);
+void rb_vm_define_method3(Class klass, SEL sel, rb_vm_block_t *node);
 void rb_vm_define_attr(Class klass, const char *name, bool read, bool write,
 	int noex);
 void rb_vm_undef_method(Class klass, const char *name, bool must_exist);
@@ -582,8 +590,9 @@
 
 	struct mcache *method_cache_get(SEL sel, bool super);
 	rb_vm_method_node_t *method_node_get(IMP imp);
-	void add_method(Class klass, SEL sel, IMP imp, IMP ruby_imp,
-		const rb_vm_arity_t &arity, int flags, const char *types);
+	rb_vm_method_node_t *add_method(Class klass, SEL sel, IMP imp,
+		IMP ruby_imp, const rb_vm_arity_t &arity, int flags,
+		const char *types);
 
 	GlobalVariable *redefined_op_gvar(SEL sel, bool create);
 	bool should_invalidate_inline_op(SEL sel, Class klass);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090614/b4f160ae/attachment-0001.html>


More information about the macruby-changes mailing list