Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix BEGIN/CHECK block scoping precomp bug.
This in turn unbusts .pick and friends in Bool after the changes to
make it a real enum.
  • Loading branch information
jnthn committed Nov 21, 2015
1 parent 6d0ca40 commit 94385dd
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 23 deletions.
66 changes: 44 additions & 22 deletions src/Perl6/Actions.nqp
Expand Up @@ -1628,9 +1628,15 @@ Compilation unit '$file' contained the following violations:
make $*W.add_phaser($/, 'QUIT', $block.ann('code_object'));
}

method statement_prefix:sym<BEGIN>($/) { make $*W.add_phaser($/, 'BEGIN', ($<blorst>.ast).ann('code_object')); }
method statement_prefix:sym<BEGIN>($/) {
begin_time_lexical_fixup($<blorst>.ast.ann('past_block'));
make $*W.add_phaser($/, 'BEGIN', $<blorst>.ast.ann('code_object'));
}
method statement_prefix:sym<CHECK>($/) {
begin_time_lexical_fixup($<blorst>.ast.ann('past_block'));
make $*W.add_phaser($/, 'CHECK', ($<blorst>.ast).ann('code_object'));
}
method statement_prefix:sym<COMPOSE>($/) { make $*W.add_phaser($/, 'COMPOSE', ($<blorst>.ast).ann('code_object')); }
method statement_prefix:sym<CHECK>($/) { make $*W.add_phaser($/, 'CHECK', ($<blorst>.ast).ann('code_object')); }
method statement_prefix:sym<INIT>($/) { make $*W.add_phaser($/, 'INIT', ($<blorst>.ast).ann('code_object'), ($<blorst>.ast).ann('past_block')); }
method statement_prefix:sym<ENTER>($/) { make $*W.add_phaser($/, 'ENTER', ($<blorst>.ast).ann('code_object')); }
method statement_prefix:sym<FIRST>($/) { make $*W.add_phaser($/, 'FIRST', ($<blorst>.ast).ann('code_object')); }
Expand Down Expand Up @@ -2318,26 +2324,8 @@ Compilation unit '$file' contained the following violations:
add_signature_binding_code($block, $sig, @params);
$block.blocktype('declaration_static');

# Need to ensure we get lexical outers fixed up properly. To
# do this we make a list of closures, which each point to the
# outer context. These surive serialization and thus point at
# what has to be fixed up.
my $throwaway_block_past := QAST::Block.new(
:blocktype('declaration'),
QAST::Var.new( :name('$_'), :scope('lexical'), :decl('var') )
);
$throwaway_block_past.annotate('outer', $block);
$block[0].push($throwaway_block_past);
my $throwaway_block := $*W.create_code_object($throwaway_block_past,
'Block', $*W.create_signature(nqp::hash('parameter_objects', [])));
my $fixup := $*W.create_lexical_capture_fixup();
$fixup.push(QAST::Op.new(
:op('p6capturelex'),
QAST::Op.new(
:op('callmethod'), :name('clone'),
QAST::WVal.new( :value($throwaway_block) )
)));
$block[1].push($fixup);
# Role bodies run at BEGIN time, so need fixup.
begin_time_lexical_fixup($block);

# As its last act, it should grab the current lexpad so that
# we have the type environment, and also return the parametric
Expand Down Expand Up @@ -2398,6 +2386,40 @@ Compilation unit '$file' contained the following violations:
);
}

# When code runs at BEGIN time, such as role bodies and BEGIN
# blocks, we need to ensure we get lexical outers fixed up
# properly when deserializing after pre-comp. To do this we
# make a list of closures, which each point to the outer
# context. These surive serialization and thus point at what
# has to be fixed up.
sub begin_time_lexical_fixup($block) {
my $has_nested_blocks := 0;
for @($block[0]) {
if nqp::istype($_, QAST::Block) {
$has_nested_blocks := 1;
last;
}
}
return 0 unless $has_nested_blocks;

my $throwaway_block_past := QAST::Block.new(
:blocktype('declaration'), :name('!LEXICAL_FIXUP'),
QAST::Var.new( :name('$_'), :scope('lexical'), :decl('var') )
);
$throwaway_block_past.annotate('outer', $block);
$block[0].push($throwaway_block_past);
my $throwaway_block := $*W.create_code_object($throwaway_block_past,
'Block', $*W.create_signature(nqp::hash('parameter_objects', [])));
my $fixup := $*W.create_lexical_capture_fixup();
$fixup.push(QAST::Op.new(
:op('p6capturelex'),
QAST::Op.new(
:op('callmethod'), :name('clone'),
QAST::WVal.new( :value($throwaway_block) )
)));
$block[0].push($fixup);
}

method scope_declarator:sym<my>($/) { make $<scoped>.ast; }
method scope_declarator:sym<our>($/) { make $<scoped>.ast; }
method scope_declarator:sym<has>($/) { make $<scoped>.ast; }
Expand Down
3 changes: 2 additions & 1 deletion src/Perl6/World.nqp
Expand Up @@ -2880,7 +2880,8 @@ class Perl6::World is HLL::World {

# Set up capturing code.
my $capturer := self.cur_lexpad();
my $c_block := QAST::Block.new( :blocktype('declaration_static') );
my $c_block := QAST::Block.new( :blocktype('declaration_static'),
:name('!LEXICAL_FIXUP_CSCOPE') );
self.create_simple_code_object($c_block, 'Code');
$capturer[0].push(QAST::Op.new(
:op('callmethod'), :name('resolve'),
Expand Down

0 comments on commit 94385dd

Please sign in to comment.