Skip to content
Permalink
Browse files

Don't lower lexicals used by traits

Otherwise, we break things like `my $x will leave { .close }` style
constructs.
  • Loading branch information...
jnthn committed Oct 30, 2018
1 parent 685f6cc commit b41e9f5723babea64a4f7f10ad25bc2c28f5c1aa
Showing with 26 additions and 1 deletion.
  1. +6 −0 src/Perl6/Actions.nqp
  2. +2 −1 src/Perl6/Optimizer.nqp
  3. +11 −0 src/Perl6/World.nqp
  4. +7 −0 src/core/Variable.pm6
@@ -3802,7 +3802,13 @@ class Perl6::Actions is HLL::Actions does STDActions {
nqp::bindattr($varvar, $Variable, '$!var', $cont);
nqp::bindattr($varvar, $Variable, '$!block', $*CODE_OBJECT);
nqp::bindattr($varvar, $Variable, '$!slash', $/);
nqp::assign(
nqp::getattr($varvar, $Variable, '$!implicit-lexical-usage'),
$*W.find_symbol(['Bool', 'True']));
$*W.apply_traits(@late_traits, $varvar);
if $varvar.implicit-lexical-usage {
$*W.mark_lexical_used_implicitly($BLOCK, $name);
}
}
}
elsif $*SCOPE eq '' {
@@ -630,7 +630,8 @@ my class BlockVarOptimizer {
my int $is_contvar := $decl eq 'contvar';
next unless $is_contvar || $decl eq 'var';

# Also ensure not dynamic.
# Also ensure not dynamic or with an implicit lexical usage.
next if $qast.ann('lexical_used_implicitly');
my $qv := $qast.value;
my $dynamic := nqp::isconcrete_nd($qv) &&
try nqp::getattr($qv, nqp::what_nd($qv), '$!descriptor').dynamic;
@@ -1668,6 +1668,17 @@ class Perl6::World is HLL::World {
$cont
}

# Mark a container as being implicitly used lexically (to prevent it
# being optimized away).
method mark_lexical_used_implicitly($block, str $name) {
for @($block[0]) {
if nqp::istype($_, QAST::Var) && $_.name eq $name {
$_.annotate('lexical_used_implicitly', 1);
last;
}
}
}

# Creates a new container descriptor and adds it to the SC.
method create_container_descriptor($of, $name, $default = $of, $dynamic = nqp::chars($name) > 2 && nqp::eqat($name, '*', 1)) {
my $cd_type := self.find_symbol(['ContainerDescriptor'], :setting-only);
@@ -13,6 +13,7 @@ my class Variable {
has $.var is rw;
has $.block;
has $.slash;
has $.implicit-lexical-usage is rw;

# make throwing easier
submethod throw ( |c ) {
@@ -157,18 +158,23 @@ multi sub trait_mod:<will>(Variable:D $v, $block, :$end! ) {
}
multi sub trait_mod:<will>(Variable:D $v, $block, :$enter! ) {
$v.block.add_phaser('ENTER', $v.willdo($block, 1) );
$v.implicit-lexical-usage = True;
}
multi sub trait_mod:<will>(Variable:D $v, $block, :$leave! ) {
$v.block.add_phaser('LEAVE', $v.willdo($block) );
$v.implicit-lexical-usage = True;
}
multi sub trait_mod:<will>(Variable:D $v, $block, :$keep! ) {
$v.block.add_phaser('KEEP', $v.willdo($block));
$v.implicit-lexical-usage = True;
}
multi sub trait_mod:<will>(Variable:D $v, $block, :$undo! ) {
$v.block.add_phaser('UNDO', $v.willdo($block));
$v.implicit-lexical-usage = True;
}
multi sub trait_mod:<will>(Variable:D $v, $block, :$first! ) {
$v.block.add_phaser('FIRST', $v.willdo($block, 1));
$v.implicit-lexical-usage = True;
}
multi sub trait_mod:<will>(Variable:D $v, $block, :$next! ) {
$v.block.add_phaser('NEXT', $block);
@@ -178,6 +184,7 @@ multi sub trait_mod:<will>(Variable:D $v, $block, :$last! ) {
}
multi sub trait_mod:<will>(Variable:D $v, $block, :$pre! ) {
$v.block.add_phaser('PRE', $v.willdo($block, 1));
$v.implicit-lexical-usage = True;
}
multi sub trait_mod:<will>(Variable:D $v, $block, :$post! ) {
$v.throw( 'X::Comp::NYI',

0 comments on commit b41e9f5

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