Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Store contextuals in lexical arrays
  • Loading branch information
sorear committed Nov 25, 2010
1 parent 34db8bc commit ccbb9b8
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 40 deletions.
2 changes: 1 addition & 1 deletion lib/Cursor.cs
Expand Up @@ -1090,7 +1090,7 @@ public class LADParam : LAD {

object o;

if (outer.lex == null || !outer.lex.TryGetValue("*params", out o)) {
if (!outer.TryGetDynamic("*params", out o)) {
reason = "no parameter block";
goto imp;
}
Expand Down
52 changes: 42 additions & 10 deletions lib/Kernel.cs
Expand Up @@ -165,6 +165,7 @@ public class SubInfo {
public Dictionary<string, object> hints;
// maybe should be a hint
public LAD ltm;
public Dictionary<string, int> dylex;

// records: $start-ip, $end-ip, $type, $goto, $lid
public const int ON_NEXT = 1;
Expand Down Expand Up @@ -227,18 +228,24 @@ public class SubInfo {
}

public SubInfo(string name, int[] lines, DynBlockDelegate code,
SubInfo outer, LAD ltm, int[] edata, string[] label_names) {
SubInfo outer, LAD ltm, int[] edata, string[] label_names,
string[] dylexn, int[] dylexi) {
this.lines = lines;
this.code = code;
this.outer = outer;
this.ltm = ltm;
this.name = name;
this.edata = edata;
this.label_names = label_names;
if (dylexn != null) {
dylex = new Dictionary<string, int>();
for (int i = 0; i < dylexn.Length; i++)
dylex[dylexn[i]] = dylexi[i];
}
}

public SubInfo(string name, DynBlockDelegate code) :
this(name, null, code, null, null, new int[0], null) { }
this(name, null, code, null, null, new int[0], null, null, null) { }
}

// We need hashy frames available to properly handle BEGIN; for the time
Expand Down Expand Up @@ -359,16 +366,42 @@ public class Frame: IP6 {
return "";
}

public void SetDynamic(int ix, object v) {
switch(ix) {
case 0: lex0 = v; break;
case 1: lex1 = v; break;
case 2: lex2 = v; break;
case 3: lex3 = v; break;
default: lexn[ix-4] = v; break;
}
}

public bool TryGetDynamic(string name, out object v) {
v = null;
if (lex == null && info.dylex == null)
return false;
if (lex != null && lex.TryGetValue(name, out v))
return true;
int ix;
if (info.dylex == null || !info.dylex.TryGetValue(name, out ix))
return false;
switch(ix) {
case 0: v = lex0; break;
case 1: v = lex1; break;
case 2: v = lex2; break;
case 3: v = lex3; break;
default: v = lexn[ix-4]; break;
}
return true;
}

public Variable LexicalFind(string name) {
Frame csr = this;
while (csr != null) {
object o;
if (csr.lex == null) {
csr = csr.outer;
continue;
}
if (csr.lex.TryGetValue(name, out o))
if (csr.TryGetDynamic(name, out o)) {
return (Variable)o;
}
csr = csr.outer;
}
return Kernel.NewROScalar(Kernel.AnyP);
Expand Down Expand Up @@ -759,7 +792,7 @@ public class Kernel {

public static Frame Take(Frame th, Variable payload) {
Frame r = TakeReturnStack.Pop();
r.lex["$*nextframe"] = NewROScalar(th);
r.SetDynamic(r.info.dylex["$*nextframe"], NewROScalar(th));
r.resultSlot = payload;
th.resultSlot = payload;
return r;
Expand Down Expand Up @@ -1079,8 +1112,7 @@ public class Kernel {
public static Variable ContextHelper(Frame th, string name, int up) {
object rt;
while (th != null) {
if (up <= 0 && th.lex != null &&
th.lex.TryGetValue(name, out rt)) {
if (up <= 0 && th.TryGetDynamic(name, out rt)) {
return (Variable)rt;
}
th = th.caller;
Expand Down
33 changes: 15 additions & 18 deletions src/CSharpBackend.pm
Expand Up @@ -360,16 +360,12 @@ sub access_lex {
if ($bp->run_once && !dynname($name)) {
return $set_to ? CgOp::rawsset($lex->{peer}, $set_to) :
CgOp::rawsget($lex->{peer});
} elsif ((my $ix = $lex->{peer}) >= 0) {
} else {
my $ix = $lex->{peer};
return $set_to ?
CgOp->new(op => [ rtpadputi => $order, $ix ],
zyg => [ $set_to ]) :
CgOp->new(op => [ rtpadgeti => 'Variable', $order, $ix ]);
} else {
return $set_to ?
CgOp->new(op => [ rtpadput => $order, $name ],
zyg => [ $set_to ]) :
CgOp->new(op => [ rtpadget => 'Variable', $order, $name ]);
}
} elsif ($lex->isa('Metamodel::Lexical::Stash')) {
die "cannot rebind stashes" if $set_to;
Expand Down Expand Up @@ -422,6 +418,14 @@ sub codegen_sub {
# (it's in a sucky format anyway), so this is safe, and it makes dumps
# much smaller.
my $code = delete $_->{code};
my @dynames;
my @dyixes;
for my $ln (sort keys %{ $_->lexicals }) {
next unless dynname($ln);
push @dynames, $ln;
push @dyixes, $_->lexicals->{$ln}{peer};
}

# TODO: Bind a return value here to catch non-ro sub use
if ($_->gather_hack) {
$ops = CgOp::prog(@enter, CgOp::sink($code->cgop($_)),
Expand Down Expand Up @@ -477,7 +481,7 @@ sub codegen_sub {
resolve_lex($_, $ops);
CodeGen->new(csname => $_->{peer}{cbase}, name => ($_->name eq 'ANON' ?
$_->{peer}{cbase} : $_->name), ops => $ops,
usednamed => $_->{peer}{uname}, minlets => $_->{peer}{nlexn});
dynames => \@dynames, dyixes => \@dyixes, minlets => $_->{peer}{nlexn});
}

sub dynname { $_[0] =~ /^.?[*?]/ }
Expand All @@ -495,7 +499,7 @@ sub sub0 {
if $_->spad_exists;
@$node{'cref','cbase'} = gsym('DynBlockDelegate', $_->name . 'C');

my ($nlexn, $uname) = (0,0);
my ($nlexn) = (0);

for my $ln (sort keys %{ $_->lexicals }) {
my $lx = $_->lexicals->{$ln};
Expand All @@ -507,18 +511,15 @@ sub sub0 {

if ($lx->isa('Metamodel::Lexical::SubDef') ||
$lx->isa('Metamodel::Lexical::Simple')) {
if (dynname($ln)) {
$lx->{peer} = -1;
$uname = 1;
} elsif ($_->run_once) {
if ($_->run_once && !dynname($ln)) {
push @decls, ($lx->{peer} = gsym('Variable', $ln));
} else {
$lx->{peer} = ($nlexn++);
}
}
}

@$node{'nlexn', 'uname'} = ($nlexn, $uname);
@$node{'nlexn'} = ($nlexn);
}

sub sub1 {
Expand Down Expand Up @@ -586,13 +587,9 @@ sub protolset {
push @thaw, CgOp::setindex(CgOp::int($ix - 4),
CgOp::getfield('lexn', CgOp::rawsget($body->{peer}{pp})),
$frag);
} elsif ($ix >= 0) {
} else {
push @thaw, CgOp::setfield("lex$ix",
CgOp::rawsget($body->{peer}{pp}), $frag);
} else {
push @thaw, CgOp::setindex($lname,
CgOp::getfield('lex', CgOp::rawsget($body->{peer}{pp})),
$frag);
}
}

Expand Down
20 changes: 9 additions & 11 deletions src/CodeGen.pm
Expand Up @@ -14,6 +14,8 @@ use CLRTypes;
has csname => (isa => 'Str', is => 'ro');
has minlets => (isa => 'Int', is => 'ro', default => 0);
has usednamed => (isa => 'Bool', is => 'ro', default => 0);
has dynames => (isa => 'ArrayRef[Str]', is => 'ro', default => sub{[]});
has dyixes => (isa => 'ArrayRef[Int]', is => 'ro', default => sub{[]});

has numlabels => (isa => 'Int', is => 'rw', default => 1);
has numips => (isa => 'Int', is => 'rw', default => 1);
Expand Down Expand Up @@ -205,16 +207,6 @@ use CLRTypes;
$self->cast($type, "object", "$data.hints[" . qm($name) . "]");
}

sub rtpadget {
my ($self, $type, $order, $name) = @_;
$self->cast($type, "object", "th" . (".outer" x $order) . ".lex[" . qm($name) . "]");
}

sub rtpadput {
my ($self, $order, $name, $ty, $val) = @_;
$self->_emit("th" . (".outer" x $order) . ".lex[" . qm($name) . "] = $val");
}

sub rtpadgeti {
my ($self, $type, $order, $name) = @_;
my $tag = $name < 4 ? "lex$name" : ("lexn[" . ($name - 4) . "]");
Expand Down Expand Up @@ -464,7 +456,13 @@ use CLRTypes;
CgOp::rawnewarr('int', map { CgOp::int($_) } @{ $self->ehspans }),
(@{ $self->ehlabels } ? CgOp::rawnewarr('str',
map { CgOp::clr_string($_) } @{ $self->ehlabels }) :
CgOp::null('clr:string[]')));
CgOp::null('clr:string[]')),
(@{ $self->dynames } ? (
CgOp::rawnewarr('str', map { CgOp::clr_string($_) } @{ $self->dynames }),
CgOp::rawnewarr('int', map { CgOp::int($_) } @{ $self->dyixes })
) : (
CgOp::null('clr:string[]'),
CgOp::null('clr:int[]'))));
}

sub csharp {
Expand Down

0 comments on commit ccbb9b8

Please sign in to comment.