Index: .poseidon ================================================================== --- .poseidon +++ .poseidon @@ -9,11 +9,11 @@ 0 main.d - -cov -g -unittest + -g -unittest Index: d2stacktrace/stacktrace.d ================================================================== --- d2stacktrace/stacktrace.d +++ d2stacktrace/stacktrace.d @@ -246,12 +246,12 @@ return trace.GetCallstack(); } public: static this(){ - Runtime.traceHandler(&TraceHandler); - SetUnhandledExceptionFilter(&UnhandeledExceptionFilterHandler); +// Runtime.traceHandler(&TraceHandler); +// SetUnhandledExceptionFilter(&UnhandeledExceptionFilterHandler); } this(){ if(isInit) return; Index: polemy/eval.d ================================================================== --- polemy/eval.d +++ polemy/eval.d @@ -125,11 +125,14 @@ ); } }, (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???? // ctx.set(e.var, "@v", new UndefinedValue, e.pos); @@ -151,17 +154,18 @@ throw genex!RuntimeException(e.pos, "Non-funcion is applied"); }, (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; memo[lay][args] = (cast(FunValue)ctx.get(lay, "(system)", e.pos)).call(e.pos, "@v", @@ -173,13 +177,21 @@ throw genex!RuntimeException(e.pos, sprintf!"Argument Number Mismatch (%d required but %d given)" (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; }); }, delegate Value (AST e) @@ -215,23 +227,28 @@ t.set("data", theLayer, new IntValue(e.data)); 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 ) { 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 { @@ -248,25 +265,34 @@ t.set("expr", theLayer, macroEval(e.expr,ctx,AlwaysMacro)); 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)); cons.set("cdr",theLayer,args); args = cons; } t.set("arg", theLayer, args); - return t; + return cast(Value)t; }, (FunLiteral e) { Table t = new Table; t.set("pos", theLayer, pos); @@ -341,11 +367,11 @@ if(x<2) { 1; } else { fib(x-1) + fib(x-2); }; }; - fib(10);`).val, new IntValue(BigInt(89))); + fib(5);`).val, new IntValue(BigInt(8))); } unittest { assert_throw!Throwable( evalString(`@@s(x){x}; @s "+"=fun(x,y){x-y};@s(1+2)`) ); Index: polemy/value.d ================================================================== --- polemy/value.d +++ polemy/value.d @@ -147,10 +147,36 @@ if(auto next = this.access!Table(lay,path)) return next.access!T(lay,rest); } return null; } + + string toStringWithoutParen() const + { + string result; + bool first = true; + foreach(k, l2d; data) + foreach(l,d; l2d) + { + if(first) first=false; else result~=", "; + result ~= k; + result ~= l; + result ~= ":"; + result ~= text(cast(Value)d); + } + if( prototype !is null ) + { + result ~= " / "; + result ~= prototype.toStringWithoutParen(); + } + return result; + } + + string toString() const + { + return "{" ~ toStringWithoutParen() ~ "}"; + } private: Table prototype; Kind kind; Value[Layer][string] data; @@ -244,12 +270,16 @@ else throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST (non-table in cons-list)"); return result; } -AST tableToAST( Layer theLayer, Table t ) +AST tableToAST( Layer theLayer, Value vvvv ) { + Table t = cast(Table)vvvv; + if( t is null ) + throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST (not a table)"); + auto nodeType = t.access!StrValue(theLayer, "is"); if( nodeType is null ) throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST {is:(not string)}"); auto pos = extractPos(t); switch(nodeType.data) @@ -306,24 +336,25 @@ Layer[] ls; foreach(lll; tableAsConsList(theLayer, ll)) if(auto l = cast(StrValue)lll) ls ~= l.data; else - throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {bad fun params}`); + throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {bad fun params %s}`(lll)); ps ~= new Parameter(ss.data, ls); continue; } else { Layer[] emp; ps ~= new Parameter(ss.data, emp); + continue; } - throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {bad fun params}`); + 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); } 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)); } } Index: sample/plusminus.pmy ================================================================== --- sample/plusminus.pmy +++ sample/plusminus.pmy @@ -1,6 +1,7 @@ +@@s(x){x}; @s "+" = fun(x, y) {@v( @s(x) - @s(y) )}; print( 1 + 2 ); print( @s(1 + 2) );