Diff
Not logged in

Differences From Artifact [a7c677ad83621b47]:

To Artifact [cd1c3d2598ac30ce]:


20 public: 20 public: 21 /// Initialize evaluator with empty context 21 /// Initialize evaluator with empty context 22 this() { theContext = new Table; } 22 this() { theContext = new Table; } 23 23 24 /// Evaluate the AST 24 /// Evaluate the AST 25 Value evalAST(AST e) 25 Value evalAST(AST e) 26 { 26 { 27 return eval(e, ValueLayer, theContext, OverwriteCtx); | 27 return macroAndEval(e, ValueLayer, theContext, OverwriteCtx)[0]; 28 } 28 } 29 29 30 /// Evaluate the string 30 /// Evaluate the string 31 Value evalString(S,T...)(S str, T fn_ln_cn) 31 Value evalString(S,T...)(S str, T fn_ln_cn) 32 { 32 { 33 return evalAST(parseString(str,fn_ln_cn)); 33 return evalAST(parseString(str,fn_ln_cn)); 34 } 34 } ................................................................................................................................................................................ 45 return theContext; 45 return theContext; 46 } 46 } 47 47 48 private: 48 private: 49 Table theContext; 49 Table theContext; 50 50 51 enum : bool { CascadeCtx=false, OverwriteCtx=true }; 51 enum : bool { CascadeCtx=false, OverwriteCtx=true }; > 52 52 Value eval( AST e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 53 Value eval( AST e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 53 { 54 { 54 // dynamic-overload-resolution-pattern: modify here 55 // dynamic-overload-resolution-pattern: modify here 55 enum funName = "eval"; 56 enum funName = "eval"; 56 alias TypeTuple!(e,lay,ctx,overwriteCtx) params; 57 alias TypeTuple!(e,lay,ctx,overwriteCtx) params; 57 58 58 // dynamic-overload-resolution-pattern: dispatch 59 // dynamic-overload-resolution-pattern: dispatch ................................................................................................................................................................................ 65 66 66 // dynamic-overload-resolution-pattern: default behavior 67 // dynamic-overload-resolution-pattern: default behavior 67 assert(false, text("eval() for ",typeid(e)," [",e.pos,"] is not 68 assert(false, text("eval() for ",typeid(e)," [",e.pos,"] is not 68 } 69 } 69 70 70 Value eval( Str e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 71 Value eval( Str e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 71 { 72 { 72 if( isMacroishLayer(lay) ) | 73 if( isASTLayer(lay) ) 73 return ast2table(e, (AST e){return eval(e,lay,ctx);}); 74 return ast2table(e, (AST e){return eval(e,lay,ctx);}); 74 if( lay==ValueLayer ) 75 if( lay==ValueLayer ) 75 return new StrValue(e.data); 76 return new StrValue(e.data); 76 return lift(new StrValue(e.data), lay, ctx, e.pos); 77 return lift(new StrValue(e.data), lay, ctx, e.pos); 77 } 78 } 78 79 79 Value eval( Int e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 80 Value eval( Int e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 80 { 81 { 81 if( isMacroishLayer(lay) ) | 82 if( isASTLayer(lay) ) 82 return ast2table(e, (AST e){return eval(e,lay,ctx);}); 83 return ast2table(e, (AST e){return eval(e,lay,ctx);}); 83 if( lay==ValueLayer ) 84 if( lay==ValueLayer ) 84 return new IntValue(e.data); 85 return new IntValue(e.data); 85 return lift(new IntValue(e.data), lay, ctx, e.pos); 86 return lift(new IntValue(e.data), lay, ctx, e.pos); 86 } 87 } 87 88 88 Value eval( Var e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 89 Value eval( Var e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 89 { 90 { 90 if( isMacroishLayer(lay) ) | 91 if( isASTLayer(lay) ) 91 if( ctx.has(e.name,MacroLayer) ) | 92 if( isMacroLayer(lay) && ctx.has(e.name,MacroLayer) ) 92 return ctx.get(e.name, MacroLayer, e.pos); 93 return ctx.get(e.name, MacroLayer, e.pos); 93 else 94 else 94 return ast2table(e, (AST e){return eval(e,lay,ct 95 return ast2table(e, (AST e){return eval(e,lay,ct 95 if( lay==ValueLayer || ctx.has(e.name, lay) ) 96 if( lay==ValueLayer || ctx.has(e.name, lay) ) 96 return ctx.get(e.name, lay, e.pos); 97 return ctx.get(e.name, lay, e.pos); 97 return lift(ctx.get(e.name, ValueLayer, e.pos), lay, ctx, e.pos) 98 return lift(ctx.get(e.name, ValueLayer, e.pos), lay, ctx, e.pos) 98 } 99 } 99 100 100 Value eval( App e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 101 Value eval( App e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 101 { 102 { 102 Value f = eval( e.fun, lay, ctx ); 103 Value f = eval( e.fun, lay, ctx ); 103 if( isMacroishLayer(lay) ) | 104 if( isASTLayer(lay) ) { 104 if( auto ff = cast(FunValue)f ) | 105 auto ff = cast(FunValue)f; > 106 if( ff !is null && isMacroLayer(lay) ) 105 return invokeFunction(ff, e.args, MacroLayer, ct | 107 return invokeFunction(ff, e.args, lay, ctx, e.po 106 else 108 else 107 return ast2table(e, (AST e){return eval(e,lay,ct 109 return ast2table(e, (AST e){return eval(e,lay,ct > 110 } 108 return invokeFunction(f, e.args, lay, ctx, e.pos, getNameIfPossi 111 return invokeFunction(f, e.args, lay, ctx, e.pos, getNameIfPossi 109 } 112 } 110 113 111 Value eval( Fun e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 114 Value eval( Fun e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 112 { 115 { 113 if( isMacroishLayer(lay) ) | 116 if( isASTLayer(lay) ) > 117 { > 118 // need this for correct scoping (outer scope macro vari > 119 Table newCtx = new Table(ctx, Table.Kind.NotPropagateSet > 120 foreach(p; e.params) > 121 newCtx.set(p.name, ValueLayer, new UndefinedValu 114 return ast2table(e, (AST e){return eval(e,lay,ctx);}); | 122 return ast2table(e, (AST e){return eval(e,lay,newCtx);}) > 123 } 115 else 124 else 116 return createNewFunction(e, ctx); 125 return createNewFunction(e, ctx); 117 } 126 } 118 127 119 Value eval( Lay e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 128 Value eval( Lay e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 120 { 129 { 121 if( isNoLayerChangeLayer(lay) ) 130 if( isNoLayerChangeLayer(lay) ) ................................................................................................................................................................................ 122 return ast2table(e, (AST e){return eval(e,lay,ctx);}); 131 return ast2table(e, (AST e){return eval(e,lay,ctx);}); 123 else 132 else 124 return eval(e.expr, e.layer, ctx); 133 return eval(e.expr, e.layer, ctx); 125 } 134 } 126 135 127 Value eval( Let e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 136 Value eval( Let e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 128 { 137 { 129 // todo @macro let | 138 Table newCtx = overwriteCtx ? ctx : new Table(ctx, Table.Kind.No 130 if( isMacroishLayer(lay) ) | 139 if( isASTLayer(lay) ) 131 return ast2table(e, (AST e){return eval(e,lay,ctx);}); | 140 return ast2table(e, (AST ee){ > 141 if(ee is e.expr) // need this for correct scopin > 142 newCtx.set(e.name, ValueLayer, new Undef > 143 return eval(ee,lay,newCtx); > 144 }); 132 else 145 else 133 { 146 { > 147 Value ri = eval(e.init, lay, newCtx); > 148 newCtx.set(e.name, e.layer.empty ? lay : e.layer, ri); > 149 return eval(e.expr, lay, newCtx, OverwriteCtx); > 150 } > 151 } > 152 > 153 private: > 154 // little little bit incremental macro defining version. > 155 // enables @macro foo(x)=... in ... foo ..., only at the top level of th > 156 // interpreter and functions. better than nothing :P > 157 Tuple!(Value,AST) macroAndEval( AST e_, Layer lay, Table ctx, bool overw > 158 { > 159 assert( !isASTLayer(lay) ); > 160 > 161 AST decodeAST(Value v, LexPosition pos) > 162 { > 163 // [TODO] more informative error message > 164 return polemy2d!(AST)(v, pos); > 165 } > 166 > 167 if(auto e = cast(Let)e_) > 168 { > 169 AST ai = decodeAST(eval(e.init, RawMacroLayer, ctx), e > 170 Value vi = eval(ai, lay, ctx); > 171 134 if( !overwriteCtx ) 172 if( !overwriteCtx ) 135 ctx = new Table(ctx, Table.Kind.NotPropagateSet) 173 ctx = new Table(ctx, Table.Kind.NotPropagateSet) 136 Value ri = eval(e.init, lay, ctx); < 137 string theLayer = e.layer.empty ? lay : e.layer; // neut | 174 string theLayer = e.layer.empty ? lay : e.layer; 138 ctx.set(e.name, theLayer, ri); | 175 ctx.set(e.name, theLayer, vi); > 176 139 return eval(e.expr, lay, ctx, OverwriteCtx); | 177 auto ave = macroAndEval( e.expr, lay, ctx, OverwriteCtx > 178 AST a = new Let(e.pos, e.name, e.layer, ai, ave[1]); > 179 return tuple(ave[0], a); > 180 } > 181 else > 182 { > 183 AST a = decodeAST(eval(e_, RawMacroLayer, ctx), e_.pos > 184 Value v = eval(a, lay, ctx); > 185 return tuple(v, a); 140 } 186 } 141 } 187 } 142 188 143 private: 189 private: 144 string getNameIfPossible(AST e) 190 string getNameIfPossible(AST e) 145 { 191 { 146 if(auto v = cast(Var)e) 192 if(auto v = cast(Var)e) ................................................................................................................................................................................ 151 Value invokeFunction(Value _f, AST[] args, Layer lay, Table ctx, LexPosi 197 Value invokeFunction(Value _f, AST[] args, Layer lay, Table ctx, LexPosi 152 { 198 { 153 if(auto f = cast(FunValue)_f) 199 if(auto f = cast(FunValue)_f) 154 { 200 { 155 Table newCtx = new Table(f.definitionContext(), Table.Ki 201 Table newCtx = new Table(f.definitionContext(), Table.Ki 156 foreach(i,p; f.params()) 202 foreach(i,p; f.params()) 157 if( p.layers.empty ) 203 if( p.layers.empty ) 158 newCtx.set(p.name, (lay==RawMacroLayer ? | 204 newCtx.set(p.name, isMacroLayer(lay)?Mac 159 else 205 else 160 foreach(argLay; p.layers) 206 foreach(argLay; p.layers) 161 newCtx.set(p.name, argLay, eval( 207 newCtx.set(p.name, argLay, eval( 162 scope _ = new PushCallStack(pos, callstackmsg); 208 scope _ = new PushCallStack(pos, callstackmsg); 163 return f.invoke(lay==RawMacroLayer ? MacroLayer : lay, n | 209 return f.invoke(isMacroLayer(lay)?MacroLayer:lay, newCtx 164 } 210 } 165 throw genex!RuntimeException(pos, text("tried to call non-functi 211 throw genex!RuntimeException(pos, text("tried to call non-functi 166 } 212 } 167 213 168 Value lift(Value v, Layer lay, Table ctx, LexPosition pos) 214 Value lift(Value v, Layer lay, Table ctx, LexPosition pos) 169 { 215 { 170 assert( !isMacroishLayer(lay), "lift to the @macro layer should | 216 assert( !isASTLayer(lay), "lift to the @macro layer should never 171 217 172 // functions are automatically lifterd 218 // functions are automatically lifterd 173 if( cast(FunValue) v ) 219 if( cast(FunValue) v ) 174 return v; 220 return v; 175 221 176 if( !ctx.has(lay, SystemLayer) ) 222 if( !ctx.has(lay, SystemLayer) ) 177 throw genex!RuntimeException(pos, "lift function for "~l 223 throw genex!RuntimeException(pos, "lift function for "~l ................................................................................................................................................................................ 229 return this.defCtx.opCmp(rhs.defCtx); 275 return this.defCtx.opCmp(rhs.defCtx); 230 } 276 } 231 assert(false, sprintf!"Cannot compare %s with %s 277 assert(false, sprintf!"Cannot compare %s with %s 232 } 278 } 233 279 234 override Value invoke(Layer lay, Table ctx, LexPosition 280 override Value invoke(Layer lay, Table ctx, LexPosition 235 { 281 { 236 if( lay == MacroLayer ) | 282 if( isASTLayer(lay) ) 237 return eval(ast.funbody, lay, ctx); 283 return eval(ast.funbody, lay, ctx); 238 try { < 239 if( afterMacroAST is null ) | 284 if( afterMacroAST is null ) > 285 { 240 afterMacroAST = polemy2d!(AST)(e | 286 auto va = macroAndEval(e.funbody, lay, c 241 return eval(afterMacroAST, lay, ctx); | 287 afterMacroAST = va[1]; 242 } catch( RuntimeException e ) { | 288 return va[0]; 243 throw e.pos is null ? new RuntimeExcepti < 244 } 289 } > 290 else > 291 return eval(afterMacroAST, lay, ctx); 245 } 292 } 246 293 247 AST afterMacroAST; 294 AST afterMacroAST; 248 } 295 } 249 return new UserDefinedFunValue(e,ctx); 296 return new UserDefinedFunValue(e,ctx); 250 } 297 } 251 298 ................................................................................................................................................................................ 310 } 357 } 311 unittest 358 unittest 312 { 359 { 313 auto e = new Evaluator; 360 auto e = new Evaluator; 314 enrollRuntimeLibrary(e); 361 enrollRuntimeLibrary(e); 315 auto r = assert_nothrow( e.evalString(`var x = 21; var x = x + x*x;`) ); 362 auto r = assert_nothrow( e.evalString(`var x = 21; var x = x + x*x;`) ); 316 assert_eq( r, new IntValue(BigInt(21+21*21)) ); 363 assert_eq( r, new IntValue(BigInt(21+21*21)) ); 317 assert_eq( e.globalContext.get("x",ValueLayer), new IntValue(BigInt(21+2 | 364 assert_eq( e.globalContext.get("x",ValueLayer), new IntValue(21+21*21) ) 318 assert_nothrow( e.globalContext.get("x",ValueLayer) ); 365 assert_nothrow( e.globalContext.get("x",ValueLayer) ); 319 assert_throw!RuntimeException( e.globalContext.get("y",ValueLayer) ); 366 assert_throw!RuntimeException( e.globalContext.get("y",ValueLayer) ); 320 } 367 } 321 unittest 368 unittest 322 { 369 { 323 auto e = new Evaluator; 370 auto e = new Evaluator; 324 enrollRuntimeLibrary(e); 371 enrollRuntimeLibrary(e); 325 assert_eq( e.evalString(`let x=1; let y=(let x=2); x`), new IntValue(Big | 372 assert_eq( e.evalString(`let x=1; let y=(let x=2); x`), new IntValue(1) 326 assert_eq( e.evalString(`let x=1; let y=(let x=2;fun(){x}); y()`), new I | 373 assert_eq( e.evalString(`let x=1; let y=(let x=2;fun(){x}); y()`), new I 327 } 374 } 328 375 329 unittest 376 unittest 330 { 377 { 331 auto e = new Evaluator; 378 auto e = new Evaluator; 332 enrollRuntimeLibrary(e); 379 enrollRuntimeLibrary(e); 333 assert_eq( e.evalString(`@a x=1; @b x=2; @a(x)`), new IntValue(BigInt(1) 380 assert_eq( e.evalString(`@a x=1; @b x=2; @a(x)`), new IntValue(BigInt(1)