@@ -126,9 +126,12 @@ } }, (LayeredExpression e) { - return eval(e.expr, ctx, false, e.lay); + if( e.lay == "@macro" ) + return macroEval(e.expr, ctx, false); + else + return eval(e.expr, ctx, false, e.lay); }, (LetExpression e) { // for letrec, we need this, but should avoid overwriting???? @@ -152,15 +155,16 @@ }, (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 FunValue(delegate Value(immutable LexPosition pos, string lay, Value[] args){ // TODO: only auto raised ones need memo? no? // auto memoization - if( lay != "@v" ) + if( lay != "@v" && lay != "@macro" ) { if( auto memolay = lay in memo ) if( auto pv = args in *memolay ) return *pv; @@ -174,11 +178,19 @@ (e.params.length, args.length)); Table ctxNeo = new Table(ctx, Table.Kind.NotPropagateSet); foreach(i,p; e.params) ctxNeo.set(p.name, lay, args[i]); - auto v = eval(e.funbody, ctxNeo, true, lay); + + // @macro run!!! + if( lay == "@macro" ) + return macroEval(e.funbody, ctxNeo, false); + if( macroMemo is null ) + macroMemo = tableToAST("@v",macroEval(e.funbody, ctxNeo, true)); + auto v = eval(macroMemo, ctxNeo, true, lay); + + //auto v = eval(e.funbody, ctxNeo, true, lay); // auto memoization - if( lay != "@v" ) + if( lay != "@v" && lay != "@macro" ) memo[lay][args] = v; return v; }); }, @@ -216,13 +228,17 @@ return t; }, (VarExpression e) { - Table t = new Table; - t.set("pos", theLayer, pos); - t.set("is", theLayer, new StrValue("var")); - t.set("name", theLayer, new StrValue(e.var)); - return t; + try { + return ctx.get(e.var, "@macro", e.pos); + } catch( Throwable ) {// [TODO] more precies... + Table t = new Table; + t.set("pos", theLayer, pos); + t.set("is", theLayer, new StrValue("var")); + t.set("name", theLayer, new StrValue(e.var)); + return cast(Value)t; + } }, (LayeredExpression e) { if( AlwaysMacro ) @@ -229,8 +245,9 @@ { Table t = new Table; t.set("pos", theLayer, pos); t.set("is", theLayer, new StrValue("lay")); + t.set("layer", theLayer, new StrValue(e.lay)); t.set("expr", theLayer, macroEval(e.expr,ctx,AlwaysMacro)); return cast(Value)t; } else @@ -249,14 +266,23 @@ return t; }, (FuncallExpression e) { - // [TODO] @macro invokation!!!! - // if e.fun is varname and its ctx[@macro] is set, switch to usual eval + Value _f = macroEval(e.fun,ctx,AlwaysMacro); + + // copy & pase from normal eval + // [TODO] sync with @layerd parameters. + if( auto f = cast(FunValue)_f ) { + Value[] args; + foreach(a; e.args) + args ~= macroEval(a, ctx, AlwaysMacro); + return f.call(e.pos, "@macro", args); // explicit @macro is the best??? + } + Table t = new Table; t.set("pos", theLayer, pos); t.set("is", theLayer, new StrValue("app")); - t.set("fun", theLayer, macroEval(e.fun,ctx,AlwaysMacro)); + t.set("fun", theLayer, _f); Table args = new Table; foreach_reverse(a; e.args) { Table cons = new Table; cons.set("car",theLayer,macroEval(a,ctx,AlwaysMacro)); @@ -263,9 +289,9 @@ cons.set("cdr",theLayer,args); args = cons; } t.set("arg", theLayer, args); - return t; + return cast(Value)t; }, (FunLiteral e) { Table t = new Table; @@ -342,9 +368,9 @@ { 1; } else { fib(x-1) + fib(x-2); }; }; - fib(10);`).val, new IntValue(BigInt(89))); + fib(5);`).val, new IntValue(BigInt(8))); } unittest {