Differences From Artifact [8d6e708eceba536a]:
- File
polemy/eval.d
- 2010-11-26 07:42:38 - part of checkin [f7e9e77316] on branch trunk - introduced "..." expression, and replaced the pattern match failure with this. (user: kinaba) [annotate]
To Artifact [10da2d7378e56ec4]:
- File
polemy/eval.d
- 2010-11-26 15:13:58 - part of checkin [6760e0dd02] on branch trunk - evaluator refactoring done. x6 speed up. (user: kinaba) [annotate]
21 21 public:
22 22 /// Initialize evaluator with empty context
23 23 this() { theContext = new Table; }
24 24
25 25 /// Evaluate the AST
26 26 Value evalAST(AST e)
27 27 {
28 - AST[void*] mandeCache;
29 - return macroAndEval(e, ValueLayer, theContext, OverwriteCtx, mandeCache)[0];
28 + return macroAndEval(e, ValueLayer, theContext, OverwriteCtx);
30 29 }
31 30
32 31 /// Evaluate the string
33 32 Value evalString(S,T...)(S str, T fn_ln_cn)
34 33 {
35 34 return evalAST(parseString(str,fn_ln_cn));
36 35 }
................................................................................
48 47 }
49 48
50 49 private:
51 50 Table theContext;
52 51
53 52 enum : bool { CascadeCtx=false, OverwriteCtx=true };
54 53
55 - Value eval( AST e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )
54 + LayerEval getLayerEvaluator(Layer lay)
56 55 {
57 - // dynamic-overload-resolution-pattern: modify here
58 - enum funName = "eval";
59 - alias TypeTuple!(e,lay,ctx,overwriteCtx) params;
60 -
61 - // dynamic-overload-resolution-pattern: dispatch
62 - alias typeof(__traits(getOverloads, this, funName)) ovTypes;
63 - alias staticMap!(firstParam, ovTypes) fstTypes;
64 - alias DerivedToFront!(fstTypes) fstTypes_sorted;
65 - foreach(i, T; fstTypes_sorted)
66 - static if( is(T == typeof(params[0])) ) {} else if( auto _x = cast(T)params[0] )
67 - return __traits(getOverloads, this, funName)[i](_x, params[1..$]);
68 -
69 - // dynamic-overload-resolution-pattern: default behavior
70 - assert(false, text("eval() for ",typeid(e)," [",e.pos,"] is not defined"));
56 + if( lay == ValueLayer )
57 + return new ValueLayerEval;
58 + if( lay == RawMacroLayer )
59 + return new RawMacroLayerEval;
60 + if( lay == MacroLayer )
61 + return new MacroLayerEval;
62 + return new UserDefinedLayerEval(lay);
71 63 }
72 64
73 - Value eval( Str e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )
74 - {
75 - if( isASTLayer(lay) )
76 - return ast2table(e, (AST e){return eval(e,lay,ctx);});
77 - if( isUserDefinedLayer(lay) )
78 - return lift(new StrValue(e.data), lay, ctx, e.pos);
79 - return new StrValue(e.data);
80 - }
81 -
82 - Value eval( Int e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )
65 + abstract class LayerEval
83 66 {
84 - if( isASTLayer(lay) )
85 - return ast2table(e, (AST e){return eval(e,lay,ctx);});
86 - if( isUserDefinedLayer(lay) )
87 - return lift(new IntValue(e.data), lay, ctx, e.pos);
88 - return new IntValue(e.data);
89 - }
90 -
91 - Value eval( Var e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )
92 - {
93 - if( isASTLayer(lay) )
94 - if( isMacroLayer(lay) && ctx.has(e.name,MacroLayer) )
95 - return ctx.get(e.name, MacroLayer, e.pos);
96 - else
97 - return ast2table(e, (AST e){return eval(e,lay,ctx);});
98 - if( isUserDefinedLayer(lay) && !ctx.has(e.name, lay) )
99 - return lift(ctx.get(e.name, ValueLayer, e.pos), lay, ctx, e.pos);
100 - return ctx.get(e.name, lay, e.pos);
101 - }
102 -
103 - Value eval( App e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )
104 - {
105 - Value f = eval( e.fun, lay, ctx );
106 - if( isASTLayer(lay) ) {
107 - auto ff = cast(FunValue)f;
108 - if( ff !is null && isMacroLayer(lay) )
109 - return invokeFunction(ff, e.args, lay, ctx, e.pos, getNameIfPossible(e.fun));
110 - else
111 - return ast2table(e, (AST e){return eval(e,lay,ctx);});
112 - }
113 - return invokeFunction(f, e.args, lay, ctx, e.pos, getNameIfPossible(e.fun));
67 + /// Concrete layers should implement these
68 + Layer currentLayer();
69 + Value eval_( Die e, Table ctx, bool ctxMod );///
70 + Value eval_( Str e, Table ctx, bool ctxMod );///
71 + Value eval_( Int e, Table ctx, bool ctxMod );///
72 + Value eval_( Var e, Table ctx, bool ctxMod );///
73 + Value eval_( Lay e, Table ctx, bool ctxMod );///
74 + Value eval_( Let e, Table ctx, bool ctxMod );///
75 + Value eval_( App e, Table ctx, bool ctxMod );///
76 + Value eval_( Fun e, Table ctx, bool ctxMod );///
77 +
78 + /// dynamic-overload-resolution
79 + Value eval( AST e, Table ctx, bool ctxMod )
80 + {
81 + enum funName = "eval_"; // modify here to customize
82 + alias TypeTuple!(e,ctx,ctxMod) params; // modify here to customize
83 +
84 + alias typeof(__traits(getOverloads, this, funName)) ovTypes;
85 + alias staticMap!(firstParam, ovTypes) fstTypes;
86 + alias DerivedToFront!(fstTypes) fstTypes_sorted;
87 + foreach(i, T; fstTypes_sorted)
88 + static if( is(T == typeof(params[0])) ) {} else if( auto _x = cast(T)params[0] )
89 + return __traits(getOverloads, this, funName)[i](_x, params[1..$]);
90 +
91 + // modify here to customize the default behavior
92 + assert(false, text("eval() for ",typeid(e)," [",e.pos,"] is not defined"));
93 + }
94 +
95 + ///
96 + Value invokeFunction(Value _f, AST[] args, Table ctx, LexPosition pos, string callstackmsg)
97 + {
98 + if(auto f = cast(FunValue)_f)
99 + {
100 + Table newCtx = new Table(f.definitionContext(), Table.Kind.NotPropagateSet);
101 + foreach(i,p; f.params())
102 + if( p.layers.empty ) {
103 + Value v = this.eval(args[i], ctx, CascadeCtx);
104 + if(v is null) v = ast2table(args[i]);
105 + newCtx.set(p.name, currentLayer(), v);
106 + }
107 + else
108 + foreach(argLay; p.layers) {
109 + Layer ll = argLay;
110 + if( isMacroLayer(argLay) && typeid(this)!=typeid(MacroLayerEval) )
111 + ll = RawMacroLayer; // explicit @macro invokes (rawmacro)
112 + Value v = getLayerEvaluator(ll).eval(args[i], ctx, CascadeCtx);
113 + if(v is null) v = ast2table(args[i]);
114 + newCtx.set(p.name, argLay, v);
115 + }
116 + scope _ = new PushCallStack(pos, callstackmsg);
117 + return f.invoke(currentLayer(), newCtx, pos);
118 + }
119 + throw genex!RuntimeException(pos, text("tried to call non-function: ",_f));
120 + }
121 +
122 + ///
123 + Value lift(Value v, Table ctx, LexPosition pos)
124 + {
125 + Layer lay = currentLayer();
126 +
127 + // functions are automatically lifterd
128 + if( cast(FunValue) v )
129 + return v;
130 +
131 + if( !ctx.has(lay, LiftLayer) )
132 + throw genex!RuntimeException(pos, "lift function for "~lay~" is not registered" );
133 +
134 + // similar to invokeFunction, but with only one argument bound to ValueLayer
135 + auto _f = ctx.get(lay, LiftLayer, pos);
136 + if(auto f = cast(FunValue)_f)
137 + {
138 + Table newCtx = new Table(f.definitionContext(), Table.Kind.NotPropagateSet);
139 + auto ps = f.params();
140 + if( ps.length != 1 )
141 + throw genex!RuntimeException(pos,
142 + text("lift function for", lay, " must take exactly one argument of ", ValueLayer));
143 + if( ps[0].layers.length==0 || ps[0].layers.length==1 && ps[0].layers[0]==ValueLayer )
144 + {
145 + newCtx.set(ps[0].name, ValueLayer, v);
146 + scope _ = new PushCallStack(pos, lay);
147 + return f.invoke(ValueLayer, newCtx, pos);
148 + }
149 + else
150 + throw genex!RuntimeException(pos,
151 + text("lift function for", lay, " must take exactly one argument of ", ValueLayer));
152 + }
153 + throw genex!RuntimeException(pos,
154 + text("non-function ", _f, " is registered as the lift function for ", lay));
155 + }
114 156 }
115 157
116 - Value eval( Fun e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )
117 - {
118 - if( isASTLayer(lay) )
119 - {
120 - // need this for correct scoping (outer scope macro variables must be hidden!)
121 - Table newCtx = new Table(ctx, Table.Kind.NotPropagateSet);
122 - foreach(p; e.params)
123 - newCtx.set(p.name, NoopLayer, null);
124 - return ast2table(e, (AST e){return eval(e,lay,newCtx);});
125 - }
126 - else
127 - return createNewFunction(e, ctx);
128 - }
129 -
130 - Value eval( Lay e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )
158 + /// Evaluator for standard @value semantics
159 + class ValueLayerEval : LayerEval
131 160 {
132 - if( isNoLayerChangeLayer(lay) )
133 - return ast2table(e, (AST e){return eval(e,lay,ctx);});
134 - else
135 - return eval(e.expr, e.layer, ctx);
136 - }
137 -
138 - Value eval( Let e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )
139 - {
140 - Table newCtx = overwriteCtx ? ctx : new Table(ctx, Table.Kind.NotPropagateSet);
141 - if( isASTLayer(lay) )
142 - return ast2table(e, (AST ee){
143 - // need this for correct scoping (outer scope macro variables must be hidden!)
144 - if(e.name!="_" && ee is e.expr)
145 - newCtx.set(e.name, NoopLayer, null);
146 - return eval(ee,lay,newCtx);
147 - });
148 - else
149 - {
150 - Value ri = eval(e.init, lay, newCtx);
161 + override Layer currentLayer()
162 + {
163 + return ValueLayer;
164 + }
165 + override Value eval_( Die e, Table ctx, bool ctxMod )
166 + {
167 + throw genex!RuntimeException(e.pos, "undefined case");
168 + }
169 + override Value eval_( Str e, Table ctx, bool ctxMod )
170 + {
171 + return new StrValue(e.data);
172 + }
173 + override Value eval_( Int e, Table ctx, bool ctxMod )
174 + {
175 + return new IntValue(e.data);
176 + }
177 + override Value eval_( Var e, Table ctx, bool ctxMod )
178 + {
179 + return ctx.get(e.name, currentLayer(), e.pos);
180 + }
181 + override Value eval_( Lay e, Table ctx, bool ctxMod )
182 + {
183 + auto le = getLayerEvaluator(e.layer);
184 + auto v = le.eval(e.expr,ctx,CascadeCtx);
185 + if( (v is null) && (cast(MacroLayerEval)le !is null) )
186 + return ast2table(e.expr);
187 + else
188 + return v;
189 + }
190 + override Value eval_( Let e, Table ctx, bool ctxMod )
191 + {
192 + Table newCtx = ctxMod ? ctx : new Table(ctx, Table.Kind.NotPropagateSet);
193 + Value ri = this.eval(e.init, newCtx, CascadeCtx);
151 194 if(e.name!="_")
152 - newCtx.set(e.name, e.layer.empty ? lay : e.layer, ri);
153 - return eval(e.expr, lay, newCtx, OverwriteCtx);
195 + newCtx.set(e.name, e.layer.empty ? currentLayer() : e.layer, ri);
196 + return this.eval(e.expr, newCtx, OverwriteCtx);
197 + }
198 + override Value eval_( App e, Table ctx, bool ctxMod )
199 + {
200 + Value f = this.eval( e.fun, ctx, CascadeCtx );
201 + return this.invokeFunction(f, e.args, ctx, e.pos, getNameIfPossible(e.fun));
202 + }
203 + override Value eval_( Fun e, Table ctx, bool ctxMod )
204 + {
205 + return createNewFunction(e, ctx);
154 206 }
155 207 }
156 208
157 - Value eval( Die e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )
209 + /// Evaluator for user-defined layer
210 + class UserDefinedLayerEval : ValueLayerEval
158 211 {
159 - if( isMacroLayer(lay) )
160 - return ast2table(e, (AST e){return eval(e,lay,ctx);});
161 - if( isUserDefinedLayer(lay) )
212 + Layer layerID;
213 + mixin SimpleConstructor;
214 +
215 + override Layer currentLayer()
216 + {
217 + return layerID;
218 + }
219 + override Value eval_( Die e, Table ctx, bool ctxMod )
220 + {
162 221 return new UndefinedValue;
163 - throw genex!RuntimeException(e.pos, "undefined case");
222 + }
223 + override Value eval_( Str e, Table ctx, bool ctxMod )
224 + {
225 + return this.lift(new StrValue(e.data), ctx, e.pos);
226 + }
227 + override Value eval_( Int e, Table ctx, bool ctxMod )
228 + {
229 + return this.lift(new IntValue(e.data), ctx, e.pos);
230 + }
231 + override Value eval_( Var e, Table ctx, bool ctxMod )
232 + {
233 + if( ctx.has(e.name, currentLayer()) )
234 + return ctx.get(e.name, currentLayer());
235 + return this.lift(ctx.get(e.name, ValueLayer, e.pos), ctx, e.pos);
236 + }
164 237 }
165 238
166 -private:
167 - // little little bit incremental macro defining version.
168 - // enables @macro foo(x)=... in ... foo ..., only at the top level of the
169 - // interpreter and functions. better than nothing :P
170 - Tuple!(Value,AST) macroAndEval( AST e_, Layer lay, Table ctx, bool overwriteCtx
171 - , ref AST[void*] mandeCache) // [TODO] avoid assuming non-moving GC
239 + // Convention!!
240 + // returns null if never used macro-like feature
241 + class MacroLayerEval : LayerEval
172 242 {
173 - assert( !isASTLayer(lay) );
174 -
175 - AST decodeAST(Value v, LexPosition pos)
243 + override Layer currentLayer()
244 + {
245 + return MacroLayer;
246 + }
247 + override Value eval_( Die e, Table ctx, bool ctxMod )
248 + {
249 + return null;
250 + }
251 + override Value eval_( Str e, Table ctx, bool ctxMod )
252 + {
253 + return null;
254 + }
255 + override Value eval_( Int e, Table ctx, bool ctxMod )
256 + {
257 + return null;
258 + }
259 + override Value eval_( Var e, Table ctx, bool ctxMod )
260 + {
261 + if( ctx.has(e.name, currentLayer()) )
262 + return ctx.get(e.name, currentLayer(), e.pos);
263 + else
264 + return null;
265 + }
266 + override Value eval_( Lay e, Table ctx, bool ctxMod )
176 267 {
177 - // [TODO] more informative error message
178 - return polemy2d!(AST)(v, pos);
268 + auto le = getLayerEvaluator(e.layer);
269 + return le.eval(e.expr,ctx,CascadeCtx);
179 270 }
180 -
181 - if(auto e = cast(Let)e_)
271 + override Value eval_( Let e, Table ctx, bool ctxMod )
182 272 {
183 - void* key = cast(void*)e.init;
184 - AST ai;
185 - if(auto p = key in mandeCache)
186 - ai = *p;
187 - else {
188 - ai = decodeAST(eval(e.init, RawMacroLayer, ctx), e.init.pos);
189 - mandeCache[key] = ai;
190 - }
191 - Value vi = eval(ai, lay, ctx);
192 -
193 - if( !overwriteCtx )
194 - ctx = new Table(ctx, Table.Kind.NotPropagateSet);
195 - string theLayer = e.layer.empty ? lay : e.layer;
196 - ctx.set(e.name, theLayer, vi);
197 -
198 - auto ave = macroAndEval( e.expr, lay, ctx, OverwriteCtx, mandeCache );
199 - AST a = new Let(e.pos, e.name, e.layer, ai, ave[1]);
200 - return tuple(ave[0], a);
273 + Table newCtx = ctxMod ? ctx : new Table(ctx, Table.Kind.NotPropagateSet);
274 + Value ai = this.eval(e.init, newCtx, CascadeCtx);
275 + newCtx.set(e.name, NoopLayer, null);
276 + Value ae = this.eval(e.expr, newCtx, OverwriteCtx);
277 + if( ai is null && ae is null )
278 + return null;
279 + if( ai is null ) ai = ast2table(e.init);
280 + if( ae is null ) ae = ast2table(e.expr);
281 + return ast2table(e, delegate Value (AST _){
282 + if(_ is e.init) { return ai; }
283 + if(_ is e.expr) { return ae; }
284 + assert(false);
285 + });
201 286 }
202 - else
287 + override Value eval_( App e, Table ctx, bool ctxMod )
203 288 {
204 - void* key = cast(void*)e_;
205 - AST a;
206 - if(auto p = key in mandeCache)
207 - a = *p;
289 + Value f = this.eval( e.fun, ctx, CascadeCtx );
290 + if(auto ff = cast(FunValue)f)
291 + return this.invokeFunction(ff, e.args, ctx, e.pos, getNameIfPossible(e.fun));
208 292 else {
209 - a = decodeAST(eval(e_, RawMacroLayer, ctx), e_.pos);
210 - mandeCache[key] = a;
293 + bool allNull = (f is null);
294 + Value[] vas;
295 + foreach(a; e.args) {
296 + Value va = this.eval(a, ctx, CascadeCtx);
297 + if(va !is null) allNull = false;
298 + vas ~= va;
299 + }
300 + if( allNull )
301 + return null;
302 + return ast2table(e, delegate Value (AST _){
303 + if(_ is e.fun) return (f is null ? ast2table(e.fun) : f);
304 + foreach(i,a; e.args) if(_ is a) return (vas[i] is null ? ast2table(a) : vas[i]);
305 + assert(false);
306 + });
211 307 }
212 - Value v = eval(a, lay, ctx, overwriteCtx);
213 - return tuple(v, a);
308 + }
309 + override Value eval_( Fun e, Table ctx, bool ctxMod )
310 + {
311 + Table newCtx = new Table(ctx, Table.Kind.NotPropagateSet);
312 + foreach(p; e.params)
313 + newCtx.set(p.name, NoopLayer, null);
314 + Value af = this.eval(e.funbody, newCtx, CascadeCtx);
315 + if( af is null )
316 + return null;
317 + return ast2table(e, (AST _){if(_ is e.funbody)return af; assert(false);});
318 + }
319 + }
320 +
321 + class RawMacroLayerEval : MacroLayerEval
322 + {
323 + override Value eval_( Lay e, Table ctx, bool ctxMod )
324 + {
325 + Value ae = this.eval(e.expr, ctx, CascadeCtx);
326 + return ae is null ? null
327 + : ast2table(e, delegate Value (AST _){if(_ is e.expr)return ae; assert(false);});
328 + }
329 + }
330 +
331 +private:
332 + Value macroAndEval( AST e_, Layer lay, Table ctx, bool ctxMod )
333 + {
334 + assert( !isASTLayer(lay) );
335 + if(auto e = cast(Let)e_)
336 + {
337 + Value vai = getLayerEvaluator(RawMacroLayer).eval(e.init, ctx, CascadeCtx);
338 + AST ai = (vai is null ? e.init : polemy2d!(AST)(vai, e.pos));
339 +
340 + if( !ctxMod )
341 + ctx = new Table(ctx, Table.Kind.NotPropagateSet);
342 +
343 + Value vi = getLayerEvaluator(lay).eval(ai, ctx, CascadeCtx);
344 + string theLayer = e.layer.empty ? lay : e.layer;
345 + ctx.set(e.name, theLayer, vi);
346 +
347 + return macroAndEval( e.expr, lay, ctx, OverwriteCtx );
348 + }
349 + else
350 + {
351 + Value va = getLayerEvaluator(RawMacroLayer).eval(e_, ctx, ctxMod);
352 + AST a = (va is null ? e_ : polemy2d!(AST)(va, e_.pos));
353 + return getLayerEvaluator(lay).eval(a, ctx, ctxMod);
214 354 }
215 355 }
216 356
217 357 private:
218 358 string getNameIfPossible(AST e)
219 359 {
220 360 if(auto v = cast(Var)e)
221 361 return v.name;
222 362 return "";
223 363 }
224 364
225 - Value invokeFunction(Value _f, AST[] args, Layer lay, Table ctx, LexPosition pos, string callstackmsg)
226 - {
227 - if(auto f = cast(FunValue)_f)
228 - {
229 - Table newCtx = new Table(f.definitionContext(), Table.Kind.NotPropagateSet);
230 - foreach(i,p; f.params())
231 - if( p.layers.empty )
232 - newCtx.set(p.name, isMacroLayer(lay)?MacroLayer:lay, eval(args[i], lay, ctx));
233 - else
234 - foreach(argLay; p.layers)
235 - if( lay!=MacroLayer && isMacroLayer(argLay) ) // explicit @macro invokes (rawmacro)
236 - newCtx.set(p.name, argLay, eval(args[i], RawMacroLayer, ctx));
237 - else
238 - newCtx.set(p.name, argLay, eval(args[i], argLay, ctx));
239 - scope _ = new PushCallStack(pos, callstackmsg);
240 - return f.invoke(isMacroLayer(lay)?MacroLayer:lay, newCtx, pos);
241 - }
242 - throw genex!RuntimeException(pos, text("tried to call non-function: ",_f));
243 - }
244 -
245 - Value lift(Value v, Layer lay, Table ctx, LexPosition pos)
246 - {
247 - assert( !isASTLayer(lay), "lift to the @macro layer should never happen" );
248 -
249 - // functions are automatically lifterd
250 - if( cast(FunValue) v )
251 - return v;
252 -
253 - if( !ctx.has(lay, LiftLayer) )
254 - throw genex!RuntimeException(pos, "lift function for "~lay~" is not registered" );
255 -
256 - // similar to invokeFunction, but with only one argument bound to ValueLayer
257 - auto _f = ctx.get(lay, LiftLayer, pos);
258 - if(auto f = cast(FunValue)_f)
259 - {
260 - Table newCtx = new Table(f.definitionContext(), Table.Kind.NotPropagateSet);
261 - auto ps = f.params();
262 - if( ps.length != 1 )
263 - throw genex!RuntimeException(pos,
264 - text("lift function for", lay, " must take exactly one argument of ", ValueLayer));
265 - if( ps[0].layers.length==0 || ps[0].layers.length==1 && ps[0].layers[0]==ValueLayer )
266 - {
267 - newCtx.set(ps[0].name, ValueLayer, v);
268 - scope _ = new PushCallStack(pos, lay);
269 - return f.invoke(ValueLayer, newCtx, pos);
270 - }
271 - else
272 - throw genex!RuntimeException(pos,
273 - text("lift function for", lay, " must take exactly one argument of ", ValueLayer));
274 - }
275 - throw genex!RuntimeException(pos,
276 - text("non-function ", _f, " is registered as the lift function for ", lay));
277 - }
278 -
279 365 Value createNewFunction(Fun e, Table ctx)
280 366 {
281 367 class UserDefinedFunValue : FunValue
282 368 {
283 369 Fun ast;
284 370 Table defCtx;
285 371 override const(Parameter[]) params() { return ast.params; }
................................................................................
318 404 mixin SimpleConstructor;
319 405 mixin SimpleCompareWithoutToHash;
320 406 }
321 407 static Tuple!(Value,int)[MemokeyType] memo;
322 408
323 409 override Value invoke(Layer lay, Table ctx, LexPosition pos)
324 410 {
325 - if( isASTLayer(lay) )
326 - return eval(ast.funbody, lay, ctx);
327 -
411 + if( isASTLayer(lay) ) {
412 + Value v = getLayerEvaluator(lay).eval(ast.funbody, ctx, CascadeCtx);
413 + if( v is null ) v = ast2table(ast.funbody);
414 + return v;
415 + }
416 + return macroAndEval(ast.funbody, lay, ctx, CascadeCtx);
417 +/*
328 418 auto nonMemoizedRun = (){
329 419 if( macroCache is null )
330 420 {
331 421 auto va = macroAndEval(e.funbody, lay, ctx, CascadeCtx, mandeCache);
332 422 macroCache = va[1];
333 423 return va[0];
334 424 }
................................................................................
351 441
352 442 Value r = nonMemoizedRun();
353 443
354 444 int touched = memo[memokey][1];
355 445 memo[memokey] = tuple(r, 12345678);
356 446 //if(touched) {DBG("rerun :: ",r);r = nonMemoizedRun();} // twice!!
357 447 return r;
448 +*/
358 449 }
359 450 }
360 451 return new UserDefinedFunValue(e,ctx);
361 452 }
362 453
363 454 public:
364 455 /// Add primitive function to the global context