[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