Diff
Not logged in

Differences From Artifact [b119954d6ce43301]:

To Artifact [5a9949a1eb8839b1]:


8 import polemy._common; 8 import polemy._common; 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 14 > 15 /// Objects for maitaining global environment and evaluation of expression on it 15 class Evaluator 16 class Evaluator 16 { 17 { 17 public: 18 public: > 19 /// Initialize evaluator with empty context 18 this() { theContext = new Table; } 20 this() { theContext = new Table; } 19 21 > 22 /// Evaluate the AST 20 Value evalAST(AST e) 23 Value evalAST(AST e) 21 { 24 { 22 return eval(e, ValueLayer, theContext, OverwriteCtx); 25 return eval(e, ValueLayer, theContext, OverwriteCtx); 23 } 26 } 24 27 > 28 /// Evaluate the string 25 Value evalString(S,T...)(S str, T fn_ln_cn) 29 Value evalString(S,T...)(S str, T fn_ln_cn) 26 { 30 { 27 return evalAST(parseString(str,fn_ln_cn)); 31 return evalAST(parseString(str,fn_ln_cn)); 28 } 32 } 29 33 > 34 /// Evaluate the file 30 Value evalFile(S,T...)(S filename, T ln_cn) 35 Value evalFile(S,T...)(S filename, T ln_cn) 31 { 36 { 32 return evalAST(parseFile(filename,ln_cn)); 37 return evalAST(parseFile(filename,ln_cn)); 33 } 38 } 34 39 > 40 /// Get the global context 35 Table globalContext() 41 Table globalContext() 36 { 42 { 37 return theContext; 43 return theContext; 38 } 44 } 39 45 40 private: 46 private: 41 Table theContext; 47 Table theContext; 42 48 43 private: < 44 enum : bool { CascadeCtx=false, OverwriteCtx=true }; 49 enum : bool { CascadeCtx=false, OverwriteCtx=true }; 45 < 46 Value eval( AST e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 50 Value eval( AST e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 47 { 51 { 48 // dynamic-overload-resolution-pattern: modify here 52 // dynamic-overload-resolution-pattern: modify here 49 enum funName = "eval"; 53 enum funName = "eval"; 50 alias TypeTuple!(e,lay,ctx,overwriteCtx) params; 54 alias TypeTuple!(e,lay,ctx,overwriteCtx) params; 51 55 52 // dynamic-overload-resolution-pattern: dispatch 56 // dynamic-overload-resolution-pattern: dispatch ................................................................................................................................................................................ 57 static if( is(T == typeof(params[0])) ) {} else if( auto 61 static if( is(T == typeof(params[0])) ) {} else if( auto 58 return __traits(getOverloads, this, funName)[i]( 62 return __traits(getOverloads, this, funName)[i]( 59 63 60 // dynamic-overload-resolution-pattern: default behavior 64 // dynamic-overload-resolution-pattern: default behavior 61 assert(false, text("eval() for ",typeid(e)," [",e.pos,"] is not 65 assert(false, text("eval() for ",typeid(e)," [",e.pos,"] is not 62 } 66 } 63 67 64 private: < 65 Value eval( Str e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 68 Value eval( Str e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 66 { 69 { 67 Value v = new StrValue(e.data); | 70 if( isMacroishLayer(lay) ) 68 if( lay==RawMacroLayer || lay==MacroLayer ) | 71 return ast2table(e, (AST e){return eval(e,lay,ctx);}); 69 { < 70 auto ast = new Table; < 71 ast.set("pos", ValueLayer, fromPos(e.pos)); < 72 ast.set("is", ValueLayer, new StrValue("str")); < 73 ast.set("data", ValueLayer, v); < 74 return ast; < 75 } < 76 if( lay==ValueLayer ) 72 if( lay==ValueLayer ) 77 return v; | 73 return new StrValue(e.data); 78 return lift(v, lay, ctx, e.pos); | 74 return lift(new StrValue(e.data), lay, ctx, e.pos); 79 } 75 } 80 76 81 Value eval( Int e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 77 Value eval( Int e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 82 { 78 { 83 Value v = new IntValue(e.data); | 79 if( isMacroishLayer(lay) ) 84 if( lay==RawMacroLayer || lay==MacroLayer ) | 80 return ast2table(e, (AST e){return eval(e,lay,ctx);}); 85 { < 86 auto ast = new Table; < 87 ast.set("pos", ValueLayer, fromPos(e.pos)); < 88 ast.set("is", ValueLayer, new StrValue("int")); < 89 ast.set("data", ValueLayer, v); < 90 return ast; < 91 } < 92 if( lay==ValueLayer ) 81 if( lay==ValueLayer ) 93 return v; | 82 return new IntValue(e.data); 94 return lift(v, lay, ctx, e.pos); | 83 return lift(new IntValue(e.data), lay, ctx, e.pos); 95 } 84 } 96 85 97 Value eval( Var e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 86 Value eval( Var e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 98 { 87 { 99 if( lay==RawMacroLayer || lay==MacroLayer ) | 88 if( isMacroishLayer(lay) ) 100 { < 101 if( ctx.has(e.name,MacroLayer) ) 89 if( ctx.has(e.name,MacroLayer) ) 102 return ctx.get(e.name, MacroLayer, e.pos); 90 return ctx.get(e.name, MacroLayer, e.pos); 103 auto ast = new Table; | 91 else 104 ast.set("pos", ValueLayer, fromPos(e.pos)); | 92 return ast2table(e, (AST e){return eval(e,lay,ct 105 ast.set("is", ValueLayer, new StrValue("var")); < 106 ast.set("name", ValueLayer, new StrValue(e.name)); < 107 return ast; < 108 } < 109 if( lay==ValueLayer || ctx.has(e.name, lay) ) 93 if( lay==ValueLayer || ctx.has(e.name, lay) ) 110 return ctx.get(e.name, lay, e.pos); 94 return ctx.get(e.name, lay, e.pos); 111 return lift(ctx.get(e.name, ValueLayer, e.pos), lay, ctx, e.pos) 95 return lift(ctx.get(e.name, ValueLayer, e.pos), lay, ctx, e.pos) 112 } 96 } 113 97 114 Value eval( App e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 98 Value eval( App e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 115 { 99 { 116 Value f = eval( e.fun, lay, ctx ); 100 Value f = eval( e.fun, lay, ctx ); 117 if( lay==RawMacroLayer || lay==MacroLayer ) | 101 if( isMacroishLayer(lay) ) 118 { < 119 if( auto ff = cast(FunValue)f ) 102 if( auto ff = cast(FunValue)f ) 120 return invokeFunction(ff, e.args, MacroLayer, ct 103 return invokeFunction(ff, e.args, MacroLayer, ct 121 Table ast = new Table; < 122 ast.set("pos", ValueLayer, fromPos(e.pos)); < 123 ast.set("is", ValueLayer, new StrValue("app")); < 124 ast.set("fun", ValueLayer, f); < 125 Table args = new Table; < 126 foreach_reverse(a; e.args) < 127 args = makeCons(eval(a, lay, ctx), args); < 128 ast.set("args", ValueLayer, args); < 129 return ast; < 130 } < 131 else | 104 else 132 { < > 105 return ast2table(e, (AST e){return eval(e,lay,ct 133 return invokeFunction(f, e.args, lay, ctx, e.pos); | 106 return invokeFunction(f, e.args, lay, ctx, e.pos); 134 } < 135 } 107 } 136 108 137 Value eval( Fun e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 109 Value eval( Fun e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 138 { 110 { 139 if( lay==RawMacroLayer || lay==MacroLayer ) | 111 if( isMacroishLayer(lay) ) 140 { | 112 return ast2table(e, (AST e){return eval(e,lay,ctx);}); 141 Table t = new Table; < 142 t.set("pos", ValueLayer, fromPos(e.pos)); < 143 t.set("is", ValueLayer, new StrValue("fun")); < 144 t.set("funbody", ValueLayer, eval(e.funbody,lay,ctx)); < 145 Table params = new Table; < 146 foreach_reverse(p; e.params) < 147 { < 148 Table lays = new Table; < 149 foreach_reverse(l; p.layers) < 150 lays = makeCons(new StrValue(l), lays); < 151 Table kv = new Table; < 152 kv.set("name", ValueLayer, new StrValue(p.name)) < 153 kv.set("layers", ValueLayer, lays); < 154 Table cons = new Table; < 155 params = makeCons(kv, params); < 156 } < 157 t.set("params", ValueLayer, params); < 158 return t; < 159 } < 160 else 113 else 161 { < 162 return createNewFunction(e, ctx); 114 return createNewFunction(e, ctx); 163 } < 164 } 115 } 165 116 166 Value eval( Lay e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 117 Value eval( Lay e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 167 { 118 { 168 if( lay == RawMacroLayer ) | 119 if( isNoLayerChangeLayer(lay) ) 169 { | 120 return ast2table(e, (AST e){return eval(e,lay,ctx);}); 170 Value r = eval(e.expr, lay, ctx); < 171 auto ast = new Table; // todo: pos < 172 ast.set("pos", ValueLayer, fromPos(e.pos)); < 173 ast.set("is", ValueLayer, new StrValue("lay")); < 174 ast.set("layer", ValueLayer, new StrValue(e.layer)); < 175 ast.set("expr", ValueLayer, r); < 176 return ast; < 177 } < 178 else 121 else 179 return eval(e.expr, e.layer, ctx); 122 return eval(e.expr, e.layer, ctx); 180 } 123 } 181 124 182 Value eval( Let e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 125 Value eval( Let e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 183 { 126 { 184 // todo @macro let 127 // todo @macro let 185 if( lay==RawMacroLayer || lay==MacroLayer ) | 128 if( isMacroishLayer(lay) ) 186 { | 129 return ast2table(e, (AST e){return eval(e,lay,ctx);}); 187 auto ast = new Table; // todo: pos < 188 ast.set("pos", ValueLayer, fromPos(e.pos)); < 189 ast.set("is", ValueLayer, new StrValue("let")); < 190 ast.set("name", ValueLayer, new StrValue(e.name)); < 191 ast.set("layer", ValueLayer, new StrValue(e.layer)); < 192 ast.set("init", ValueLayer, eval(e.init, lay, ctx)); < 193 ast.set("expr", ValueLayer, eval(e.expr, lay, ctx)); < 194 return ast; < 195 } < 196 else 130 else 197 { 131 { 198 if( !overwriteCtx ) 132 if( !overwriteCtx ) 199 ctx = new Table(ctx, Table.Kind.NotPropagateSet) 133 ctx = new Table(ctx, Table.Kind.NotPropagateSet) 200 Value ri = eval(e.init, lay, ctx); 134 Value ri = eval(e.init, lay, ctx); 201 string theLayer = e.layer.empty ? (lay==RawMacroLayer ? | 135 string theLayer = e.layer.empty ? lay : e.layer; // neut 202 ctx.set(e.name, theLayer, ri); 136 ctx.set(e.name, theLayer, ri); 203 return eval(e.expr, lay, ctx, OverwriteCtx); 137 return eval(e.expr, lay, ctx, OverwriteCtx); 204 } 138 } 205 } 139 } 206 140 207 private: 141 private: 208 Value invokeFunction(Value _f, AST[] args, Layer lay, Table ctx, LexPosi 142 Value invokeFunction(Value _f, AST[] args, Layer lay, Table ctx, LexPosi ................................................................................................................................................................................ 212 Table newCtx = new Table(f.definitionContext(), Table.Ki 146 Table newCtx = new Table(f.definitionContext(), Table.Ki 213 foreach(i,p; f.params()) 147 foreach(i,p; f.params()) 214 if( p.layers.empty ) 148 if( p.layers.empty ) 215 newCtx.set(p.name, (lay==RawMacroLayer ? 149 newCtx.set(p.name, (lay==RawMacroLayer ? 216 else 150 else 217 foreach(argLay; p.layers) 151 foreach(argLay; p.layers) 218 newCtx.set(p.name, argLay, eval( 152 newCtx.set(p.name, argLay, eval( 219 return f.invoke(pos, lay, newCtx); | 153 return f.invoke(lay==RawMacroLayer ? MacroLayer : lay, n 220 } 154 } 221 throw genex!RuntimeException(pos, text("tried to call non-functi 155 throw genex!RuntimeException(pos, text("tried to call non-functi 222 } 156 } 223 157 224 Value lift(Value v, Layer lay, Table ctx, LexPosition pos=null) 158 Value lift(Value v, Layer lay, Table ctx, LexPosition pos=null) 225 { 159 { > 160 assert( !isMacroishLayer(lay), "lift to the @macro layer should > 161 226 // functions are automatically lifterd 162 // functions are automatically lifterd 227 if( cast(FunValue) v ) 163 if( cast(FunValue) v ) 228 return v; 164 return v; 229 165 230 // similar to invoke Function, but with only one argument bound 166 // similar to invoke Function, but with only one argument bound 231 if(auto f = cast(FunValue)ctx.get(lay, SystemLayer, pos)) 167 if(auto f = cast(FunValue)ctx.get(lay, SystemLayer, pos)) 232 { 168 { ................................................................................................................................................................................ 233 Table newCtx = new Table(f.definitionContext(), Table.Ki 169 Table newCtx = new Table(f.definitionContext(), Table.Ki 234 auto ps = f.params(); 170 auto ps = f.params(); 235 if( ps.length != 1 ) 171 if( ps.length != 1 ) 236 throw genex!RuntimeException(pos, "lift function 172 throw genex!RuntimeException(pos, "lift function 237 if( ps[0].layers.length==0 || ps[0].layers.length==1 && 173 if( ps[0].layers.length==0 || ps[0].layers.length==1 && 238 { 174 { 239 newCtx.set(ps[0].name, ValueLayer, v); 175 newCtx.set(ps[0].name, ValueLayer, v); 240 return f.invoke(pos, ValueLayer, newCtx); | 176 return f.invoke(ValueLayer, newCtx, pos); 241 } 177 } 242 else 178 else 243 throw genex!RuntimeException(pos, "lift function 179 throw genex!RuntimeException(pos, "lift function 244 } 180 } 245 throw genex!RuntimeException(pos, "tried to call non-function"); 181 throw genex!RuntimeException(pos, "tried to call non-function"); 246 } 182 } 247 183 ................................................................................................................................................................................ 273 if(auto i = this.ast.opCmp(rhs.ast)) 209 if(auto i = this.ast.opCmp(rhs.ast)) 274 return i; 210 return i; 275 return this.defCtx.opCmp(rhs.defCtx); 211 return this.defCtx.opCmp(rhs.defCtx); 276 } 212 } 277 assert(false, sprintf!"Cannot compare %s with %s 213 assert(false, sprintf!"Cannot compare %s with %s 278 } 214 } 279 215 280 override Value invoke(LexPosition pos, Layer lay, Table | 216 override Value invoke(Layer lay, Table ctx, LexPosition 281 { 217 { 282 if( lay == MacroLayer ) 218 if( lay == MacroLayer ) 283 return eval(ast.funbody, lay, ctx); 219 return eval(ast.funbody, lay, ctx); > 220 if( afterMacroAST is null ) 284 auto macroed = tableToAST(ValueLayer, eval(e.fun | 221 afterMacroAST = tableToAST(ValueLayer, e 285 return eval(macroed, lay, ctx); | 222 return eval(afterMacroAST, lay, ctx); 286 } 223 } > 224 > 225 AST afterMacroAST; 287 } 226 } 288 return new UserDefinedFunValue(e,ctx); 227 return new UserDefinedFunValue(e,ctx); 289 } 228 } 290 229 291 public: 230 public: 292 /// TODO: move up | 231 /// Add primitive function to the global context 293 /// TDOO: to other layers? < 294 void addPrimitive(R,T...)(string name, Layer lay, R delegate (T) dg) | 232 void addPrimitive(R,T...)(string name, Layer defLay, R delegate (T) dg) 295 { 233 { 296 class NativeFunValue : FunValue 234 class NativeFunValue : FunValue 297 { 235 { 298 Parameter[] params_data; < 299 override string toString() { return sprintf!"(native:%x) < 300 override const(Parameter[]) params() { return params_dat 236 override const(Parameter[]) params() { return params_dat 301 override Table definitionContext() { return new Table; } | 237 override Table definitionContext() { return theContext > 238 > 239 override string toString() { return sprintf!"(native:%x) > 240 override int opCmp(Object rhs) { > 241 if(auto r = cast(NativeFunValue)rhs) return type > 242 if(auto r = cast(Value)rhs) return type > 243 throw genex!RuntimeException(LexPosition.dummy, > 244 } > 245 mixin SimpleToHash; > 246 > 247 R delegate(T) dg; > 248 Parameter[] params_data; > 249 > 250 this(R delegate(T) dg) > 251 { 302 this(){ | 252 this.dg = dg; 303 foreach(i, Ti; T) 253 foreach(i, Ti; T) 304 params_data ~= new Parameter(text(i), [] 254 params_data ~= new Parameter(text(i), [] 305 } 255 } > 256 306 override Value invoke(LexPosition pos, Layer lay, Table | 257 override Value invoke(Layer lay, Table ctx, LexPosition 307 { 258 { 308 if( lay != ValueLayer ) | 259 if( lay != defLay ) 309 throw genex!RuntimeException(pos, "only | 260 throw genex!RuntimeException(pos, text(" 310 T typed_args; 261 T typed_args; 311 foreach(i, Ti; T) { 262 foreach(i, Ti; T) { 312 typed_args[i] = cast(Ti) ctx.get(text(i) | 263 typed_args[i] = cast(Ti) ctx.get(text(i) 313 if( typed_args[i] is null ) 264 if( typed_args[i] is null ) 314 throw genex!RuntimeException(pos | 265 throw genex!RuntimeException(pos 315 } 266 } 316 try { 267 try { 317 return dg(typed_args); 268 return dg(typed_args); 318 } catch( RuntimeException e ) { 269 } catch( RuntimeException e ) { 319 throw e.pos is null ? new RuntimeExcepti 270 throw e.pos is null ? new RuntimeExcepti 320 } 271 } 321 } 272 } 322 } 273 } 323 theContext.set(name, lay, new NativeFunValue); | 274 theContext.set(name, defLay, new NativeFunValue(dg)); 324 } 275 } 325 } 276 } 326 277 327 version(unittest) import polemy.runtime; 278 version(unittest) import polemy.runtime; 328 unittest 279 unittest 329 { 280 { 330 auto e = new Evaluator; 281 auto e = new Evaluator;