Skip to content

Commit

Permalink
Move 'create_parameterized_role' from a macro to a subroutine in guts…
Browse files Browse the repository at this point in the history
….pir.
  • Loading branch information
pmichaud committed Apr 4, 2009
1 parent 5942053 commit e0cf1ed
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 37 deletions.
33 changes: 33 additions & 0 deletions src/builtins/guts.pir
Expand Up @@ -1051,6 +1051,39 @@ Helper method to compose the attributes of a role into a class.
fixup_iter_loop_end:
.end

=item !create_parametric_role

Helper method for creating parametric roles.

=cut

.sub '!create_parametric_role'
.param pmc mr
'!meta_compose'(mr)
.local pmc orig_role, meths, meth_iter
orig_role = getprop '$!orig_role', mr
meths = orig_role.'methods'()
meth_iter = iter meths
it_loop:
unless meth_iter goto it_loop_end
$S0 = shift meth_iter
$P0 = meths[$S0]
$P1 = clone $P0
$P2 = getprop '$!signature', $P0
setprop $P1, '$!signature', $P2
$I0 = isa $P0, 'Code'
unless $I0 goto ret_pir_skip_rs
$P2 = getattribute $P0, ['Sub'], 'proxy'
$P2 = getprop '$!real_self', $P2
$P3 = getattribute $P1, ['Sub'], 'proxy'
setprop $P3, '$!real_self', $P2
ret_pir_skip_rs:
mr.'add_method'($S0, $P1)
goto it_loop
it_loop_end:
.return (mr)
.end


=item !keyword_role(name)

Expand Down
47 changes: 10 additions & 37 deletions src/parser/actions.pm
Expand Up @@ -20,34 +20,8 @@ method TOP($/) {
declare_implicit_routine_vars($past);
$past.lexical(0);

# Make sure we have the interpinfo constants and parametric role macro.
# Make sure we have the interpinfo constants.
$past.unshift( PAST::Op.new( :inline('.include "interpinfo.pasm"') ) );
$past.unshift( PAST::Op.new( :inline('.macro create_parametric_role(mr)',
' "!meta_compose"(.mr)',
' .local pmc orig_role, meths, meth_iter',
' orig_role = getprop "$!orig_role", .mr',
' meths = orig_role."methods"()',
' meth_iter = iter meths',
' it_loop:',
' unless meth_iter goto it_loop_end',
' $S0 = shift meth_iter',
' $P0 = meths[$S0]',
' $P1 = clone $P0',
' $P2 = getprop "$!signature", $P0',
' setprop $P1, "$!signature", $P2',
' $I0 = isa $P0, "Code"',
' unless $I0 goto ret_pir_skip_rs',
' $P2 = getattribute $P0, ["Sub"], "proxy"',
' $P2 = getprop "$!real_self", $P2',
' $P3 = getattribute $P1, ["Sub"], "proxy"',
' setprop $P3, "$!real_self", $P2',
' ret_pir_skip_rs:',
' .mr."add_method"($S0, $P1)',
' goto it_loop',
' it_loop_end:',
' .return (.mr)',
'.endm') ) );

# Set package for unit mainline
$past.unshift(set_package_magical());

Expand Down Expand Up @@ -1801,16 +1775,15 @@ method package_def($/, $key) {
# ...and at the end of the block's initializer (after any other
# items added by the block), we finalize the composition.
if $?PKGDECL eq 'role' {
# For a role, we now need to produce a new one which clones the original,
# but without the methods. Then we need to add back the methods. We emit
# PIR here to do it rather than doing a call, since we need to call
# new_closure from the correct scope. (Note: create_parametric_role is a
# PIR macro).
$block[0].push(PAST::Op.new(:inline(
' .create_parametric_role(%0)',
),
$?METACLASS
));
# For a role, we now need to produce a copy of the role
# and clones of the methods (having captured the current
# lexical context).
$block[0].push(
PAST::Op.new(
:inline(' .tailcall "!create_parametric_role"(%0)'),
$?METACLASS
)
);
}
elsif $is_anon && ($?PKGDECL eq 'class' || $?PKGDECL eq 'grammar') {
# We need to keep the proto around and return it at the end of
Expand Down

0 comments on commit e0cf1ed

Please sign in to comment.