<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>flash/src/ruby/internals/ISeqCatchTableEntry.as</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,12 +1,8 @@
 package
 {
-import flash.events.Event;
-import flash.events.KeyboardEvent;
-
 import mx.core.UIComponent;
 import mx.core.Window;
 import mx.events.AIREvent;
-import mx.events.FlexEvent;
 
 import ruby.internals.RubyCore;
 
@@ -42,7 +38,8 @@ public class RubyWindow extends Window
     rc.variable_c.rb_define_global_const(&quot;AIRWindow&quot;, rc.wrap_flash_obj(this));
     rc.variable_c.rb_define_global_const(&quot;Document&quot;, rc.wrap_flash_obj(this));
     rc.define_flash_package(&quot;Mx&quot;);
-    rc.run(bytecode, fullUIC);
+    var result:int = rc.run(bytecode, fullUIC);
+    trace(&quot;Execution of main ruby bytecode resulting in code: &quot;+result);
   }
 
 }</diff>
      <filename>chromosphere/src/RubyWindow.as</filename>
    </modified>
    <modified>
      <diff>@@ -118,7 +118,6 @@ public class Error_c
   {
     var rstring:RString = rc.string_c.rb_str_new(mesg);
     rc.eval_c.rb_exc_raise(rc.error_c.rb_exc_new3(exc, rstring));
-    throw new Error(exc.toString() + mesg);
   }
 
   public function</diff>
      <filename>flash/src/ruby/internals/Error_c.as</filename>
    </modified>
    <modified>
      <diff>@@ -91,9 +91,9 @@ public class Eval_c
   rb_raise_jump(mesg:Value):void
   {
     var th:RbThread = rc.GET_THREAD();
-    th.cfp = rc.vm_c.RUBY_VM_PREVIOUS_CONTROL_FRAME(th, th.cfp);
+    th.cfp = th.cfp_stack.pop();
     /* TODO: fix me */
-    throw new RTag(RTag.TAG_RAISE, mesg);
+    rb_longjmp(RTag.TAG_RAISE, mesg);
   }
 
   // eval.c:544
@@ -217,20 +217,44 @@ public class Eval_c
   }
 
 
+  // eval.c:349
+  public function
+  rb_longjmp(tag:int, mesg:Value):void
+  {
+    var th:RbThread = rc.GET_THREAD();
+
+    // LOTS OF CODE HERE
+
+    if (rc.NIL_P(mesg)) {
+      mesg = th.errinfo;
+    }
+    if (rc.NIL_P(mesg)) {
+      mesg = rc.error_c.rb_exc_new(rc.error_c.rb_eRuntimeError, null);
+    }
+
+    if (!rc.NIL_P(mesg)) {
+      th.errinfo = mesg;
+    }
+
+    // LOTS OF DEBUGGING CODE HERE
+
+    throw new RTag(tag, mesg);
+  }
+
   // eval.c:424
   public function
   rb_exc_raise(mesg:Value):void
   {
-    throw new RTag(RTag.TAG_RAISE, mesg);
+    rb_longjmp(RTag.TAG_RAISE, mesg);
   }
 
   // eval.c:233
   public function
-  ruby_run_node(n:Value):void
+  ruby_run_node(n:Value):int
   {
     // TODO: @skipped
     // Init_stack(n);
-    ruby_cleanup(ruby_exec_node(n, null));
+    return ruby_cleanup(ruby_exec_node(n, null));
   }
 
   // eval.c:141
@@ -239,6 +263,13 @@ public class Eval_c
   {
     // TODO: @skipped
     // cleanup, GC, stop threads, error hanlding
+
+    if (ex != 0) {
+      trace(&quot;Ruby exited with abnormal status.&quot;);
+      var errinfo:Value = rc.GET_THREAD().errinfo;
+      trace(&quot;&quot;+errinfo);
+      //trace(&quot;klass: &quot; + );
+    }
     return ex;
   }
 </diff>
      <filename>flash/src/ruby/internals/Eval_c.as</filename>
    </modified>
    <modified>
      <diff>@@ -79,6 +79,8 @@ public class Object_c
     rc.class_c.rb_define_private_method(rb_cModule, &quot;method_removed&quot;, rb_obj_dummy, 1);
     rc.class_c.rb_define_private_method(rb_cModule, &quot;method_undefined&quot;, rb_obj_dummy, 1);
 
+    rc.class_c.rb_define_method(rb_mKernel, &quot;===&quot;, rb_equal, 1);
+
     rc.class_c.rb_define_method(rb_mKernel, &quot;class&quot;, rb_obj_class, 0);
 
     rc.class_c.rb_define_method(rb_mKernel, &quot;to_s&quot;, rb_any_to_s, 0);
@@ -90,6 +92,7 @@ public class Object_c
     rc.variable_c.rb_define_global_const(&quot;NIL&quot;, rc.Qnil);
 
     // Lots of module methods
+    rc.class_c.rb_define_method(rb_cModule, &quot;===&quot;, rb_mod_eqq, 1);
     // Lots of class methods
     rc.class_c.rb_define_method(rb_cClass, &quot;allocate&quot;, rb_obj_alloc, 0);
     rc.class_c.rb_define_method(rb_cClass, &quot;new&quot;, rb_class_new_instance, -1);
@@ -263,6 +266,37 @@ public class Object_c
     return obj;
   }
 
+  // object.c:452
+  public function
+  rb_obj_is_kind_of(obj:Value, c:RClass):Value
+  {
+    var cl:RClass = rc.CLASS_OF(obj);
+
+    switch (rc.TYPE(c)) {
+      case Value.T_MODULE:
+      case Value.T_CLASS:
+      case Value.T_ICLASS:
+        break;
+      default:
+        rc.error_c.rb_raise(rc.error_c.rb_eTypeError, &quot;class or module required&quot;);
+    }
+
+    while (cl) {
+      if (cl == c || cl.klass.m_tbl == c.klass.m_tbl) {
+        return rc.Qtrue;
+      }
+      cl = cl.super_class;
+    }
+    return rc.Qfalse;
+  }
+
+  // object.c:1185
+  public function
+  rb_mod_eqq(mod:RClass, arg:Value):Value
+  {
+    return rb_obj_is_kind_of(arg, mod);
+  }
+
 
   // object.c:1964
   public function</diff>
      <filename>flash/src/ruby/internals/Object_c.as</filename>
    </modified>
    <modified>
      <diff>@@ -17,5 +17,10 @@ public class RObject extends RBasic
     this.flags = Value.T_OBJECT;
   }
 
+  public function toString():String
+  {
+    return &quot;&lt;&quot;+klass.name+&quot;&gt;&quot;;
+  }
+
 }
 }</diff>
      <filename>flash/src/ruby/internals/RObject.as</filename>
    </modified>
    <modified>
      <diff>@@ -116,27 +116,27 @@ public class RubyCore
   }
 
   public function
-  run(bytecode:String, doc_class:DisplayObject=null):void
+  run(bytecode:String, doc_class:DisplayObject=null):int
   {
     var decoder:JSONDecoder = new JSONDecoder( bytecode, this )
-    run_array(decoder.getValue(), doc_class);
+    return run_array(decoder.getValue(), doc_class);
   }
 
   public function
-  run_array(iseq_array:Array, doc_class:DisplayObject=null):void
+  run_array(iseq_array:Array, doc_class:DisplayObject=null):int
   {
     init();
-    run_iseqval(iseqval_from_array(iseq_array), doc_class);
+    return run_iseqval(iseqval_from_array(iseq_array), doc_class);
   }
 
   public function
-  run_iseqval(iseqval:Value, doc_class:DisplayObject=null):void
+  run_iseqval(iseqval:Value, doc_class:DisplayObject=null):int
   {
     init();
     if (doc_class) {
       variable_c.rb_define_global_const(&quot;TopSprite&quot;, wrap_flash_obj(doc_class));
     }
-    eval_c.ruby_run_node(iseqval);
+    return eval_c.ruby_run_node(iseqval);
   }
 
   public function
@@ -1064,6 +1064,24 @@ public class RubyCore
       iseq.arg_simple = 0;
     }
 
+    var catch_table:Array = new Array();
+
+    for each (var catch_def:Array in iseq_array[10]) {
+      var entry:ISeqCatchTableEntry = new ISeqCatchTableEntry();
+      entry.type = catch_def[0];
+      if (catch_def[1] is Array) {
+        entry.iseq = iseqval_from_array(catch_def[1]);
+      }
+      entry.start = catch_def[2];
+      entry.end = catch_def[3];
+      entry.cont = catch_def[4];
+      entry.sp = catch_def[5];
+      catch_table.push(entry);
+    }
+
+    iseq.catch_table = catch_table;
+    iseq.catch_table_size = catch_table.length;
+
     iseq.iseq = yarv_iseq(iseq_array);
 
     return iseqval;</diff>
      <filename>flash/src/ruby/internals/RubyCore.as</filename>
    </modified>
    <modified>
      <diff>@@ -34,6 +34,12 @@ public class RubyFrame
   }
 
   public function
+  nop():void
+  {
+
+  }
+
+  public function
   pop():void
   {
     reg_sp.popn(1);
@@ -184,6 +190,10 @@ public class RubyFrame
   putobject(val:*):void
   {
     if (val is String) {
+      if (val == &quot;StandardError&quot;) {
+        reg_sp.push(rc.error_c.rb_eStandardError);
+        return;
+      }
       reg_sp.push(rc.string_c.rb_str_new(val));
     } else if (val is int || val is uint) {
       reg_sp.push(rc.numeric_c.INT2FIX(val));</diff>
      <filename>flash/src/ruby/internals/RubyFrame.as</filename>
    </modified>
    <modified>
      <diff>@@ -28,6 +28,13 @@ public class Vm_c
   public var ruby_vm_redefined_flag:uint = 0;
   public var vm_opt_method_table:Object;
 
+  public const CATCH_TYPE_RESCUE:String = &quot;rescue&quot;;
+  public const CATCH_TYPE_ENSURE:String = &quot;ensure&quot;;
+  public const CATCH_TYPE_RETRY:String = &quot;retry&quot;;
+  public const CATCH_TYPE_BREAK:String = &quot;break&quot;;
+  public const CATCH_TYPE_REDO:String = &quot;redo&quot;;
+  public const CATCH_TYPE_NEXT:String = &quot;next&quot;;
+
   public function Init_VM():void
   {
     var opts:Value;
@@ -404,34 +411,154 @@ public class Vm_c
   public function
   vm_eval_body(th:RbThread):Value
   {
+    var state:int;
     var result:Value;
+    var err:Value;
     var initial:Value;
+    var escape_dfp:StackPointer;
+
+    var tag:RbVmTag;
 
+    tag = rc.PUSH_TAG(th);
+    tag.retval = rc.Qnil;
+
+    var went_to_exception_handler:Boolean = false;
     try {
+      // state = EXEC_TAG()
+      // vm_loop_start:
       result = rc.vm_evalbody_c.vm_eval(th, initial);
-    } catch (e:Error) {
-      trace(&quot;error: &quot; +e.message);
-      trace(e.getStackTrace());
 
+      state = th.state;
+      if (state != 0) {
+        err = result;
+        th.state = 0;
+        // goto exception_handler
+        trace(&quot;goto exception_handler&quot;);
+        went_to_exception_handler = true;
+        throw new RTag(state, rc.Qnil);
+      }
 
-      // Exception handling.
+    } catch (e:RTag) {
+      //trace(&quot;error: &quot; +e.message);
+      //trace(e.getStackTrace());
 
-      // if state == TAG_RETRY
-      // search catch_table for RETRY entry
-      // etc.
+      var i:int;
+      var entry:ISeqCatchTableEntry;
+      var epc:int;
+      var cont_pc:int;
+      var cont_sp:int;
+      var catch_iseqval:Value;
+      var cfp:RbControlFrame;
+      var type:Value
 
-      th.cfp = th.cfp_stack.pop();
-      if (th.cfp.pc_fn != finish_insn_seq) {
-        trace(&quot;goto exception_handler&quot;);
-        // goto exception_handler;
-      } else {
-        rc.vm_insnhelper_c.vm_pop_frame(th);
-        // th.errinfo = err;
-        // TH_POP_TAG2();
-        // JUMP_TAG(state);
+      state = e.tag;
+
+      // Exception handling.
+      if (!went_to_exception_handler) {
+        err = th.errinfo;
+
+        if (state == RTag.TAG_RAISE) {
+          if (rc.OBJ_FROZEN(err)) rc.eval_c.rb_exc_raise(err);
+          rc.variable_c.rb_ivar_set(err, rc.id_c.idThrowState, rc.numeric_c.INT2FIX(state));
+        }
       }
+
+      // exception_handler:
+      do {
+        cont_pc = 0;
+        cont_sp = 0;
+        catch_iseqval = null;
+
+        while (th.cfp.pc_ary == null || th.cfp.iseq == null) {
+          th.cfp = th.cfp_stack.pop();
+        }
+
+        cfp = th.cfp;
+        //epc = cfp.pc - cfp.iseq.iseq_encoded;
+        // this is equivalent to the previous line
+        epc = cfp.pc_index;
+
+        if (state == RTag.TAG_BREAK || state == RTag.TAG_RETURN) {
+          trace(&quot;unhandled tags break and return&quot;);
+          // LOTS OF CODE HERE
+        }
+
+        if (state == RTag.TAG_RAISE) {
+          for (i = 0; i &lt; cfp.iseq.catch_table_size; i++) {
+            entry = cfp.iseq.catch_table[i];
+            var start_label:int = cfp.iseq.iseq.indexOf(entry.start);
+            var end_label:int = cfp.iseq.iseq.indexOf(entry.end);
+            if (start_label &lt; epc &amp;&amp; end_label &gt;= epc) {
+              if (entry.type == CATCH_TYPE_RESCUE ||
+                  entry.type == CATCH_TYPE_ENSURE)
+              {
+                catch_iseqval = entry.iseq;
+                cont_pc = cfp.iseq.iseq.indexOf(entry.cont);
+                cont_sp = entry.sp;
+                break;
+              }
+            }
+          }
+        }
+        else if (state == RTag.TAG_RETRY) {
+          // LOTS OF CODE HERE
+        }
+        else if (state == RTag.TAG_BREAK &amp;&amp; escape_dfp == null) {
+          // LOTS OF CODE HERE
+        }
+        else if (state == RTag.TAG_REDO) {
+          // LOTS OF CODE HERE
+        }
+        else if (state == RTag.TAG_NEXT) {
+          // LOTS OF CODE HERE
+        }
+        else {
+          // LOTS OF CODE HERE
+        }
+
+        if (catch_iseqval != null) {
+          var catch_iseq:RbISeq;
+
+          catch_iseq = rc.iseq_c.GetISeqPtr(catch_iseqval);
+          cfp.sp = cfp.bp.clone_down_stack(cont_sp);
+          cfp.pc_index = cont_pc;
+
+          cfp.sp.set_at(0, err);
+          rc.vm_insnhelper_c.vm_push_frame(th, catch_iseq, RbVm.VM_FRAME_MAGIC_BLOCK,
+                                           cfp.self, cfp.dfp.clone(),
+                                           null, catch_iseq.iseq, 0,
+                                           cfp.sp.clone_down_stack(1),
+                                           cfp.lfp.clone(),
+                                           catch_iseq.local_size-1);
+          state = 0;
+          th.errinfo = rc.Qnil;
+          // goto vm_loop_start;
+          vm_eval_body(th);
+
+        }
+        else {
+
+          th.cfp = th.cfp_stack.pop();
+          if (th.cfp.pc_fn != finish_insn_seq) {
+            trace(&quot;goto exception_handler&quot;);
+            continue;
+            // goto exception_handler;
+          } else {
+            rc.vm_insnhelper_c.vm_pop_frame(th);
+            th.errinfo = err;
+            // TH_POP_TAG2();
+            rc.POP_TAG(tag, th);
+            // JUMP_TAG(state);
+            throw new RTag(state, e.mesg);
+          }
+        }
+        break;
+      } while (1)
     }
 
+    // finish_vme:
+    // TH_POP_TAG();
+    rc.POP_TAG(tag, th);
     return result;
   }
 </diff>
      <filename>flash/src/ruby/internals/Vm_c.as</filename>
    </modified>
    <modified>
      <diff>@@ -55,7 +55,17 @@ module RedSun
               if i and i.length &gt; 0
                 puts &quot;#{indent}[&quot;
                 i.each do |label|
-                  puts &quot;#{indent}  #{pp_value(label,as3)},&quot;
+                  if label[1].is_a? Array
+                    puts(&quot;#{indent}  [#{pp_value(label[0],as3)},&quot;)
+                    pp_yarv(label[1], indent+&quot;    &quot;, as3)
+                    print(&quot;#{indent}    &quot;)
+                    label[2..-1].each do |v|
+                      print(&quot;#{pp_value(v,as3)}, &quot;)
+                    end
+                    puts(&quot;],&quot;)
+                  else
+                    puts &quot;#{indent}  #{pp_value(label,as3)},&quot;
+                  end
                 end
                 puts &quot;#{indent}]&quot;
               else</diff>
      <filename>lib/redsun/abc.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,10 +1,10 @@
 
 # Testing exceptions
 puts &quot;Before Raise&quot;
-#begin
+begin
   raise &quot;Something&quot;
   puts &quot;Not Rescued&quot;
-#rescue 
-#  puts &quot;Rescued&quot;
-#end
+rescue 
+  puts &quot;Rescued&quot;
+end
 </diff>
      <filename>research/exceptions.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>ff87d0d2bee00da7a0649e5fa57dd95d8e8651ab</id>
    </parent>
  </parents>
  <author>
    <name>Jonathan Branam</name>
    <email>github@jonathanbranam.net</email>
  </author>
  <url>http://github.com/jonathanbranam/redsun/commit/2095a0c03206f693aaafca81325d56305322db98</url>
  <id>2095a0c03206f693aaafca81325d56305322db98</id>
  <committed-date>2008-12-15T11:01:34-08:00</committed-date>
  <authored-date>2008-12-15T11:01:34-08:00</authored-date>
  <message>Completed implementation of intial raise and rescue.
Correctly raised and rescued a single exception from a string.
Doesn't handle raising custom exceptions yet.
Does propogate the raise through the stack.</message>
  <tree>773eaccb5453aea11ed4a9092f0e2c15223505c6</tree>
  <committer>
    <name>Jonathan Branam</name>
    <email>github@jonathanbranam.net</email>
  </committer>
</commit>
