# New Ticket Created by  Stephen Weeks 
# Please include the string:  [perl #59410]
# in the subject line of all future correspondence about this issue. 
# <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=59410 >


This patch adds support for handling CONTROL_LOOP_NEXT exceptions in
pct-generated for loops.  It also adds a 'next' sub to both rakudo and
cardinal.

Cardinal's works fine, but with this patch, rakudo hangs while building.
Specifically, on parrot -o perl6.pbc perl6.pir.
I don't yet have time to track it down more than this beyond gdb always
showing parrot somewhere inside imcc when I looked.

I don't quite have time to track this down right now, but this is a
desired feature for rakudo, so I'll put it here for now.
>From 3a8fe82c992dac72a77df35a984a02db3808c372 Mon Sep 17 00:00:00 2001
From: Stephen Weeks <[EMAIL PROTECTED]>
Date: Sat, 27 Sep 2008 01:14:22 -0600
Subject: [PATCH] [pct]
 * Generate an exception handler for CONTROL_LOOP_NEXT exceptions in for loops
 [perl6]
 * Add a 'next' sub to throw CONTROL_LOOP_NEXT exceptions
 [cardinal]
 * Add a 'next' sub to throw CONTROL_LOOP_NEXT exceptions

---
 MANIFEST                                    |    1 +
 compilers/pct/src/PAST/Compiler.pir         |   21 +++++++++++++++++----
 include/parrot/exceptions.h                 |    6 +++++-
 languages/cardinal/config/makefiles/root.in |    1 +
 languages/cardinal/src/builtins/control.pir |   17 +++++++++++++++++
 languages/cardinal/src/parser/actions.pm    |    5 ++++-
 languages/cardinal/t/07-loops.t             |   15 ++++++++++++---
 languages/perl6/src/builtins/control.pir    |   11 +++++++++++
 8 files changed, 68 insertions(+), 9 deletions(-)
 create mode 100644 languages/cardinal/src/builtins/control.pir

diff --git a/MANIFEST b/MANIFEST
index c5a5c64..c94b2a7 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -1216,6 +1216,7 @@ languages/c99/t/spi.t                                     
  [c99]
 languages/cardinal/cardinal.pir                             [cardinal]
 languages/cardinal/config/makefiles/root.in                 [cardinal]
 languages/cardinal/src/builtins/cmp.pir                     [cardinal]
+languages/cardinal/src/builtins/control.pir                 [cardinal]
 languages/cardinal/src/builtins/eval.pir                    [cardinal]
 languages/cardinal/src/builtins/globals.pir                 [cardinal]
 languages/cardinal/src/builtins/guts.pir                    [cardinal]
diff --git a/compilers/pct/src/PAST/Compiler.pir 
b/compilers/pct/src/PAST/Compiler.pir
index 6eec545..f5ddbe4 100644
--- a/compilers/pct/src/PAST/Compiler.pir
+++ b/compilers/pct/src/PAST/Compiler.pir
@@ -1125,24 +1125,31 @@ by C<node>.
     $P0 = get_hll_global ['POST'], 'Ops'
     ops = $P0.'new'('node'=>node)
 
-    .local pmc looplabel, endlabel
+    .local pmc looplabel, nextlabel, endlabel
     $P0 = get_hll_global ['POST'], 'Label'
     $S0 = self.'unique'('for_')
     looplabel = $P0.'new'('result'=>$S0)
-    $S0 = concat $S0, '_end'
-    endlabel = $P0.'new'('result'=>$S0)
+    $S1 = concat $S0, '_next'
+    nextlabel = $P0.'new'('result'=>$S1)
+    $S2 = concat $S0, '_end'
+    endlabel = $P0.'new'('result'=>$S2)
 
     .local pmc collpast, collpost
     collpast = node[0]
     collpost = self.'as_post'(collpast, 'rtype'=>'P')
     ops.'push'(collpost)
 
-    .local string iter
+    .local string iter, next_handler
     iter = self.'uniquereg'('P')
     ops.'result'(iter)
     $S0 = self.'uniquereg'('I')
     ops.'push_pirop'('defined', $S0, collpost)
     ops.'push_pirop'('unless', $S0, endlabel)
+    next_handler = self.'uniquereg'('P')
+    ops.'push_pirop'('new', next_handler, "'ExceptionHandler'")
+    ops.'push_pirop'('set_addr', next_handler, nextlabel)
+    ops.'push_pirop'('callmethod', 'handle_types', next_handler, 
.CONTROL_LOOP_NEXT)
+    ops.'push_pirop'('push_eh', next_handler)
     ops.'push_pirop'('iter', iter, collpost)
     ops.'push'(looplabel)
     ops.'push_pirop'('unless', iter, endlabel)
@@ -1183,7 +1190,13 @@ by C<node>.
     ops.'push'(subpost)
     ops.'push_pirop'('call', subpost, arglist :flat)
     ops.'push_pirop'('goto', looplabel)
+    ops.'push'(nextlabel)
+    ops.'push_pirop'('.local pmc exception')
+    ops.'push_pirop'('.get_results (exception)')
+    ops.'push_pirop'('set', next_handler, 0)
+    ops.'push_pirop'('goto', looplabel)
     ops.'push'(endlabel)
+    ops.'push_pirop'('pop_eh')
     .return (ops)
 .end
 
diff --git a/include/parrot/exceptions.h b/include/parrot/exceptions.h
index cab79aa..6363c4e 100644
--- a/include/parrot/exceptions.h
+++ b/include/parrot/exceptions.h
@@ -88,7 +88,11 @@ typedef enum {
         CONTROL_BREAK,
         CONTROL_CONTINUE,
         CONTROL_ERROR,
-        CONTROL_TAKE
+        CONTROL_TAKE,
+
+        CONTROL_LOOP_NEXT,
+        CONTROL_LOOP_LAST,
+        CONTROL_LOOP_REDO
 } exception_type_enum;
 
 /* &end_gen */
diff --git a/languages/cardinal/config/makefiles/root.in 
b/languages/cardinal/config/makefiles/root.in
index b94b8b9..99e011c 100644
--- a/languages/cardinal/config/makefiles/root.in
+++ b/languages/cardinal/config/makefiles/root.in
@@ -45,6 +45,7 @@ SOURCES = cardinal.pir \
 
 BUILTINS_PIR = \
   src/builtins/guts.pir \
+  src/builtins/control.pir \
   src/builtins/say.pir \
   src/builtins/cmp.pir \
   src/builtins/op.pir \
diff --git a/languages/cardinal/src/builtins/control.pir 
b/languages/cardinal/src/builtins/control.pir
new file mode 100644
index 0000000..bf61f0c
--- /dev/null
+++ b/languages/cardinal/src/builtins/control.pir
@@ -0,0 +1,17 @@
+.include 'include/except_severity.pasm'
+.include 'include/except_types.pasm'
+
+.sub 'next'
+    .local pmc e
+    e = new 'Exception'
+    e['type'] = .CONTROL_LOOP_NEXT
+    e['severity'] = .EXCEPT_NORMAL
+    throw e
+.end
+
+# Local Variables:
+#   mode: pir
+#   fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:
+
diff --git a/languages/cardinal/src/parser/actions.pm 
b/languages/cardinal/src/parser/actions.pm
index f0ac120..b9a1d4f 100644
--- a/languages/cardinal/src/parser/actions.pm
+++ b/languages/cardinal/src/parser/actions.pm
@@ -419,7 +419,10 @@ method for_stmt($/) {
 }
 
 method control_command($/,$key) {
-    $/.panic("next, break, and redo aren't implemented yet");
+    make PAST::Op.new(
+            :pasttype('call'),
+            :name(~$/),
+        );
 }
 
 method module($/) {
diff --git a/languages/cardinal/t/07-loops.t b/languages/cardinal/t/07-loops.t
index 052d634..443fb6d 100644
--- a/languages/cardinal/t/07-loops.t
+++ b/languages/cardinal/t/07-loops.t
@@ -1,13 +1,22 @@
-puts "1..8"
+require 'test'
+plan 12
 
 i = 1
 while i < 5
-    puts "ok ", i
+    ok(i < 5, 'while loop')
     i = i + 1
 end
 
 a = [ 5, 6, 7, 8 ]
 
 for i in a
-    puts "ok ", i
+    ok(i < 9, 'for loop')
 end
+
+a = [1,2,3,4,5,6,7,8]
+
+for i in a
+    next if i % 2
+    nok(i % 2, 'next in for loop')
+end
+
diff --git a/languages/perl6/src/builtins/control.pir 
b/languages/perl6/src/builtins/control.pir
index d37e61c..df22cbc 100644
--- a/languages/perl6/src/builtins/control.pir
+++ b/languages/perl6/src/builtins/control.pir
@@ -114,6 +114,17 @@ the moment -- we'll do more complex handling a bit later.)
     continuation()
 .end
 
+=item next
+
+=cut
+
+.sub 'next'
+    .local pmc e
+    e = new 'Exception'
+    e['severity'] = .EXCEPT_NORMAL
+    e['type'] = .CONTROL_LOOP_NEXT
+    throw e
+.end
 
 =item term:...
 
-- 
1.5.5.1

Reply via email to