# 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