@@ -8,47 +8,69 @@ import polemy._common; import polemy.failure; import polemy.ast; import polemy.layer; +import std.string; /// Runtime values of Polemy abstract class Value { + override bool opEquals(Object rhs) { return 0==opCmp(rhs); } } /// class IntValue : Value { BigInt data; - mixin SimpleClass; - override string toString() const { return std.bigint.toDecimalString(cast(BigInt)data); } + this(int n) { this.data = n; } + this(long n) { this.data = n; } + this(BigInt n) { this.data = n; } + this(string n) { this.data = BigInt(n); } + override string toString() const { return toDecimalString(cast(BigInt)data); } + override int opCmp(Object rhs) { + if(auto r = cast(IntValue)rhs) return data.opCmp(r.data); + if(auto r = cast(Value)rhs) return typeid(this).opCmp(typeid(r)); + throw genex!RuntimeException(LexPosition.dummy, "comparison with value and somithing other"); + } + mixin SimpleToHash; } /// class StrValue : Value { string data; - mixin SimpleClass; + mixin SimpleConstructor; override string toString() const { return data; } + override int opCmp(Object rhs) { + if(auto r = cast(StrValue)rhs) return typeid(string).compare(&data, &r.data); + if(auto r = cast(Value)rhs) return typeid(this).opCmp(typeid(r)); + throw genex!RuntimeException(LexPosition.dummy, "comparison with value and somithing other"); + } + mixin SimpleToHash; } /// -class UndValue : Value +class UndefinedValue : Value { - mixin SimpleClass; + mixin SimpleConstructor; override string toString() const { return ""; } + override int opCmp(Object rhs) { + if(auto r = cast(StrValue)rhs) return 0; + if(auto r = cast(Value)rhs) return typeid(this).opCmp(typeid(r)); + throw genex!RuntimeException(LexPosition.dummy, "comparison with value and somithing other"); + } + mixin SimpleToHash; } - /// abstract class FunValue : Value { const(Parameter[]) params(); Table definitionContext(); - Value invoke(LexPosition pos, Layer lay, Table ctx); + Value invoke(Layer lay, Table ctx, LexPosition pos); } /// Context (variable environment) /// Simlar to prototype chain of ECMAScript etc. @@ -337,13 +359,64 @@ { Table t = new Table; if( pos !is null ) { t.set("filename", ValueLayer, new StrValue(pos.filename)); - t.set("lineno", ValueLayer, new IntValue(BigInt(pos.lineno))); - t.set("column", ValueLayer, new IntValue(BigInt(pos.column))); + t.set("lineno", ValueLayer, new IntValue(pos.lineno)); + t.set("column", ValueLayer, new IntValue(pos.column)); } else { t.set("filename", ValueLayer, new StrValue("nullpos")); - t.set("lineno", ValueLayer, new IntValue(BigInt(0))); - t.set("column", ValueLayer, new IntValue(BigInt(0))); + t.set("lineno", ValueLayer, new IntValue(0)); + t.set("column", ValueLayer, new IntValue(0)); } return t; } + +/// Convert AST to Table so that it can be used in Polemy +/// TODO: generalize to DValue2PolemyValue + +Value ast2table(T)(T e, Value delegate(AST) rec) +{ + assert( typeid(e) == typeid(T) ); + + static if(is(T==BigInt) || is(T==long) || is(T==int)) + return new IntValue(e); + else + static if(is(T==string)) + return new StrValue(e); + else + static if(is(T S : S[])) + { + Table lst = new Table; + foreach_reverse(a; e) + static if(is(S : AST)) + lst = makeCons(rec(a), lst); + else + lst = makeCons(ast2table(a,rec), lst); + return lst; + } + else + static if(is(T : AST)) + { + auto t = new Table; + t.set("pos", ValueLayer, fromPos(e.pos)); + t.set("is" , ValueLayer, new StrValue(typeid(e).name.split(".")[$-1].tolower())); + foreach(i,m; e.tupleof) + static if(is(typeof(m) : AST)) + t.set(e.tupleof[i].stringof[2..$], ValueLayer, rec(m)); + else + t.set(e.tupleof[i].stringof[2..$], ValueLayer, ast2table(m,rec)); + return t; + } + else + static if(is(T == class)) + { + auto t = new Table; + foreach(i,m; e.tupleof) + static if(is(typeof(m) : AST)) + t.set(e.tupleof[i].stringof[2..$], ValueLayer, rec(m)); + else + t.set(e.tupleof[i].stringof[2..$], ValueLayer, ast2table(m,rec)); + return t; + } + else + static assert(false, "unknown type <"~T.stringof~"> during AST encoding"); +}