Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Reimplement $?FOO in new metamodel
  • Loading branch information
sorear committed Dec 28, 2010
1 parent c2857c1 commit 711b4c6
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 37 deletions.
65 changes: 54 additions & 11 deletions lib/CLRBackend.cs
Expand Up @@ -58,6 +58,7 @@ sealed class JScalar {
throw new ArgumentException(s);
}
public static int I(object x) { return (int)((JScalar)x).num; }
public static int IN(object x) { return x == null ? -1 : (int)((JScalar)x).num; }
public static string S(object x) { return x == null ? null : ((JScalar)x).str; }
public override string ToString() { return text; }
}
Expand Down Expand Up @@ -457,6 +458,7 @@ class StaticSub {
public readonly int[] zyg;
public readonly Xref parametric_role_hack;
public readonly object augment_hack;
public readonly object[] hint_hack;
public readonly int is_phaser;
public readonly Xref body_of;
public readonly Xref in_class;
Expand All @@ -482,17 +484,18 @@ class StaticSub {
zyg = JScalar.IA(0, s[4]);
parametric_role_hack = Xref.from(s[5]);
augment_hack = s[6];
is_phaser = s[7] == null ? -1 : (int) ((JScalar) s[7]).num;
body_of = Xref.from(s[8]);
in_class = Xref.from(s[9]);
cur_pkg = JScalar.SA(0, s[10]);
sclass = JScalar.S(s[11]);
ltm = s[12];
exports = (object[]) s[13];
sig = s[14];

object[] r_lexicals = s[15] as object[];
body = s[16];
hint_hack = s[7] as object[];
is_phaser = JScalar.IN(s[8]);
body_of = Xref.from(s[9]);
in_class = Xref.from(s[10]);
cur_pkg = JScalar.SA(0, s[11]);
sclass = JScalar.S(s[12]);
ltm = s[13];
exports = (object[]) s[14];
sig = s[15];

object[] r_lexicals = s[16] as object[];
body = s[17];
lexicals = new List<KeyValuePair<string,Lexical>>();
l_lexicals = new Dictionary<string,Lexical>();
for (int i = 0; i < r_lexicals.Length; i++) {
Expand All @@ -505,6 +508,8 @@ class StaticSub {
obj = new LexSimple(bl);
} else if (type == "common") {
obj = new LexCommon(bl);
} else if (type == "hint") {
obj = new LexHint(bl);
} else if (type == "sub") {
obj = new LexSub(bl);
} else if (type == "alias") {
Expand Down Expand Up @@ -603,6 +608,19 @@ class LexSimple : LexVarish {
}
}

class LexHint : Lexical {
public FieldInfo stg;
public LexHint(object[] l) {}
public override ClrOp GetCode(int up) {
return new ClrGetField(Tokens.BValue_v,
new ClrGetSField(stg));
}
public override void BindFields(int six, int lix, StaticSub sub,
string name, Func<string,Type,FieldInfo> binder) {
stg = binder(Unit.SharedName('B', six, name), Tokens.BValue);
}
}

class LexCommon : Lexical {
public readonly string[] path;
public FieldInfo stg;
Expand Down Expand Up @@ -862,6 +880,8 @@ sealed class Tokens {
IP6.GetMethod("SetSlot");
public static readonly MethodInfo IP6_GetSlot =
IP6.GetMethod("GetSlot");
public static readonly MethodInfo SubInfo_AddHint =
SubInfo.GetMethod("AddHint");
public static readonly MethodInfo Variable_Fetch =
Variable.GetMethod("Fetch");
public static readonly MethodInfo VVarList_Item =
Expand All @@ -888,6 +908,8 @@ sealed class Tokens {
typeof(Kernel).GetMethod("NewRWListVar");
public static readonly MethodInfo Kernel_NewRWScalar =
typeof(Kernel).GetMethod("NewRWScalar");
public static readonly MethodInfo Kernel_Decontainerize =
typeof(Kernel).GetMethod("Decontainerize");
public static readonly MethodInfo Kernel_NewBoundVar =
typeof(Kernel).GetMethod("NewBoundVar");
public static readonly MethodInfo Kernel_IterHasFlat =
Expand Down Expand Up @@ -2685,6 +2707,13 @@ class NamProcessor {
return th.SubyCall(true, zyg); };
handlers["subcall"] = delegate (NamProcessor th, object[] zyg) {
return th.SubyCall(false, zyg); };
handlers["_hintset"] = delegate (NamProcessor th, object[] zyg) {
int d;
Lexical lx = th.ResolveLex(JScalar.S(zyg[1]), out d, false);
FieldInfo peer = (lx is LexCommon) ? ((LexCommon)lx).stg :
((LexHint)lx).stg;
return CpsOp.SetField(Tokens.BValue_v, CpsOp.GetSField(peer),
CpsOp.MethodCall(null, Tokens.Kernel_Decontainerize, new CpsOp[] { th.Scan(zyg[2]) })); };
handlers["letn"] = delegate(NamProcessor th, object[] zyg) {
int i = 1;
Dictionary<string,Type> old =
Expand Down Expand Up @@ -3273,6 +3302,12 @@ class NamProcessor {
new object[] { new JScalar("corelex"), new JScalar("EMPTY") } } });
enter.Add(new object[] { new JScalar("return") });
b = enter.ToArray();
} else if (sub.hint_hack != null) {
enter.Insert(0, new JScalar("prog"));
enter.Add(new object[] { new JScalar("_hintset"),
sub.hint_hack[1], b });
enter.Add(new object[] { new JScalar("return") });
b = enter.ToArray();
} else if (sub.augment_hack != null) {
enter = new List<object>();
object[] tuples = (object[]) sub.augment_hack;
Expand Down Expand Up @@ -3609,6 +3644,12 @@ public class CLRBackend {
thaw.Add(CpsOp.SetSField(lx.stg,
CpsOp.MethodCall(null, Tokens.Kernel_GetVar, new CpsOp[] {
CpsOp.StringArray(false, lx.path) })));
} else if (l.Value is LexHint) {
LexHint lx = (LexHint)l.Value;
thaw.Add(CpsOp.SetSField(lx.stg,
CpsOp.MethodCall(null, Tokens.SubInfo_AddHint,
new CpsOp[] { CpsOp.GetSField(obj.subinfo),
CpsOp.StringLiteral(l.Key) })));
} else if (l.Value is LexSub) {
LexSub lx = (LexSub)l.Value;
if ((obj.flags & StaticSub.SPAD_EXISTS) == 0) continue;
Expand Down Expand Up @@ -3636,6 +3677,8 @@ public class CLRBackend {
}
});

thaw.Add(CpsOp.MethodCall(null, Tokens.Kernel_FirePhasers,
new CpsOp[] { CpsOp.IntLiteral(2), CpsOp.BoolLiteral(false) }));
if (asmain)
thaw.Add(CpsOp.MethodCall(null, Tokens.Kernel_FirePhasers,
new CpsOp[] { CpsOp.IntLiteral(0), CpsOp.BoolLiteral(false) }));
Expand Down
53 changes: 32 additions & 21 deletions lib/Kernel.cs
Expand Up @@ -219,7 +219,7 @@ public class SubInfo {
// for inheriting hints
public SubInfo outer;
public string name;
public Dictionary<string, object> hints;
public Dictionary<string, BValue> hints;
// maybe should be a hint
public LAD ltm;
public int nspill;
Expand Down Expand Up @@ -453,21 +453,22 @@ public class SubInfo {
return th;
}

public void PutHint(string name, object val) {
public BValue AddHint(string name) {
if (hints == null)
hints = new Dictionary<string,object>();
hints[name] = val;
hints = new Dictionary<string,BValue>();
return hints[name] = new BValue(Kernel.NewROScalar(Kernel.AnyP));
}

public bool GetLocalHint<T>(string name, out T val) where T: class {
object o;
if (hints != null && hints.TryGetValue(name, out o)) {
val = o as T;
return true;
} else {
val = null;
return false;
}
public bool GetLocalHint(string name, out BValue val) {
return (hints != null && hints.TryGetValue(name, out val));
}

public bool GetHint(string name, out BValue val) {
for (SubInfo s = this; s != null; s = s.outer)
if (s.GetLocalHint(name, out val))
return true;
val = null;
return false;
}

public static uint FilterForName(string name) {
Expand Down Expand Up @@ -622,14 +623,10 @@ public class Frame: IP6 {
}

public string ExecutingFile() {
string l;
BValue l;
SubInfo i = info;
while (i != null) {
// possibly, using $?FILE and Fetch would be better
if (i.GetLocalHint("?file", out l))
return l;
i = i.outer;
}
if (i.GetHint("$?FILE", out l))
return l.v.Fetch().mo.mro_raw_Str.Get(l.v);
return "";
}

Expand Down Expand Up @@ -676,6 +673,13 @@ public class Frame: IP6 {

public Variable LexicalFind(string name) {
Frame csr = this;
if (name.Length >= 2 && name[1] == '?') {
BValue b;
if (info.GetHint(name, out b))
return b.v;
else
return Kernel.NewROScalar(Kernel.AnyP);
}
uint m = SubInfo.FilterForName(name);
while (csr != null) {
object o;
Expand Down Expand Up @@ -1546,6 +1550,12 @@ public class Kernel {
w.Do(v);
}

public static Variable Decontainerize(Variable rhs) {
if (!rhs.rw) return rhs;
IP6 v = rhs.Fetch();
return new SimpleVariable(false, rhs.islist, v.mo, null, v);
}

public static Frame NewBoundVar(Frame th, bool ro, bool islist,
DynMetaObject type, Variable rhs) {
if (islist) ro = true;
Expand Down Expand Up @@ -2144,7 +2154,8 @@ class LastFrameNode {
public static IP6 ProcessO;

static Kernel() {
PhaserBanks = new VarDeque[] { new VarDeque(), new VarDeque() };
PhaserBanks = new VarDeque[] { new VarDeque(), new VarDeque(),
new VarDeque() };

BoolMO = new DynMetaObject("Bool");
BoolMO.loc_Bool = new CtxReturnSelf();
Expand Down
40 changes: 38 additions & 2 deletions src/Metamodel.pm
Expand Up @@ -492,6 +492,17 @@ our %units;
__PACKAGE__->meta->make_immutable;
}

# These are used for $?foo et al, and should be inaccessible until assigned,
# although the current code won't enforce that well.
{
package Metamodel::Lexical::Hint;
use Moose;
extends 'Metamodel::Lexical';

no Moose;
__PACKAGE__->meta->make_immutable;
}

# our...
{
package Metamodel::Lexical::Common;
Expand Down Expand Up @@ -578,6 +589,8 @@ our %units;
has parametric_role_hack => (isa => 'Maybe[ArrayRef]', is => 'rw');
# some tuples for method definitions; munged into a phaser
has augment_hack => (isa => 'Maybe[ArrayRef]', is => 'rw');
# emit code to assign to a hint; [ $subref, $name ]
has hint_hack => (isa => 'Maybe[ArrayRef]', is => 'rw');
has is_phaser => (isa => 'Maybe[Int]', is => 'rw', default => undef);
has strong_used => (isa => 'Bool', is => 'rw', default => 0);
has body_of => (isa => 'Maybe[ArrayRef]', is => 'ro');
Expand Down Expand Up @@ -667,6 +680,10 @@ our %units;
$self->lexicals->{$slot} = Metamodel::Lexical::Simple->new(@ops);
}

sub add_hint { my ($self, $slot) = @_;
$self->lexicals->{$slot} = Metamodel::Lexical::Hint->new;
}

sub add_common_name { my ($self, $slot, $path, $name) = @_;
$unit->create_stash(@$path);
$self->lexicals->{$slot} = Metamodel::Lexical::Common->new(
Expand Down Expand Up @@ -838,6 +855,8 @@ sub Unit::begin {
$unit;
}

my %type2phaser = ( init => 0, end => 1, begin => 2 );

sub Body::begin {
my $self = shift;
my %args = @_;
Expand All @@ -859,7 +878,7 @@ sub Body::begin {
returnable => $self->returnable,
gather_hack=> $args{gather_hack},
augment_hack=> $args{augment_hack},
is_phaser => ($type eq 'init' ? 0 : $type eq 'end' ? 1 : undef),
is_phaser => $type2phaser{$type},
class => $self->class,
ltm => $self->ltm,
run_once => $args{once} && (!@opensubs || $rtop->run_once));
Expand Down Expand Up @@ -990,8 +1009,25 @@ sub Op::ConstantDecl::begin {
$opensubs[-1]->add_common_name($self->name,
$opensubs[-1]->find_pkg($self->path), $self->name);
} else {
$opensubs[-1]->add_my_name($self->name);
$opensubs[-1]->add_hint($self->name);
}

if (!$self->init) {
die "Malformed constant decl";
}

my $nb = Metamodel::StaticSub->new(
unit => $unit,
outer => $opensubs[-1]->xref,
name => $self->name,
cur_pkg => $opensubs[-1]->cur_pkg,
class => 'Sub',
run_once => 0,
is_phaser => 2,
hint_hack => [ $opensubs[-1]->xref, $self->name ],
code => $self->init);
$opensubs[-1]->create_static_pad; # for protosub instance
$opensubs[-1]->add_child($nb);
}

sub Op::PackageVar::begin {
Expand Down
2 changes: 2 additions & 0 deletions src/NAMBackend.pm
Expand Up @@ -67,6 +67,7 @@ sub Metamodel::StaticSub::to_nam {
[ map { $_->xref->[1] } @{ $self->zyg } ],
$self->parametric_role_hack,
$self->augment_hack,
$self->hint_hack,
$self->is_phaser,
$self->body_of,
$self->in_class,
Expand Down Expand Up @@ -156,6 +157,7 @@ sub Metamodel::Lexical::Simple::to_nam {
}
sub Metamodel::Lexical::Common::to_nam { ['common', @{$_[0]->path}, $_[0]->name ] }
sub Metamodel::Lexical::Alias::to_nam { ['alias', $_[0]->to] }
sub Metamodel::Lexical::Hint::to_nam { ['hint'] }
sub Metamodel::Lexical::SubDef::to_nam { ['sub', @{ $_[0]->body->xref } ] }
sub Metamodel::Lexical::Stash::to_nam { ['stash', @{ $_[0]->path } ] }

Expand Down
7 changes: 5 additions & 2 deletions src/Niecza/Actions.pm
Expand Up @@ -2806,8 +2806,11 @@ sub statement_prefix__S_INIT { my ($cl, $M) = @_;
$M->{_ast} = Op::VoidPhaser->new(node($M), body => $M->{blast}{_ast});
}
# XXX 'As soon as possible' isn't quite soon enough here
*statement_prefix__S_CHECK = *statement_prefix__S_INIT;
*statement_prefix__S_BEGIN = *statement_prefix__S_INIT;
sub statement_prefix__S_BEGIN { my ($cl, $M) = @_;
$M->{blast}{_ast}->type('begin');
$M->{_ast} = Op::VoidPhaser->new(node($M), body => $M->{blast}{_ast});
}
*statement_prefix__S_CHECK = *statement_prefix__S_BEGIN;

sub statement_prefix__S_END { my ($cl, $M) = @_;
$M->{blast}{_ast}->type('end');
Expand Down
2 changes: 1 addition & 1 deletion src/Op.pm
Expand Up @@ -980,7 +980,7 @@ use CgOp;

sub code {
my ($self, $body) = @_;
CgOp::rnull(CgOp::scopedlex($self->name, $self->init->cgop($body)));
CgOp::scopedlex($self->name);
}

__PACKAGE__->meta->make_immutable;
Expand Down

0 comments on commit 711b4c6

Please sign in to comment.