Index: polemy/eval.d ================================================================== --- polemy/eval.d +++ polemy/eval.d @@ -107,10 +107,14 @@ throw genex!RuntimeException(pos, "tried to call non-function"); } Value lift(in LexPosition pos, Value v, Layer lay, Table callerCtx) { + // functions are automatically lifterd + if( cast(FunValue) v ) + return v; + // similar to invoke Function, but with only one argument bound to ValueLayer Value _f = callerCtx.get(lay, SystemLayer, pos); if(auto f = cast(FunValue)_f) { Table ctx = new Table(f.definitionContext(), Table.Kind.NotPropagateSet); @@ -153,15 +157,14 @@ }, (VarExpression e) { if( lay == ValueLayer ) return ctx.get(e.name, lay, e.pos); - try { + if( ctx.has(e.name, lay, e.pos) ) return ctx.get(e.name, lay, e.pos); - } catch( Throwable ) { // [TODO] more precise... + else return lift(e.pos, ctx.get(e.name, ValueLayer, e.pos), lay, ctx); - } }, (LayExpression e) { if( e.layer == MacroLayer ) return macroEval(e.expr, ctx, false); @@ -182,15 +185,10 @@ { return invokeFunction(e.pos, eval(e.fun, ctx, true, lay), e.args, ctx, lay); }, (FunLiteral e) { - Value[Value[]][Layer] memo; - AST macroMemo = null; // cache - - // funvalue need not be rised - // no, need to be rised !! suppose @t(fib)("int") return new UserDefinedFunValue(e, ctx); }, delegate Value (AST e) { throw genex!RuntimeException(e.pos, sprintf!"Unknown Kind of Expression %s"(typeid(e))); @@ -239,13 +237,13 @@ t.set("data", theLayer, new IntValue(e.data)); return t; }, (VarExpression e) { - try { + if( ctx.has(e.name, MacroLayer, e.pos) ) return ctx.get(e.name, MacroLayer, e.pos); - } catch( Throwable ) {// [TODO] more precies... + else { Table t = new Table; t.set("pos", theLayer, pos); t.set("is", theLayer, new StrValue("var")); t.set("name", theLayer, new StrValue(e.name)); return cast(Value)t; Index: polemy/value.d ================================================================== --- polemy/value.d +++ polemy/value.d @@ -49,53 +49,96 @@ 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? - // 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 { @@ -169,17 +212,17 @@ Value get(string i, Layer lay, in LexPosition pos=null) { 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 ) { Index: sample/pattern.pmy ================================================================== --- sample/pattern.pmy +++ sample/pattern.pmy @@ -17,11 +17,11 @@ when( {car:x, cdr:{car: y, cdr:z}} ) { {car: x+y, cdr: adjSum(z)} } when( {car:x, cdr:{}} ) { {car: x, cdr: {}} } when( {} ) { {} } }; -var xs = fromTo(1,11); +var xs = fromTo(1,101); print( xs ); print( length(xs) ); print( adjSum(xs) ); print( length(adjSum(xs)) ); Index: sample/type.pmy ================================================================== --- sample/type.pmy +++ sample/type.pmy @@ -5,11 +5,11 @@ else { if( _isundefined(x) ) { "undefined" } else { "any" }}}} }; def binop(a,b,c) { - fun(x,y){@v( + fun(x,y){@value( if( @type(x)=="undefined" || @type(y)=="undefined" ) { "undefined" } else { if( @type(x)==a && @type(y)==b ) { c } else { "error" } } )} }; @@ -21,8 +21,8 @@ def mergeType(a,b) { if( a == "undefined" ) { if(b=="undefined"){"error"}else{b} } else { a } }; -@type "if" = fun(c,t,e) {@v( +@type "if" = fun(c,t,e) {@value( if(@type(c)=="int" ) { mergeType(@type(t()), @type(e())) } else { "error" } )};