Diff
Not logged in

Differences From Artifact [10da2d7378e56ec4]:

To Artifact [9460508c714f0a1b]:


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 }