Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
A little more sketching out of how we'll handle lazy magicals.
  • Loading branch information
jnthn committed May 23, 2011
1 parent 403525b commit 5ee5d8e
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 31 deletions.
29 changes: 7 additions & 22 deletions src/Perl6/Actions.pm
Expand Up @@ -329,7 +329,7 @@ class Perl6::Actions is HLL::Actions {
));
}
else {
add_implicit_var($block, '$_', 1);
add_implicit_var($block, '$_');
}
}
}
Expand Down Expand Up @@ -380,19 +380,17 @@ class Perl6::Actions is HLL::Actions {

method finishpad($/) {
# Generate the $_, $/, and $! lexicals if they aren't already
# declared. For routines and methods, they're simply created as
# undefs; for other blocks they initialize to their outer lexical.

# declared. We don't actually give them a value, but rather the
# Perl6LexPad will generate containers (and maybe fill them with
# the outer's value) on demand.
my $BLOCK := $*ST.cur_lexpad();
my $outer := $BLOCK<IN_DECL> ne 'routine' && $BLOCK<IN_DECL> ne 'method';

for <$_ $/ $!> {
# Generate the lexical variable except if...
# (1) the block already has one, or
# (2) the variable is '$_' and $*IMPLICIT is set
# (this case gets handled by getsig)
unless $BLOCK.symbol($_) || ($_ eq '$_' && $*IMPLICIT) {
add_implicit_var($BLOCK, $_, $outer);
add_implicit_var($BLOCK, $_);
}
}
}
Expand Down Expand Up @@ -2898,21 +2896,8 @@ class Perl6::Actions is HLL::Actions {
$past;
}

sub add_implicit_var($block, $name, $outer) {
# If we have an outer block, set $_ explicitly to what it is in the outer
# block. For routines they are auto-viv. (TODO: make routine case more
# optimal too.)
if $outer {
my $base := PAST::Op.new( :inline(" %r = new ['Perl6Scalar'], %0"),
PAST::Op.new(:pirop('find_lex_skip_current Ps'), $name)
);
$base := PAST::Op.new( $base, 'rw', $TRUE, :pirop('setprop') ); # XXX
$block[0].push(PAST::Op.new(
:pasttype('bind'),
PAST::Var.new( :name($name), :scope('lexical') ),
$base
));
}
sub add_implicit_var($block, $name) {
$block[0].push(PAST::Var.new( :name($name), :scope('lexical'), :isdecl(1) ));
$block.symbol($name, :scope('lexical') );
}

Expand Down
21 changes: 12 additions & 9 deletions src/pmc/perl6lexpad.pmc
Expand Up @@ -13,17 +13,11 @@ pmclass Perl6LexPad
/* The current context, including the registers. */
ATTR PMC *ctx;

/* We keep a vivified-on-demand store for $_, $! and $/. Every block has them
* but they often go unused, so saves a bunch of memory allocations to just
* create them on demand if used. */
ATTR PMC *topic;
ATTR PMC *error;
ATTR PMC *match;

/* For %_ we rarely need it, but methods always want to collect it by default.
* We can't really statically eliminate it, but we can make sure we only create
* it on demand. This contains a Parrot hash by default, or NULL if there's no
* named args. It will become a Perl 6 hash "magically" if asked for. */
* named args. The binder sets it, and it'll magically become initialized to
* a Perl 6 hash if accessed. */
ATTR PMC *default_named_slurpy;

VTABLE void init() {
Expand Down Expand Up @@ -145,6 +139,7 @@ Return the LexInfo PMC, if any or a Null PMC.
const Hash *hash;
PMC *ctx;
HashBucket *b;
PMC *result;

GET_ATTR_lexinfo(INTERP, SELF, info);
if (info->vtable->base_type != enum_class_LexInfo) {
Expand All @@ -164,7 +159,15 @@ Return the LexInfo PMC, if any or a Null PMC.
return PMCNULL;

GET_ATTR_ctx(INTERP, SELF, ctx);
return CTX_REG_PMC(interp, ctx, (INTVAL)b->value);
result = CTX_REG_PMC(interp, ctx, (INTVAL)b->value);

if (PMC_IS_NULL(result)) {
/* XXX TODO: This is where we magically create an empty
* container and/or grab the outer value for special
* on-demand lexicals like $_. */
}

return result;
}

VTABLE PMC *get_pmc_keyed(PMC *name) {
Expand Down

0 comments on commit 5ee5d8e

Please sign in to comment.