@@ -50,51 +50,94 @@ 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? - // auto memoization -/* - if( lay != ValueLayer && lay != MacroLayer ) + // how can we integrate re-run ?? + version(AutoMemoization) { - if( auto memolay = lay in memo ) - if( auto pv = args in *memolay ) - return *pv; - memo[lay][args] = lift(e.pos,new UndValue,lay,ctx); + 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); -/*TODO memo*/ AST macroMemo; - if( macroMemo is null ) { - // .prototype!, forced macro cannot access parameters - ctx.kill = true; scope(exit)ctx.kill=false; - auto tbl = macroEval(ast.funbody, ctx, true); - macroMemo = tableToAST(ValueLayer,tbl); + + 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(macroMemo, ctx, true, lay); - //auto v = eval(e.funbody, ctxNeo, true, lay); - // auto memoization -// if( lay != ValueLayer && lay != MacroLayer ) -// memo[lay][args] = v; + 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; } - - mixin SimpleClass; - override string toString() const { return sprintf!"(function:%x:%x)"(cast(void*)ast, cast(void*)defCtx); } } /// abstract class NativeFunValue : FunValue @@ -170,15 +213,15 @@ { if( i in data ) { // [TODO] consider forwarding to proto also in this case if( lay !in data[i] ) - throw genex!RuntimeException(pos, sprintf!"variable %s is not set in layer %s"(i,lay)); + throw genex!RuntimeException(pos, sprintf!"'%s' is not set in layer %s"(i,lay)); if(kill) - throw genex!RuntimeException(pos, sprintf!"variable %s is killed in macro"(i)); + throw genex!RuntimeException(pos, sprintf!"'%s' is killed in macro"(i)); return data[i][lay]; } if( prototype is null ) - throw new RuntimeException(pos, sprintf!"variable %s not found"(i)); + throw new RuntimeException(pos, sprintf!"'%s' not found"(i)); return prototype.get(i, lay, pos); } T access(T,S...)( Layer lay, string path, S rest )