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

source_changes at macosforge.org source_changes at macosforge.org
Tue Aug 4 19:58:50 PDT 2009


Revision: 2213
          http://trac.macosforge.org/projects/ruby/changeset/2213
Author:   lsansonetti at apple.com
Date:     2009-08-04 19:58:50 -0700 (Tue, 04 Aug 2009)
Log Message:
-----------
Proc: fixing bugs and implementing missing features

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

Modified: MacRuby/branches/experimental/proc.c
===================================================================
--- MacRuby/branches/experimental/proc.c	2009-08-05 02:44:01 UTC (rev 2212)
+++ MacRuby/branches/experimental/proc.c	2009-08-05 02:58:50 UTC (rev 2213)
@@ -37,8 +37,13 @@
 VALUE
 rb_proc_alloc_with_block(VALUE klass, rb_vm_block_t *proc)
 {
+    if (proc->proc != Qnil) {
+	return proc->proc;
+    }
+
     VALUE obj;
     obj = Data_Wrap_Struct(klass, NULL, NULL, proc);
+    GC_WB(&proc->proc, obj);
     if (!(proc->flags & VM_BLOCK_PROC)) {
 	proc->flags |= VM_BLOCK_PROC;
 	if (!(proc->flags & VM_BLOCK_METHOD)) {
@@ -63,21 +68,9 @@
 static VALUE
 proc_dup(VALUE self, SEL sel)
 {
-    VALUE procval = rb_proc_alloc(rb_cProc);
-    rb_vm_block_t *src, *dst;
+    rb_vm_block_t *src;
     GetProcPtr(self, src);
-    GetProcPtr(procval, dst);
-
-    // TODO
-#if 0
-    dst->block = src->block;
-    GC_WB(&dst->block.proc, procval);
-    GC_WB(&dst->envval, src->envval);
-    dst->safe_level = src->safe_level;
-    dst->is_lambda = src->is_lambda;
-#endif
-
-    return procval;
+    return Data_Wrap_Struct(CLASS_OF(self), NULL, NULL, src);
 }
 
 static VALUE
@@ -196,7 +189,8 @@
     rb_vm_block_t *proc;
     GetProcPtr(procval, proc);
 
-    return proc->flags & VM_BLOCK_LAMBDA ? Qtrue : Qfalse;
+    return (proc->flags & VM_BLOCK_LAMBDA) == VM_BLOCK_LAMBDA
+	? Qtrue : Qfalse;
 }
 
 /* Binding */
@@ -297,13 +291,16 @@
 }
 
 static VALUE
-proc_new(VALUE klass, int is_lambda)
+proc_new(VALUE klass, bool is_lambda)
 {
     rb_vm_block_t *block = rb_vm_first_block();
     if (block == NULL) {
 	rb_raise(rb_eArgError,
 		"tried to create Proc object without a block");
     }
+    if (is_lambda) {
+	block->flags |= VM_BLOCK_LAMBDA;
+    }
     return rb_proc_alloc_with_block(klass, block);
 }
 
@@ -327,7 +324,7 @@
 static VALUE
 rb_proc_s_new(VALUE klass, SEL sel, int argc, VALUE *argv)
 {
-    VALUE block = proc_new(klass, Qfalse);
+    VALUE block = proc_new(klass, false);
 
     rb_obj_call_init(block, argc, argv);
     return block;
@@ -343,7 +340,7 @@
 VALUE
 rb_block_proc(void)
 {
-    return proc_new(rb_cProc, Qfalse);
+    return proc_new(rb_cProc, false);
 }
 
 VALUE
@@ -355,7 +352,7 @@
 VALUE
 rb_block_lambda(void)
 {
-    return proc_new(rb_cProc, Qtrue);
+    return proc_new(rb_cProc, true);
 }
 
 VALUE
@@ -485,30 +482,14 @@
 static VALUE
 proc_arity(VALUE self, SEL sel)
 {
-#if 0 // TODO
-    rb_proc_t *proc;
-    rb_iseq_t *iseq;
-    GetProcPtr(self, proc);
-    iseq = proc->block.iseq;
-    if (iseq) {
-	if (BUILTIN_TYPE(iseq) != T_NODE) {
-	    if (iseq->arg_rest < 0) {
-		return INT2FIX(iseq->argc);
-	    }
-	    else {
-		return INT2FIX(-(iseq->argc + 1 + iseq->arg_post_len));
-	    }
-	}
-	else {
-	    NODE *node = (NODE *)iseq;
-	    if (nd_type(node) == NODE_IFUNC && node->nd_cfnc == bmcall) {
-		/* method(:foo).to_proc.arity */
-		return INT2FIX(method_arity(node->nd_tval));
-	    }
-	}
+    rb_vm_block_t *b;
+    GetProcPtr(self, b);
+
+    int arity = b->arity.min;
+    if (b->arity.min != b->arity.max) {
+	arity = -arity - 1;
     }
-#endif
-    return INT2FIX(-1);
+    return INT2FIX(arity);
 }
 
 int
@@ -560,23 +541,15 @@
 static VALUE
 proc_eq(VALUE self, SEL sel, VALUE other)
 {
-#if 0 // TODO
     if (self == other) {
 	return Qtrue;
     }
-    else {
-	if (TYPE(other)          == T_DATA &&
-	    RBASIC(other)->klass == rb_cProc &&
-	    CLASS_OF(self)       == CLASS_OF(other)) {
-	    rb_proc_t *p1, *p2;
-	    GetProcPtr(self, p1);
-	    GetProcPtr(other, p2);
-	    if (p1->block.iseq == p2->block.iseq && p1->envval == p2->envval) {
-		return Qtrue;
-	    }
-	}
+    else if (rb_obj_is_kind_of(other, rb_cProc)) {
+	rb_vm_block_t *self_b, *other_b;
+	GetProcPtr(self, self_b);
+	GetProcPtr(other, other_b);
+	return self_b == other_b ? Qtrue : Qfalse;
     }
-#endif
     return Qfalse;
 }
 
@@ -590,16 +563,9 @@
 static VALUE
 proc_hash(VALUE self, SEL sel)
 {
-#if 0 // TODO
-    int hash;
-    rb_proc_t *proc;
-    GetProcPtr(self, proc);
-    hash = (long)proc->block.iseq;
-    hash ^= (long)proc->envval;
-    hash ^= (long)proc->block.lfp >> 16;
-    return INT2FIX(hash);
-#endif
-    return Qnil;
+    rb_vm_block_t *b;
+    GetProcPtr(self, b);
+    return LONG2FIX(b);
 }
 
 /*
@@ -1422,51 +1388,8 @@
     return Data_Wrap_Struct(rb_cBinding, NULL, NULL, binding);
 }
 
-//static VALUE curry(VALUE dummy, VALUE args, int argc, VALUE *argv);
-
-static VALUE
-make_curry_proc(VALUE proc, VALUE passed, VALUE arity)
-{
-    // TODO
-    return Qnil;
-#if 0
-#if WITH_OBJC
-    VALUE args = rb_ary_new3(3, proc, passed, arity);
-#else
-    VALUE args = rb_ary_new2(3);
-    RARRAY_PTR(args)[0] = proc;
-    RARRAY_PTR(args)[1] = passed;
-    RARRAY_PTR(args)[2] = arity;
-    RARRAY_LEN(args) = 3;
-#endif
-    rb_ary_freeze(passed);
-    rb_ary_freeze(args);
-    return rb_proc_new(curry, args);
-#endif
-}
-
-#if 0
-static VALUE
-curry(VALUE dummy, VALUE args, int argc, VALUE *argv)
-{
-    VALUE proc, passed, arity;
-    proc = RARRAY_AT(args, 0);
-    passed = RARRAY_AT(args, 1);
-    arity = RARRAY_AT(args, 2);
-
-    passed = rb_ary_plus(passed, rb_ary_new4(argc, argv));
-    rb_ary_freeze(passed);
-    if(RARRAY_LEN(passed) < FIX2INT(arity)) {
-	arity = make_curry_proc(proc, passed, arity);
-	return arity;
-    }
-    arity = rb_proc_call(proc, passed);
-    return arity;
-}
-#endif
-
  /*
-  curry*  call-seq:
+  *  call-seq:
   *     prc.curry         => a_proc
   *     prc.curry(arity)  => a_proc
   *
@@ -1529,7 +1452,7 @@
 	}
     }
 
-    return make_curry_proc(self, rb_ary_new(), arity);
+    return rb_vm_make_curry_proc(self, rb_ary_new(), arity);
 }
 
 /*
@@ -1561,6 +1484,7 @@
     rb_objc_define_method(*(VALUE *)rb_cProc, "new", rb_proc_s_new, -1);
     rb_objc_define_method(rb_cProc, "call", proc_call, -1);
     rb_objc_define_method(rb_cProc, "[]", proc_call, -1);
+    rb_objc_define_method(rb_cProc, "===", proc_call, -1);
     rb_objc_define_method(rb_cProc, "yield", proc_call, -1);
     rb_objc_define_method(rb_cProc, "to_proc", proc_to_proc, 0);
     rb_objc_define_method(rb_cProc, "arity", proc_arity, 0);

Modified: MacRuby/branches/experimental/vm.cpp
===================================================================
--- MacRuby/branches/experimental/vm.cpp	2009-08-05 02:44:01 UTC (rev 2212)
+++ MacRuby/branches/experimental/vm.cpp	2009-08-05 02:58:50 UTC (rev 2213)
@@ -279,6 +279,7 @@
 	    b = (rb_vm_block_t *)xmalloc(block_size);
 	    memcpy(b, orig, block_size);
 
+	    GC_WB(&b->proc, orig->proc);
 	    GC_WB(&b->self, orig->self);
 	    GC_WB(&b->locals, orig->locals);
 	    GC_WB(&b->parent_block, orig->parent_block);  // XXX not sure
@@ -2931,6 +2932,7 @@
     rb_vm_block_t *new_b = (rb_vm_block_t *)xmalloc(block_size);
 
     memcpy(new_b, src_b, block_size);
+    GC_WB(&new_b->proc, src_b->proc);
     GC_WB(&new_b->parent_block, src_b->parent_block);
     GC_WB(&new_b->self, src_b->self);
     new_b->flags = src_b->flags & ~VM_BLOCK_ACTIVE;
@@ -3023,6 +3025,7 @@
 	assert((b->flags & flags) == flags);
     }
 
+    b->proc = Qnil;
     b->self = self;
     b->parent_var_uses = parent_var_uses;
     GC_WB(&b->parent_block, parent_block);
@@ -3365,9 +3368,6 @@
 {
     rb_vm_block_t *b = GET_VM()->current_block();
     if (b != NULL) {
-#if ROXOR_VM_DEBUG
-	printf("create Proc object based on block %p\n", b);
-#endif
 	return rb_proc_alloc_with_block(rb_cProc, b);
     }
     return Qnil;
@@ -3442,6 +3442,7 @@
 {
     rb_vm_block_t *b = (rb_vm_block_t *)xmalloc(sizeof(rb_vm_block_t));
 
+    b->proc = Qnil;
     GC_WB(&b->self, method->recv);
     b->arity = method->node == NULL
 	? rb_vm_arity(method->arity) : method->node->arity;
@@ -3472,6 +3473,7 @@
     rb_vm_block_t *b = (rb_vm_block_t *)xmalloc(sizeof(rb_vm_block_t)
 	    + sizeof(VALUE *));
 
+    b->proc = Qnil;
     b->arity = rb_vm_arity(1);
     b->flags = VM_BLOCK_PROC;
     b->imp = (IMP)rb_vm_block_call_sel;
@@ -3480,6 +3482,44 @@
     return b;
 }
 
+static VALUE
+rb_vm_block_curry(VALUE rcv, SEL sel, VALUE **dvars, rb_vm_block_t *b,
+	VALUE args)
+{
+    VALUE proc = (VALUE)dvars[0];
+    VALUE passed = (VALUE)dvars[1];
+    VALUE arity = (VALUE)dvars[2];
+
+    passed = rb_ary_plus(passed, args);
+    rb_ary_freeze(passed);
+    if (RARRAY_LEN(passed) < FIX2INT(arity)) {
+	return rb_vm_make_curry_proc(proc, passed, arity);
+    }
+    return rb_proc_call(proc, passed);
+}
+
+extern "C"
+VALUE
+rb_vm_make_curry_proc(VALUE proc, VALUE passed, VALUE arity)
+{
+    // Proc.new { |*args| curry... }
+    rb_vm_block_t *b = (rb_vm_block_t *)xmalloc(sizeof(rb_vm_block_t)
+	    + (3 * sizeof(VALUE *)));
+
+    b->proc = Qnil;
+    b->arity.min = 0;
+    b->arity.max = -1;
+    b->arity.left_req = 0;
+    b->arity.real = 1;
+    b->flags = VM_BLOCK_PROC;
+    b->imp = (IMP)rb_vm_block_curry;
+    b->dvars[0] = (VALUE *)proc;
+    b->dvars[1] = (VALUE *)passed;
+    b->dvars[2] = (VALUE *)arity;
+
+    return rb_proc_alloc_with_block(rb_cProc, b);
+}
+
 static inline VALUE
 rb_vm_block_eval0(rb_vm_block_t *b, VALUE self, int argc, const VALUE *argv)
 {
@@ -3499,6 +3539,11 @@
     rb_vm_arity_t arity = b->arity;    
 
     if (argc < arity.min || argc > arity.max) {
+	if (arity.max != -1
+		&& (b->flags & VM_BLOCK_LAMBDA) == VM_BLOCK_LAMBDA) {
+	    rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
+		    argc, arity.min);
+	}
 	VALUE *new_argv;
 	if (argc == 1 && TYPE(argv[0]) == T_ARRAY
 	    && (arity.min > 1 || (arity.min == 1 && arity.min != arity.max))) {

Modified: MacRuby/branches/experimental/vm.h
===================================================================
--- MacRuby/branches/experimental/vm.h	2009-08-05 02:44:01 UTC (rev 2212)
+++ MacRuby/branches/experimental/vm.h	2009-08-05 02:58:50 UTC (rev 2213)
@@ -36,6 +36,7 @@
 #define VM_BLOCK_AOT	0x1000  // block is created by the AOT compiler (temporary)
 
 typedef struct rb_vm_block {
+    VALUE proc; // a reference to a Proc object, or nil
     VALUE self;
     VALUE userdata; // if VM_BLOCK_IFUNC, contains the user data, otherwise
 		    // contains the key used in the blocks cache.
@@ -336,11 +337,12 @@
 rb_vm_method_t *rb_vm_get_method(VALUE klass, VALUE obj, ID mid, int scope);
 rb_vm_block_t *rb_vm_create_block_from_method(rb_vm_method_t *method);
 rb_vm_block_t *rb_vm_create_block_calling_sel(SEL sel);
+VALUE rb_vm_make_curry_proc(VALUE proc, VALUE passed, VALUE arity);
 
 static inline rb_vm_block_t *
 rb_proc_get_block(VALUE proc)
 {
-   return (rb_vm_block_t *)DATA_PTR(proc);
+    return (rb_vm_block_t *)DATA_PTR(proc);
 }
 
 void rb_vm_add_block_lvar_use(rb_vm_block_t *block);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090804/4075ee90/attachment-0001.html>


More information about the macruby-changes mailing list