Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Implement typed variables (low level)
  • Loading branch information
sorear committed Oct 5, 2010
1 parent eeab430 commit 36ef3b7
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 27 deletions.
8 changes: 4 additions & 4 deletions lib/Cursor.cs
Expand Up @@ -286,8 +286,8 @@ public sealed class RxFrame {
VarDeque ks = new VarDeque();
ks.Push(Kernel.NewROScalar(m));
DynObject it = new DynObject(GatherIteratorMO);
it.slots[0 /*frame*/] = Kernel.NewRWScalar(th);
it.slots[1 /*reify*/] = Kernel.NewRWScalar(Kernel.AnyP);
it.slots[0 /*frame*/] = Kernel.NewRWScalar(Kernel.AnyMO, th);
it.slots[1 /*reify*/] = Kernel.NewRWScalar(Kernel.AnyMO, Kernel.AnyP);
VarDeque iss = new VarDeque();
iss.Push(Kernel.NewROScalar(it));
DynObject lst = new DynObject(ListMO);
Expand Down Expand Up @@ -367,7 +367,7 @@ public Cursor(IP6 proto, string text)
if (it.cap == null) {
list = true;
} else {
caps.Unshift(Kernel.NewRWScalar(it.cap));
caps.Unshift(Kernel.NewRWScalar(Kernel.AnyMO, it.cap));
}
no:
it = it.prev;
Expand All @@ -381,7 +381,7 @@ public Cursor(IP6 proto, string text)
return Kernel.NewRWListVar(l);
} else {
return caps.Count() != 0 ? caps[0] :
Kernel.NewRWScalar(Kernel.AnyP);
Kernel.NewRWScalar(Kernel.AnyMO, Kernel.AnyP);
}
}

Expand Down
46 changes: 32 additions & 14 deletions lib/Kernel.cs
Expand Up @@ -84,11 +84,14 @@ public abstract class IP6 {
// A Variable is the meaning of function arguments, of any subexpression
// except the targets of := and ::=.

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public abstract class Variable : IP6 {
public IP6 whence;

// these should be treated as ro for the life of the variable
public DynMetaObject type;
public bool rw;
public bool islist;
public IP6 whence;

public abstract IP6 Fetch();
public abstract void Store(IP6 v);
Expand All @@ -103,15 +106,18 @@ public abstract class Variable : IP6 {
public sealed class SimpleVariable: Variable {
IP6 val;

public SimpleVariable(bool rw, bool islist, IP6 whence, IP6 val) {
public SimpleVariable(bool rw, bool islist, DynMetaObject type, IP6 whence, IP6 val) {
this.val = val; this.whence = whence; this.rw = rw;
this.islist = islist;
this.islist = islist; this.type = type;
}

public override IP6 Fetch() { return val; }
public override void Store(IP6 v) {
if (!rw) {
throw new InvalidOperationException("Writing to readonly scalar");
throw new NieczaException("Writing to readonly scalar");
}
if (!v.Isa(type)) {
throw new NieczaException("Nominal type check failed for scalar store; got " + v.GetMO().name + ", needed " + type.name + " or subtype");
}
val = v;
}
Expand Down Expand Up @@ -769,12 +775,14 @@ public class Kernel {
}

public static Frame NewBoundVar(Frame th, bool ro, bool islist,
Variable rhs) {
DynMetaObject type, Variable rhs) {
Frame n;
if (islist) ro = true;
if (!rhs.rw) ro = true;
// fast path
if (ro == !rhs.rw && islist == rhs.islist && rhs.whence == null) {
if (!rhs.type.HasMRO(type))
return Kernel.Die(th, "Nominal type check failed in binding; got " + rhs.type.name + ", needed " + type.name);
th.resultSlot = rhs;
return th;
}
Expand All @@ -783,17 +791,25 @@ public class Kernel {
// whence != null (and rhs.rw = true)

if (!rhs.rw) {
th.resultSlot = new SimpleVariable(false, islist, null,
rhs.Fetch());
IP6 v = rhs.Fetch();
if (!v.Isa(type))
return Kernel.Die(th, "Nominal type check failed in binding; got " + v.GetMO().name + ", needed " + type.name);
th.resultSlot = new SimpleVariable(false, islist, v.GetMO(), null, v);
return th;
}
// ro = true and rhw.rw = true OR
// whence != null
if (ro) {
th.resultSlot = new SimpleVariable(false, islist, null, rhs.Fetch());
IP6 v = rhs.Fetch();
if (!v.Isa(type))
return Kernel.Die(th, "Nominal type check failed in binding; got " + v.GetMO().name + ", needed " + type.name);
th.resultSlot = new SimpleVariable(false, islist, v.GetMO(), null, rhs.Fetch());
return th;
}

if (!rhs.type.HasMRO(type))
return Kernel.Die(th, "Nominal type check failed in binding; got " + rhs.type.name + ", needed " + type.name);

th.resultSlot = rhs;

n = th.MakeChild(null, BindSI);
Expand Down Expand Up @@ -842,15 +858,16 @@ public class Kernel {

// ro, not rebindable
public static Variable NewROScalar(IP6 obj) {
return new SimpleVariable(false, false, null, obj);
return new SimpleVariable(false, false, obj.GetMO(), null, obj);
}

public static Variable NewRWScalar(IP6 obj) {
return new SimpleVariable(true, false, null, obj);
public static Variable NewRWScalar(DynMetaObject t, IP6 obj) {
return new SimpleVariable(true, false, t, null, obj);
}

public static Variable NewRWListVar(IP6 container) {
return new SimpleVariable(false, true, null, container);
return new SimpleVariable(false, true, container.GetMO(), null,
container);
}

public static VarDeque SlurpyHelper(Frame th, int from) {
Expand Down Expand Up @@ -891,7 +908,7 @@ public class Kernel {

for (int i = mro.Length - 1; i >= 0; i--) {
foreach (string s in mro[i].local_attr) {
n.SetSlot(s, NewRWScalar(AnyP));
n.SetSlot(s, NewRWScalar(AnyMO, AnyP));
}
}

Expand All @@ -912,6 +929,7 @@ public class Kernel {
NewROScalar(lst) }, null);
}

public static DynMetaObject AnyMO;
public static IP6 AnyP;
public static IP6 ArrayP;
public static IP6 HashP;
Expand All @@ -933,7 +951,7 @@ public class Kernel {
StashP)));
} else {
// TODO: @foo, %foo
return (stash[name] = new BValue(NewRWScalar(AnyP)));
return (stash[name] = new BValue(NewRWScalar(AnyMO, AnyP)));
}
}

Expand Down
1 change: 1 addition & 0 deletions src/CLRTypes.pm
Expand Up @@ -131,6 +131,7 @@ my %typedata = (
'System.Environment.Exit' => [m => 'Void'],
'String.Concat' => [m => 'String'],
'Kernel.AnyP' => [f => 'IP6'],
'Kernel.AnyMO' => [f => 'DynMetaObject'],
'Kernel.ArrayP' => [f => 'IP6'],
'Kernel.HashP' => [f => 'IP6'],
'Kernel.StashP', => [f => 'IP6'],
Expand Down
4 changes: 3 additions & 1 deletion src/CSharpBackend.pm
Expand Up @@ -133,6 +133,7 @@ sub stash2 {

# xxx check for SAFE::
my %loopbacks = (
'MAny', 'Kernel.AnyMO',
'MCallFrame', 'Kernel.CallFrameMO',
'MGatherIterator', 'RxFrame.GatherIteratorMO',
'MList', 'RxFrame.ListMO',
Expand Down Expand Up @@ -350,7 +351,8 @@ sub codegen_sub {

local %haslet;
resolve_lex($_, $ops);
CodeGen->new(csname => $_->{peer}{cbase}, name => $_->name, ops => $ops,
CodeGen->new(csname => $_->{peer}{cbase}, name => ($_->name eq 'ANON' ?
$_->{peer}{cbase} : $_->name), ops => $ops,
usednamed => $_->{peer}{uname}, minlets => $_->{peer}{nlexn});
}

Expand Down
10 changes: 6 additions & 4 deletions src/CgOp.pm
Expand Up @@ -76,10 +76,12 @@ use warnings;
}

sub newblankrwscalar {
rawscall('Kernel.NewRWScalar', rawsget('Kernel.AnyP'));
rawscall('Kernel.NewRWScalar', rawsget('Kernel.AnyMO'),
rawsget('Kernel.AnyP'));
}

sub newrwscalar { rawscall('Kernel.NewRWScalar', $_[0]); }
sub newrwscalar { rawscall('Kernel.NewRWScalar', rawsget('Kernel.AnyMO'),
$_[0]); }

sub newrwlistvar { rawscall('Kernel.NewRWListVar', $_[0]); }

Expand Down Expand Up @@ -146,7 +148,7 @@ use warnings;
sub varhash_contains_key { rawcall($_[0], 'ContainsKey', _str($_[1])) }
sub varhash_new { rawnew('varhash') }

sub newgeneralvar { rawnew('clr:SimpleVariable', @_) }
sub newgeneralvar { rawnew('clr:SimpleVariable', $_[0], $_[1], rawsget('Kernel.AnyMO'), $_[2], $_[3]) }

sub num_to_string { rawcall($_[0], 'ToString') }
sub str_length { getfield('Length', $_[0]) }
Expand All @@ -169,7 +171,7 @@ use warnings;

sub newboundvar {
rawscall('Kernel.NewBoundVar', bool($_[0] || $_[1]), bool($_[1]),
$_[2]);
rawsget('Kernel.AnyMO'), $_[2]);
}

sub assign {
Expand Down
8 changes: 4 additions & 4 deletions test.pl
Expand Up @@ -68,17 +68,17 @@
ok (foo) == 42, "can call argless function without parens";
}

ok !Mu, "undefined type objects are false";
ok !Mu.defined, "type objects are undefined";
ok !Cool, "undefined type objects are false";
ok !Cool.defined, "type objects are undefined";
ok "Foo".defined, "strings are defined";
ok !Str.defined, "derived type objects are still undefined";

ok "foo" eq "foo", "equal strings are equal";
ok !("foo" ne "foo"), "equal strings are not not equal";
ok "foo" ne "bar", "unequal strings are unequal";

ok Mu === Mu, "identical objects are identical";
ok !(Mu === Any), "unidentical objects are unidentical";
ok Cool === Cool, "identical objects are identical";
ok !(Cool === Any), "unidentical objects are unidentical";

ok 12 eq "12", "eq stringifies";
ok ("a" ~ "b") eq "ab", "a + b = ab";
Expand Down

0 comments on commit 36ef3b7

Please sign in to comment.