Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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
diakopter committed May 12, 2012
1 parent f0bf33d commit bda247f
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 15 deletions.
40 changes: 27 additions & 13 deletions src/NQP/Actions.pm
Expand Up @@ -40,6 +40,7 @@ class NQP::Actions is HLL::Actions {
}

method comp_unit($/) {
resolve_gotos($/);
my $mainline := $<statementlist>.ast;
my $unit := $*W.pop_lexpad();

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
12 changes: 10 additions & 2 deletions src/NQP/Grammar.pm
Expand Up @@ -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>
Expand All @@ -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 {
Expand Down Expand Up @@ -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> ')'
Expand All @@ -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>
Expand Down

0 comments on commit bda247f

Please sign in to comment.