Skip to content

Commit

Permalink
Differentiate required and optional implicit topic
Browse files Browse the repository at this point in the history
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 64d08ad
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 14 deletions.
5 changes: 3 additions & 2 deletions src/Perl6/Actions.nqp
Expand Up @@ -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('$_') {
Expand Down
32 changes: 20 additions & 12 deletions src/Perl6/Grammar.nqp
Expand Up @@ -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;
Expand Down Expand Up @@ -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',
Expand All @@ -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',
Expand Down Expand Up @@ -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> {
Expand All @@ -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> {
Expand Down Expand Up @@ -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>
Expand Down Expand Up @@ -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\'?)'> }
Expand Down Expand Up @@ -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>
}
Expand Down

0 comments on commit 64d08ad

Please sign in to comment.