Diff
Not logged in

Differences From Artifact [9a9618fb0277f966]:

To Artifact [b119954d6ce43301]:


7 module polemy.eval; 7 module polemy.eval; 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 import std.typecons; < 15 import std.stdio; < 16 14 17 /// < 18 Table createGlobalContext() < > 15 class Evaluator 19 { 16 { > 17 public: 20 auto ctx = new Table; | 18 this() { theContext = new Table; } 21 ctx.set("+", ValueLayer, native( (IntValue lhs, IntValue rhs){return new < 22 ctx.set("-", ValueLayer, native( (IntValue lhs, IntValue rhs){return new < > 19 23 ctx.set("*", ValueLayer, native( (IntValue lhs, IntValue rhs){return new | 20 Value evalAST(AST e) 24 ctx.set("/", ValueLayer, native( (IntValue lhs, IntValue rhs){return new < > 21 { 25 ctx.set("%", ValueLayer, native( (IntValue lhs, IntValue rhs){return new | 22 return eval(e, ValueLayer, theContext, OverwriteCtx); 26 ctx.set("||", ValueLayer, native( (IntValue lhs, IntValue rhs){return ne < 27 ctx.set("&&", ValueLayer, native( (IntValue lhs, IntValue rhs){return ne < > 23 } > 24 28 ctx.set("<", ValueLayer, native( (Value lhs, Value rhs){return new IntVa | 25 Value evalString(S,T...)(S str, T fn_ln_cn) 29 ctx.set(">", ValueLayer, native( (Value lhs, Value rhs){return new IntVa < > 26 { 30 ctx.set("<=", ValueLayer, native( (Value lhs, Value rhs){return new IntV | 27 return evalAST(parseString(str,fn_ln_cn)); 31 ctx.set(">=", ValueLayer, native( (Value lhs, Value rhs){return new IntV < 32 ctx.set("==", ValueLayer, native( (Value lhs, Value rhs){return new IntV < > 28 } > 29 33 ctx.set("!=", ValueLayer, native( (Value lhs, Value rhs){return new IntV | 30 Value evalFile(S,T...)(S filename, T ln_cn) 34 ctx.set("print", ValueLayer, native( (Value a){ < > 31 { 35 writeln(a); | 32 return evalAST(parseFile(filename,ln_cn)); 36 return new IntValue(BigInt(0)); < 37 })); < > 33 } > 34 38 ctx.set("if", ValueLayer, native( (IntValue x, FunValue ft, FunValue fe) | 35 Table globalContext() 39 auto toRun = (x.data==0 ? fe : ft); < > 36 { 40 // [TODO] fill positional information | 37 return theContext; 41 return toRun.invoke(null, ValueLayer, toRun.definitionContext()) < 42 // return toRun.invoke(pos, lay, toRun.definitionContext()); < 43 })); < > 38 } > 39 > 40 private: 44 ctx.set("_isint", ValueLayer, native( (Value v){return new IntValue(BigI | 41 Table theContext; 45 ctx.set("_isstr", ValueLayer, native( (Value v){return new IntValue(BigI < > 42 46 ctx.set("_isfun", ValueLayer, native( (Value v){return new IntValue(BigI | 43 private: 47 ctx.set("_isundefined", ValueLayer, native( (Value v){return new IntValu | 44 enum : bool { CascadeCtx=false, OverwriteCtx=true }; 48 ctx.set("_istable", ValueLayer, native( (Value v){return new IntValue(Bi < > 45 49 ctx.set(".", ValueLayer, native( (Table t, StrValue s){ | 46 Value eval( AST e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 50 return (t.has(s.data, ValueLayer) ? t.get(s.data, ValueLayer) : < > 47 { 51 }) ); | 48 // dynamic-overload-resolution-pattern: modify here 52 ctx.set(".?", ValueLayer, native( (Table t, StrValue s){ | 49 enum funName = "eval"; 53 return new IntValue(BigInt(t.has(s.data, ValueLayer) ? 1 : 0)); | 50 alias TypeTuple!(e,lay,ctx,overwriteCtx) params; 54 }) ); < > 51 55 ctx.set(".=", ValueLayer, native( (Table t, StrValue s, Value v){ | 52 // dynamic-overload-resolution-pattern: dispatch 56 auto t2 = new Table(t, Table.Kind.NotPropagateSet); | 53 alias typeof(__traits(getOverloads, this, funName)) ovTypes; > 54 alias staticMap!(firstParam, ovTypes) fstTypes; > 55 alias DerivedToFront!(fstTypes) fstTypes_sorted; > 56 foreach(i, T; fstTypes_sorted) > 57 static if( is(T == typeof(params[0])) ) {} else if( auto > 58 return __traits(getOverloads, this, funName)[i]( > 59 > 60 // dynamic-overload-resolution-pattern: default behavior > 61 assert(false, text("eval() for ",typeid(e)," [",e.pos,"] is not > 62 } > 63 > 64 private: > 65 Value eval( Str e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) > 66 { > 67 Value v = new StrValue(e.data); > 68 if( lay==RawMacroLayer || lay==MacroLayer ) > 69 { > 70 auto ast = new Table; > 71 ast.set("pos", ValueLayer, fromPos(e.pos)); > 72 ast.set("is", ValueLayer, new StrValue("str")); 57 t2.set(s.data, ValueLayer, v); | 73 ast.set("data", ValueLayer, v); > 74 return ast; > 75 } > 76 if( lay==ValueLayer ) 58 return t2; | 77 return v; 59 }) ); < > 78 return lift(v, lay, ctx, e.pos); > 79 } > 80 > 81 Value eval( Int e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) > 82 { > 83 Value v = new IntValue(e.data); > 84 if( lay==RawMacroLayer || lay==MacroLayer ) > 85 { > 86 auto ast = new Table; > 87 ast.set("pos", ValueLayer, fromPos(e.pos)); > 88 ast.set("is", ValueLayer, new StrValue("int")); 60 ctx.set("{}", ValueLayer, native( (){ | 89 ast.set("data", ValueLayer, v); 61 return new Table; | 90 return ast; 62 }) ); < > 91 } > 92 if( lay==ValueLayer ) 63 return ctx; | 93 return v; > 94 return lift(v, lay, ctx, e.pos); 64 } | 95 } 65 | 96 66 /// Entry point of this module < > 97 Value eval( Var e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 67 | 98 { 68 Tuple!(Value,"val",Table,"ctx") evalString(S,T...)(S str, T fn_ln_cn) < > 99 if( lay==RawMacroLayer || lay==MacroLayer ) 69 { | 100 { 70 return eval( polemy.parse.parseString(str, fn_ln_cn) ); < > 101 if( ctx.has(e.name,MacroLayer) ) > 102 return ctx.get(e.name, MacroLayer, e.pos); > 103 auto ast = new Table; > 104 ast.set("pos", ValueLayer, fromPos(e.pos)); > 105 ast.set("is", ValueLayer, new StrValue("var")); > 106 ast.set("name", ValueLayer, new StrValue(e.name)); > 107 return ast; 71 } | 108 } > 109 if( lay==ValueLayer || ctx.has(e.name, lay) ) > 110 return ctx.get(e.name, lay, e.pos); > 111 return lift(ctx.get(e.name, ValueLayer, e.pos), lay, ctx, e.pos) 72 | 112 } 73 /// Entry point of this module < 74 | 113 75 Tuple!(Value,"val",Table,"ctx") evalFile(S, T...)(S filename, T ln_cn) < > 114 Value eval( App e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 76 { | 115 { 77 return eval( polemy.parse.parseFile(filename, ln_cn) ); < > 116 Value f = eval( e.fun, lay, ctx ); > 117 if( lay==RawMacroLayer || lay==MacroLayer ) > 118 { > 119 if( auto ff = cast(FunValue)f ) > 120 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; 78 } | 130 } > 131 else 79 | 132 { 80 /// Entry point of this module < > 133 return invokeFunction(f, e.args, lay, ctx, e.pos); 81 | 134 } 82 Tuple!(Value,"val",Table,"ctx") eval(AST e) < > 135 } 83 { | 136 84 Table ctx = createGlobalContext(); < 85 return typeof(return)(eval(e, ctx, false, ValueLayer), ctx); < > 137 Value eval( Fun e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) > 138 { > 139 if( lay==RawMacroLayer || lay==MacroLayer ) > 140 { > 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); 86 } | 156 } > 157 t.set("params", ValueLayer, params); > 158 return t; 87 | 159 } 88 Value invokeFunction(in LexPosition pos, Value _f, AST[] args, Table callerCtx, < > 160 else 89 { | 161 { 90 if(auto f = cast(FunValue)_f) < > 162 return createNewFunction(e, ctx); > 163 } > 164 } > 165 > 166 Value eval( Lay e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 91 { 167 { 92 Table ctx = new Table(f.definitionContext(), Table.Kind.NotPropa < 93 foreach(i,p; f.params()) < 94 if( p.layers.empty ) < 95 if(lay==MacroLayer) | 168 if( lay == RawMacroLayer ) > 169 { > 170 Value r = eval(e.expr, lay, ctx); > 171 auto ast = new Table; // todo: pos 96 ctx.set(p.name, lay, macroEval(args[i], | 172 ast.set("pos", ValueLayer, fromPos(e.pos)); 97 else | 173 ast.set("is", ValueLayer, new StrValue("lay")); 98 ctx.set(p.name, lay, eval(args[i], calle | 174 ast.set("layer", ValueLayer, new StrValue(e.layer)); 99 else | 175 ast.set("expr", ValueLayer, r); 100 foreach(argLay; p.layers) | 176 return ast; 101 if(argLay==MacroLayer) < 102 ctx.set(p.name, argLay, macroEva < > 177 } 103 else | 178 else 104 ctx.set(p.name, argLay, eval(arg < 105 return f.invoke(pos, lay, ctx); < > 179 return eval(e.expr, e.layer, ctx); 106 } 180 } 107 throw genex!RuntimeException(pos, "tried to call non-function"); < 108 } < 109 181 110 Value lift(in LexPosition pos, Value v, Layer lay, Table callerCtx) | 182 Value eval( Let e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 111 { < 112 // functions are automatically lifterd < 113 if( cast(FunValue) v ) < 114 return v; < 115 < 116 // similar to invoke Function, but with only one argument bound to Value < 117 Value _f = callerCtx.get(lay, SystemLayer, pos); < 118 if(auto f = cast(FunValue)_f) < 119 { 183 { 120 Table ctx = new Table(f.definitionContext(), Table.Kind.NotPropa | 184 // todo @macro let 121 auto ps = f.params(); | 185 if( lay==RawMacroLayer || lay==MacroLayer ) 122 if( ps.length != 1 ) < 123 throw genex!RuntimeException(pos, "lift function must ta < 124 if( ps[0].layers.length==0 || ps[0].layers.length==1 && ps[0].la < 125 { 186 { 126 ctx.set(ps[0].name, ValueLayer, v); | 187 auto ast = new Table; // todo: pos 127 return f.invoke(pos, ValueLayer, ctx); | 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; 128 } 195 } 129 else 196 else 130 throw genex!RuntimeException(pos, "lift function must ta < 131 } < 132 throw genex!RuntimeException(pos, "tried to call non-function"); < 133 } < 134 < 135 /// Entry point of this module < 136 /// If splitCtx = true, then inner variable declaration do not overwrite ctx. < 137 /// lay is the layer ID for evaluation (standard value semantics uses ValueLayer < 138 < 139 Value eval(AST e, Table ctx, bool splitCtx, Layer lay) < 140 { < 141 return e.match( < 142 (StrLiteral e) < 143 { 197 { 144 Value v = new StrValue(e.data); | 198 if( !overwriteCtx ) 145 if( lay == ValueLayer ) < 146 return v; < 147 else < 148 return lift(e.pos,v,lay,ctx); < 149 }, < 150 (IntLiteral e) < 151 { < 152 Value v = new IntValue(e.data); < 153 if( lay == ValueLayer ) < 154 return v; < 155 else // rise < 156 return lift(e.pos,v,lay,ctx); < 157 }, < 158 (VarExpression e) < 159 { < 160 if( lay == ValueLayer ) < 161 return ctx.get(e.name, lay, e.pos); < 162 if( ctx.has(e.name, lay, e.pos) ) < 163 return ctx.get(e.name, lay, e.pos); < 164 else < 165 return lift(e.pos, ctx.get(e.name, ValueLayer, e < 166 }, < 167 (LayExpression e) < 168 { < 169 if( e.layer == MacroLayer ) < 170 return macroEval(e.expr, ctx, false); < 171 else < 172 return eval(e.expr, ctx, true, e.layer); < 173 }, < 174 (LetExpression e) < 175 { < 176 // for letrec, we need this, but should avoid overwritin < 177 // ctx.set(e.var, ValueLayer, new UndefinedValue, e.pos) < 178 if(splitCtx) < 179 ctx = new Table(ctx, Table.Kind.NotPropagateSet) 199 ctx = new Table(ctx, Table.Kind.NotPropagateSet) 180 Value v = eval(e.init, ctx, true, lay); | 200 Value ri = eval(e.init, lay, ctx); > 201 string theLayer = e.layer.empty ? (lay==RawMacroLayer ? 181 ctx.set(e.name, (e.layer.length ? e.layer : lay), v, e.p | 202 ctx.set(e.name, theLayer, ri); 182 return eval(e.expr, ctx, false, lay); | 203 return eval(e.expr, lay, ctx, OverwriteCtx); 183 }, < 184 (FuncallExpression e) < > 204 } > 205 } 185 { | 206 186 return invokeFunction(e.pos, eval(e.fun, ctx, true, lay) < 187 }, < > 207 private: 188 (FunLiteral e) | 208 Value invokeFunction(Value _f, AST[] args, Layer lay, Table ctx, LexPosi 189 { | 209 { 190 return new UserDefinedFunValue(e, ctx); | 210 if(auto f = cast(FunValue)_f) 191 }, < 192 delegate Value (AST e) < 193 { 211 { 194 throw genex!RuntimeException(e.pos, sprintf!"Unknown Kin | 212 Table newCtx = new Table(f.definitionContext(), Table.Ki > 213 foreach(i,p; f.params()) > 214 if( p.layers.empty ) > 215 newCtx.set(p.name, (lay==RawMacroLayer ? > 216 else > 217 foreach(argLay; p.layers) > 218 newCtx.set(p.name, argLay, eval( > 219 return f.invoke(pos, lay, newCtx); 195 } 220 } 196 ); | 221 throw genex!RuntimeException(pos, text("tried to call non-functi 197 } | 222 } 198 < 199 // [TODO] Optimization < 200 Value macroEval(AST e, Table ctx, bool AlwaysMacro) < 201 { < 202 Layer theLayer = ValueLayer; < 203 223 204 Table makeCons(Value a, Value d) | 224 Value lift(Value v, Layer lay, Table ctx, LexPosition pos=null) 205 { 225 { 206 Table t = new Table; | 226 // functions are automatically lifterd 207 t.set("car", theLayer, a); | 227 if( cast(FunValue) v ) 208 t.set("cdr", theLayer, d); < 209 return t; | 228 return v; > 229 > 230 // similar to invoke Function, but with only one argument bound > 231 if(auto f = cast(FunValue)ctx.get(lay, SystemLayer, pos)) > 232 { > 233 Table newCtx = new Table(f.definitionContext(), Table.Ki > 234 auto ps = f.params(); > 235 if( ps.length != 1 ) > 236 throw genex!RuntimeException(pos, "lift function > 237 if( ps[0].layers.length==0 || ps[0].layers.length==1 && > 238 { > 239 newCtx.set(ps[0].name, ValueLayer, v); > 240 return f.invoke(pos, ValueLayer, newCtx); > 241 } > 242 else > 243 throw genex!RuntimeException(pos, "lift function > 244 } > 245 throw genex!RuntimeException(pos, "tried to call non-function"); 210 } 246 } 211 247 212 Table pos = new Table; | 248 Value createNewFunction(Fun e, Table ctx) 213 if( e.pos !is null ) { < 214 pos.set("filename", theLayer, new StrValue(e.pos.filename)); < 215 pos.set("lineno", theLayer, new IntValue(BigInt(e.pos.lineno)) < 216 pos.set("column", theLayer, new IntValue(BigInt(e.pos.column)) < 217 } else { < 218 pos.set("filename", theLayer, new StrValue("nullpos")); < 219 pos.set("lineno", theLayer, new IntValue(BigInt(0))); < 220 pos.set("column", theLayer, new IntValue(BigInt(0))); < 221 } < 222 | 249 { 223 return e.match( < 224 (StrLiteral e) < > 250 class UserDefinedFunValue : FunValue 225 { 251 { 226 Table t = new Table; | 252 Fun ast; 227 t.set("pos", theLayer, pos); | 253 Table defCtx; 228 t.set("is", theLayer, new StrValue("str")); | 254 override const(Parameter[]) params() { return ast.params 229 t.set("data", theLayer, new StrValue(e.data)); | 255 override Table definitionContext() { return defCtx; } 230 return t; < > 256 231 }, | 257 this(Fun ast, Table defCtx) { this.ast=ast; this.defCtx= 232 (IntLiteral e) | 258 override string toString() const { return sprintf!"(func > 259 override bool opEquals(Object rhs_) const /// member-by- 233 { | 260 { 234 Table t = new Table; < 235 t.set("pos", theLayer, pos); | 261 if( auto rhs = cast(typeof(this))rhs_ ) 236 t.set("is", theLayer, new StrValue("int")); | 262 return this.ast==rhs.ast && this.defCtx= 237 t.set("data", theLayer, new IntValue(e.data)); | 263 assert(false, sprintf!"Cannot compare %s with %s 238 return t; < 239 }, < 240 (VarExpression e) < > 264 } > 265 override hash_t toHash() const /// member-by-member hash 241 { | 266 { 242 if( ctx.has(e.name, MacroLayer, e.pos) ) < > 267 return typeid(this.ast).getHash(&this.ast) + typ > 268 } 243 return ctx.get(e.name, MacroLayer, e.pos); | 269 override int opCmp(Object rhs_) /// member-by-member com 244 else { < > 270 { 245 Table t = new Table; | 271 if( auto rhs = cast(typeof(this))rhs_ ) 246 t.set("pos", theLayer, pos); < > 272 { 247 t.set("is", theLayer, new StrValue("var")); | 273 if(auto i = this.ast.opCmp(rhs.ast)) 248 t.set("name", theLayer, new StrValue(e.name)); < 249 return cast(Value)t; | 274 return i; > 275 return this.defCtx.opCmp(rhs.defCtx); > 276 } > 277 assert(false, sprintf!"Cannot compare %s with %s 250 } 278 } 251 }, < 252 (LayExpression e) < 253 { | 279 254 if( AlwaysMacro ) < > 280 override Value invoke(LexPosition pos, Layer lay, Table 255 { 281 { 256 Table t = new Table; | 282 if( lay == MacroLayer ) 257 t.set("pos", theLayer, pos); | 283 return eval(ast.funbody, lay, ctx); 258 t.set("is", theLayer, new StrValue("lay")); | 284 auto macroed = tableToAST(ValueLayer, eval(e.fun 259 t.set("layer", theLayer, new StrValue(e.layer)); | 285 return eval(macroed, lay, ctx); 260 t.set("expr", theLayer, macroEval(e.expr,ctx,Al < 261 return cast(Value)t; < 262 } 286 } 263 else < > 287 } > 288 return new UserDefinedFunValue(e,ctx); > 289 } 264 { | 290 265 if( e.layer == MacroLayer ) < 266 return macroEval(e.expr, ctx, false); < 267 else | 291 public: 268 return eval(e.expr, ctx, true, e.layer); | 292 /// TODO: move up 269 } < > 293 /// TDOO: to other layers? 270 }, | 294 void addPrimitive(R,T...)(string name, Layer lay, R delegate (T) dg) 271 (LetExpression e) < > 295 { > 296 class NativeFunValue : FunValue 272 { 297 { 273 Table t = new Table; | 298 Parameter[] params_data; 274 t.set("pos", theLayer, pos); | 299 override string toString() { return sprintf!"(native:%x) 275 t.set("is", theLayer, new StrValue("let")); | 300 override const(Parameter[]) params() { return params_dat 276 t.set("name", theLayer, new StrValue(e.name)); | 301 override Table definitionContext() { return new Table; } 277 t.set("init", theLayer, macroEval(e.init,ctx,AlwaysMacro | 302 this(){ 278 t.set("expr", theLayer, macroEval(e.expr,ctx,AlwaysMacro | 303 foreach(i, Ti; T) 279 return t; | 304 params_data ~= new Parameter(text(i), [] 280 }, < > 305 } 281 (FuncallExpression e) | 306 override Value invoke(LexPosition pos, Layer lay, Table 282 { | 307 { 283 Value _f = macroEval(e.fun,ctx,AlwaysMacro); | 308 if( lay != ValueLayer ) > 309 throw genex!RuntimeException(pos, "only > 310 T typed_args; > 311 foreach(i, Ti; T) { > 312 typed_args[i] = cast(Ti) ctx.get(text(i) > 313 if( typed_args[i] is null ) > 314 throw genex!RuntimeException(pos 284 | 315 } 285 if( auto f = cast(FunValue)_f ) < 286 return invokeFunction(e.pos, f, e.args, ctx, Mac < > 316 try { > 317 return dg(typed_args); > 318 } catch( RuntimeException e ) { > 319 throw e.pos is null ? new RuntimeExcepti 287 | 320 } 288 Table t = new Table; < 289 t.set("pos", theLayer, pos); < 290 t.set("is", theLayer, new StrValue("app")); < 291 t.set("fun", theLayer, _f); < 292 Table args = new Table; < 293 foreach_reverse(a; e.args) { < 294 Table cons = new Table; < 295 cons.set("car",theLayer,macroEval(a,ctx,AlwaysMa < 296 cons.set("cdr",theLayer,args); < 297 args = cons; < 298 } 321 } 299 t.set("args", theLayer, args); < 300 return cast(Value)t; < 301 }, < 302 (FunLiteral e) < 303 { < 304 Table t = new Table; < 305 t.set("pos", theLayer, pos); < 306 t.set("is", theLayer, new StrValue("fun")); < 307 t.set("funbody", theLayer, macroEval(e.funbody,ctx,Alwa < 308 Table params = new Table; < 309 foreach_reverse(p; e.params) < 310 { < 311 Table lays = new Table; < 312 foreach_reverse(lay; p.layers) < 313 lays = makeCons(new StrValue(lay), lays) < 314 Table kv = new Table; < 315 kv.set("name", theLayer, new StrValue(p.name)); < 316 kv.set("layers", theLayer, lays); < 317 Table cons = new Table; < 318 params = makeCons(kv, params); < 319 } < 320 t.set("params", theLayer, params); < 321 return t; < 322 }, < 323 delegate Value (AST e) < 324 { < 325 throw genex!RuntimeException(e.pos, sprintf!"Unknown Kin < 326 } 322 } > 323 theContext.set(name, lay, new NativeFunValue); > 324 } > 325 } > 326 > 327 version(unittest) import polemy.runtime; > 328 unittest > 329 { > 330 auto e = new Evaluator; > 331 enrollRuntimeLibrary(e); > 332 auto r = assert_nothrow( e.evalString(`var x = 21; x + x*x;`) ); > 333 assert_eq( r, new IntValue(BigInt(21+21*21)) ); > 334 assert_eq( e.globalContext.get("x",ValueLayer), new IntValue(BigInt(21)) > 335 assert_nothrow( e.globalContext.get("x",ValueLayer) ); > 336 assert_throw!RuntimeException( e.globalContext.get("y",ValueLayer) ); > 337 } > 338 unittest > 339 { > 340 auto e = new Evaluator; > 341 enrollRuntimeLibrary(e); > 342 auto r = assert_nothrow( e.evalString(`var x = 21; var x = x + x*x;`) ); > 343 assert_eq( r, new IntValue(BigInt(21+21*21)) ); > 344 assert_eq( e.globalContext.get("x",ValueLayer), new IntValue(BigInt(21+2 > 345 assert_nothrow( e.globalContext.get("x",ValueLayer) ); > 346 assert_throw!RuntimeException( e.globalContext.get("y",ValueLayer) ); > 347 } > 348 unittest > 349 { > 350 auto e = new Evaluator; > 351 enrollRuntimeLibrary(e); > 352 assert_eq( e.evalString(`let x=1; let y=(let x=2); x`), new IntValue(Big > 353 assert_eq( e.evalString(`let x=1; let y=(let x=2;fun(){x}); y()`), new I > 354 } > 355 > 356 unittest > 357 { > 358 auto e = new Evaluator; > 359 enrollRuntimeLibrary(e); > 360 assert_eq( e.evalString(`@a x=1; @b x=2; @a(x)`), new IntValue(BigInt(1) > 361 assert_eq( e.evalString(`@a x=1; @b x=2; @b(x)`), new IntValue(BigInt(2) > 362 assert_eq( e.evalString(`let x=1; let _ = (@a x=2;2); x`), new IntValue( > 363 e = new Evaluator; > 364 assert_throw!Throwable( e.evalString(`let x=1; let _ = (@a x=2;2); @a(x) > 365 } > 366 > 367 unittest > 368 { > 369 auto e = new Evaluator; > 370 enrollRuntimeLibrary(e); > 371 assert_eq( e.evalString(` > 372 @@s(x){x}; > 373 @s "+" = fun(x, y) {@value( > 374 @s(x) - @s(y) 327 ); | 375 )}; > 376 @s(1 + 2) > 377 `), new IntValue(BigInt(-1)) ); > 378 } > 379 > 380 unittest > 381 { > 382 auto e = new Evaluator; > 383 enrollRuntimeLibrary(e); > 384 assert_eq( e.evalString(` > 385 @@3(x){x}; > 386 def incr(x) { x+1 }; > 387 @ 3 incr(x) {@value( if(@ 3(x)+1< 3){@ 3(x)+1}else{0} )}; > 388 def fb(n @value @3) { @3(n) }; > 389 fb(incr(incr(incr(0)))) > 390 `), new IntValue(BigInt(0)) ); 328 } 391 } 329 392 330 unittest 393 unittest 331 { 394 { 332 auto r = assert_nothrow( evalString(`var x = 21; x + x*x;`) ); | 395 auto e = new Evaluator; 333 assert_eq( r.val, new IntValue(BigInt(21+21*21)) ); | 396 enrollRuntimeLibrary(e); 334 assert_eq( r.ctx.get("x",ValueLayer), new IntValue(BigInt(21)) ); < 335 assert_nothrow( r.ctx.get("x",ValueLayer) ); | 397 assert_nothrow( e.evalString(` > 398 @macro twice(x) { x; x }; 336 assert_throw!RuntimeException( r.ctx.get("y",ValueLayer) ); | 399 def main() { twice(1) }; 337 } < 338 unittest < 339 { < 340 auto r = assert_nothrow( evalString(`var x = 21; var x = x + x*x;`) ); < 341 assert_eq( r.val, new IntValue(BigInt(21+21*21)) ); < 342 assert_eq( r.ctx.get("x",ValueLayer), new IntValue(BigInt(21+21*21)) ); < 343 assert_nothrow( r.ctx.get("x",ValueLayer) ); < 344 assert_throw!RuntimeException( r.ctx.get("y",ValueLayer) ); < 345 } < 346 unittest < 347 { < 348 assert_eq( evalString(`let x=1; let y=(let x=2); x`).val, new IntValue(B < 349 assert_eq( evalString(`let x=1; let y=(let x=2;fun(){x}); y()`).val, new < 350 } < 351 unittest < 352 { < 353 assert_eq( evalString(`@a x=1; @b x=2; @a(x)`).val, new IntValue(BigInt( < 354 assert_eq( evalString(`@a x=1; @b x=2; @b(x)`).val, new IntValue(BigInt( < 355 assert_eq( evalString(`let x=1; let _ = (@a x=2;2); x`).val, new IntValu < 356 assert_throw!Throwable( evalString(`let x=1; let _ = (@a x=2;2); @a(x)`) < > 400 main() > 401 `) ); 357 } 402 } 358 /* 403 /* 359 unittest 404 unittest 360 { 405 { 361 assert_eq( evalString(`var fac = fun(x){ 406 assert_eq( evalString(`var fac = fun(x){ 362 if(x) 407 if(x) 363 { x*fac(x-1); } 408 { x*fac(x-1); } ................................................................................................................................................................................ 369 if(x<2) 414 if(x<2) 370 { 1; } 415 { 1; } 371 else 416 else 372 { fib(x-1) + fib(x-2); }; 417 { fib(x-1) + fib(x-2); }; 373 }; 418 }; 374 fib(5);`).val, new IntValue(BigInt(8))); 419 fib(5);`).val, new IntValue(BigInt(8))); 375 } 420 } 376 < 377 unittest < 378 { < 379 assert_throw!Throwable( evalString(`@@s(x){x}; @s "+"=fun(x,y){x-y};@s(1 < 380 assert_eq( evalString(`@@s(x){x}; @s "+"=fun(x,y){x-y};1+2`).val, new In < 381 assert_eq( evalString(`@@s(x){x}; @s "+"=fun(x,y){@value(@s(x)-@s(y))};1 < 382 assert_eq( evalString(`@@s(x){x}; @s "+"=fun(x,y){@value(@s(x)-@s(y))};@ < 383 } < 384 < 385 unittest 421 unittest 386 { 422 { 387 assert_eq( evalString(`@@t = fun(x){x+1}; @t(123)`).val, new IntValue(Bi 423 assert_eq( evalString(`@@t = fun(x){x+1}; @t(123)`).val, new IntValue(Bi 388 // there was a bug that declaration in the first line of function defini 424 // there was a bug that declaration in the first line of function defini 389 // cannot be recursive 425 // cannot be recursive 390 assert_nothrow( evalString(`def foo() { 426 assert_nothrow( evalString(`def foo() { 391 def bar(y) { if(y<1) {0} else {bar(0)} }; 427 def bar(y) { if(y<1) {0} else {bar(0)} }; 392 bar(1) 428 bar(1) 393 }; foo()`) ); 429 }; foo()`) ); 394 } 430 } 395 */ 431 */