8de5b49cdf 2010-11-09 kinaba: /** 4198578702 2010-11-07 kinaba: * Authors: k.inaba 4198578702 2010-11-07 kinaba: * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 4198578702 2010-11-07 kinaba: * 4198578702 2010-11-07 kinaba: * Evaluator for Polemy programming language. 423f308350 2010-11-07 kinaba: */ 4198578702 2010-11-07 kinaba: module polemy.eval; 4198578702 2010-11-07 kinaba: import polemy._common; 3464a035ec 2010-11-20 kinaba: import polemy.failure; 423f308350 2010-11-07 kinaba: import polemy.ast; 3f5dc76a75 2010-11-07 kinaba: import polemy.parse; b0d8d7875b 2010-11-08 kinaba: import polemy.value; 435fa085ec 2010-11-21 kinaba: import polemy.layer; 423f308350 2010-11-07 kinaba: 6ac127ddd0 2010-11-23 kinaba: class Evaluator 423f308350 2010-11-07 kinaba: { 6ac127ddd0 2010-11-23 kinaba: public: 6ac127ddd0 2010-11-23 kinaba: this() { theContext = new Table; } 6ac127ddd0 2010-11-23 kinaba: 6ac127ddd0 2010-11-23 kinaba: Value evalAST(AST e) 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: return eval(e, ValueLayer, theContext, OverwriteCtx); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: 6ac127ddd0 2010-11-23 kinaba: Value evalString(S,T...)(S str, T fn_ln_cn) 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: return evalAST(parseString(str,fn_ln_cn)); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: 6ac127ddd0 2010-11-23 kinaba: Value evalFile(S,T...)(S filename, T ln_cn) 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: return evalAST(parseFile(filename,ln_cn)); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: 6ac127ddd0 2010-11-23 kinaba: Table globalContext() 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: return theContext; 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: 6ac127ddd0 2010-11-23 kinaba: private: 6ac127ddd0 2010-11-23 kinaba: Table theContext; 6ac127ddd0 2010-11-23 kinaba: 6ac127ddd0 2010-11-23 kinaba: private: 6ac127ddd0 2010-11-23 kinaba: enum : bool { CascadeCtx=false, OverwriteCtx=true }; 6ac127ddd0 2010-11-23 kinaba: 6ac127ddd0 2010-11-23 kinaba: Value eval( AST e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: // dynamic-overload-resolution-pattern: modify here 6ac127ddd0 2010-11-23 kinaba: enum funName = "eval"; 6ac127ddd0 2010-11-23 kinaba: alias TypeTuple!(e,lay,ctx,overwriteCtx) params; 6ac127ddd0 2010-11-23 kinaba: 6ac127ddd0 2010-11-23 kinaba: // dynamic-overload-resolution-pattern: dispatch 6ac127ddd0 2010-11-23 kinaba: alias typeof(__traits(getOverloads, this, funName)) ovTypes; 6ac127ddd0 2010-11-23 kinaba: alias staticMap!(firstParam, ovTypes) fstTypes; 6ac127ddd0 2010-11-23 kinaba: alias DerivedToFront!(fstTypes) fstTypes_sorted; 6ac127ddd0 2010-11-23 kinaba: foreach(i, T; fstTypes_sorted) 6ac127ddd0 2010-11-23 kinaba: static if( is(T == typeof(params[0])) ) {} else if( auto _x = cast(T)params[0] ) 6ac127ddd0 2010-11-23 kinaba: return __traits(getOverloads, this, funName)[i](_x, params[1..$]); 6ac127ddd0 2010-11-23 kinaba: 6ac127ddd0 2010-11-23 kinaba: // dynamic-overload-resolution-pattern: default behavior 6ac127ddd0 2010-11-23 kinaba: assert(false, text("eval() for ",typeid(e)," [",e.pos,"] is not defined")); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: 6ac127ddd0 2010-11-23 kinaba: private: 6ac127ddd0 2010-11-23 kinaba: Value eval( Str e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: Value v = new StrValue(e.data); 6ac127ddd0 2010-11-23 kinaba: if( lay==RawMacroLayer || lay==MacroLayer ) 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: auto ast = new Table; 6ac127ddd0 2010-11-23 kinaba: ast.set("pos", ValueLayer, fromPos(e.pos)); 6ac127ddd0 2010-11-23 kinaba: ast.set("is", ValueLayer, new StrValue("str")); 6ac127ddd0 2010-11-23 kinaba: ast.set("data", ValueLayer, v); 6ac127ddd0 2010-11-23 kinaba: return ast; 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: if( lay==ValueLayer ) 6ac127ddd0 2010-11-23 kinaba: return v; 6ac127ddd0 2010-11-23 kinaba: return lift(v, lay, ctx, e.pos); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: 6ac127ddd0 2010-11-23 kinaba: Value eval( Int e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: Value v = new IntValue(e.data); 6ac127ddd0 2010-11-23 kinaba: if( lay==RawMacroLayer || lay==MacroLayer ) 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: auto ast = new Table; 6ac127ddd0 2010-11-23 kinaba: ast.set("pos", ValueLayer, fromPos(e.pos)); 6ac127ddd0 2010-11-23 kinaba: ast.set("is", ValueLayer, new StrValue("int")); 6ac127ddd0 2010-11-23 kinaba: ast.set("data", ValueLayer, v); 6ac127ddd0 2010-11-23 kinaba: return ast; 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: if( lay==ValueLayer ) 6ac127ddd0 2010-11-23 kinaba: return v; 6ac127ddd0 2010-11-23 kinaba: return lift(v, lay, ctx, e.pos); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: 6ac127ddd0 2010-11-23 kinaba: Value eval( Var e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: if( lay==RawMacroLayer || lay==MacroLayer ) 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: if( ctx.has(e.name,MacroLayer) ) 6ac127ddd0 2010-11-23 kinaba: return ctx.get(e.name, MacroLayer, e.pos); 6ac127ddd0 2010-11-23 kinaba: auto ast = new Table; 6ac127ddd0 2010-11-23 kinaba: ast.set("pos", ValueLayer, fromPos(e.pos)); 6ac127ddd0 2010-11-23 kinaba: ast.set("is", ValueLayer, new StrValue("var")); 6ac127ddd0 2010-11-23 kinaba: ast.set("name", ValueLayer, new StrValue(e.name)); 6ac127ddd0 2010-11-23 kinaba: return ast; 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: if( lay==ValueLayer || ctx.has(e.name, lay) ) 6ac127ddd0 2010-11-23 kinaba: return ctx.get(e.name, lay, e.pos); 6ac127ddd0 2010-11-23 kinaba: return lift(ctx.get(e.name, ValueLayer, e.pos), lay, ctx, e.pos); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: 6ac127ddd0 2010-11-23 kinaba: Value eval( App e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: Value f = eval( e.fun, lay, ctx ); 6ac127ddd0 2010-11-23 kinaba: if( lay==RawMacroLayer || lay==MacroLayer ) 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: if( auto ff = cast(FunValue)f ) 6ac127ddd0 2010-11-23 kinaba: return invokeFunction(ff, e.args, MacroLayer, ctx, e.pos); 6ac127ddd0 2010-11-23 kinaba: Table ast = new Table; 6ac127ddd0 2010-11-23 kinaba: ast.set("pos", ValueLayer, fromPos(e.pos)); 6ac127ddd0 2010-11-23 kinaba: ast.set("is", ValueLayer, new StrValue("app")); 6ac127ddd0 2010-11-23 kinaba: ast.set("fun", ValueLayer, f); 6ac127ddd0 2010-11-23 kinaba: Table args = new Table; 6ac127ddd0 2010-11-23 kinaba: foreach_reverse(a; e.args) 6ac127ddd0 2010-11-23 kinaba: args = makeCons(eval(a, lay, ctx), args); 6ac127ddd0 2010-11-23 kinaba: ast.set("args", ValueLayer, args); 6ac127ddd0 2010-11-23 kinaba: return ast; 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: else 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: return invokeFunction(f, e.args, lay, ctx, e.pos); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: 6ac127ddd0 2010-11-23 kinaba: Value eval( Fun e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: if( lay==RawMacroLayer || lay==MacroLayer ) 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: Table t = new Table; 6ac127ddd0 2010-11-23 kinaba: t.set("pos", ValueLayer, fromPos(e.pos)); 6ac127ddd0 2010-11-23 kinaba: t.set("is", ValueLayer, new StrValue("fun")); 6ac127ddd0 2010-11-23 kinaba: t.set("funbody", ValueLayer, eval(e.funbody,lay,ctx)); 6ac127ddd0 2010-11-23 kinaba: Table params = new Table; 6ac127ddd0 2010-11-23 kinaba: foreach_reverse(p; e.params) 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: Table lays = new Table; 6ac127ddd0 2010-11-23 kinaba: foreach_reverse(l; p.layers) 6ac127ddd0 2010-11-23 kinaba: lays = makeCons(new StrValue(l), lays); 6ac127ddd0 2010-11-23 kinaba: Table kv = new Table; 6ac127ddd0 2010-11-23 kinaba: kv.set("name", ValueLayer, new StrValue(p.name)); 6ac127ddd0 2010-11-23 kinaba: kv.set("layers", ValueLayer, lays); 6ac127ddd0 2010-11-23 kinaba: Table cons = new Table; 6ac127ddd0 2010-11-23 kinaba: params = makeCons(kv, params); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: t.set("params", ValueLayer, params); 6ac127ddd0 2010-11-23 kinaba: return t; 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: else 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: return createNewFunction(e, ctx); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: 6ac127ddd0 2010-11-23 kinaba: Value eval( Lay e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) f86026acb8 2010-11-21 kinaba: { 6ac127ddd0 2010-11-23 kinaba: if( lay == RawMacroLayer ) 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: Value r = eval(e.expr, lay, ctx); 6ac127ddd0 2010-11-23 kinaba: auto ast = new Table; // todo: pos 6ac127ddd0 2010-11-23 kinaba: ast.set("pos", ValueLayer, fromPos(e.pos)); 6ac127ddd0 2010-11-23 kinaba: ast.set("is", ValueLayer, new StrValue("lay")); 6ac127ddd0 2010-11-23 kinaba: ast.set("layer", ValueLayer, new StrValue(e.layer)); 6ac127ddd0 2010-11-23 kinaba: ast.set("expr", ValueLayer, r); 6ac127ddd0 2010-11-23 kinaba: return ast; 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: else 6ac127ddd0 2010-11-23 kinaba: return eval(e.expr, e.layer, ctx); f86026acb8 2010-11-21 kinaba: } f86026acb8 2010-11-21 kinaba: 6ac127ddd0 2010-11-23 kinaba: Value eval( Let e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) f86026acb8 2010-11-21 kinaba: { 6ac127ddd0 2010-11-23 kinaba: // todo @macro let 6ac127ddd0 2010-11-23 kinaba: if( lay==RawMacroLayer || lay==MacroLayer ) a5fe6233c1 2010-11-21 kinaba: { 6ac127ddd0 2010-11-23 kinaba: auto ast = new Table; // todo: pos 6ac127ddd0 2010-11-23 kinaba: ast.set("pos", ValueLayer, fromPos(e.pos)); 6ac127ddd0 2010-11-23 kinaba: ast.set("is", ValueLayer, new StrValue("let")); 6ac127ddd0 2010-11-23 kinaba: ast.set("name", ValueLayer, new StrValue(e.name)); 6ac127ddd0 2010-11-23 kinaba: ast.set("layer", ValueLayer, new StrValue(e.layer)); 6ac127ddd0 2010-11-23 kinaba: ast.set("init", ValueLayer, eval(e.init, lay, ctx)); 6ac127ddd0 2010-11-23 kinaba: ast.set("expr", ValueLayer, eval(e.expr, lay, ctx)); 6ac127ddd0 2010-11-23 kinaba: return ast; f86026acb8 2010-11-21 kinaba: } f86026acb8 2010-11-21 kinaba: else 1c01f44f52 2010-11-13 kinaba: { 6ac127ddd0 2010-11-23 kinaba: if( !overwriteCtx ) a5fe6233c1 2010-11-21 kinaba: ctx = new Table(ctx, Table.Kind.NotPropagateSet); 6ac127ddd0 2010-11-23 kinaba: Value ri = eval(e.init, lay, ctx); 6ac127ddd0 2010-11-23 kinaba: string theLayer = e.layer.empty ? (lay==RawMacroLayer ? MacroLayer : lay) : e.layer; 6ac127ddd0 2010-11-23 kinaba: ctx.set(e.name, theLayer, ri); 6ac127ddd0 2010-11-23 kinaba: return eval(e.expr, lay, ctx, OverwriteCtx); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: 6ac127ddd0 2010-11-23 kinaba: private: 6ac127ddd0 2010-11-23 kinaba: Value invokeFunction(Value _f, AST[] args, Layer lay, Table ctx, LexPosition pos=null) 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: if(auto f = cast(FunValue)_f) 3f6f41b558 2010-11-20 kinaba: { 6ac127ddd0 2010-11-23 kinaba: Table newCtx = new Table(f.definitionContext(), Table.Kind.NotPropagateSet); 6ac127ddd0 2010-11-23 kinaba: foreach(i,p; f.params()) 6ac127ddd0 2010-11-23 kinaba: if( p.layers.empty ) 6ac127ddd0 2010-11-23 kinaba: newCtx.set(p.name, (lay==RawMacroLayer ? MacroLayer : lay), eval(args[i], lay, ctx)); 6ac127ddd0 2010-11-23 kinaba: else 6ac127ddd0 2010-11-23 kinaba: foreach(argLay; p.layers) 6ac127ddd0 2010-11-23 kinaba: newCtx.set(p.name, argLay, eval(args[i], argLay, ctx)); 6ac127ddd0 2010-11-23 kinaba: return f.invoke(pos, lay, newCtx); 3f6f41b558 2010-11-20 kinaba: } 6ac127ddd0 2010-11-23 kinaba: throw genex!RuntimeException(pos, text("tried to call non-function: ",_f)); 6ac127ddd0 2010-11-23 kinaba: } f86026acb8 2010-11-21 kinaba: 6ac127ddd0 2010-11-23 kinaba: Value lift(Value v, Layer lay, Table ctx, LexPosition pos=null) f86026acb8 2010-11-21 kinaba: { 6ac127ddd0 2010-11-23 kinaba: // functions are automatically lifterd 6ac127ddd0 2010-11-23 kinaba: if( cast(FunValue) v ) 6ac127ddd0 2010-11-23 kinaba: return v; 6ac127ddd0 2010-11-23 kinaba: 6ac127ddd0 2010-11-23 kinaba: // similar to invoke Function, but with only one argument bound to ValueLayer 6ac127ddd0 2010-11-23 kinaba: if(auto f = cast(FunValue)ctx.get(lay, SystemLayer, pos)) 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: Table newCtx = new Table(f.definitionContext(), Table.Kind.NotPropagateSet); 6ac127ddd0 2010-11-23 kinaba: auto ps = f.params(); 6ac127ddd0 2010-11-23 kinaba: if( ps.length != 1 ) 6ac127ddd0 2010-11-23 kinaba: throw genex!RuntimeException(pos, "lift function must take exactly one argument at "~ValueLayer~" layer"); 6ac127ddd0 2010-11-23 kinaba: if( ps[0].layers.length==0 || ps[0].layers.length==1 && ps[0].layers[0]==ValueLayer ) 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: newCtx.set(ps[0].name, ValueLayer, v); 6ac127ddd0 2010-11-23 kinaba: return f.invoke(pos, ValueLayer, newCtx); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: else 6ac127ddd0 2010-11-23 kinaba: throw genex!RuntimeException(pos, "lift function must take exactly one argument at "~ValueLayer~" layer"); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: throw genex!RuntimeException(pos, "tried to call non-function"); 3995a5eb6a 2010-11-21 kinaba: } 3995a5eb6a 2010-11-21 kinaba: 6ac127ddd0 2010-11-23 kinaba: Value createNewFunction(Fun e, Table ctx) 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: class UserDefinedFunValue : FunValue 1c01f44f52 2010-11-13 kinaba: { 6ac127ddd0 2010-11-23 kinaba: Fun ast; 6ac127ddd0 2010-11-23 kinaba: Table defCtx; 6ac127ddd0 2010-11-23 kinaba: override const(Parameter[]) params() { return ast.params; } 6ac127ddd0 2010-11-23 kinaba: override Table definitionContext() { return defCtx; } 6ac127ddd0 2010-11-23 kinaba: 6ac127ddd0 2010-11-23 kinaba: this(Fun ast, Table defCtx) { this.ast=ast; this.defCtx=defCtx; } 6ac127ddd0 2010-11-23 kinaba: override string toString() const { return sprintf!"(function:%x:%x)"(cast(void*)ast, cast(void*)defCtx); } 6ac127ddd0 2010-11-23 kinaba: override bool opEquals(Object rhs_) const /// member-by-member equality 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: if( auto rhs = cast(typeof(this))rhs_ ) 6ac127ddd0 2010-11-23 kinaba: return this.ast==rhs.ast && this.defCtx==rhs.defCtx; 6ac127ddd0 2010-11-23 kinaba: assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), typeid(rhs_))); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: override hash_t toHash() const /// member-by-member hash 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: return typeid(this.ast).getHash(&this.ast) + typeid(this.defCtx).getHash(&this.defCtx); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: override int opCmp(Object rhs_) /// member-by-member compare 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: if( auto rhs = cast(typeof(this))rhs_ ) 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: if(auto i = this.ast.opCmp(rhs.ast)) 6ac127ddd0 2010-11-23 kinaba: return i; 6ac127ddd0 2010-11-23 kinaba: return this.defCtx.opCmp(rhs.defCtx); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), typeid(rhs_))); a5fe6233c1 2010-11-21 kinaba: } 6ac127ddd0 2010-11-23 kinaba: 6ac127ddd0 2010-11-23 kinaba: override Value invoke(LexPosition pos, Layer lay, Table ctx) a5fe6233c1 2010-11-21 kinaba: { 6ac127ddd0 2010-11-23 kinaba: if( lay == MacroLayer ) 6ac127ddd0 2010-11-23 kinaba: return eval(ast.funbody, lay, ctx); 6ac127ddd0 2010-11-23 kinaba: auto macroed = tableToAST(ValueLayer, eval(e.funbody, RawMacroLayer, ctx)); 6ac127ddd0 2010-11-23 kinaba: return eval(macroed, lay, ctx); 3f6f41b558 2010-11-20 kinaba: } 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: return new UserDefinedFunValue(e,ctx); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: 6ac127ddd0 2010-11-23 kinaba: public: 6ac127ddd0 2010-11-23 kinaba: /// TODO: move up 6ac127ddd0 2010-11-23 kinaba: /// TDOO: to other layers? 6ac127ddd0 2010-11-23 kinaba: void addPrimitive(R,T...)(string name, Layer lay, R delegate (T) dg) 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: class NativeFunValue : FunValue a5fe6233c1 2010-11-21 kinaba: { 6ac127ddd0 2010-11-23 kinaba: Parameter[] params_data; 6ac127ddd0 2010-11-23 kinaba: override string toString() { return sprintf!"(native:%x)"(dg.funcptr); } 6ac127ddd0 2010-11-23 kinaba: override const(Parameter[]) params() { return params_data; } 6ac127ddd0 2010-11-23 kinaba: override Table definitionContext() { return new Table; } // todo: cache 6ac127ddd0 2010-11-23 kinaba: this(){ 6ac127ddd0 2010-11-23 kinaba: foreach(i, Ti; T) 6ac127ddd0 2010-11-23 kinaba: params_data ~= new Parameter(text(i), []); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: override Value invoke(LexPosition pos, Layer lay, Table ctx) 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: if( lay != ValueLayer ) 6ac127ddd0 2010-11-23 kinaba: throw genex!RuntimeException(pos, "only "~ValueLayer~" layer can call native function"); 6ac127ddd0 2010-11-23 kinaba: T typed_args; 6ac127ddd0 2010-11-23 kinaba: foreach(i, Ti; T) { 6ac127ddd0 2010-11-23 kinaba: typed_args[i] = cast(Ti) ctx.get(text(i), ValueLayer); 6ac127ddd0 2010-11-23 kinaba: if( typed_args[i] is null ) 6ac127ddd0 2010-11-23 kinaba: throw genex!RuntimeException(pos, sprintf!"type mismatch on the argument %d"(i+1)); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: try { 6ac127ddd0 2010-11-23 kinaba: return dg(typed_args); 6ac127ddd0 2010-11-23 kinaba: } catch( RuntimeException e ) { 6ac127ddd0 2010-11-23 kinaba: throw e.pos is null ? new RuntimeException(pos, e.msg, e.file, e.line) : e; 6ac127ddd0 2010-11-23 kinaba: } 8e3db9ef20 2010-11-20 kinaba: } 1c01f44f52 2010-11-13 kinaba: } 6ac127ddd0 2010-11-23 kinaba: theContext.set(name, lay, new NativeFunValue); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: 6ac127ddd0 2010-11-23 kinaba: version(unittest) import polemy.runtime; 6ac127ddd0 2010-11-23 kinaba: unittest 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: auto e = new Evaluator; 6ac127ddd0 2010-11-23 kinaba: enrollRuntimeLibrary(e); 6ac127ddd0 2010-11-23 kinaba: auto r = assert_nothrow( e.evalString(`var x = 21; x + x*x;`) ); 6ac127ddd0 2010-11-23 kinaba: assert_eq( r, new IntValue(BigInt(21+21*21)) ); 6ac127ddd0 2010-11-23 kinaba: assert_eq( e.globalContext.get("x",ValueLayer), new IntValue(BigInt(21)) ); 6ac127ddd0 2010-11-23 kinaba: assert_nothrow( e.globalContext.get("x",ValueLayer) ); 6ac127ddd0 2010-11-23 kinaba: assert_throw!RuntimeException( e.globalContext.get("y",ValueLayer) ); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: unittest 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: auto e = new Evaluator; 6ac127ddd0 2010-11-23 kinaba: enrollRuntimeLibrary(e); 6ac127ddd0 2010-11-23 kinaba: auto r = assert_nothrow( e.evalString(`var x = 21; var x = x + x*x;`) ); 6ac127ddd0 2010-11-23 kinaba: assert_eq( r, new IntValue(BigInt(21+21*21)) ); 6ac127ddd0 2010-11-23 kinaba: assert_eq( e.globalContext.get("x",ValueLayer), new IntValue(BigInt(21+21*21)) ); 6ac127ddd0 2010-11-23 kinaba: assert_nothrow( e.globalContext.get("x",ValueLayer) ); 6ac127ddd0 2010-11-23 kinaba: assert_throw!RuntimeException( e.globalContext.get("y",ValueLayer) ); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: unittest 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: auto e = new Evaluator; 6ac127ddd0 2010-11-23 kinaba: enrollRuntimeLibrary(e); 6ac127ddd0 2010-11-23 kinaba: assert_eq( e.evalString(`let x=1; let y=(let x=2); x`), new IntValue(BigInt(1)) ); 6ac127ddd0 2010-11-23 kinaba: assert_eq( e.evalString(`let x=1; let y=(let x=2;fun(){x}); y()`), new IntValue(BigInt(2)) ); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: 6ac127ddd0 2010-11-23 kinaba: unittest 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: auto e = new Evaluator; 6ac127ddd0 2010-11-23 kinaba: enrollRuntimeLibrary(e); 6ac127ddd0 2010-11-23 kinaba: assert_eq( e.evalString(`@a x=1; @b x=2; @a(x)`), new IntValue(BigInt(1)) ); 6ac127ddd0 2010-11-23 kinaba: assert_eq( e.evalString(`@a x=1; @b x=2; @b(x)`), new IntValue(BigInt(2)) ); 6ac127ddd0 2010-11-23 kinaba: assert_eq( e.evalString(`let x=1; let _ = (@a x=2;2); x`), new IntValue(BigInt(1)) ); 6ac127ddd0 2010-11-23 kinaba: e = new Evaluator; 6ac127ddd0 2010-11-23 kinaba: assert_throw!Throwable( e.evalString(`let x=1; let _ = (@a x=2;2); @a(x)`) ); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: 6ac127ddd0 2010-11-23 kinaba: unittest 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: auto e = new Evaluator; 6ac127ddd0 2010-11-23 kinaba: enrollRuntimeLibrary(e); 6ac127ddd0 2010-11-23 kinaba: assert_eq( e.evalString(` 6ac127ddd0 2010-11-23 kinaba: @@s(x){x}; 6ac127ddd0 2010-11-23 kinaba: @s "+" = fun(x, y) {@value( 6ac127ddd0 2010-11-23 kinaba: @s(x) - @s(y) 6ac127ddd0 2010-11-23 kinaba: )}; 6ac127ddd0 2010-11-23 kinaba: @s(1 + 2) 6ac127ddd0 2010-11-23 kinaba: `), new IntValue(BigInt(-1)) ); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: 6ac127ddd0 2010-11-23 kinaba: unittest 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: auto e = new Evaluator; 6ac127ddd0 2010-11-23 kinaba: enrollRuntimeLibrary(e); 6ac127ddd0 2010-11-23 kinaba: assert_eq( e.evalString(` 6ac127ddd0 2010-11-23 kinaba: @@3(x){x}; 6ac127ddd0 2010-11-23 kinaba: def incr(x) { x+1 }; 6ac127ddd0 2010-11-23 kinaba: @ 3 incr(x) {@value( if(@ 3(x)+1< 3){@ 3(x)+1}else{0} )}; 6ac127ddd0 2010-11-23 kinaba: def fb(n @value @3) { @3(n) }; 6ac127ddd0 2010-11-23 kinaba: fb(incr(incr(incr(0)))) 6ac127ddd0 2010-11-23 kinaba: `), new IntValue(BigInt(0)) ); 423f308350 2010-11-07 kinaba: } 8d297342aa 2010-11-08 kinaba: 5e407d7cf8 2010-11-08 kinaba: unittest 5e407d7cf8 2010-11-08 kinaba: { 6ac127ddd0 2010-11-23 kinaba: auto e = new Evaluator; 6ac127ddd0 2010-11-23 kinaba: enrollRuntimeLibrary(e); 6ac127ddd0 2010-11-23 kinaba: assert_nothrow( e.evalString(` 6ac127ddd0 2010-11-23 kinaba: @macro twice(x) { x; x }; 6ac127ddd0 2010-11-23 kinaba: def main() { twice(1) }; 6ac127ddd0 2010-11-23 kinaba: main() 6ac127ddd0 2010-11-23 kinaba: `) ); 5e407d7cf8 2010-11-08 kinaba: } 3995a5eb6a 2010-11-21 kinaba: /* 423f308350 2010-11-07 kinaba: unittest 423f308350 2010-11-07 kinaba: { 2459e9a821 2010-11-09 kinaba: assert_eq( evalString(`var fac = fun(x){ 633e700889 2010-11-07 kinaba: if(x) 633e700889 2010-11-07 kinaba: { x*fac(x-1); } 633e700889 2010-11-07 kinaba: else 633e700889 2010-11-07 kinaba: { 1; }; 633e700889 2010-11-07 kinaba: }; 2459e9a821 2010-11-09 kinaba: fac(10);`).val, new IntValue(BigInt(10*9*8*5040))); 2459e9a821 2010-11-09 kinaba: assert_eq( evalString(`var fib = fun(x){ 172a537bea 2010-11-07 kinaba: if(x<2) 172a537bea 2010-11-07 kinaba: { 1; } 172a537bea 2010-11-07 kinaba: else 172a537bea 2010-11-07 kinaba: { fib(x-1) + fib(x-2); }; 172a537bea 2010-11-07 kinaba: }; 8e3db9ef20 2010-11-20 kinaba: fib(5);`).val, new IntValue(BigInt(8))); 7465fcdd7f 2010-11-09 kinaba: } 7465fcdd7f 2010-11-09 kinaba: unittest 7465fcdd7f 2010-11-09 kinaba: { c368edbcb1 2010-11-13 kinaba: assert_eq( evalString(`@@t = fun(x){x+1}; @t(123)`).val, new IntValue(BigInt(124)) ); 060f267779 2010-11-20 kinaba: // there was a bug that declaration in the first line of function definition 060f267779 2010-11-20 kinaba: // cannot be recursive 060f267779 2010-11-20 kinaba: assert_nothrow( evalString(`def foo() { 060f267779 2010-11-20 kinaba: def bar(y) { if(y<1) {0} else {bar(0)} }; 060f267779 2010-11-20 kinaba: bar(1) 060f267779 2010-11-20 kinaba: }; foo()`) ); 423f308350 2010-11-07 kinaba: } 3995a5eb6a 2010-11-21 kinaba: */