Diff
Not logged in

Differences From Artifact [27ad20bc14df9938]:

To Artifact [0e6e0e9d77fcbedc]:


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