Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Implement the possibility of metaobject cloning
  • Loading branch information
sorear committed Jul 7, 2010
1 parent 4281ff6 commit af32687
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 33 deletions.
24 changes: 17 additions & 7 deletions CodeGen.pm
Expand Up @@ -8,13 +8,23 @@ use 5.010;

# Beta will do this using reflection
my %typedata = (
DynObject => { klass => 'DynMetaObject',
slots => 'Dictionary<string,Object>' },
DynMetaObject => { how => 'IP6',
local => 'Dictionary<String,DynMetaObject.Method>',
outers => 'List<Frame>',
name => 'String' },
'List<Frame>' => { Add => 'Void' },
DynObject =>
{ klass => 'DynMetaObject',
slots => 'Dictionary<string,Object>' },

DynMetaObject =>
{ proto => 'DynProtoMetaObject',
outers => 'List<Frame>' },

DynProtoMetaObject =>
{ how => 'IP6',
local => 'Dictionary<String,DynMetaObject.Method>',
def_outers => 'List<Frame>',
name => 'String' },

'List<Frame>' =>
{ Add => 'Void' },

'Kernel.NewROVar' => 'Variable',
'Kernel.NewRWVar' => 'Variable',
'Kernel.NewROLValue' => 'LValue',
Expand Down
68 changes: 42 additions & 26 deletions Kernel.cs
Expand Up @@ -110,7 +110,7 @@ public class Frame: IP6 {

// NOT IP6; these things should only be exposed through a ClassHOW-like
// façade
public class DynMetaObject {
public class DynProtoMetaObject {
public struct Method {
public Method(DynBlockDelegate code, Frame proto, int outer_index) {
this.code = code;
Expand All @@ -122,25 +122,34 @@ public struct Method {
public int outer_index;
}

public DynMetaObject[] mro = new DynMetaObject[0] {};
public Dictionary<string, Method> local
= new Dictionary<string, Method>();

public List<Frame> outers = new List<Frame>();

public IP6 how;
public string name;

public InvokeHandler OnInvoke;
public FetchHandler OnFetch;
public StoreHandler OnStore;

//public List<DynMetaObject> mro = new List<DynMetaObject>();
public Dictionary<string, Method> local
= new Dictionary<string, Method>();

public List<Frame> def_outers = new List<Frame>();

public delegate Frame InvokeHandler(DynObject th, Frame c,
LValue[] pos, Dictionary<string, LValue> named);
public delegate Frame FetchHandler(DynObject th, Frame c);
public delegate Frame StoreHandler(DynObject th, Frame c, IP6 n);
}

public class DynMetaObject {
public DynProtoMetaObject proto;
public List<Frame> outers = new List<Frame>();

public DynMetaObject(DynProtoMetaObject proto) {
this.proto = proto;
}
}

// This is quite similar to DynFrame and I wonder if I can unify them.
// These are always hashy for the same reason as Frame above
public class DynObject: IP6 {
Expand All @@ -151,14 +160,17 @@ public class DynObject: IP6 {
public DynMetaObject klass;

private Frame Fail(Frame caller, string msg) {
return Kernel.Die(caller, msg + " in class " + klass.name);
return Kernel.Die(caller, msg + " in class " + klass.proto.name);
}

public Frame InvokeMethod(Frame caller, string name,
LValue[] pos, Dictionary<string, LValue> named) {
DynMetaObject.Method m;
DynProtoMetaObject.Method m;
while (klass.outers.Count < klass.proto.def_outers.Count) {
klass.outers.Add(klass.proto.def_outers[klass.outers.Count]);
}
// TODO MRO
if (klass.local.TryGetValue(name, out m)) {
if (klass.proto.local.TryGetValue(name, out m)) {
Frame n = new Frame(caller, klass.outers[m.outer_index],
m.code);
n.proto = m.proto;
Expand All @@ -180,29 +192,29 @@ public class DynObject: IP6 {
}

public Frame HOW(Frame caller) {
caller.resultSlot = klass.how;
caller.resultSlot = klass.proto.how;
return caller;
}

public Frame Invoke(Frame c, LValue[] p, Dictionary<string, LValue> n) {
if (klass.OnInvoke != null) {
return klass.OnInvoke(this, c, p, n);
if (klass.proto.OnInvoke != null) {
return klass.proto.OnInvoke(this, c, p, n);
} else {
return Fail(c, "No invoke handler set");
}
}

public Frame Fetch(Frame c) {
if (klass.OnFetch != null) {
return klass.OnFetch(this, c);
if (klass.proto.OnFetch != null) {
return klass.proto.OnFetch(this, c);
} else {
return Fail(c, "No fetch handler set");
}
}

public Frame Store(Frame c, IP6 o) {
if (klass.OnStore != null) {
return klass.OnStore(this, c, o);
if (klass.proto.OnStore != null) {
return klass.proto.OnStore(this, c, o);
} else {
return Fail(c, "No store handler set");
}
Expand Down Expand Up @@ -403,18 +415,22 @@ public class Kernel {
}

static Kernel() {
SubMO = new DynMetaObject();
SubMO.name = "Sub";
SubMO.OnInvoke = new DynMetaObject.InvokeHandler(SubInvoke);
SubMO.local["clone"] = new DynMetaObject.Method(
DynProtoMetaObject SubPMO = new DynProtoMetaObject();
SubPMO.name = "Sub";
SubPMO.OnInvoke = new DynProtoMetaObject.InvokeHandler(SubInvoke);
SubPMO.local["clone"] = new DynProtoMetaObject.Method(
new DynBlockDelegate(SubCloneC),
null, 0);
SubMO.outers.Add(null);
SubPMO.def_outers.Add(null);

SubMO = new DynMetaObject(SubPMO);

DynProtoMetaObject ScalarContainerPMO = new DynProtoMetaObject();
ScalarContainerPMO.name = "ScalarContainer";
ScalarContainerPMO.OnFetch = new DynProtoMetaObject.FetchHandler(SCFetch);
ScalarContainerPMO.OnStore = new DynProtoMetaObject.StoreHandler(SCStore);

ScalarContainerMO = new DynMetaObject();
ScalarContainerMO.name = "ScalarContainer";
ScalarContainerMO.OnFetch = new DynMetaObject.FetchHandler(SCFetch);
ScalarContainerMO.OnStore = new DynMetaObject.StoreHandler(SCStore);
ScalarContainerMO = new DynMetaObject(ScalarContainerPMO);

DieSub = MakeSub(new DynBlockDelegate(ThrowC), null, null);
}
Expand Down
1 change: 1 addition & 0 deletions Niecza/Actions.pm
Expand Up @@ -32,6 +32,7 @@ sub comment__S_Sharp { }
sub spacey { }
sub nofun { }
sub curlycheck { }
sub pod_comment { }

sub decint { my ($cl, $M) = @_;
$M->{_ast} = eval $M->Str; # XXX use a real string parser
Expand Down
2 changes: 2 additions & 0 deletions setting
Expand Up @@ -59,6 +59,7 @@
# Foo.^bind-outer($scopenum, callframe);
my class ClassHOW { ... }

=begin comment
PRE-INIT {
sub wrap-metaclass { # $metaclass-mo, $mo
Q:NIL {
Expand Down Expand Up @@ -124,6 +125,7 @@ PRE-INIT {
null:Variable
}
}
=end comment

sub infix:<~> { Q:NIL {
=[0] @ unwrap:String =[1] @ unwrap:String .plaincall/2:String.Concat
Expand Down

0 comments on commit af32687

Please sign in to comment.