Diff
Not logged in

Differences From Artifact [97875541a42dbc7a]:

To Artifact [27ad20bc14df9938]:


26 26 ctx.set("&&", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(BigInt((lhs.data!=0) && (rhs.data!=0) ? 1:0));} )); 27 27 ctx.set("<", "@v", native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs < rhs ? 1: 0));} )); 28 28 ctx.set(">", "@v", native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs > rhs ? 1: 0));} )); 29 29 ctx.set("<=", "@v", native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs <= rhs ? 1: 0));} )); 30 30 ctx.set(">=", "@v", native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs >= rhs ? 1: 0));} )); 31 31 ctx.set("==", "@v", native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs == rhs ? 1: 0));} )); 32 32 ctx.set("!=", "@v", native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs != rhs ? 1: 0));} )); 33 - ctx.set("print", "@v", new FunValue(delegate Value(immutable LexPosition pos, Layer lay, Value[] args){ 34 - foreach(a; args) 35 - write(a); 36 - writeln(""); 33 + ctx.set("print", "@v", native( (Value a){ 34 + writeln(a); 37 35 return new IntValue(BigInt(178)); 38 36 })); 39 - ctx.set("if", "@v", new FunValue(delegate Value(immutable LexPosition pos, Layer lay, Value[] args){ 40 - if( args.length != 3 ) 41 - throw genex!RuntimeException(pos, "if takes three arguments!!"); 42 - if( auto x = cast(IntValue)args[0] ) 43 - if( auto ft = cast(FunValue)args[1] ) 44 - if( auto fe = cast(FunValue)args[2] ) 45 - return (x.data == 0 ? fe : ft).call(pos,lay,[]); 46 - throw genex!RuntimeException(pos, "type mismatch in if"); 37 + ctx.set("if", "@v", native( (IntValue x, FunValue ft, FunValue fe){ 38 + auto toRun = (x.data==0 ? fe : ft); 39 + return toRun.invoke(null, "@v", toRun.definitionContext()); 40 +// return toRun.invoke(pos, lay, toRun.definitionContext()); 47 41 })); 48 42 ctx.set("_isint", "@v", native( (Value v){return new IntValue(BigInt(cast(IntValue)v is null ? 0 : 1));} )); 49 43 ctx.set("_isstr", "@v", native( (Value v){return new IntValue(BigInt(cast(StrValue)v is null ? 0 : 1));} )); 50 44 ctx.set("_isfun", "@v", native( (Value v){return new IntValue(BigInt(cast(FunValue)v is null ? 0 : 1));} )); 51 45 ctx.set("_isundefined", "@v", native( (Value v){return new IntValue(BigInt(cast(UndValue)v is null ? 0 : 1));} )); 52 46 ctx.set("_istable", "@v", native( (Value v){return new IntValue(BigInt(cast(Table)v is null ? 0 : 1));} )); 53 47 ctx.set(".", "@v", native( (Table t, StrValue s){ ................................................................................ 84 78 /// Entry point of this module 85 79 86 80 Tuple!(Value,"val",Table,"ctx") eval(AST e) 87 81 { 88 82 Table ctx = createGlobalContext(); 89 83 return typeof(return)(eval(e, ctx, false, "@v"), ctx); 90 84 } 85 + 86 +Value invokeFunction(in LexPosition pos, Value _f, AST[] args, Table callerCtx, Layer lay, bool AlwaysMacro=false) 87 +{ 88 + if(auto f = cast(FunValue)_f) 89 + { 90 + Table ctx = new Table(f.definitionContext(), Table.Kind.NotPropagateSet); 91 + foreach(i,p; f.params()) 92 + if( p.layers.empty ) 93 + if(lay=="@macro") 94 + ctx.set(p.name, lay, macroEval(args[i], callerCtx, AlwaysMacro)); 95 + else 96 + ctx.set(p.name, lay, eval(args[i], callerCtx, true, lay)); 97 + else 98 + foreach(argLay; p.layers) 99 + if(argLay=="@macro") 100 + ctx.set(p.name, argLay, macroEval(args[i], callerCtx, AlwaysMacro)); 101 + else 102 + ctx.set(p.name, argLay, eval(args[i], callerCtx, true, argLay)); 103 + return f.invoke(pos, lay, ctx); 104 + } 105 + throw genex!RuntimeException(pos, "tried to call non-function"); 106 +} 107 + 108 +Value lift(in LexPosition pos, Value v, Layer lay, Table callerCtx) 109 +{ 110 + // similar to invoke Function, but with only one argument bound to @v 111 + Value _f = callerCtx.get(lay, "(system)", pos); 112 + if(auto f = cast(FunValue)_f) 113 + { 114 + Table ctx = new Table(f.definitionContext(), Table.Kind.NotPropagateSet); 115 + auto ps = f.params(); 116 + if( ps.length != 1 ) 117 + throw genex!RuntimeException(pos, "lift function must take exactly one argument at @v layer"); 118 + if( ps[0].layers.length==0 || ps[0].layers.length==1 && ps[0].layers[0]=="@v" ) 119 + { 120 + ctx.set(ps[0].name, "@v", v); 121 + return f.invoke(pos, "@v", ctx); 122 + } 123 + else 124 + throw genex!RuntimeException(pos, "lift function must take exactly one argument at @v layer"); 125 + } 126 + throw genex!RuntimeException(pos, "tried to call non-function"); 127 +} 91 128 92 129 /// Entry point of this module 93 130 /// If splitCtx = true, then inner variable declaration do not overwrite ctx. 94 131 /// lay is the layer ID for evaluation (standard value semantics uses "@v"). 95 132 96 133 Value eval(AST e, Table ctx, bool splitCtx, Layer lay) 97 134 { 98 135 return e.match( 99 136 (StrLiteral e) 100 137 { 101 138 Value v = new StrValue(e.data); 102 139 if( lay == "@v" ) 103 140 return v; 104 - else // rise 105 - return (cast(FunValue)ctx.get(lay, "(system)", e.pos)).call(e.pos, "@v", [v]); 141 + else 142 + return lift(e.pos,v,lay,ctx); 106 143 }, 107 144 (IntLiteral e) 108 145 { 109 146 Value v = new IntValue(e.data); 110 147 if( lay == "@v" ) 111 148 return v; 112 149 else // rise 113 - return (cast(FunValue)ctx.get(lay, "(system)", e.pos)).call(e.pos, "@v", [v]); 150 + return lift(e.pos,v,lay,ctx); 114 151 }, 115 152 (VarExpression e) 116 153 { 117 154 if( lay == "@v" ) 118 155 return ctx.get(e.var, lay, e.pos); 119 156 try { 120 157 return ctx.get(e.var, lay, e.pos); 121 158 } catch( Throwable ) { // [TODO] more precise... 122 - // rise from @v 123 - return (cast(FunValue)ctx.get(lay, "(system)", e.pos)).call(e.pos, "@v", 124 - [ctx.get(e.var, "@v", e.pos)] 125 - ); 159 + return lift(e.pos, ctx.get(e.var, "@v", e.pos), lay, ctx); 126 160 } 127 161 }, 128 162 (LayeredExpression e) 129 163 { 130 164 if( e.lay == "@macro" ) 131 165 return macroEval(e.expr, ctx, false); 132 166 else ................................................................................ 140 174 ctx = new Table(ctx, Table.Kind.NotPropagateSet); 141 175 Value v = eval(e.init, ctx, true, lay); 142 176 ctx.set(e.var, (e.layer.length ? e.layer : lay), v, e.pos); 143 177 return eval(e.expr, ctx, false, lay); 144 178 }, 145 179 (FuncallExpression e) 146 180 { 147 - Value _f = eval(e.fun, ctx, true, lay); 148 - if( auto f = cast(FunValue)_f ) { 149 - Value[] args; 150 - foreach(a; e.args) 151 - args ~= eval(a, ctx, true, lay); 152 - return f.call(e.pos, lay, args); 153 - } 154 - throw genex!RuntimeException(e.pos, "Non-funcion is applied"); 181 + return invokeFunction(e.pos, eval(e.fun, ctx, true, lay), e.args, ctx, lay); 155 182 }, 156 183 (FunLiteral e) 157 184 { 158 185 Value[Value[]][Layer] memo; 159 186 AST macroMemo = null; // cache 160 187 161 188 // funvalue need not be rised 162 189 // no, need to be rised !! suppose @t(fib)("int") 163 - return new FunValue(delegate Value(immutable LexPosition pos, string lay, Value[] args){ 164 - // TODO: only auto raised ones need memo? no? 165 - // auto memoization 166 - if( lay != "@v" && lay != "@macro" ) 167 - { 168 - if( auto memolay = lay in memo ) 169 - if( auto pv = args in *memolay ) 170 - return *pv; 171 - memo[lay][args] = (cast(FunValue)ctx.get(lay, "(system)", e.pos)).call(e.pos, "@v", 172 - [new UndValue] 173 - ); 174 - } 175 - 176 - if( e.params.length != args.length ) 177 - throw genex!RuntimeException(e.pos, sprintf!"Argument Number Mismatch (%d required but %d given)" 178 - (e.params.length, args.length)); 179 - Table ctxNeo = new Table(ctx, Table.Kind.NotPropagateSet); 180 - foreach(i,p; e.params) 181 - ctxNeo.set(p.name, lay, args[i]); 182 - 183 - // @macro run!!! 184 - if( lay == "@macro" ) 185 - return macroEval(e.funbody, ctxNeo, false); 186 - if( macroMemo is null ) 187 - macroMemo = tableToAST("@v",macroEval(e.funbody, ctxNeo, true)); 188 - auto v = eval(macroMemo, ctxNeo, true, lay); 189 - 190 - //auto v = eval(e.funbody, ctxNeo, true, lay); 191 - // auto memoization 192 - if( lay != "@v" && lay != "@macro" ) 193 - memo[lay][args] = v; 194 - return v; 195 - }); 190 + return new UserDefinedFunValue(e, ctx); 196 191 }, 197 192 delegate Value (AST e) 198 193 { 199 194 throw genex!RuntimeException(e.pos, sprintf!"Unknown Kind of Expression %s"(typeid(e))); 200 195 } 201 196 ); 202 197 } ................................................................................ 248 243 t.set("is", theLayer, new StrValue("lay")); 249 244 t.set("layer", theLayer, new StrValue(e.lay)); 250 245 t.set("expr", theLayer, macroEval(e.expr,ctx,AlwaysMacro)); 251 246 return cast(Value)t; 252 247 } 253 248 else 254 249 { 255 - return eval(e.expr, ctx, true, e.lay); 250 + if( e.lay == "@macro" ) 251 + return macroEval(e.expr, ctx, false); 252 + else 253 + return eval(e.expr, ctx, true, e.lay); 256 254 } 257 255 }, 258 256 (LetExpression e) 259 257 { 260 258 Table t = new Table; 261 259 t.set("pos", theLayer, pos); 262 260 t.set("is", theLayer, new StrValue("let")); ................................................................................ 265 263 t.set("expr", theLayer, macroEval(e.expr,ctx,AlwaysMacro)); 266 264 return t; 267 265 }, 268 266 (FuncallExpression e) 269 267 { 270 268 Value _f = macroEval(e.fun,ctx,AlwaysMacro); 271 269 272 - // copy & pase from normal eval 273 - // [TODO] sync with @layerd parameters. 274 - if( auto f = cast(FunValue)_f ) { 275 - Value[] args; 276 - foreach(a; e.args) 277 - args ~= macroEval(a, ctx, AlwaysMacro); 278 - return f.call(e.pos, "@macro", args); // explicit @macro is the best??? 279 - } 270 + if( auto f = cast(FunValue)_f ) 271 + return invokeFunction(e.pos, f, e.args, ctx, "@macro", AlwaysMacro); 280 272 281 273 Table t = new Table; 282 274 t.set("pos", theLayer, pos); 283 275 t.set("is", theLayer, new StrValue("app")); 284 276 t.set("fun", theLayer, _f); 285 277 Table args = new Table; 286 278 foreach_reverse(a; e.args) { ................................................................................ 386 378 // there was a bug that declaration in the first line of function definition 387 379 // cannot be recursive 388 380 assert_nothrow( evalString(`def foo() { 389 381 def bar(y) { if(y<1) {0} else {bar(0)} }; 390 382 bar(1) 391 383 }; foo()`) ); 392 384 } 385 +