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

source_changes at macosforge.org source_changes at macosforge.org
Mon Apr 6 01:11:24 PDT 2009


Revision: 1378
          http://trac.macosforge.org/projects/ruby/changeset/1378
Author:   lsansonetti at apple.com
Date:     2009-04-06 01:11:23 -0700 (Mon, 06 Apr 2009)
Log Message:
-----------
implemented catch/throw

Modified Paths:
--------------
    MacRuby/branches/experimental/roxor.cpp
    MacRuby/branches/experimental/roxor.h
    MacRuby/branches/experimental/vm_eval.c

Modified: MacRuby/branches/experimental/roxor.cpp
===================================================================
--- MacRuby/branches/experimental/roxor.cpp	2009-04-06 06:15:03 UTC (rev 1377)
+++ MacRuby/branches/experimental/roxor.cpp	2009-04-06 08:11:23 UTC (rev 1378)
@@ -418,6 +418,7 @@
 	rb_vm_block_t *previous_block;
 	bool parse_in_eval;
 
+	CFMutableDictionaryRef catch_jmp_bufs;
 	std::vector<jmp_buf *> return_from_block_jmp_bufs;
 
 	RoxorVM(void);
@@ -2184,6 +2185,8 @@
     previous_block = NULL;
     parse_in_eval = false;
 
+    catch_jmp_bufs = NULL;
+
     load_path = rb_ary_new();
     rb_objc_retain((void *)load_path);
     loaded_features = rb_ary_new();
@@ -6694,7 +6697,69 @@
     }
 }
 
+typedef struct {
+    jmp_buf *buf;
+    VALUE throw_value;
+} rb_vm_catch_t;
+
 extern "C"
+VALUE
+rb_vm_catch(VALUE tag)
+{
+    CFMutableDictionaryRef dict = GET_VM()->catch_jmp_bufs;
+    if (dict == NULL) {
+	dict = CFDictionaryCreateMutable(NULL, 0,
+		&kCFTypeDictionaryKeyCallBacks, NULL);
+	GET_VM()->catch_jmp_bufs = dict;
+    }
+    
+    void *key = RB2OC(tag);
+    rb_vm_catch_t *s = NULL;
+    if (!CFDictionaryGetValueIfPresent(dict, (void *)key, (const void **)&s)) {
+	s = (rb_vm_catch_t *)malloc(sizeof(rb_vm_catch_t));
+	s->buf = (jmp_buf *)malloc(sizeof(jmp_buf));
+	s->throw_value = Qnil;
+	CFDictionarySetValue(dict, (void *)key, (void *)s);
+    }
+
+    if (setjmp(*s->buf) == 0) {
+        return rb_vm_yield(1, &tag);
+    }
+
+    VALUE retval = s->throw_value;
+    rb_objc_release((void *)retval);
+
+    // FIXME this crashes for a strange reason - to investigate
+    //CFDictionaryRemoveValue(GET_VM()->catch_jmp_bufs, key); 
+    //free(s->buf);
+    //free(s);
+
+    return retval;
+}
+
+extern "C"
+VALUE
+rb_vm_throw(VALUE tag, VALUE value)
+{
+    CFMutableDictionaryRef dict = GET_VM()->catch_jmp_bufs;
+    rb_vm_catch_t *s = NULL;
+    void *key = RB2OC(tag);
+    if (dict != NULL) {
+	CFDictionaryGetValueIfPresent(dict, (void *)key, (const void **)&s);
+    }
+    if (s == NULL) {
+        VALUE desc = rb_inspect(tag);
+        rb_raise(rb_eArgError, "uncaught throw %s", RSTRING_PTR(desc));
+    }
+
+    rb_objc_retain((void *)value);
+    s->throw_value = value;
+    longjmp(*s->buf, 1);
+
+    return Qnil; // never reached
+}
+
+extern "C"
 void 
 Init_PreVM(void)
 {

Modified: MacRuby/branches/experimental/roxor.h
===================================================================
--- MacRuby/branches/experimental/roxor.h	2009-04-06 06:15:03 UTC (rev 1377)
+++ MacRuby/branches/experimental/roxor.h	2009-04-06 08:11:23 UTC (rev 1378)
@@ -78,6 +78,8 @@
 VALUE rb_vm_method_missing(VALUE obj, int argc, const VALUE *argv);
 int rb_vm_find_class_ivar_slot(VALUE klass, ID name);
 void rb_vm_set_outer(VALUE klass, VALUE under);
+VALUE rb_vm_catch(VALUE tag);
+VALUE rb_vm_throw(VALUE tag, VALUE value);
 
 static inline void
 rb_vm_regrow_robject_slots(struct RObject *obj, unsigned int new_num_slot)

Modified: MacRuby/branches/experimental/vm_eval.c
===================================================================
--- MacRuby/branches/experimental/vm_eval.c	2009-04-06 06:15:03 UTC (rev 1377)
+++ MacRuby/branches/experimental/vm_eval.c	2009-04-06 08:11:23 UTC (rev 1378)
@@ -607,8 +607,11 @@
 static VALUE
 rb_f_throw(VALUE rcv, SEL sel, int argc, VALUE *argv)
 {
-    // TODO
-    return Qnil;
+    VALUE tag, value;
+
+    rb_scan_args(argc, argv, "11", &tag, &value);
+   
+    return rb_vm_throw(tag, value);
 }
 
 void
@@ -663,11 +666,9 @@
  */
 
 static VALUE
-rb_f_catch(VALUE rcv, SEL sel, int argc, VALUE *argv)
+rb_f_catch(VALUE rcv, SEL sel, VALUE tag)
 {
-    // TODO
-    rb_yield(Qundef);
-    return Qnil;
+    return rb_vm_catch(tag);
 }
 
 /*
@@ -738,7 +739,7 @@
 void
 Init_vm_eval(void)
 {
-    rb_objc_define_method(rb_mKernel, "catch", rb_f_catch, -1);
+    rb_objc_define_method(rb_mKernel, "catch", rb_f_catch, 1);
     rb_objc_define_method(rb_mKernel, "throw", rb_f_throw, -1);
 
     rb_objc_define_method(rb_mKernel, "loop", rb_f_loop, 0);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090406/6894fe3b/attachment.html>


More information about the macruby-changes mailing list