Differences From 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]
To Artifact [9460508c714f0a1b]:
- File
polemy/eval.d
- 2010-11-27 11:46:26 - part of checkin [203e4cb208] on branch trunk - fixed automatic memoization bug (whole part of the contexts are now used as the memo key) (user: kinaba) [annotate]
15 import polemy.valueconv; 15 import polemy.valueconv;
16 import std.signals; 16 import std.signals;
17 17
18 /// Objects for maitaining global environment and evaluation of expression on it 18 /// Objects for maitaining global environment and evaluation of expression on it
19 class Evaluator 19 class Evaluator
20 { 20 {
21 public: 21 public:
22 /// Initialize evaluator with empty context <
23 this() { theContext = new Table; } <
24 <
25 /// Evaluate the AST 22 /// Evaluate the AST
26 Value evalAST(AST e) 23 Value evalAST(AST e)
27 { | 24 { return getLayerEval(ValueLayer).macroAndEval(e, theContext, La
28 return macroAndEval(e, ValueLayer, theContext, OverwriteCtx); <
29 } <
30 25
31 /// Evaluate the string 26 /// Evaluate the string
32 Value evalString(S,T...)(S str, T fn_ln_cn) 27 Value evalString(S,T...)(S str, T fn_ln_cn)
33 { <
34 return evalAST(parseString(str,fn_ln_cn)); | 28 { return evalAST(parseString(str,fn_ln_cn)); }
35 } <
36 29
37 /// Evaluate the file 30 /// Evaluate the file
38 Value evalFile(S,T...)(S filename, T ln_cn) 31 Value evalFile(S,T...)(S filename, T ln_cn)
39 { <
40 return evalAST(parseFile(filename,ln_cn)); | 32 { return evalAST(parseFile(filename,ln_cn)); }
41 } <
42 33
43 /// Get the global context 34 /// Get the global context
44 Table globalContext() 35 Table globalContext()
> 36 { return theContext; }
> 37
> 38 /// Initialize evaluator with empty context
> 39 this()
45 { 40 {
46 return theContext; | 41 theContext = new Table;
> 42 theLayers[ValueLayer] = new ValueLayerEval;
> 43 theLayers[MacroLayer] = new MacroLayerEval;
> 44 theLayers[RawMacroLayer] = new RawMacroLayerEval;
47 } 45 }
48 46
49 private: 47 private:
50 Table theContext; | 48 Table theContext;
> 49 LayerEval[Layer] theLayers;
51 50
52 enum : bool { CascadeCtx=false, OverwriteCtx=true }; | 51 /// Get the layer evaluator from layer ID
53 <
54 LayerEval getLayerEvaluator(Layer lay) | 52 LayerEval getLayerEval(Layer lay)
55 { 53 {
56 if( lay == ValueLayer ) | 54 if(auto p = lay in theLayers)
57 return new ValueLayerEval; | 55 return *p;
58 if( lay == RawMacroLayer ) <
59 return new RawMacroLayerEval; <
60 if( lay == MacroLayer ) <
61 return new MacroLayerEval; <
62 return new UserDefinedLayerEval(lay); | 56 return theLayers[lay] = new UserDefinedLayerEval(lay);
63 } 57 }
64 58
> 59 /// Interface of layers
65 abstract class LayerEval 60 abstract class LayerEval
66 { 61 {
> 62 enum : bool { CascadeCtx=false, OverwriteCtx=true };
> 63
67 /// Concrete layers should implement these 64 /// Concrete layers should implement these
68 Layer currentLayer(); | 65 protected Layer layerID();
69 Value eval_( Die e, Table ctx, bool ctxMod );/// | 66 protected Value eval_( Die e, Table ctx, bool ctxMod );///
70 Value eval_( Str e, Table ctx, bool ctxMod );/// | 67 protected Value eval_( Str e, Table ctx, bool ctxMod );///
71 Value eval_( Int e, Table ctx, bool ctxMod );/// | 68 protected Value eval_( Int e, Table ctx, bool ctxMod );///
72 Value eval_( Var e, Table ctx, bool ctxMod );/// | 69 protected Value eval_( Var e, Table ctx, bool ctxMod );///
73 Value eval_( Lay e, Table ctx, bool ctxMod );/// | 70 protected Value eval_( Lay e, Table ctx, bool ctxMod );///
74 Value eval_( Let e, Table ctx, bool ctxMod );/// | 71 protected Value eval_( Let e, Table ctx, bool ctxMod );///
75 Value eval_( App e, Table ctx, bool ctxMod );/// | 72 protected Value eval_( App e, Table ctx, bool ctxMod );///
76 Value eval_( Fun e, Table ctx, bool ctxMod );/// | 73 protected Value eval_( Fun e, Table ctx, bool ctxMod );///
> 74
> 75 /// Should override this also, if the layer may return null for
> 76 Value evalToNonNull( AST e, Table ctx, bool ctxMod = CascadeCtx
> 77 { return eval(e,ctx,ctxMod); }
> 78
> 79 /// Do macro expansion first, and then eval. Should override thi
> 80 Value macroAndEval( AST e, Table ctx, bool ctxMod = CascadeCtx )
> 81 { return evalToNonNull(e,ctx,ctxMod); }
77 82
78 /// dynamic-overload-resolution 83 /// dynamic-overload-resolution
79 Value eval( AST e, Table ctx, bool ctxMod ) | 84 Value eval( AST e, Table ctx, bool ctxMod = CascadeCtx )
80 { 85 {
81 enum funName = "eval_"; // modify here t | 86 enum funName = "eval_"; // modify here f
82 alias TypeTuple!(e,ctx,ctxMod) params; // modify here t | 87 alias TypeTuple!(e,ctx,ctxMod) params; // modify here f
83 88
84 alias typeof(__traits(getOverloads, this, funName)) ovTy 89 alias typeof(__traits(getOverloads, this, funName)) ovTy
85 alias staticMap!(firstParam, ovTypes) fstTy 90 alias staticMap!(firstParam, ovTypes) fstTy
86 alias DerivedToFront!(fstTypes) fstTypes_sor 91 alias DerivedToFront!(fstTypes) fstTypes_sor
87 foreach(i, T; fstTypes_sorted) 92 foreach(i, T; fstTypes_sorted)
88 static if( is(T == typeof(params[0])) ) {} else 93 static if( is(T == typeof(params[0])) ) {} else
89 return __traits(getOverloads, this, funN 94 return __traits(getOverloads, this, funN
90 95
91 // modify here to customize the default behavior 96 // modify here to customize the default behavior
92 assert(false, text("eval() for ",typeid(e)," [",e.pos,"] 97 assert(false, text("eval() for ",typeid(e)," [",e.pos,"]
93 } 98 }
94 99
95 /// | 100 /// Function calling convention.
> 101 /// Run all arugment AST in the appropriate layer and invoke the
96 Value invokeFunction(Value _f, AST[] args, Table ctx, LexPositio | 102 Value invokeFunction(Value f_, AST[] args, Table ctx, LexPositio
97 { 103 {
98 if(auto f = cast(FunValue)_f) | 104 FunValue f = cast(FunValue)f_;
> 105 if( f is null )
> 106 throw genex!RuntimeException(pos, text("tried to
> 107 if( f.params().length != args.length )
> 108 throw genex!RuntimeException(pos,
> 109 sprintf!("%d arguments required but %d p
99 { | 110
100 Table newCtx = new Table(f.definitionContext(), | 111 Table newCtx = new Table(f.definitionContext(), Table.Ki
101 foreach(i,p; f.params()) | 112 foreach(i,p; f.params())
102 if( p.layers.empty ) { | 113 if( p.layers.empty )
103 Value v = this.eval(args[i], ctx <
104 if(v is null) v = ast2table(args <
105 newCtx.set(p.name, currentLayer( | 114 newCtx.set(p.name, layerID(), this.evalT
> 115 else
> 116 foreach(argLay; p.layers)
> 117 {
> 118 Layer ll = argLay;
> 119 if( isMacroLayer(argLay) && type
> 120 ll = RawMacroLayer; // e
> 121 newCtx.set(p.name, argLay, getLa
106 } 122 }
107 else <
108 foreach(argLay; p.layers) { <
109 Layer ll = argLay; <
110 if( isMacroLayer(argLay) <
111 ll = RawMacroLay <
112 Value v = getLayerEvalua <
113 if(v is null) v = ast2ta <
114 newCtx.set(p.name, argLa <
115 } <
116 scope _ = new PushCallStack(pos, callstackmsg); | 123 scope _ = new PushCallStack(pos, callstackmsg);
117 return f.invoke(currentLayer(), newCtx, pos); | 124 return f.invoke(layerID(), newCtx, pos);
118 } <
119 throw genex!RuntimeException(pos, text("tried to call no <
120 } 125 }
121 126
122 /// | 127 /// Lift the value v to the current layer
123 Value lift(Value v, Table ctx, LexPosition pos) 128 Value lift(Value v, Table ctx, LexPosition pos)
124 { 129 {
125 Layer lay = currentLayer(); <
126 <
127 // functions are automatically lifterd | 130 // functions are automatically lifted by itself
128 if( cast(FunValue) v ) 131 if( cast(FunValue) v )
129 return v; 132 return v;
130 133
> 134 Layer lay = layerID();
> 135
> 136 // load the lift function
131 if( !ctx.has(lay, LiftLayer) ) 137 if( !ctx.has(lay, LiftLayer) )
132 throw genex!RuntimeException(pos, "lift function 138 throw genex!RuntimeException(pos, "lift function
133 139
134 // similar to invokeFunction, but with only one argument <
135 auto _f = ctx.get(lay, LiftLayer, pos); | 140 Value f_ = ctx.get(lay, LiftLayer, pos);
136 if(auto f = cast(FunValue)_f) | 141 FunValue f = cast(FunValue) f_;
137 { <
> 142 if( f is null )
> 143 throw genex!RuntimeException(pos,
138 Table newCtx = new Table(f.definitionContext(), | 144 text("non-function ", f_, " is registere
139 auto ps = f.params(); | 145 if( f.params().length != 1 || f.params()[0].layers.lengt
140 if( ps.length != 1 ) <
141 throw genex!RuntimeException(pos, | 146 throw genex!RuntimeException(pos,
142 text("lift function for", lay, " <
143 if( ps[0].layers.length==0 || ps[0].layers.lengt <
> 147 text("lift function must take exactly 1
144 { | 148
> 149 // invokeFunction
> 150 Table newCtx = new Table(f.definitionContext(), Table.Ki
145 newCtx.set(ps[0].name, ValueLayer, v); | 151 newCtx.set(f.params()[0].name, ValueLayer, v);
146 scope _ = new PushCallStack(pos, lay); | 152 scope _ = new PushCallStack(pos, "lift to "~lay);
147 return f.invoke(ValueLayer, newCtx, pos) | 153 return f.invoke(ValueLayer, newCtx, pos);
148 } <
149 else <
150 throw genex!RuntimeException(pos, <
151 text("lift function for", lay, " <
152 } <
153 throw genex!RuntimeException(pos, <
154 text("non-function ", _f, " is registered as the <
155 } 154 }
156 } 155 }
157 156
158 /// Evaluator for standard @value semantics 157 /// Evaluator for standard @value semantics
159 class ValueLayerEval : LayerEval 158 class ValueLayerEval : LayerEval
160 { 159 {
161 override Layer currentLayer() | 160 override Layer layerID()
162 { 161 {
163 return ValueLayer; 162 return ValueLayer;
164 } 163 }
165 override Value eval_( Die e, Table ctx, bool ctxMod ) 164 override Value eval_( Die e, Table ctx, bool ctxMod )
166 { 165 {
167 throw genex!RuntimeException(e.pos, "undefined case"); 166 throw genex!RuntimeException(e.pos, "undefined case");
168 } 167 }
................................................................................................................................................................................
172 } 171 }
173 override Value eval_( Int e, Table ctx, bool ctxMod ) 172 override Value eval_( Int e, Table ctx, bool ctxMod )
174 { 173 {
175 return new IntValue(e.data); 174 return new IntValue(e.data);
176 } 175 }
177 override Value eval_( Var e, Table ctx, bool ctxMod ) 176 override Value eval_( Var e, Table ctx, bool ctxMod )
178 { 177 {
179 return ctx.get(e.name, currentLayer(), e.pos); | 178 return ctx.get(e.name, layerID(), e.pos);
180 } 179 }
181 override Value eval_( Lay e, Table ctx, bool ctxMod ) 180 override Value eval_( Lay e, Table ctx, bool ctxMod )
182 { 181 {
183 auto le = getLayerEvaluator(e.layer); | 182 return getLayerEval(e.layer).evalToNonNull(e.expr, ctx);
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 } 183 }
190 override Value eval_( Let e, Table ctx, bool ctxMod ) 184 override Value eval_( Let e, Table ctx, bool ctxMod )
191 { 185 {
> 186 if( !ctxMod )
192 Table newCtx = ctxMod ? ctx : new Table(ctx, Table.Kind. | 187 ctx = new Table(ctx, Table.Kind.NotPropagateSet)
193 Value ri = this.eval(e.init, newCtx, CascadeCtx); | 188 Value ri = this.eval(e.init, ctx);
194 if(e.name!="_") <
195 newCtx.set(e.name, e.layer.empty ? currentLayer( | 189 ctx.set(e.name, e.layer.empty ? layerID(): e.layer, ri);
196 return this.eval(e.expr, newCtx, OverwriteCtx); | 190 return this.eval(e.expr, ctx, OverwriteCtx);
197 } 191 }
198 override Value eval_( App e, Table ctx, bool ctxMod ) 192 override Value eval_( App e, Table ctx, bool ctxMod )
199 { 193 {
200 Value f = this.eval( e.fun, ctx, CascadeCtx ); 194 Value f = this.eval( e.fun, ctx, CascadeCtx );
201 return this.invokeFunction(f, e.args, ctx, e.pos, getNam 195 return this.invokeFunction(f, e.args, ctx, e.pos, getNam
202 } 196 }
203 override Value eval_( Fun e, Table ctx, bool ctxMod ) 197 override Value eval_( Fun e, Table ctx, bool ctxMod )
204 { 198 {
205 return createNewFunction(e, ctx); 199 return createNewFunction(e, ctx);
206 } 200 }
> 201 override Value macroAndEval( AST e, Table ctx, bool ctxMod )
> 202 {
> 203 // incremental execution of let-expressions
> 204 if(auto le = cast(Let)e)
> 205 {
> 206 AST ai = runMacro(le.init, ctx);
> 207
> 208 if( !ctxMod )
> 209 ctx = new Table(ctx, Table.Kind.NotPropa
> 210
> 211 Value vi = this.eval(ai, ctx);
> 212 ctx.set(le.name, le.layer.empty ? layerID() : le
> 213 return this.macroAndEval(le.expr, ctx, Overwrite
> 214 }
> 215 else
> 216 return this.eval(runMacro(e,ctx,ctxMod), ctx, ct
> 217 }
207 } 218 }
208 219
209 /// Evaluator for user-defined layer 220 /// Evaluator for user-defined layer
210 class UserDefinedLayerEval : ValueLayerEval 221 class UserDefinedLayerEval : ValueLayerEval
211 { 222 {
212 Layer layerID; | 223 Layer theID;
213 mixin SimpleConstructor; 224 mixin SimpleConstructor;
214 225
215 override Layer currentLayer() | 226 override Layer layerID()
216 { 227 {
217 return layerID; | 228 return theID;
218 } 229 }
219 override Value eval_( Die e, Table ctx, bool ctxMod ) 230 override Value eval_( Die e, Table ctx, bool ctxMod )
220 { 231 {
221 return new UndefinedValue; | 232 return new BottomValue;
222 } 233 }
223 override Value eval_( Str e, Table ctx, bool ctxMod ) 234 override Value eval_( Str e, Table ctx, bool ctxMod )
224 { 235 {
225 return this.lift(new StrValue(e.data), ctx, e.pos); | 236 return this.lift(super.eval_(e,ctx,ctxMod), ctx, e.pos);
226 } 237 }
227 override Value eval_( Int e, Table ctx, bool ctxMod ) 238 override Value eval_( Int e, Table ctx, bool ctxMod )
228 { 239 {
229 return this.lift(new IntValue(e.data), ctx, e.pos); | 240 return this.lift(super.eval_(e,ctx,ctxMod), ctx, e.pos);
230 } 241 }
231 override Value eval_( Var e, Table ctx, bool ctxMod ) 242 override Value eval_( Var e, Table ctx, bool ctxMod )
232 { 243 {
233 if( ctx.has(e.name, currentLayer()) ) | 244 if( ctx.has(e.name, layerID()) )
234 return ctx.get(e.name, currentLayer()); | 245 return ctx.get(e.name, layerID());
235 return this.lift(ctx.get(e.name, ValueLayer, e.pos), ctx 246 return this.lift(ctx.get(e.name, ValueLayer, e.pos), ctx
236 } 247 }
237 } 248 }
238 249
239 // Convention!! | 250 // Macro layer. For optimization, if AST didn't change it returns null
240 // returns null if never used macro-like feature <
241 class MacroLayerEval : LayerEval 251 class MacroLayerEval : LayerEval
242 { 252 {
243 override Layer currentLayer() | 253 override Layer layerID()
244 { 254 {
245 return MacroLayer; 255 return MacroLayer;
> 256 }
> 257 override Value evalToNonNull( AST e, Table ctx, bool ctxMod = Ca
> 258 {
> 259 Value v = this.eval(e, ctx, ctxMod);
> 260 return v is null ? ast2table(e) : v;
246 } 261 }
247 override Value eval_( Die e, Table ctx, bool ctxMod ) 262 override Value eval_( Die e, Table ctx, bool ctxMod )
248 { 263 {
249 return null; 264 return null;
250 } 265 }
251 override Value eval_( Str e, Table ctx, bool ctxMod ) 266 override Value eval_( Str e, Table ctx, bool ctxMod )
252 { 267 {
................................................................................................................................................................................
254 } 269 }
255 override Value eval_( Int e, Table ctx, bool ctxMod ) 270 override Value eval_( Int e, Table ctx, bool ctxMod )
256 { 271 {
257 return null; 272 return null;
258 } 273 }
259 override Value eval_( Var e, Table ctx, bool ctxMod ) 274 override Value eval_( Var e, Table ctx, bool ctxMod )
260 { 275 {
261 if( ctx.has(e.name, currentLayer()) ) | 276 if( ctx.has(e.name, layerID()) )
262 return ctx.get(e.name, currentLayer(), e.pos); | 277 return ctx.get(e.name, layerID(), e.pos);
263 else <
264 return null; | 278 return null;
265 } 279 }
266 override Value eval_( Lay e, Table ctx, bool ctxMod ) 280 override Value eval_( Lay e, Table ctx, bool ctxMod )
267 { 281 {
268 auto le = getLayerEvaluator(e.layer); <
269 return le.eval(e.expr,ctx,CascadeCtx); | 282 return getLayerEval(e.layer).eval(e.expr,ctx);
270 } 283 }
271 override Value eval_( Let e, Table ctx, bool ctxMod ) 284 override Value eval_( Let e, Table ctx, bool ctxMod )
272 { 285 {
> 286 if( !ctxMod )
273 Table newCtx = ctxMod ? ctx : new Table(ctx, Table.Kind. | 287 ctx = new Table(ctx, Table.Kind.NotPropagateSet)
> 288
274 Value ai = this.eval(e.init, newCtx, CascadeCtx); | 289 Value ai = this.eval(e.init, ctx);
275 newCtx.set(e.name, NoopLayer, null); | 290 ctx.set(e.name, NoopLayer, null);
276 Value ae = this.eval(e.expr, newCtx, OverwriteCtx); | 291 Value ae = this.eval(e.expr, ctx, OverwriteCtx);
> 292
277 if( ai is null && ae is null ) | 293 if( ai is null && ae is null ) return null;
278 return null; <
279 if( ai is null ) ai = ast2table(e.init); 294 if( ai is null ) ai = ast2table(e.init);
280 if( ae is null ) ae = ast2table(e.expr); 295 if( ae is null ) ae = ast2table(e.expr);
> 296
281 return ast2table(e, delegate Value (AST _){ 297 return ast2table(e, delegate Value (AST _){
282 if(_ is e.init) { return ai; } 298 if(_ is e.init) { return ai; }
283 if(_ is e.expr) { return ae; } 299 if(_ is e.expr) { return ae; }
284 assert(false); 300 assert(false);
285 }); 301 });
286 } 302 }
287 override Value eval_( App e, Table ctx, bool ctxMod ) 303 override Value eval_( App e, Table ctx, bool ctxMod )
288 { 304 {
289 Value f = this.eval( e.fun, ctx, CascadeCtx ); | 305 Value f = this.eval( e.fun, ctx );
290 if(auto ff = cast(FunValue)f) 306 if(auto ff = cast(FunValue)f)
291 return this.invokeFunction(ff, e.args, ctx, e.po 307 return this.invokeFunction(ff, e.args, ctx, e.po
292 else { | 308 else
> 309 {
293 bool allNull = (f is null); 310 bool allNull = (f is null);
294 Value[] vas; 311 Value[] vas;
295 foreach(a; e.args) { | 312 foreach(a; e.args)
> 313 {
296 Value va = this.eval(a, ctx, CascadeCtx) 314 Value va = this.eval(a, ctx, CascadeCtx)
297 if(va !is null) allNull = false; 315 if(va !is null) allNull = false;
298 vas ~= va; 316 vas ~= va;
299 } 317 }
300 if( allNull ) 318 if( allNull )
301 return null; 319 return null;
302 return ast2table(e, delegate Value (AST _){ 320 return ast2table(e, delegate Value (AST _){
................................................................................................................................................................................
304 foreach(i,a; e.args) if(_ is a) return ( 322 foreach(i,a; e.args) if(_ is a) return (
305 assert(false); 323 assert(false);
306 }); 324 });
307 } 325 }
308 } 326 }
309 override Value eval_( Fun e, Table ctx, bool ctxMod ) 327 override Value eval_( Fun e, Table ctx, bool ctxMod )
310 { 328 {
311 Table newCtx = new Table(ctx, Table.Kind.NotPropagateSet | 329 ctx = new Table(ctx, Table.Kind.NotPropagateSet);
312 foreach(p; e.params) 330 foreach(p; e.params)
313 newCtx.set(p.name, NoopLayer, null); | 331 ctx.set(p.name, NoopLayer, null);
314 Value af = this.eval(e.funbody, newCtx, CascadeCtx); | 332 Value af = this.eval(e.funbody, ctx);
315 if( af is null ) 333 if( af is null )
316 return null; 334 return null;
317 return ast2table(e, (AST _){if(_ is e.funbody)return af; 335 return ast2table(e, (AST _){if(_ is e.funbody)return af;
318 } 336 }
319 } 337 }
320 338
> 339 /// (rawmacro) layer. almost same as @macro, but the Layer expression be
321 class RawMacroLayerEval : MacroLayerEval 340 class RawMacroLayerEval : MacroLayerEval
322 { 341 {
323 override Value eval_( Lay e, Table ctx, bool ctxMod ) 342 override Value eval_( Lay e, Table ctx, bool ctxMod )
324 { 343 {
325 Value ae = this.eval(e.expr, ctx, CascadeCtx); | 344 Value ae = this.eval(e.expr, ctx);
326 return ae is null ? null 345 return ae is null ? null
327 : ast2table(e, delegate Value (AST _){if(_ is e.e 346 : ast2table(e, delegate Value (AST _){if(_ is e.e
328 } 347 }
329 } 348 }
330 349
331 private: | 350 private: // short utils
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 <
338 AST ai = (vai is null ? e.init : polemy2d!(AST)(vai, e.p <
339 351
340 if( !ctxMod ) <
341 ctx = new Table(ctx, Table.Kind.NotPropagateSet) <
342 <
343 Value vi = getLayerEvaluator(lay).eval(ai, ctx, CascadeC <
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 <
352 AST a = (va is null ? e_ : polemy2d!(AST)(va, e_.pos)); <
353 return getLayerEvaluator(lay).eval(a, ctx, ctxMod); <
354 } <
355 } <
356 <
357 private: <
358 string getNameIfPossible(AST e) 352 string getNameIfPossible(AST e)
359 { 353 {
360 if(auto v = cast(Var)e) 354 if(auto v = cast(Var)e)
361 return v.name; 355 return v.name;
362 return ""; 356 return "";
363 } 357 }
364 358
> 359 AST runMacro(AST e, Table ctx, bool ctxMod=LayerEval.CascadeCtx)
> 360 {
> 361 Value v = getLayerEval(RawMacroLayer).eval(e, ctx, ctxMod);
> 362 return (v is null ? e : polemy2d!(AST)(v, e.pos));
> 363 }
> 364
> 365 private:
365 Value createNewFunction(Fun e, Table ctx) 366 Value createNewFunction(Fun e, Table ctx)
366 { 367 {
367 class UserDefinedFunValue : FunValue 368 class UserDefinedFunValue : FunValue
368 { 369 {
369 Fun ast; 370 Fun ast;
370 Table defCtx; 371 Table defCtx;
371 override const(Parameter[]) params() { return ast.params 372 override const(Parameter[]) params() { return ast.params
................................................................................................................................................................................
385 if(auto r = cast(Value)rhs) return typeid(this). 386 if(auto r = cast(Value)rhs) return typeid(this).
386 throw genex!RuntimeException("comparison with va 387 throw genex!RuntimeException("comparison with va
387 } 388 }
388 override hash_t toHash() { 389 override hash_t toHash() {
389 return (cast(hash_t)cast(void*)ast) + (cast(hash 390 return (cast(hash_t)cast(void*)ast) + (cast(hash
390 } 391 }
391 392
392 AST macroCache; <
393 AST[void*] mandeCache; 393 AST[void*] mandeCache;
394 static class MemokeyType 394 static class MemokeyType
395 { 395 {
396 void* a; Layer b; Tuple!(string,Layer,Value)[] c | 396 void* a; Layer b; Table c;
397 hash_t toHash() { <
398 hash_t h = structuralHash(a) + structura <
399 foreach(e; c) <
400 h += structuralHash(e[0])+struct <
401 return h; <
402 } <
403 mixin SimpleToString; | 397 mixin SimpleClass;
404 mixin SimpleConstructor; <
405 mixin SimpleCompareWithoutToHash; <
406 } 398 }
407 static Tuple!(Value,int)[MemokeyType] memo; 399 static Tuple!(Value,int)[MemokeyType] memo;
408 400
409 override Value invoke(Layer lay, Table ctx, LexPosition 401 override Value invoke(Layer lay, Table ctx, LexPosition
410 { 402 {
411 if( isASTLayer(lay) ) { | 403 auto evlay = getLayerEval(lay);
412 Value v = getLayerEvaluator(lay).eval(as <
413 if( v is null ) v = ast2table(ast.funbod <
414 return v; <
415 } <
416 return macroAndEval(ast.funbody, lay, ctx, Casca <
417 /* <
418 auto nonMemoizedRun = (){ | 404 auto nonMemoizedRun = (){ return evlay.macroAndE
419 if( macroCache is null ) <
420 { <
421 auto va = macroAndEval(e.funbody <
422 macroCache = va[1]; <
423 return va[0]; <
424 } <
425 else <
426 return eval(macroCache, lay, ctx <
427 }; <
428 405
429 if( !isUserDefinedLayer(lay) ) 406 if( !isUserDefinedLayer(lay) )
430 return nonMemoizedRun(); 407 return nonMemoizedRun();
431 408
> 409 // automatic memoized co-recursive execution
432 MemokeyType memokey = new MemokeyType(cast(void* | 410 MemokeyType memokey = new MemokeyType(cast(void*
433 <
434 if(auto p = memokey in memo) 411 if(auto p = memokey in memo)
435 { 412 {
436 (*p)[1] ++; 413 (*p)[1] ++;
437 return (*p)[0]; 414 return (*p)[0];
438 } 415 }
439 else 416 else
440 memo[memokey] = tuple(lift(new Undefined | 417 memo[memokey] = tuple(evlay.lift(new Bot
441 418
442 Value r = nonMemoizedRun(); 419 Value r = nonMemoizedRun();
443 420
444 int touched = memo[memokey][1]; 421 int touched = memo[memokey][1];
445 memo[memokey] = tuple(r, 12345678); 422 memo[memokey] = tuple(r, 12345678);
446 //if(touched) {DBG("rerun :: ",r);r = nonMemoize <
447 return r; 423 return r;
448 */ <
449 } 424 }
450 } 425 }
451 return new UserDefinedFunValue(e,ctx); 426 return new UserDefinedFunValue(e,ctx);
452 } 427 }
453 428
454 public: 429 public:
455 /// Add primitive function to the global context 430 /// Add primitive function to the global context
................................................................................................................................................................................
499 } 474 }
500 } 475 }
501 } 476 }
502 theContext.set(name, defLay, new NativeFunValue(dg)); 477 theContext.set(name, defLay, new NativeFunValue(dg));
503 } 478 }
504 } 479 }
505 480
> 481 version(unittest)
506 version(unittest) import polemy.runtime; | 482 import polemy.runtime;
> 483
507 unittest 484 unittest
508 { 485 {
509 auto e = new Evaluator; 486 auto e = new Evaluator;
510 enrollRuntimeLibrary(e); 487 enrollRuntimeLibrary(e);
511 auto r = assert_nothrow( e.evalString(`var x = 21; x + x*x;`) ); 488 auto r = assert_nothrow( e.evalString(`var x = 21; x + x*x;`) );
512 assert_eq( r, new IntValue(BigInt(21+21*21)) ); 489 assert_eq( r, new IntValue(BigInt(21+21*21)) );
513 assert_eq( e.globalContext.get("x",ValueLayer), new IntValue(BigInt(21)) 490 assert_eq( e.globalContext.get("x",ValueLayer), new IntValue(BigInt(21))
514 assert_nothrow( e.globalContext.get("x",ValueLayer) ); 491 assert_nothrow( e.globalContext.get("x",ValueLayer) );
515 assert_throw!RuntimeException( e.globalContext.get("y",ValueLayer) ); 492 assert_throw!RuntimeException( e.globalContext.get("y",ValueLayer) );
516 } 493 }
> 494
517 unittest 495 unittest
518 { 496 {
519 auto e = new Evaluator; 497 auto e = new Evaluator;
520 enrollRuntimeLibrary(e); 498 enrollRuntimeLibrary(e);
521 auto r = assert_nothrow( e.evalString(`var x = 21; var x = x + x*x;`) ); 499 auto r = assert_nothrow( e.evalString(`var x = 21; var x = x + x*x;`) );
522 assert_eq( r, new IntValue(BigInt(21+21*21)) ); 500 assert_eq( r, new IntValue(BigInt(21+21*21)) );
523 assert_eq( e.globalContext.get("x",ValueLayer), new IntValue(21+21*21) ) 501 assert_eq( e.globalContext.get("x",ValueLayer), new IntValue(21+21*21) )
................................................................................................................................................................................
593 } 571 }
594 572
595 unittest 573 unittest
596 { 574 {
597 auto e = new Evaluator; 575 auto e = new Evaluator;
598 enrollRuntimeLibrary(e); 576 enrollRuntimeLibrary(e);
599 assert_throw!RuntimeException( e.evalString(`...`) ); 577 assert_throw!RuntimeException( e.evalString(`...`) );
600 assert_eq( e.evalString(`@@foo(x){x}; @foo(...)`), new UndefinedValue ); | 578 assert_eq( e.evalString(`@@foo(x){x}; @foo(...)`), new BottomValue );
601 } 579 }