From c6bd89e5da855f112acf50b156a725d9495258c6 Mon Sep 17 00:00:00 2001 From: Stefan O'Rear Date: Sun, 10 Oct 2010 22:00:24 -0700 Subject: [PATCH] Implement nextsame --- lib/Kernel.cs | 44 ++++++++++++++++++++++++++++++++++++++------ test2.pl | 21 +++++++++++++++++++++ 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/lib/Kernel.cs b/lib/Kernel.cs index 9db65e6c..7e5cd6eb 100644 --- a/lib/Kernel.cs +++ b/lib/Kernel.cs @@ -175,15 +175,16 @@ public class SubInfo { public const int ON_SUCCEED = 6; public const int ON_PROCEED = 7; public const int ON_GOTO = 8; + public const int ON_NEXTDISPATCH = 9; public int[] edata; public string[] label_names; + private static string[] controls = new string[] { "unknown", "next", + "last", "redo", "return", "die", "succeed", "proceed", "goto", + "nextsame/nextwith" }; public static string DescribeControl(int type, Frame tgt, int lid, string name) { - string ty = (type == ON_RETURN) ? "return" : - (type == ON_REDO) ? "redo" : - (type == ON_LAST) ? "last" : - (type == ON_NEXT) ? "next" : "unknown control"; + string ty = (type < controls.Length) ? controls[type] : "unknown"; if (lid >= 0) { return ty + "(" + tgt.info.label_names[lid] + ", lexotic)"; } else if (name != null) { @@ -1141,6 +1142,13 @@ class ExitRunloopException : Exception { } int unip = 0; for (csr = th; csr != null; csr = csr.caller) { + if (type == SubInfo.ON_NEXTDISPATCH) { + if (csr.curDisp != null) { + unf = csr; + break; + } + continue; + } // for lexoticism if (tgt != null && tgt != csr) continue; @@ -1169,7 +1177,7 @@ class ExitRunloopException : Exception { } r.lex0 = mp; return r; } else { - return Unwind(th, unf, unip, payload); + return Unwind(th, type, unf, unip, payload); } } @@ -1200,8 +1208,32 @@ class ExitRunloopException : Exception { } } } - public static Frame Unwind(Frame th, Frame tf, int tip, object td) { + public static Frame Unwind(Frame th, int type, Frame tf, int tip, + object td) { // LEAVE handlers aren't implemented yet. + if (type == SubInfo.ON_NEXTDISPATCH) { + // These are a bit special because there isn't actually a + // catching frame. + DispatchEnt de = tf.curDisp.next; + DynObject o = td as DynObject; + if (de != null) { + Variable[] p = tf.pos; + Dictionary n = tf.named; + tf = tf.caller.MakeChild(de.outer, de.info); + if (o != null) { + tf.pos = (Variable[]) o.slots[0]; + tf.named = o.slots[1] as Dictionary; + } else { + tf.pos = p; + tf.named = n; + } + tf.curDisp = de; + return tf; + } else { + tf.caller.resultSlot = Kernel.NewROScalar(Kernel.AnyP); + return tf.caller; + } + } tf.ip = tip; tf.resultSlot = td; return tf; diff --git a/test2.pl b/test2.pl index 29650c39..c51add2c 100644 --- a/test2.pl +++ b/test2.pl @@ -1,6 +1,27 @@ # vim: ft=perl6 use Test; +sub nextsame() { + Q:CgOp { (control 9 (null frame) (int -1) (null str) (null obj)) } +} + +{ + my class A { + method tom() { 12 } + method foo($x) { $x * $x } + method bar(:$x) { $x + $x } + } + my class B is A { + method tom() { nextsame; } + method foo($x) { nextsame; } #OK + method bar(:$x) { nextsame; } #OK + } + is B.tom(), 12, "nextsame functional"; + is B.foo(5), 25, "nextsame functional w/ argument"; + # TODO + # is B.bar(:x(7)), 14, "nextsame functional w/ named arg"; +} + #is $?FILE, 'test.pl', '$?FILE works'; #is $?ORIG.substr(0,5), '# vim', '$?ORIG works';