Differences From Artifact [56f0a662740b0906]:
- File
polemy/eval.d
- 2010-11-26 05:29:24 - part of checkin [f8684f4d69] on branch trunk - changed the desugaring of >>@macro x=e from >>@macro x=e in x to >>@macro x=e in "(macro definition)" for convenience during REPL interaction (user: kinaba) [annotate]
To Artifact [1c0a1caee00496c7]:
- File
polemy/eval.d
- 2010-11-26 06:46:09 - part of checkin [552d43f567] on branch trunk - one-by-one M&E memoizer (user: kinaba) [annotate]
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 */ <