@@ -101,12 +101,12 @@ { Value f = eval( e.fun, lay, ctx ); if( isMacroishLayer(lay) ) if( auto ff = cast(FunValue)f ) - return invokeFunction(ff, e.args, MacroLayer, ctx, e.pos); + return invokeFunction(ff, e.args, MacroLayer, ctx, e.pos, getNameIfPossible(e.fun)); else return ast2table(e, (AST e){return eval(e,lay,ctx);}); - return invokeFunction(f, e.args, lay, ctx, e.pos); + return invokeFunction(f, e.args, lay, ctx, e.pos, getNameIfPossible(e.fun)); } Value eval( Fun e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) { @@ -140,9 +140,16 @@ } } private: - Value invokeFunction(Value _f, AST[] args, Layer lay, Table ctx, LexPosition pos=null) + string getNameIfPossible(AST e) + { + if(auto v = cast(Var)e) + return v.name; + return ""; + } + + Value invokeFunction(Value _f, AST[] args, Layer lay, Table ctx, LexPosition pos, string callstackmsg) { if(auto f = cast(FunValue)_f) { Table newCtx = new Table(f.definitionContext(), Table.Kind.NotPropagateSet); @@ -151,37 +158,46 @@ newCtx.set(p.name, (lay==RawMacroLayer ? MacroLayer : lay), eval(args[i], lay, ctx)); else foreach(argLay; p.layers) newCtx.set(p.name, argLay, eval(args[i], argLay, ctx)); + scope _ = new PushCallStack(pos, callstackmsg); return f.invoke(lay==RawMacroLayer ? MacroLayer : lay, newCtx, pos); } throw genex!RuntimeException(pos, text("tried to call non-function: ",_f)); } - Value lift(Value v, Layer lay, Table ctx, LexPosition pos=null) + Value lift(Value v, Layer lay, Table ctx, LexPosition pos) { - assert( !isMacroishLayer(lay), "lift to the @macro layer should not happen" ); + assert( !isMacroishLayer(lay), "lift to the @macro layer should never happen" ); // functions are automatically lifterd if( cast(FunValue) v ) return v; - // similar to invoke Function, but with only one argument bound to ValueLayer - if(auto f = cast(FunValue)ctx.get(lay, SystemLayer, pos)) + if( !ctx.has(lay, SystemLayer) ) + throw genex!RuntimeException(pos, "lift function for "~lay~" is not registered" ); + + // similar to invokeFunction, but with only one argument bound to ValueLayer + auto _f = ctx.get(lay, SystemLayer, pos); + if(auto f = cast(FunValue)_f) { Table newCtx = new Table(f.definitionContext(), Table.Kind.NotPropagateSet); auto ps = f.params(); if( ps.length != 1 ) - throw genex!RuntimeException(pos, "lift function must take exactly one argument at "~ValueLayer~" layer"); + throw genex!RuntimeException(pos, + text("lift function for", lay, " must take exactly one argument of ", ValueLayer)); if( ps[0].layers.length==0 || ps[0].layers.length==1 && ps[0].layers[0]==ValueLayer ) { newCtx.set(ps[0].name, ValueLayer, v); + scope _ = new PushCallStack(pos, lay); return f.invoke(ValueLayer, newCtx, pos); } else - throw genex!RuntimeException(pos, "lift function must take exactly one argument at "~ValueLayer~" layer"); + throw genex!RuntimeException(pos, + text("lift function for", lay, " must take exactly one argument of ", ValueLayer)); } - throw genex!RuntimeException(pos, "tried to call non-function"); + throw genex!RuntimeException(pos, + text("non-function ", _f, " is registered as the lift function for ", lay)); } Value createNewFunction(Fun e, Table ctx) { @@ -218,11 +234,15 @@ override Value invoke(Layer lay, Table ctx, LexPosition pos) { if( lay == MacroLayer ) return eval(ast.funbody, lay, ctx); - if( afterMacroAST is null ) - afterMacroAST = tableToAST(ValueLayer, eval(e.funbody, RawMacroLayer, ctx)); - return eval(afterMacroAST, lay, ctx); + try { + if( afterMacroAST is null ) + afterMacroAST = polemy2d!(AST)(eval(e.funbody, RawMacroLayer, ctx), pos); + return eval(afterMacroAST, lay, ctx); + } catch( RuntimeException e ) { + throw e.pos is null ? new RuntimeException(pos, e.msg, e.file, e.line, e.next) : e; + } } AST afterMacroAST; }