[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