Skip to content

Commit

Permalink
Actually implement variable and attribute type constraining
Browse files Browse the repository at this point in the history
  • Loading branch information
sorear committed Mar 8, 2011
1 parent bb8c799 commit 2e201e7
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 14 deletions.
40 changes: 30 additions & 10 deletions lib/CLRBackend.cs
Original file line number Diff line number Diff line change
Expand Up @@ -415,12 +415,14 @@ class Attribute {
public readonly bool publ;
public readonly string ivar;
public readonly Xref ibody;
public readonly Xref type;

public Attribute(object[] x) {
name = JScalar.S(x[0]);
publ = JScalar.B(x[1]);
ivar = JScalar.S(x[2]);
ibody = Xref.from(x[3]);
type = Xref.from(x[4]);
}

public static Attribute[] fromArray(object x) {
Expand Down Expand Up @@ -629,9 +631,11 @@ class LexSimple : LexVarish {
public const int LIST = 2;
public const int HASH = 1;
public readonly int flags;
public readonly Xref type;

public LexSimple(object[] l) {
flags = JScalar.I(l[2]);
type = Xref.from(l[3]);
}
}

Expand Down Expand Up @@ -942,6 +946,8 @@ private static Dictionary<string,ConstructorInfo> _LADctors() {
typeof(Kernel).GetMethod("NewRWListVar");
public static readonly MethodInfo Kernel_NewRWScalar =
typeof(Kernel).GetMethod("NewRWScalar");
public static readonly MethodInfo Kernel_NewTypedScalar =
typeof(Kernel).GetMethod("NewTypedScalar");
public static readonly MethodInfo Kernel_Decontainerize =
typeof(Kernel).GetMethod("Decontainerize");
public static readonly MethodInfo Kernel_NewBoundVar =
Expand Down Expand Up @@ -2897,10 +2903,12 @@ static NamProcessor() {
new CpsOp[] { CpsOp.Operator(Tokens.IntPtr, OpCodes.Ldlen,
z) });
};
handlers["_newoftype"] = delegate(NamProcessor th, object[] z) {
return CpsOp.MethodCall(null, Tokens.Kernel_NewTypedScalar,
new CpsOp[] { CpsOp.GetSField((FieldInfo)z[1]) }); };
thandlers["newblankrwscalar"] = delegate(CpsOp[] z) {
return CpsOp.MethodCall(null, Tokens.Kernel_NewRWScalar,
new CpsOp[] { CpsOp.GetSField(Tokens.Kernel_AnyMO),
CpsOp.GetSField(Tokens.Kernel_AnyP) }); };
return CpsOp.MethodCall(null, Tokens.Kernel_NewTypedScalar,
new CpsOp[] { CpsOp.GetSField(Tokens.Kernel_AnyMO) }); };
// XXX - wrong order - problem?
thandlers["fvarlist_item"] = delegate(CpsOp[] z) {
return CpsOp.Operator(Tokens.Variable, OpCodes.Ldelem_Ref,
Expand Down Expand Up @@ -3392,18 +3400,22 @@ void EnterCode(List<object> frags) {
new object[] { new JScalar("_makesub"),
ls.def.Resolve<StaticSub>() } } });
} else if (kv.Value is LexSimple) {
int f = ((LexSimple) kv.Value).flags;
LexSimple ls = kv.Value as LexSimple;
int f = ls.flags;
if ((f & LexSimple.NOINIT) != 0) continue;

object bit;
FieldInfo tc = ls.type == null ?
Tokens.Kernel_AnyMO :
ls.type.Resolve<Class>().metaObject;
if ((f & (LexSimple.HASH | LexSimple.LIST)) != 0) {
string s = ((f & LexSimple.HASH) != 0) ? "Hash" : "Array";
bit = new object[] { new JScalar("methodcall"),
new JScalar("new"), new JScalar(""),
new object[] { new JScalar("fetch"), new object[] { new JScalar("corelex"), new JScalar(s) } },
new object[] { new JScalar("corelex"), new JScalar(s) } };
} else {
bit = new object[] { new JScalar("newblankrwscalar") };
bit = new object[] { new JScalar("_newoftype"), tc };
}
frags.Add(new object[] { new JScalar("scopedlex"),
new JScalar(kv.Key), bit });
Expand Down Expand Up @@ -3447,8 +3459,11 @@ CpsOp FillParamRole() {
CpsOp publ = CpsOp.BoolLiteral(a.publ);
CpsOp init = a.ivar == null ? CpsOp.Null(Tokens.P6any) :
RawAccessLex("scopedlex", a.ivar, null);
CpsOp type = a.type == null ?
CpsOp.GetSField(Tokens.Kernel_AnyMO) :
CpsOp.GetSField(a.type.Resolve<Class>().metaObject);
build.Add(CpsOp.MethodCall(null, Tokens.DMO_AddAttribute,
new CpsOp[] { mo, name, publ, init }));
new CpsOp[] { mo, name, publ, init, type }));
}

build.Add(CpsOp.MethodCall(null, Tokens.DMO_Invalidate, new CpsOp[] { mo }));
Expand Down Expand Up @@ -3797,10 +3812,13 @@ void Process(Unit unit, bool asmain) {
foreach (Attribute a in attrs) {
CpsOp init = a.ibody == null ? CpsOp.Null(Tokens.P6any) :
CpsOp.GetSField(a.ibody.Resolve<StaticSub>().protosub);
CpsOp type = a.type == null ?
CpsOp.GetSField(Tokens.Kernel_AnyMO) :
CpsOp.GetSField(a.type.Resolve<Class>().metaObject);
thaw.Add(CpsOp.MethodCall(null, Tokens.DMO_AddAttribute,
new CpsOp[] { CpsOp.GetSField(m.metaObject),
CpsOp.StringLiteral(a.name),
CpsOp.BoolLiteral(a.publ), init }));
CpsOp.BoolLiteral(a.publ), init, type }));
}
thaw.Add(CpsOp.MethodCall(null, Tokens.DMO_Invalidate,
new CpsOp [] { CpsOp.GetSField(m.metaObject) }));
Expand Down Expand Up @@ -3858,10 +3876,12 @@ void Process(Unit unit, bool asmain) {
CpsOp.GetSField(c.typeObject),
CpsOp.GetSField(c.typeVar) }));
} else {
FieldInfo tc = lx.type == null ?
Tokens.Kernel_AnyMO :
lx.type.Resolve<Class>().metaObject;
SetProtolex(obj, l.Key, lx, CpsOp.MethodCall(null,
Tokens.Kernel_NewRWScalar, new CpsOp[] {
CpsOp.GetSField(Tokens.Kernel_AnyMO),
CpsOp.GetSField(Tokens.Kernel_AnyP) }));
Tokens.Kernel_NewTypedScalar, new CpsOp[] {
CpsOp.GetSField(tc) }));
}
}
}
Expand Down
15 changes: 11 additions & 4 deletions lib/Kernel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1130,6 +1130,7 @@ public struct AttrInfo {
public string name;
public P6any init;
public bool publ;
public STable type;
}

public static readonly ContextHandler<Variable> CallStr
Expand Down Expand Up @@ -1366,11 +1367,13 @@ public void AddSubMethod(string name, P6any code) {
submethods[name] = code;
}

public void AddAttribute(string name, bool publ, P6any init) {
public void AddAttribute(string name, bool publ, P6any init,
STable type) {
AttrInfo ai;
ai.name = name;
ai.publ = publ;
ai.init = init;
ai.type = type;
local_attr.Add(ai);
}

Expand Down Expand Up @@ -1712,6 +1715,10 @@ public static Variable NewRWScalar(STable t, P6any obj) {
return new SimpleVariable(true, false, t, null, obj);
}

public static Variable NewTypedScalar(STable t) {
return new SimpleVariable(true, false, t, null, t.typeObject);
}

public static Variable NewRWListVar(P6any container) {
return new SimpleVariable(false, true, container.mo, null,
container);
Expand Down Expand Up @@ -1821,12 +1828,12 @@ public static Variable DefaultNew(P6any proto, VarHash args) {
if (a.publ && args.TryGetValue(a.name, out vx)) {
val = vx.Fetch();
} else if (a.init == null) {
val = AnyP;
val = a.type.typeObject;
} else {
val = RunInferior(a.init.Invoke(GetInferiorRoot(),
Variable.None, null)).Fetch();
}
n.SetSlot(a.name, NewRWScalar(AnyMO, val));
n.SetSlot(a.name, NewRWScalar(a.type, val));
}
}

Expand Down Expand Up @@ -2123,7 +2130,7 @@ private static STable DoRoleApply(STable b,
foreach (KeyValuePair<string, P6any> kv in role.priv)
n.AddPrivateMethod(kv.Key, kv.Value);
foreach (STable.AttrInfo ai in role.local_attr)
n.AddAttribute(ai.name, ai.publ, ai.init);
n.AddAttribute(ai.name, ai.publ, ai.init, ai.type);
foreach (KeyValuePair<string, P6any> kv in role.ord_methods)
n.AddMethod(kv.Key, kv.Value);
n.Invalidate();
Expand Down
18 changes: 18 additions & 0 deletions test2.pl
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,24 @@
eval_dies_ok 'my class A::B { }; B', 'A::B does not install B alias';
}

{
my class K { }
my class L { has Str $.y }

my Str $x;
ok $x === Str, "typed variable initializes to type object";
lives_ok { $x = "pie" }, "can assign correct type";
dies_ok { $x = True }, "cannot assign wrong type";

#my K $z .= new;
#ok ($z.defined && $z ~~ K), 'my K $z .= new syntax works';

my $l = L.new;
ok $l.y === Str, "typed attribute initializes to type object";
lives_ok { $l.y = "pie" }, "can assign correct type";
dies_ok { $l.y = True }, "cannot assign wrong type";
}

#is $?FILE, 'test.pl', '$?FILE works';
#is $?ORIG.substr(0,5), '# vim', '$?ORIG works';

Expand Down

0 comments on commit 2e201e7

Please sign in to comment.