Diff
Not logged in

Differences From Artifact [56f0a662740b0906]:

To Artifact [1c0a1caee00496c7]:


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 polemy.layer; 14 import polemy.value; 14 import polemy.value; 15 import polemy.valueconv; 15 import polemy.valueconv; > 16 import std.signals; 16 17 17 /// Objects for maitaining global environment and evaluation of expression on it 18 /// Objects for maitaining global environment and evaluation of expression on it 18 class Evaluator 19 class Evaluator 19 { 20 { 20 public: 21 public: 21 /// Initialize evaluator with empty context 22 /// Initialize evaluator with empty context 22 this() { theContext = new Table; } 23 this() { theContext = new Table; } 23 24 24 /// Evaluate the AST 25 /// Evaluate the AST 25 Value evalAST(AST e) 26 Value evalAST(AST e) 26 { 27 { > 28 AST[void*] mandeCache; 27 return macroAndEval(e, ValueLayer, theContext, OverwriteCtx)[0]; | 29 return macroAndEval(e, ValueLayer, theContext, OverwriteCtx, man 28 } 30 } 29 31 30 /// Evaluate the string 32 /// Evaluate the string 31 Value evalString(S,T...)(S str, T fn_ln_cn) 33 Value evalString(S,T...)(S str, T fn_ln_cn) 32 { 34 { 33 return evalAST(parseString(str,fn_ln_cn)); 35 return evalAST(parseString(str,fn_ln_cn)); 34 } 36 } ................................................................................................................................................................................ 152 } 154 } 153 } 155 } 154 156 155 private: 157 private: 156 // little little bit incremental macro defining version. 158 // little little bit incremental macro defining version. 157 // enables @macro foo(x)=... in ... foo ..., only at the top level of th 159 // enables @macro foo(x)=... in ... foo ..., only at the top level of th 158 // interpreter and functions. better than nothing :P 160 // interpreter and functions. better than nothing :P 159 Tuple!(Value,AST) macroAndEval( AST e_, Layer lay, Table ctx, bool overw | 161 Tuple!(Value,AST) macroAndEval( AST e_, Layer lay, Table ctx, bool overw > 162 , ref AST[void*] mandeCache) // [TODO] avoid assuming non-moving 160 { 163 { 161 assert( !isASTLayer(lay) ); 164 assert( !isASTLayer(lay) ); 162 165 163 AST decodeAST(Value v, LexPosition pos) 166 AST decodeAST(Value v, LexPosition pos) 164 { 167 { 165 // [TODO] more informative error message 168 // [TODO] more informative error message 166 return polemy2d!(AST)(v, pos); 169 return polemy2d!(AST)(v, pos); 167 } 170 } 168 171 169 if(auto e = cast(Let)e_) 172 if(auto e = cast(Let)e_) 170 { 173 { > 174 void* key = cast(void*)e.init; > 175 AST ai; > 176 if(auto p = key in mandeCache) > 177 ai = *p; > 178 else { 171 AST ai = decodeAST(eval(e.init, RawMacroLayer, ctx), e | 179 ai = decodeAST(eval(e.init, RawMacroLayer, ctx), > 180 mandeCache[key] = ai; > 181 } 172 Value vi = eval(ai, lay, ctx); 182 Value vi = eval(ai, lay, ctx); 173 183 174 if( !overwriteCtx ) 184 if( !overwriteCtx ) 175 ctx = new Table(ctx, Table.Kind.NotPropagateSet) 185 ctx = new Table(ctx, Table.Kind.NotPropagateSet) 176 string theLayer = e.layer.empty ? lay : e.layer; 186 string theLayer = e.layer.empty ? lay : e.layer; 177 ctx.set(e.name, theLayer, vi); 187 ctx.set(e.name, theLayer, vi); 178 188 179 auto ave = macroAndEval( e.expr, lay, ctx, OverwriteCtx | 189 auto ave = macroAndEval( e.expr, lay, ctx, OverwriteCtx, 180 AST a = new Let(e.pos, e.name, e.layer, ai, ave[1]); 190 AST a = new Let(e.pos, e.name, e.layer, ai, ave[1]); 181 return tuple(ave[0], a); 191 return tuple(ave[0], a); 182 } 192 } 183 else 193 else 184 { 194 { > 195 void* key = cast(void*)e_; > 196 AST a; > 197 if(auto p = key in mandeCache) > 198 a = *p; > 199 else { 185 AST a = decodeAST(eval(e_, RawMacroLayer, ctx), e_.pos | 200 a = decodeAST(eval(e_, RawMacroLayer, ctx), e_.p > 201 mandeCache[key] = a; > 202 } 186 Value v = eval(a, lay, ctx); | 203 Value v = eval(a, lay, ctx, overwriteCtx); 187 return tuple(v, a); 204 return tuple(v, a); 188 } 205 } 189 } 206 } 190 207 191 private: 208 private: 192 string getNameIfPossible(AST e) 209 string getNameIfPossible(AST e) 193 { 210 { ................................................................................................................................................................................ 271 throw genex!RuntimeException("comparison with va 288 throw genex!RuntimeException("comparison with va 272 } 289 } 273 override hash_t toHash() { 290 override hash_t toHash() { 274 return (cast(hash_t)cast(void*)ast) + (cast(hash 291 return (cast(hash_t)cast(void*)ast) + (cast(hash 275 } 292 } 276 293 277 AST macroCache; 294 AST macroCache; > 295 AST[void*] mandeCache; 278 static class MemokeyType 296 static class MemokeyType 279 { 297 { 280 void* a; Layer b; Tuple!(string,Layer,Value)[] c 298 void* a; Layer b; Tuple!(string,Layer,Value)[] c 281 hash_t toHash() { 299 hash_t toHash() { 282 hash_t h = structuralHash(a) + structura 300 hash_t h = structuralHash(a) + structura 283 foreach(e; c) 301 foreach(e; c) 284 h += structuralHash(e[0])+struct 302 h += structuralHash(e[0])+struct ................................................................................................................................................................................ 294 { 312 { 295 if( isASTLayer(lay) ) 313 if( isASTLayer(lay) ) 296 return eval(ast.funbody, lay, ctx); 314 return eval(ast.funbody, lay, ctx); 297 315 298 auto nonMemoizedRun = (){ 316 auto nonMemoizedRun = (){ 299 if( macroCache is null ) 317 if( macroCache is null ) 300 { 318 { 301 auto va = macroAndEval(e.funbody | 319 auto va = macroAndEval(e.funbody 302 macroCache = va[1]; 320 macroCache = va[1]; 303 return va[0]; 321 return va[0]; 304 } 322 } 305 else 323 else 306 return eval(macroCache, lay, ctx 324 return eval(macroCache, lay, ctx 307 }; 325 }; 308 326 ................................................................................................................................................................................ 466 assert_nothrow( e.evalString(`case 1 when 1: 2`) ); 484 assert_nothrow( e.evalString(`case 1 when 1: 2`) ); 467 485 468 // this is a shorthand for 486 // this is a shorthand for 469 // @macro x = fun(){} in @macro(x) 487 // @macro x = fun(){} in @macro(x) 470 // so it is ok to fail, but it is really incovenient on REPL 488 // so it is ok to fail, but it is really incovenient on REPL 471 assert_nothrow( e.evalString(`@macro x=fun(){}`) ); 489 assert_nothrow( e.evalString(`@macro x=fun(){}`) ); 472 } 490 } 473 < 474 /* < 475 unittest < 476 { < 477 assert_eq( evalString(`var fac = fun(x){ < 478 if(x) < 479 { x*fac(x-1); } < 480 else < 481 { 1; }; < 482 }; < 483 fac(10);`).val, new IntValue(BigInt(10*9*8*5040))); < 484 assert_eq( evalString(`var fib = fun(x){ < 485 if(x<2) < 486 { 1; } < 487 else < 488 { fib(x-1) + fib(x-2); }; < 489 }; < 490 fib(5);`).val, new IntValue(BigInt(8))); < 491 } < 492 unittest < 493 { < 494 assert_eq( evalString(`@@t = fun(x){x+1}; @t(123)`).val, new IntValue(Bi < 495 // there was a bug that declaration in the first line of function defini < 496 // cannot be recursive < 497 assert_nothrow( evalString(`def foo() { < 498 def bar(y) { if(y<1) {0} else {bar(0)} }; < 499 bar(1) < 500 }; foo()`) ); < 501 } < 502 */ <