Diff
Not logged in

Differences From Artifact [27ad20bc14df9938]:

To Artifact [0e6e0e9d77fcbedc]:


6 6 */ 7 7 module polemy.eval; 8 8 import polemy._common; 9 9 import polemy.failure; 10 10 import polemy.ast; 11 11 import polemy.parse; 12 12 import polemy.value; 13 +import polemy.layer; 13 14 import std.typecons; 14 15 import std.stdio; 15 16 16 17 /// 17 18 Table createGlobalContext() 18 19 { 19 20 auto ctx = new Table; 20 - ctx.set("+", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(lhs.data + rhs.data);} )); 21 - ctx.set("-", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(lhs.data - rhs.data);} )); 22 - ctx.set("*", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(lhs.data * rhs.data);} )); 23 - ctx.set("/", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(lhs.data / rhs.data);} )); 24 - ctx.set("%", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(lhs.data % rhs.data);} )); 25 - ctx.set("||", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(BigInt((lhs.data!=0) || (rhs.data!=0) ? 1:0));} )); 26 - ctx.set("&&", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(BigInt((lhs.data!=0) && (rhs.data!=0) ? 1:0));} )); 27 - ctx.set("<", "@v", native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs < rhs ? 1: 0));} )); 28 - ctx.set(">", "@v", native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs > rhs ? 1: 0));} )); 29 - ctx.set("<=", "@v", native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs <= rhs ? 1: 0));} )); 30 - ctx.set(">=", "@v", native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs >= rhs ? 1: 0));} )); 31 - ctx.set("==", "@v", native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs == rhs ? 1: 0));} )); 32 - ctx.set("!=", "@v", native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs != rhs ? 1: 0));} )); 33 - ctx.set("print", "@v", native( (Value a){ 21 + ctx.set("+", ValueLayer, native( (IntValue lhs, IntValue rhs){return new IntValue(lhs.data + rhs.data);} )); 22 + ctx.set("-", ValueLayer, native( (IntValue lhs, IntValue rhs){return new IntValue(lhs.data - rhs.data);} )); 23 + ctx.set("*", ValueLayer, native( (IntValue lhs, IntValue rhs){return new IntValue(lhs.data * rhs.data);} )); 24 + ctx.set("/", ValueLayer, native( (IntValue lhs, IntValue rhs){return new IntValue(lhs.data / rhs.data);} )); 25 + ctx.set("%", ValueLayer, native( (IntValue lhs, IntValue rhs){return new IntValue(lhs.data % rhs.data);} )); 26 + ctx.set("||", ValueLayer, native( (IntValue lhs, IntValue rhs){return new IntValue(BigInt((lhs.data!=0) || (rhs.data!=0) ? 1:0));} )); 27 + ctx.set("&&", ValueLayer, native( (IntValue lhs, IntValue rhs){return new IntValue(BigInt((lhs.data!=0) && (rhs.data!=0) ? 1:0));} )); 28 + ctx.set("<", ValueLayer, native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs < rhs ? 1: 0));} )); 29 + ctx.set(">", ValueLayer, native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs > rhs ? 1: 0));} )); 30 + ctx.set("<=", ValueLayer, native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs <= rhs ? 1: 0));} )); 31 + ctx.set(">=", ValueLayer, native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs >= rhs ? 1: 0));} )); 32 + ctx.set("==", ValueLayer, native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs == rhs ? 1: 0));} )); 33 + ctx.set("!=", ValueLayer, native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs != rhs ? 1: 0));} )); 34 + ctx.set("print", ValueLayer, native( (Value a){ 34 35 writeln(a); 35 36 return new IntValue(BigInt(178)); 36 37 })); 37 - ctx.set("if", "@v", native( (IntValue x, FunValue ft, FunValue fe){ 38 + ctx.set("if", ValueLayer, native( (IntValue x, FunValue ft, FunValue fe){ 38 39 auto toRun = (x.data==0 ? fe : ft); 39 - return toRun.invoke(null, "@v", toRun.definitionContext()); 40 + return toRun.invoke(null, ValueLayer, toRun.definitionContext()); 40 41 // return toRun.invoke(pos, lay, toRun.definitionContext()); 41 42 })); 42 - ctx.set("_isint", "@v", native( (Value v){return new IntValue(BigInt(cast(IntValue)v is null ? 0 : 1));} )); 43 - ctx.set("_isstr", "@v", native( (Value v){return new IntValue(BigInt(cast(StrValue)v is null ? 0 : 1));} )); 44 - ctx.set("_isfun", "@v", native( (Value v){return new IntValue(BigInt(cast(FunValue)v is null ? 0 : 1));} )); 45 - ctx.set("_isundefined", "@v", native( (Value v){return new IntValue(BigInt(cast(UndValue)v is null ? 0 : 1));} )); 46 - ctx.set("_istable", "@v", native( (Value v){return new IntValue(BigInt(cast(Table)v is null ? 0 : 1));} )); 47 - ctx.set(".", "@v", native( (Table t, StrValue s){ 48 - return (t.has(s.data, "@v") ? t.get(s.data, "@v") : new UndValue); 43 + ctx.set("_isint", ValueLayer, native( (Value v){return new IntValue(BigInt(cast(IntValue)v is null ? 0 : 1));} )); 44 + ctx.set("_isstr", ValueLayer, native( (Value v){return new IntValue(BigInt(cast(StrValue)v is null ? 0 : 1));} )); 45 + ctx.set("_isfun", ValueLayer, native( (Value v){return new IntValue(BigInt(cast(FunValue)v is null ? 0 : 1));} )); 46 + ctx.set("_isundefined", ValueLayer, native( (Value v){return new IntValue(BigInt(cast(UndValue)v is null ? 0 : 1));} )); 47 + ctx.set("_istable", ValueLayer, native( (Value v){return new IntValue(BigInt(cast(Table)v is null ? 0 : 1));} )); 48 + ctx.set(".", ValueLayer, native( (Table t, StrValue s){ 49 + return (t.has(s.data, ValueLayer) ? t.get(s.data, ValueLayer) : new UndValue); 50 + }) ); 51 + ctx.set(".?", ValueLayer, native( (Table t, StrValue s){ 52 + return new IntValue(BigInt(t.has(s.data, ValueLayer) ? 1 : 0)); 49 53 }) ); 50 - ctx.set(".?", "@v", native( (Table t, StrValue s){ 51 - return new IntValue(BigInt(t.has(s.data, "@v") ? 1 : 0)); 52 - }) ); 53 - ctx.set(".=", "@v", native( (Table t, StrValue s, Value v){ 54 + ctx.set(".=", ValueLayer, native( (Table t, StrValue s, Value v){ 54 55 auto t2 = new Table(t, Table.Kind.NotPropagateSet); 55 - t2.set(s.data, "@v", v); 56 + t2.set(s.data, ValueLayer, v); 56 57 return t2; 57 58 }) ); 58 - ctx.set("{}", "@v", native( (){ 59 + ctx.set("{}", ValueLayer, native( (){ 59 60 return new Table; 60 61 }) ); 61 62 return ctx; 62 63 } 63 64 64 65 /// Entry point of this module 65 66 ................................................................................ 76 77 } 77 78 78 79 /// Entry point of this module 79 80 80 81 Tuple!(Value,"val",Table,"ctx") eval(AST e) 81 82 { 82 83 Table ctx = createGlobalContext(); 83 - return typeof(return)(eval(e, ctx, false, "@v"), ctx); 84 + return typeof(return)(eval(e, ctx, false, ValueLayer), ctx); 84 85 } 85 86 86 87 Value invokeFunction(in LexPosition pos, Value _f, AST[] args, Table callerCtx, Layer lay, bool AlwaysMacro=false) 87 88 { 88 89 if(auto f = cast(FunValue)_f) 89 90 { 90 91 Table ctx = new Table(f.definitionContext(), Table.Kind.NotPropagateSet); 91 92 foreach(i,p; f.params()) 92 93 if( p.layers.empty ) 93 - if(lay=="@macro") 94 + if(lay==MacroLayer) 94 95 ctx.set(p.name, lay, macroEval(args[i], callerCtx, AlwaysMacro)); 95 96 else 96 97 ctx.set(p.name, lay, eval(args[i], callerCtx, true, lay)); 97 98 else 98 99 foreach(argLay; p.layers) 99 - if(argLay=="@macro") 100 + if(argLay==MacroLayer) 100 101 ctx.set(p.name, argLay, macroEval(args[i], callerCtx, AlwaysMacro)); 101 102 else 102 103 ctx.set(p.name, argLay, eval(args[i], callerCtx, true, argLay)); 103 104 return f.invoke(pos, lay, ctx); 104 105 } 105 106 throw genex!RuntimeException(pos, "tried to call non-function"); 106 107 } 107 108 108 109 Value lift(in LexPosition pos, Value v, Layer lay, Table callerCtx) 109 110 { 110 - // similar to invoke Function, but with only one argument bound to @v 111 - Value _f = callerCtx.get(lay, "(system)", pos); 111 + // similar to invoke Function, but with only one argument bound to ValueLayer 112 + Value _f = callerCtx.get(lay, SystemLayer, pos); 112 113 if(auto f = cast(FunValue)_f) 113 114 { 114 115 Table ctx = new Table(f.definitionContext(), Table.Kind.NotPropagateSet); 115 116 auto ps = f.params(); 116 117 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" ) 118 + throw genex!RuntimeException(pos, "lift function must take exactly one argument at "~ValueLayer~" layer"); 119 + if( ps[0].layers.length==0 || ps[0].layers.length==1 && ps[0].layers[0]==ValueLayer ) 119 120 { 120 - ctx.set(ps[0].name, "@v", v); 121 - return f.invoke(pos, "@v", ctx); 121 + ctx.set(ps[0].name, ValueLayer, v); 122 + return f.invoke(pos, ValueLayer, ctx); 122 123 } 123 124 else 124 - throw genex!RuntimeException(pos, "lift function must take exactly one argument at @v layer"); 125 + throw genex!RuntimeException(pos, "lift function must take exactly one argument at "~ValueLayer~" layer"); 125 126 } 126 127 throw genex!RuntimeException(pos, "tried to call non-function"); 127 128 } 128 129 129 130 /// Entry point of this module 130 131 /// If splitCtx = true, then inner variable declaration do not overwrite ctx. 131 -/// lay is the layer ID for evaluation (standard value semantics uses "@v"). 132 +/// lay is the layer ID for evaluation (standard value semantics uses ValueLayer). 132 133 133 134 Value eval(AST e, Table ctx, bool splitCtx, Layer lay) 134 135 { 135 136 return e.match( 136 137 (StrLiteral e) 137 138 { 138 139 Value v = new StrValue(e.data); 139 - if( lay == "@v" ) 140 + if( lay == ValueLayer ) 140 141 return v; 141 142 else 142 143 return lift(e.pos,v,lay,ctx); 143 144 }, 144 145 (IntLiteral e) 145 146 { 146 147 Value v = new IntValue(e.data); 147 - if( lay == "@v" ) 148 + if( lay == ValueLayer ) 148 149 return v; 149 150 else // rise 150 151 return lift(e.pos,v,lay,ctx); 151 152 }, 152 153 (VarExpression e) 153 154 { 154 - if( lay == "@v" ) 155 + if( lay == ValueLayer ) 155 156 return ctx.get(e.var, lay, e.pos); 156 157 try { 157 158 return ctx.get(e.var, lay, e.pos); 158 159 } catch( Throwable ) { // [TODO] more precise... 159 - return lift(e.pos, ctx.get(e.var, "@v", e.pos), lay, ctx); 160 + return lift(e.pos, ctx.get(e.var, ValueLayer, e.pos), lay, ctx); 160 161 } 161 162 }, 162 163 (LayeredExpression e) 163 164 { 164 - if( e.lay == "@macro" ) 165 + if( e.lay == MacroLayer ) 165 166 return macroEval(e.expr, ctx, false); 166 167 else 167 168 return eval(e.expr, ctx, true, e.lay); 168 169 }, 169 170 (LetExpression e) 170 171 { 171 172 // for letrec, we need this, but should avoid overwriting???? 172 - // ctx.set(e.var, "@v", new UndefinedValue, e.pos); 173 + // ctx.set(e.var, ValueLayer, new UndefinedValue, e.pos); 173 174 if(splitCtx) 174 175 ctx = new Table(ctx, Table.Kind.NotPropagateSet); 175 176 Value v = eval(e.init, ctx, true, lay); 176 177 ctx.set(e.var, (e.layer.length ? e.layer : lay), v, e.pos); 177 178 return eval(e.expr, ctx, false, lay); 178 179 }, 179 180 (FuncallExpression e) ................................................................................ 195 196 } 196 197 ); 197 198 } 198 199 199 200 // [TODO] Optimization 200 201 Value macroEval(AST e, Table ctx, bool AlwaysMacro) 201 202 { 202 - Layer theLayer = "@v"; 203 + Layer theLayer = ValueLayer; 203 204 204 205 Table pos = new Table; 205 206 pos.set("filename", theLayer, new StrValue(e.pos.filename)); 206 207 pos.set("lineno", theLayer, new IntValue(BigInt(e.pos.lineno))); 207 208 pos.set("column", theLayer, new IntValue(BigInt(e.pos.column))); 208 209 return e.match( 209 210 (StrLiteral e) ................................................................................ 221 222 t.set("is", theLayer, new StrValue("int")); 222 223 t.set("data", theLayer, new IntValue(e.data)); 223 224 return t; 224 225 }, 225 226 (VarExpression e) 226 227 { 227 228 try { 228 - return ctx.get(e.var, "@macro", e.pos); 229 + return ctx.get(e.var, MacroLayer, e.pos); 229 230 } catch( Throwable ) {// [TODO] more precies... 230 231 Table t = new Table; 231 232 t.set("pos", theLayer, pos); 232 233 t.set("is", theLayer, new StrValue("var")); 233 234 t.set("name", theLayer, new StrValue(e.var)); 234 235 return cast(Value)t; 235 236 } ................................................................................ 243 244 t.set("is", theLayer, new StrValue("lay")); 244 245 t.set("layer", theLayer, new StrValue(e.lay)); 245 246 t.set("expr", theLayer, macroEval(e.expr,ctx,AlwaysMacro)); 246 247 return cast(Value)t; 247 248 } 248 249 else 249 250 { 250 - if( e.lay == "@macro" ) 251 + if( e.lay == MacroLayer ) 251 252 return macroEval(e.expr, ctx, false); 252 253 else 253 254 return eval(e.expr, ctx, true, e.lay); 254 255 } 255 256 }, 256 257 (LetExpression e) 257 258 { ................................................................................ 264 265 return t; 265 266 }, 266 267 (FuncallExpression e) 267 268 { 268 269 Value _f = macroEval(e.fun,ctx,AlwaysMacro); 269 270 270 271 if( auto f = cast(FunValue)_f ) 271 - return invokeFunction(e.pos, f, e.args, ctx, "@macro", AlwaysMacro); 272 + return invokeFunction(e.pos, f, e.args, ctx, MacroLayer, AlwaysMacro); 272 273 273 274 Table t = new Table; 274 275 t.set("pos", theLayer, pos); 275 276 t.set("is", theLayer, new StrValue("app")); 276 277 t.set("fun", theLayer, _f); 277 278 Table args = new Table; 278 279 foreach_reverse(a; e.args) { ................................................................................ 317 318 ); 318 319 } 319 320 320 321 unittest 321 322 { 322 323 auto r = assert_nothrow( evalString(`var x = 21; x + x*x;`) ); 323 324 assert_eq( r.val, new IntValue(BigInt(21+21*21)) ); 324 - assert_eq( r.ctx.get("x","@v"), new IntValue(BigInt(21)) ); 325 - assert_nothrow( r.ctx.get("x","@v") ); 326 - assert_throw!RuntimeException( r.ctx.get("y","@v") ); 325 + assert_eq( r.ctx.get("x",ValueLayer), new IntValue(BigInt(21)) ); 326 + assert_nothrow( r.ctx.get("x",ValueLayer) ); 327 + assert_throw!RuntimeException( r.ctx.get("y",ValueLayer) ); 327 328 } 328 329 unittest 329 330 { 330 331 auto r = assert_nothrow( evalString(`var x = 21; var x = x + x*x;`) ); 331 332 assert_eq( r.val, new IntValue(BigInt(21+21*21)) ); 332 - assert_eq( r.ctx.get("x","@v"), new IntValue(BigInt(21+21*21)) ); 333 - assert_nothrow( r.ctx.get("x","@v") ); 334 - assert_throw!RuntimeException( r.ctx.get("y","@v") ); 333 + assert_eq( r.ctx.get("x",ValueLayer), new IntValue(BigInt(21+21*21)) ); 334 + assert_nothrow( r.ctx.get("x",ValueLayer) ); 335 + assert_throw!RuntimeException( r.ctx.get("y",ValueLayer) ); 335 336 } 336 337 unittest 337 338 { 338 339 assert_eq( evalString(`let x=1; let y=(let x=2); x`).val, new IntValue(BigInt(1)) ); 339 340 assert_eq( evalString(`let x=1; let y=(let x=2;fun(){x}); y()`).val, new IntValue(BigInt(2)) ); 340 341 } 341 342 unittest ................................................................................ 364 365 fib(5);`).val, new IntValue(BigInt(8))); 365 366 } 366 367 367 368 unittest 368 369 { 369 370 assert_throw!Throwable( evalString(`@@s(x){x}; @s "+"=fun(x,y){x-y};@s(1+2)`) ); 370 371 assert_eq( evalString(`@@s(x){x}; @s "+"=fun(x,y){x-y};1+2`).val, new IntValue(BigInt(3)) ); 371 - assert_eq( evalString(`@@s(x){x}; @s "+"=fun(x,y){@v(@s(x)-@s(y))};1+2`).val, new IntValue(BigInt(3)) ); 372 - assert_eq( evalString(`@@s(x){x}; @s "+"=fun(x,y){@v(@s(x)-@s(y))};@s(1+2)`).val, new IntValue(BigInt(-1)) ); 372 + assert_eq( evalString(`@@s(x){x}; @s "+"=fun(x,y){@value(@s(x)-@s(y))};1+2`).val, new IntValue(BigInt(3)) ); 373 + assert_eq( evalString(`@@s(x){x}; @s "+"=fun(x,y){@value(@s(x)-@s(y))};@s(1+2)`).val, new IntValue(BigInt(-1)) ); 373 374 } 374 375 375 376 unittest 376 377 { 377 378 assert_eq( evalString(`@@t = fun(x){x+1}; @t(123)`).val, new IntValue(BigInt(124)) ); 378 379 // there was a bug that declaration in the first line of function definition 379 380 // cannot be recursive 380 381 assert_nothrow( evalString(`def foo() { 381 382 def bar(y) { if(y<1) {0} else {bar(0)} }; 382 383 bar(1) 383 384 }; foo()`) ); 384 385 } 385 -