@@ -46,135 +46,9 @@ abstract class FunValue : Value { const(Parameter[]) params(); Table definitionContext(); - Value invoke(in LexPosition pos, Layer lay, Table ctx); -} - -import polemy.eval; // circular... -version = MacroCache; -//version = AutoMemoization; -//version = AutoRerun; - -/// -class UserDefinedFunValue : FunValue -{ - FunLiteral ast; - Table defCtx; - - this(FunLiteral ast, Table defCtx) { this.ast=ast; this.defCtx=defCtx; } - override string toString() const { return sprintf!"(function:%x:%x)"(cast(void*)ast, cast(void*)defCtx); } - override bool opEquals(Object rhs_) const /// member-by-member equality - { - if( auto rhs = cast(typeof(this))rhs_ ) - return this.ast==rhs.ast && this.defCtx==rhs.defCtx; - assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), typeid(rhs_))); - } - override hash_t toHash() const /// member-by-member hash - { - return typeid(this.ast).getHash(&this.ast) + typeid(this.defCtx).getHash(&this.defCtx); - } - override int opCmp(Object rhs_) /// member-by-member compare - { - if( auto rhs = cast(typeof(this))rhs_ ) - { - if(auto i = this.ast.opCmp(rhs.ast)) - return i; - return this.defCtx.opCmp(rhs.defCtx); - } - assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), typeid(rhs_))); - } - - private AST preprocessed_funbody; - private Value[Value[]][Layer] memo; - - override const(Parameter[]) params() { return ast.params; } - override Table definitionContext() { return defCtx; } - override Value invoke(in LexPosition pos, Layer lay, Table ctx) - { - // TODO: only auto raised ones need memo? no? - // how can we integrate re-run ?? - version(AutoMemoization) - { - Value[] memokey; - if( lay != ValueLayer && lay != MacroLayer ) - { - foreach(i,p; ast.params) - memokey ~= ctx.get(p.name, lay); // lay? - if( auto memolay = lay in memo ) - if( auto pv = memokey in *memolay ) - return *pv; - memo[lay][memokey] = lift(ast.pos,new UndValue,lay,ctx); - } - } - - // @macro run!!! - if( lay == MacroLayer ) - return macroEval(ast.funbody, ctx, false); - - version(MacroCache) { - if( preprocessed_funbody is null ) { - // .prototype!, forced macro cannot access parameters - ctx.kill = true; scope(exit)ctx.kill=false; - preprocessed_funbody = tableToAST(ValueLayer,macroEval(ast.funbody, ctx, true)); - } - } else { - if( preprocessed_funbody is null ) { - // .prototype!, forced macro cannot access parameters - ctx.kill = true; scope(exit)ctx.kill=false; - preprocessed_funbody = tableToAST(ValueLayer,macroEval(ast.funbody, ctx, true)); - } - } - - auto v = eval(preprocessed_funbody, ctx, true, lay); - version(AutoMemoization) - { - if( lay != ValueLayer && lay != MacroLayer ) - { - memo[lay][memokey] = v; - version(AutoReRun) - memo[lay][memokey] = eval(preprocessed_funbody, ctx, true, lay); // re-Run!! - } - } - return v; - } -} - -/// -abstract class NativeFunValue : FunValue -{ - Parameter[] params_data; - override const(Parameter[]) params() { return params_data; } - override Table definitionContext() { return new Table; } // todo: cache overrie -} - -/// Named Constructor for FunValue - -FunValue native(R,T...)(R delegate (T) dg) -{ - return new class NativeFunValue { - this() - { - foreach(i, Ti; T) - params_data ~= new Parameter(text(i), []); - } - override Value invoke(in LexPosition pos, Layer lay, Table ctx) - { - if( lay != ValueLayer ) - throw genex!RuntimeException(pos, "only "~ValueLayer~" layer can call native function"); - T typed_args; - foreach(i, Ti; T) { - typed_args[i] = cast(Ti) ctx.get(text(i), ValueLayer); - if( typed_args[i] is null ) - throw genex!RuntimeException(pos, sprintf!"type mismatch on the argument %d"(i+1)); - } - try { - return dg(typed_args); - } catch( RuntimeException e ) { - throw e.pos is null ? new RuntimeException(pos, e.msg, e.file, e.line) : e; - } - } - }; + Value invoke(LexPosition pos, Layer lay, Table ctx); } /// Context (variable environment) /// Simlar to prototype chain of ECMAScript etc. @@ -187,16 +61,16 @@ this( Table proto=null, Kind k = Kind.PropagateSet ) { this.prototype = proto; this.kind = k; } - void set(string i, Layer lay, Value v, in LexPosition pos=null) + void set(string i, Layer lay, Value v, LexPosition pos=null) { if( setIfExist(i, lay, v) ) return; data[i][lay] = v; } - bool has(string i, Layer lay, in LexPosition pos=null) + bool has(string i, Layer lay) const { if( i in data ) { if( lay !in data[i] ) return false; @@ -205,12 +79,12 @@ return true; } if( prototype is null ) return false; - return prototype.has(i, lay, pos); + return prototype.has(i, lay); } - Value get(string i, Layer lay, in LexPosition pos=null) + Value get(string i, Layer lay, LexPosition pos=null) { if( i in data ) { // [TODO] consider forwarding to proto also in this case if( lay !in data[i] ) @@ -247,9 +121,12 @@ foreach(l,d; l2d) { if(first) first=false; else result~=", "; result ~= k; - result ~= l; + if( l.empty ) + result ~= "(emptylayer)"; + else if( l != ValueLayer ) + result ~= l; result ~= ":"; result ~= text(cast(Value)d); } if( prototype !is null ) @@ -374,22 +251,22 @@ switch(nodeType.data) { case "int": if(auto v = t.access!IntValue(theLayer, "data")) - return new IntLiteral(pos, v.data); + return new Int(pos, v.data); throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"int", data:(not int)}`); case "str": if(auto v = t.access!StrValue(theLayer, "data")) - return new StrLiteral(pos, v.data); + return new Str(pos, v.data); throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"str", data:(not string)}`); case "var": if(auto v = t.access!StrValue(theLayer, "name")) - return new VarExpression(pos, v.data); + return new Var(pos, v.data); throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"var", name:(not string)}`); case "lay": if(auto v = t.access!StrValue(theLayer, "layer")) if(auto e = t.access!Table(theLayer, "expr")) - return new LayExpression(pos, v.data, tableToAST(theLayer,e)); + return new Lay(pos, v.data, tableToAST(theLayer,e)); else throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"lay", expr:(not table)}`); throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"lay", layer:(not string)}`); case "let": @@ -402,15 +279,15 @@ auto bb = tableToAST(theLayer, b); Layer lay=""; if(auto l = t.access!StrValue(theLayer, "layer")) lay = l.data; - return new LetExpression(pos, nn, lay, ee, bb); + return new Let(pos, nn, lay, ee, bb); } throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"let", name:"???", init:"???", expr:"???"}`); case "app": if(auto f = t.access!Table(theLayer, "fun")) if(auto a = t.access!Table(theLayer, "args")) - return new FuncallExpression(pos, tableToAST(theLayer,f), tableToASTList(theLayer,a)); + return new App(pos, tableToAST(theLayer,f), tableToASTList(theLayer,a)); throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"app", fun:???, args:???}`); case "fun": if(auto p = t.access!Table(theLayer, "params")) if(auto b = t.access!Table(theLayer, "funbody")) @@ -439,11 +316,34 @@ } throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {bad fun params %s}`(v)); } auto bb = tableToAST(theLayer, b); - return new FunLiteral(pos,ps,bb); + return new Fun(pos,ps,bb); } throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"fun", param:???, body:???}`); default: throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {is: "%s"} unknown`(nodeType.data)); } } + +Table makeCons(Value a, Value d) +{ + Table t = new Table; + t.set("car", ValueLayer, a); + t.set("cdr", ValueLayer, d); + return t; +} + +Table fromPos(LexPosition pos) +{ + 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))); + } else { + t.set("filename", ValueLayer, new StrValue("nullpos")); + t.set("lineno", ValueLayer, new IntValue(BigInt(0))); + t.set("column", ValueLayer, new IntValue(BigInt(0))); + } + return t; +}