Skip to content
Permalink
Browse files

Differentiate required and optional implicit topic

When we have `for @A { }` then there is no need for the `$_` parameter
to be optional, since we know we'll always be invoking the block with a
parameter. This should lead to slightly more compact/efficient code for
such cases, and will make the static optimizer's job easier with regard
to having to try and track outer lexical accesses.
  • Loading branch information...
jnthn committed Jan 3, 2019
1 parent f741374 commit 64d08ad63729687cf91af5d46b4f22165f548577
Showing with 23 additions and 14 deletions.
  1. +3 −2 src/Perl6/Actions.nqp
  2. +20 −12 src/Perl6/Grammar.nqp
@@ -1705,10 +1705,11 @@ class Perl6::Actions is HLL::Actions does STDActions {
}
else {
if $*IMPLICIT {
my $optional := $*IMPLICIT == 1;
@params.push(hash(
:variable_name('$_'), :optional(1),
:variable_name('$_'), :$optional,
:nominal_type($*W.find_symbol(['Mu'])),
:default_from_outer(1), :is_raw(1),
:default_from_outer($optional), :is_raw(1),
));
}
elsif !$block.symbol('$_') {
@@ -981,13 +981,18 @@ grammar Perl6::Grammar is HLL::Grammar does STD {
|| { $/.typed_panic( 'X::Syntax::Confused', reason => "Confused" ) }
}
token xblock($*IMPLICIT = 0) {
# Options for xblock/block implicit topic.
my $PBLOCK_NO_TOPIC := 0;
my $PBLOCK_OPTIONAL_TOPIC := 1;
my $PBLOCK_REQUIRED_TOPIC := 2;
token xblock($*IMPLICIT = $PBLOCK_NO_TOPIC) {
:my $*GOAL := '{';
:my $*BORG := {};
<EXPR> <.ws> <pblock($*IMPLICIT)>
}
token pblock($*IMPLICIT = 0) {
token pblock($*IMPLICIT = $PBLOCK_NO_TOPIC) {
:my $*DECLARAND := $*W.stub_code_object('Block');
:my $*CODE_OBJECT := $*DECLARAND;
:my $*SIG_OBJ;
@@ -1111,22 +1116,25 @@ grammar Perl6::Grammar is HLL::Grammar does STD {
rule statement_control:sym<if> {
$<sym>=[if|with]<.kok> {}
<xblock(so ~$<sym>[0] ~~ /with/)>
<xblock(~$<sym>[0] ~~ /with/ ?? $PBLOCK_REQUIRED_TOPIC !! $PBLOCK_NO_TOPIC)>
[
[
| 'else'\h*'if' <.typed_panic: 'X::Syntax::Malformed::Elsif'>
| 'elif' { $/.typed_panic('X::Syntax::Malformed::Elsif', what => "elif") }
| $<sym>='elsif' <xblock>
| $<sym>='orwith' <xblock(1)>
| $<sym>='orwith' <xblock($PBLOCK_REQUIRED_TOPIC)>
]
]*
{}
[ 'else' <else=.pblock(so ~$<sym>[-1] ~~ /with/)> ]?
[
'else'
<else=.pblock(~$<sym>[-1] ~~ /with/ ?? $PBLOCK_REQUIRED_TOPIC !! $PBLOCK_NO_TOPIC)>
]?
}
rule statement_control:sym<unless> {
$<sym>='unless'<.kok>
<xblock(0)> # 0 means we're not parsing `without`
<xblock($PBLOCK_NO_TOPIC)> # 0 means we're not parsing `without`
[ <!before [els[e|if]|orwith]» >
|| $<wrong-keyword>=[els[e|if]|orwith]» {}
<.typed_panic: 'X::Syntax::UnlessElse',
@@ -1137,7 +1145,7 @@ grammar Perl6::Grammar is HLL::Grammar does STD {
rule statement_control:sym<without> {
$<sym>='without'<.kok>
<xblock(1)> # 1 means we're not parsing `unless`
<xblock($PBLOCK_REQUIRED_TOPIC)> # 1 means we're not parsing `unless`
[ <!before [els[e|if]|orwith]» >
|| $<wrong-keyword>=[els[e|if]|orwith]» {}
<.typed_panic: 'X::Syntax::WithoutElse',
@@ -1167,7 +1175,7 @@ grammar Perl6::Grammar is HLL::Grammar does STD {
<.typed_panic: 'X::Syntax::P5'> ]?
[ <?before '(' <.EXPR>? ';' <.EXPR>? ';' <.EXPR>? ')' >
<.obs('C-style "for (;;)" loop', '"loop (;;)"')> ]?
<xblock(1)>
<xblock($PBLOCK_REQUIRED_TOPIC)>
}
rule statement_control:sym<whenever> {
@@ -1180,7 +1188,7 @@ grammar Perl6::Grammar is HLL::Grammar does STD {
|| <.typed_panic('X::Comp::WheneverOutOfScope')>
]
{ $*WHENEVER_COUNT++ }
<xblock(1)>
<xblock($PBLOCK_REQUIRED_TOPIC)>
}
rule statement_control:sym<foreach> {
@@ -1341,7 +1349,7 @@ grammar Perl6::Grammar is HLL::Grammar does STD {
}
rule statement_control:sym<given> {
<sym><.kok> <xblock(1)>
<sym><.kok> <xblock($PBLOCK_REQUIRED_TOPIC)>
}
rule statement_control:sym<when> {
<sym><.kok> <xblock>
@@ -2964,7 +2972,7 @@ grammar Perl6::Grammar is HLL::Grammar does STD {
}
rule trait_mod:sym<hides> { <sym> [ <typename> || <.bad_trait_typename>] }
rule trait_mod:sym<does> { <sym> [ <typename> || <.bad_trait_typename>] }
rule trait_mod:sym<will> { <sym> [ <identifier> || <.panic: 'Invalid name'>] <pblock(1)> }
rule trait_mod:sym<will> { <sym> [ <identifier> || <.panic: 'Invalid name'>] <pblock($PBLOCK_OPTIONAL_TOPIC)> }
rule trait_mod:sym<of> { <sym> [ <typename> || <.bad_trait_typename>] }
rule trait_mod:sym<returns> { <sym> [ <typename> || <.bad_trait_typename>]
|| 'return' <.panic: 'Invalid trait modifier (did you mean \'returns\'?)'> }
@@ -3548,7 +3556,7 @@ grammar Perl6::Grammar is HLL::Grammar does STD {
token circumfix:sym<« »> { :dba('shell-quote words') '«' ~ '»' <nibble(self.quote_lang(self.slang_grammar('Quote'), "«", "»", ['qq', 'ww', 'v']))> }
token circumfix:sym<{ }> {
:my $*FAKE_INFIX_FOUND := 0;
<?[{]> <pblock(1)>
<?[{]> <pblock($PBLOCK_OPTIONAL_TOPIC)>
{
$*BORG<block> := $<pblock>
}

0 comments on commit 64d08ad

Please sign in to comment.
You can’t perform that action at this time.