diff --git a/compilers/pct/src/PAST/Compiler.pir b/compilers/pct/src/PAST/Compiler.pir index 9262a1aa02..ef66c1cac2 100644 --- a/compilers/pct/src/PAST/Compiler.pir +++ b/compilers/pct/src/PAST/Compiler.pir @@ -997,9 +997,18 @@ Return the POST representation of a C. bpost = $P0.'new'( bpost, 'node'=>node, 'result'=>blockreg) bpost.'push_pirop'( blockref, 'result'=>blockreg ) unless islexical goto block_done + $I0 = node.'closure'() + if $I0 goto block_closure bpost.'push_pirop'('capture_lex', blockreg) goto block_done + block_closure: + ## return a reference to a clone of the block with captured outer context + result = self.'uniquereg'('P') + bpost.'push_pirop'('newclosure', result, blockreg) + bpost.'result'(result) + goto block_done + block_immediate: .local pmc arglist arglist = options['arglist'] diff --git a/compilers/pct/src/PAST/Node.pir b/compilers/pct/src/PAST/Node.pir index 82669d24d2..2b14e38dc5 100644 --- a/compilers/pct/src/PAST/Node.pir +++ b/compilers/pct/src/PAST/Node.pir @@ -498,6 +498,21 @@ blocks in Perl6 C, C, and other similar statements). .end +=item closure([value]) + +Get/set the closure flag for the block to C. If set, +any block reference returned by the node is to a clone of the +block that has captured the current lexical context. + +=cut + +.sub 'closure' :method + .param pmc value :optional + .param int has_value :opt_flag + .tailcall self.'attr'('closure', value, has_value) +.end + + =item control([value]) Get/set the control exception handler for this block to C. diff --git a/docs/pdds/pdd26_ast.pod b/docs/pdds/pdd26_ast.pod index eceed7cc3d..6feeb73709 100644 --- a/docs/pdds/pdd26_ast.pod +++ b/docs/pdds/pdd26_ast.pod @@ -481,13 +481,20 @@ the C method below. =item blocktype([type]) Get/set the type of the block to C. The currently -understood values are 'declaration' and 'immediate'. 'Declaration' -indicates that a block is simply being defined at this point, the -result of the node is a reference to the block. A C -of 'immediate' indicates a block that is to be immediately +understood values are 'declaration', 'immediate', and 'method'. +'Declaration' indicates that a block is simply being defined at +this point, the result of the node is a reference to the block. +A C of 'immediate' indicates a block that is to be immediately executed when it is evaluated in the AST, and the result of the last operation is used as the return value for the block. +=item closure([value]) + +Get/set the closure flag for the block to C. If the closure +flag on a (non-immediate) block is true, then the node returns a +reference to a clone of the block that has captured the current +lexical context. + =item namespace([value]) Get/set the namespace for this particular block (and any nested