Permalink
Browse files

enable forward gotos. can't have unused labels. can't jump into block…

…s, and can't jump out of blocks that declare their own lexicals.
  • Loading branch information...
1 parent f0bf33d commit bda247f4b46be502afc591c6819d94228df08ae0 @diakopter diakopter committed May 12, 2012
Showing with 37 additions and 15 deletions.
  1. +27 −13 src/NQP/Actions.pm
  2. +10 −2 src/NQP/Grammar.pm
View
@@ -40,6 +40,7 @@ class NQP::Actions is HLL::Actions {
}
method comp_unit($/) {
+ resolve_gotos($/);
my $mainline := $<statementlist>.ast;
my $unit := $*W.pop_lexpad();
@@ -127,25 +128,25 @@ class NQP::Actions is HLL::Actions {
}
method label($/) {
- my $name := 'VNDUNVD84VN'~$<identifier>;
- my $BLOCK := $*W.cur_lexpad();
- if $BLOCK.symbol($name) {
- $/.CURSOR.panic("Redeclaration of symbol ", $name);
- }
- $BLOCK.symbol($name, :scope('label') );
- my $past := PAST::Label.new( :node($/), :name($name) );
+ my $name := $<identifier>;
+ if (%*LABELS{$name}) {
+ $/.CURSOR.panic("Duplicate label: ", $name);
+ }
+ $*W.cur_lexpad().symbol($name, :scope('label') );
+ $*LABEL_INDEX++;
+ my $mangled := "nqp_label_"~$*LABEL_INDEX~'_'~$name;
+ my $past := PAST::Label.new( :node($/), :name($mangled) );
+ %*LABELS{$name} := $past;
make $past;
}
method goto($/) {
- my $origname := $<identifier>;
- my $name := 'VNDUNVD84VN'~$origname;
- unless $*W.is_scope($name, 'label') {
- $/.CURSOR.panic("missing label (no forward gotos) ", $origname);
- }
+ my $name := $<identifier>;
+ my $glabel := PAST::Label.new( :node($/), :name($name) );
+ @*GOTOS.push($glabel);
my $past := PAST::Op.new(
:pasttype('goto'),
- PAST::Label.new( :node($/), :name($name) )
+ $glabel
);
make $past;
}
@@ -714,10 +715,22 @@ class NQP::Actions is HLL::Actions {
}
+ sub resolve_gotos($/) {
+ for @*GOTOS {
+ my $name := $_.name();
+ my $label := %*LABELS{$name};
+ unless $label {
+ $/.CURSOR.panic('Could not find label '~$name~' for a goto');
+ }
+ $_.name($label.name());
+ }
+ }
+
method routine_declarator:sym<sub>($/) { make $<routine_def>.ast; }
method routine_declarator:sym<method>($/) { make $<method_def>.ast; }
method routine_def($/) {
+ resolve_gotos($/);
# If it's just got * as a body, make a multi-dispatch enterer.
# Otherwise, need to build a sub.
my $past;
@@ -852,6 +865,7 @@ class NQP::Actions is HLL::Actions {
method method_def($/) {
+ resolve_gotos($/);
# If it's just got * as a body, make a multi-dispatch enterer.
# Otherwise, build method block PAST.
my $past;
View
@@ -106,7 +106,9 @@ grammar NQP::Grammar is HLL::Grammar {
:my $*HAS_YOU_ARE_HERE := 0;
:my $*MAIN_SUB;
<.newpad>
-
+ :my %*LABELS;
+ :my @*GOTOS;
+ :my $*LABEL_INDEX := 0;
:my $*PACKAGE;
:my $*GLOBALish;
<.GLOBALish>
@@ -128,7 +130,7 @@ grammar NQP::Grammar is HLL::Grammar {
# not a real Perl 6 goto, so not a real &goto
token goto {
- 'goto' <?before \s> <.ws> <identifier>
+ 'goto' <?before \s> <.ws> <identifier> <.ws>
}
token statement {
@@ -429,6 +431,9 @@ grammar NQP::Grammar is HLL::Grammar {
rule routine_def {
:my $*RETURN_USED := 0;
+ :my %*LABELS;
+ :my @*GOTOS;
+ :my $*LABEL_INDEX := 0;
[ $<sigil>=['&'?]<deflongname> ]?
<.newpad>
[ '(' <signature> ')'
@@ -443,6 +448,9 @@ grammar NQP::Grammar is HLL::Grammar {
rule method_def {
:my $*RETURN_USED := 0;
:my $*INVOCANT_OK := 1;
+ :my %*LABELS;
+ :my @*GOTOS;
+ :my $*LABEL_INDEX := 0;
$<private>=['!'?]
<deflongname>?
<.newpad>

0 comments on commit bda247f

Please sign in to comment.