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