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; 36c517dfc4 2010-11-23 kinaba: import polemy.value; 36c517dfc4 2010-11-23 kinaba: import polemy.valueconv; 552d43f567 2010-11-26 kinaba: import std.signals; a5fe6233c1 2010-11-21 kinaba: b97bd4f713 2010-11-23 kinaba: /// Objects for maitaining global environment and evaluation of expression on it 6ac127ddd0 2010-11-23 kinaba: class Evaluator 423f308350 2010-11-07 kinaba: { 6ac127ddd0 2010-11-23 kinaba: public: b97bd4f713 2010-11-23 kinaba: /// Evaluate the AST 6ac127ddd0 2010-11-23 kinaba: Value evalAST(AST e) 203e4cb208 2010-11-27 kinaba: { return getLayerEval(ValueLayer).macroAndEval(e, theContext, LayerEval.OverwriteCtx); } 6ac127ddd0 2010-11-23 kinaba: b97bd4f713 2010-11-23 kinaba: /// Evaluate the string 6ac127ddd0 2010-11-23 kinaba: Value evalString(S,T...)(S str, T fn_ln_cn) 203e4cb208 2010-11-27 kinaba: { return evalAST(parseString(str,fn_ln_cn)); } 6ac127ddd0 2010-11-23 kinaba: b97bd4f713 2010-11-23 kinaba: /// Evaluate the file 6ac127ddd0 2010-11-23 kinaba: Value evalFile(S,T...)(S filename, T ln_cn) 203e4cb208 2010-11-27 kinaba: { return evalAST(parseFile(filename,ln_cn)); } 6ac127ddd0 2010-11-23 kinaba: b97bd4f713 2010-11-23 kinaba: /// Get the global context 6ac127ddd0 2010-11-23 kinaba: Table globalContext() 203e4cb208 2010-11-27 kinaba: { return theContext; } 203e4cb208 2010-11-27 kinaba: 203e4cb208 2010-11-27 kinaba: /// Initialize evaluator with empty context 203e4cb208 2010-11-27 kinaba: this() 6ac127ddd0 2010-11-23 kinaba: { 203e4cb208 2010-11-27 kinaba: theContext = new Table; 203e4cb208 2010-11-27 kinaba: theLayers[ValueLayer] = new ValueLayerEval; 203e4cb208 2010-11-27 kinaba: theLayers[MacroLayer] = new MacroLayerEval; 203e4cb208 2010-11-27 kinaba: theLayers[RawMacroLayer] = new RawMacroLayerEval; 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: 6ac127ddd0 2010-11-23 kinaba: private: 203e4cb208 2010-11-27 kinaba: Table theContext; 203e4cb208 2010-11-27 kinaba: LayerEval[Layer] theLayers; b97bd4f713 2010-11-23 kinaba: 203e4cb208 2010-11-27 kinaba: /// Get the layer evaluator from layer ID 203e4cb208 2010-11-27 kinaba: LayerEval getLayerEval(Layer lay) 6ac127ddd0 2010-11-23 kinaba: { 203e4cb208 2010-11-27 kinaba: if(auto p = lay in theLayers) 203e4cb208 2010-11-27 kinaba: return *p; 203e4cb208 2010-11-27 kinaba: return theLayers[lay] = new UserDefinedLayerEval(lay); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: 203e4cb208 2010-11-27 kinaba: /// Interface of layers 6760e0dd02 2010-11-26 kinaba: abstract class LayerEval a5fe6233c1 2010-11-21 kinaba: { 203e4cb208 2010-11-27 kinaba: enum : bool { CascadeCtx=false, OverwriteCtx=true }; 203e4cb208 2010-11-27 kinaba: 6760e0dd02 2010-11-26 kinaba: /// Concrete layers should implement these 203e4cb208 2010-11-27 kinaba: protected Layer layerID(); 203e4cb208 2010-11-27 kinaba: protected Value eval_( Die e, Table ctx, bool ctxMod );/// 203e4cb208 2010-11-27 kinaba: protected Value eval_( Str e, Table ctx, bool ctxMod );/// 203e4cb208 2010-11-27 kinaba: protected Value eval_( Int e, Table ctx, bool ctxMod );/// 203e4cb208 2010-11-27 kinaba: protected Value eval_( Var e, Table ctx, bool ctxMod );/// 203e4cb208 2010-11-27 kinaba: protected Value eval_( Lay e, Table ctx, bool ctxMod );/// 203e4cb208 2010-11-27 kinaba: protected Value eval_( Let e, Table ctx, bool ctxMod );/// 203e4cb208 2010-11-27 kinaba: protected Value eval_( App e, Table ctx, bool ctxMod );/// 203e4cb208 2010-11-27 kinaba: protected Value eval_( Fun e, Table ctx, bool ctxMod );/// 203e4cb208 2010-11-27 kinaba: 203e4cb208 2010-11-27 kinaba: /// Should override this also, if the layer may return null for optimization 203e4cb208 2010-11-27 kinaba: Value evalToNonNull( AST e, Table ctx, bool ctxMod = CascadeCtx ) 203e4cb208 2010-11-27 kinaba: { return eval(e,ctx,ctxMod); } 203e4cb208 2010-11-27 kinaba: 203e4cb208 2010-11-27 kinaba: /// Do macro expansion first, and then eval. Should override this also if it is NOT macro layer. 203e4cb208 2010-11-27 kinaba: Value macroAndEval( AST e, Table ctx, bool ctxMod = CascadeCtx ) 203e4cb208 2010-11-27 kinaba: { return evalToNonNull(e,ctx,ctxMod); } 6760e0dd02 2010-11-26 kinaba: 6760e0dd02 2010-11-26 kinaba: /// dynamic-overload-resolution 203e4cb208 2010-11-27 kinaba: Value eval( AST e, Table ctx, bool ctxMod = CascadeCtx ) 6760e0dd02 2010-11-26 kinaba: { 203e4cb208 2010-11-27 kinaba: enum funName = "eval_"; // modify here for customization 203e4cb208 2010-11-27 kinaba: alias TypeTuple!(e,ctx,ctxMod) params; // modify here for customization 6760e0dd02 2010-11-26 kinaba: 6760e0dd02 2010-11-26 kinaba: alias typeof(__traits(getOverloads, this, funName)) ovTypes; 6760e0dd02 2010-11-26 kinaba: alias staticMap!(firstParam, ovTypes) fstTypes; 6760e0dd02 2010-11-26 kinaba: alias DerivedToFront!(fstTypes) fstTypes_sorted; 6760e0dd02 2010-11-26 kinaba: foreach(i, T; fstTypes_sorted) 6760e0dd02 2010-11-26 kinaba: static if( is(T == typeof(params[0])) ) {} else if( auto _x = cast(T)params[0] ) 6760e0dd02 2010-11-26 kinaba: return __traits(getOverloads, this, funName)[i](_x, params[1..$]); 6760e0dd02 2010-11-26 kinaba: 6760e0dd02 2010-11-26 kinaba: // modify here to customize the default behavior 6760e0dd02 2010-11-26 kinaba: assert(false, text("eval() for ",typeid(e)," [",e.pos,"] is not defined")); 6760e0dd02 2010-11-26 kinaba: } 6760e0dd02 2010-11-26 kinaba: 203e4cb208 2010-11-27 kinaba: /// Function calling convention. 203e4cb208 2010-11-27 kinaba: /// Run all arugment AST in the appropriate layer and invoke the function. 203e4cb208 2010-11-27 kinaba: Value invokeFunction(Value f_, AST[] args, Table ctx, LexPosition pos, string callstackmsg) 6760e0dd02 2010-11-26 kinaba: { 203e4cb208 2010-11-27 kinaba: FunValue f = cast(FunValue)f_; 203e4cb208 2010-11-27 kinaba: if( f is null ) 203e4cb208 2010-11-27 kinaba: throw genex!RuntimeException(pos, text("tried to call non-function: ",f)); 203e4cb208 2010-11-27 kinaba: if( f.params().length != args.length ) 203e4cb208 2010-11-27 kinaba: throw genex!RuntimeException(pos, 203e4cb208 2010-11-27 kinaba: sprintf!("%d arguments required but %d passed")(f.params().length, args.length)); 203e4cb208 2010-11-27 kinaba: 203e4cb208 2010-11-27 kinaba: Table newCtx = new Table(f.definitionContext(), Table.Kind.NotPropagateSet); 203e4cb208 2010-11-27 kinaba: foreach(i,p; f.params()) 203e4cb208 2010-11-27 kinaba: if( p.layers.empty ) 203e4cb208 2010-11-27 kinaba: newCtx.set(p.name, layerID(), this.evalToNonNull(args[i], ctx)); 203e4cb208 2010-11-27 kinaba: else 203e4cb208 2010-11-27 kinaba: foreach(argLay; p.layers) 203e4cb208 2010-11-27 kinaba: { 203e4cb208 2010-11-27 kinaba: Layer ll = argLay; 203e4cb208 2010-11-27 kinaba: if( isMacroLayer(argLay) && typeid(this)!=typeid(MacroLayerEval) ) 203e4cb208 2010-11-27 kinaba: ll = RawMacroLayer; // explicit @macro invokes (rawmacro) 203e4cb208 2010-11-27 kinaba: newCtx.set(p.name, argLay, getLayerEval(ll).evalToNonNull(args[i], ctx)); 6760e0dd02 2010-11-26 kinaba: } 203e4cb208 2010-11-27 kinaba: scope _ = new PushCallStack(pos, callstackmsg); 203e4cb208 2010-11-27 kinaba: return f.invoke(layerID(), newCtx, pos); 6760e0dd02 2010-11-26 kinaba: } 6760e0dd02 2010-11-26 kinaba: 203e4cb208 2010-11-27 kinaba: /// Lift the value v to the current layer 6760e0dd02 2010-11-26 kinaba: Value lift(Value v, Table ctx, LexPosition pos) 6760e0dd02 2010-11-26 kinaba: { 203e4cb208 2010-11-27 kinaba: // functions are automatically lifted by itself 6760e0dd02 2010-11-26 kinaba: if( cast(FunValue) v ) 6760e0dd02 2010-11-26 kinaba: return v; 6760e0dd02 2010-11-26 kinaba: 203e4cb208 2010-11-27 kinaba: Layer lay = layerID(); 203e4cb208 2010-11-27 kinaba: 203e4cb208 2010-11-27 kinaba: // load the lift function 6760e0dd02 2010-11-26 kinaba: if( !ctx.has(lay, LiftLayer) ) 6760e0dd02 2010-11-26 kinaba: throw genex!RuntimeException(pos, "lift function for "~lay~" is not registered" ); 6760e0dd02 2010-11-26 kinaba: 203e4cb208 2010-11-27 kinaba: Value f_ = ctx.get(lay, LiftLayer, pos); 203e4cb208 2010-11-27 kinaba: FunValue f = cast(FunValue) f_; 203e4cb208 2010-11-27 kinaba: if( f is null ) 203e4cb208 2010-11-27 kinaba: throw genex!RuntimeException(pos, 203e4cb208 2010-11-27 kinaba: text("non-function ", f_, " is registered as the lift function for ", lay)); 203e4cb208 2010-11-27 kinaba: if( f.params().length != 1 || f.params()[0].layers.length>=1 ) 203e4cb208 2010-11-27 kinaba: throw genex!RuntimeException(pos, 203e4cb208 2010-11-27 kinaba: text("lift function must take exactly 1 neutral parameter:",lay)); 203e4cb208 2010-11-27 kinaba: 203e4cb208 2010-11-27 kinaba: // invokeFunction 203e4cb208 2010-11-27 kinaba: Table newCtx = new Table(f.definitionContext(), Table.Kind.NotPropagateSet); 203e4cb208 2010-11-27 kinaba: newCtx.set(f.params()[0].name, ValueLayer, v); 203e4cb208 2010-11-27 kinaba: scope _ = new PushCallStack(pos, "lift to "~lay); 203e4cb208 2010-11-27 kinaba: return f.invoke(ValueLayer, newCtx, pos); 6760e0dd02 2010-11-26 kinaba: } 2134cd44cc 2010-11-23 kinaba: } 2134cd44cc 2010-11-23 kinaba: 6760e0dd02 2010-11-26 kinaba: /// Evaluator for standard @value semantics 6760e0dd02 2010-11-26 kinaba: class ValueLayerEval : LayerEval 2134cd44cc 2010-11-23 kinaba: { 203e4cb208 2010-11-27 kinaba: override Layer layerID() 6760e0dd02 2010-11-26 kinaba: { 6760e0dd02 2010-11-26 kinaba: return ValueLayer; 6760e0dd02 2010-11-26 kinaba: } 6760e0dd02 2010-11-26 kinaba: override Value eval_( Die e, Table ctx, bool ctxMod ) 6760e0dd02 2010-11-26 kinaba: { 6760e0dd02 2010-11-26 kinaba: throw genex!RuntimeException(e.pos, "undefined case"); 6760e0dd02 2010-11-26 kinaba: } 6760e0dd02 2010-11-26 kinaba: override Value eval_( Str e, Table ctx, bool ctxMod ) 6760e0dd02 2010-11-26 kinaba: { 6760e0dd02 2010-11-26 kinaba: return new StrValue(e.data); 6760e0dd02 2010-11-26 kinaba: } 6760e0dd02 2010-11-26 kinaba: override Value eval_( Int e, Table ctx, bool ctxMod ) 6760e0dd02 2010-11-26 kinaba: { 6760e0dd02 2010-11-26 kinaba: return new IntValue(e.data); 6760e0dd02 2010-11-26 kinaba: } 6760e0dd02 2010-11-26 kinaba: override Value eval_( Var e, Table ctx, bool ctxMod ) 6760e0dd02 2010-11-26 kinaba: { 203e4cb208 2010-11-27 kinaba: return ctx.get(e.name, layerID(), e.pos); 6760e0dd02 2010-11-26 kinaba: } 6760e0dd02 2010-11-26 kinaba: override Value eval_( Lay e, Table ctx, bool ctxMod ) 6760e0dd02 2010-11-26 kinaba: { 203e4cb208 2010-11-27 kinaba: return getLayerEval(e.layer).evalToNonNull(e.expr, ctx); 6760e0dd02 2010-11-26 kinaba: } 6760e0dd02 2010-11-26 kinaba: override Value eval_( Let e, Table ctx, bool ctxMod ) 6760e0dd02 2010-11-26 kinaba: { 203e4cb208 2010-11-27 kinaba: if( !ctxMod ) 203e4cb208 2010-11-27 kinaba: ctx = new Table(ctx, Table.Kind.NotPropagateSet); a795c97dc3 2010-11-27 kinaba: Value ri = this.eval(e.vdef, ctx); 203e4cb208 2010-11-27 kinaba: ctx.set(e.name, e.layer.empty ? layerID(): e.layer, ri); 203e4cb208 2010-11-27 kinaba: return this.eval(e.expr, ctx, OverwriteCtx); 6760e0dd02 2010-11-26 kinaba: } 6760e0dd02 2010-11-26 kinaba: override Value eval_( App e, Table ctx, bool ctxMod ) 6760e0dd02 2010-11-26 kinaba: { 6760e0dd02 2010-11-26 kinaba: Value f = this.eval( e.fun, ctx, CascadeCtx ); 6760e0dd02 2010-11-26 kinaba: return this.invokeFunction(f, e.args, ctx, e.pos, getNameIfPossible(e.fun)); 6760e0dd02 2010-11-26 kinaba: } 6760e0dd02 2010-11-26 kinaba: override Value eval_( Fun e, Table ctx, bool ctxMod ) 6760e0dd02 2010-11-26 kinaba: { ba11f1d551 2010-11-23 kinaba: return createNewFunction(e, ctx); 6760e0dd02 2010-11-26 kinaba: } 203e4cb208 2010-11-27 kinaba: override Value macroAndEval( AST e, Table ctx, bool ctxMod ) 203e4cb208 2010-11-27 kinaba: { 203e4cb208 2010-11-27 kinaba: // incremental execution of let-expressions 203e4cb208 2010-11-27 kinaba: if(auto le = cast(Let)e) 203e4cb208 2010-11-27 kinaba: { a795c97dc3 2010-11-27 kinaba: AST ai = runMacro(le.vdef, ctx); 203e4cb208 2010-11-27 kinaba: 203e4cb208 2010-11-27 kinaba: if( !ctxMod ) 203e4cb208 2010-11-27 kinaba: ctx = new Table(ctx, Table.Kind.NotPropagateSet); 203e4cb208 2010-11-27 kinaba: 203e4cb208 2010-11-27 kinaba: Value vi = this.eval(ai, ctx); 203e4cb208 2010-11-27 kinaba: ctx.set(le.name, le.layer.empty ? layerID() : le.layer, vi); 203e4cb208 2010-11-27 kinaba: return this.macroAndEval(le.expr, ctx, OverwriteCtx); 203e4cb208 2010-11-27 kinaba: } 203e4cb208 2010-11-27 kinaba: else 203e4cb208 2010-11-27 kinaba: return this.eval(runMacro(e,ctx,ctxMod), ctx, ctxMod); 203e4cb208 2010-11-27 kinaba: } ba11f1d551 2010-11-23 kinaba: } ba11f1d551 2010-11-23 kinaba: 6760e0dd02 2010-11-26 kinaba: /// Evaluator for user-defined layer 6760e0dd02 2010-11-26 kinaba: class UserDefinedLayerEval : ValueLayerEval ba11f1d551 2010-11-23 kinaba: { 203e4cb208 2010-11-27 kinaba: Layer theID; 6760e0dd02 2010-11-26 kinaba: mixin SimpleConstructor; 6760e0dd02 2010-11-26 kinaba: 203e4cb208 2010-11-27 kinaba: override Layer layerID() 6760e0dd02 2010-11-26 kinaba: { 203e4cb208 2010-11-27 kinaba: return theID; 6760e0dd02 2010-11-26 kinaba: } 6760e0dd02 2010-11-26 kinaba: override Value eval_( Die e, Table ctx, bool ctxMod ) 6760e0dd02 2010-11-26 kinaba: { 203e4cb208 2010-11-27 kinaba: return new BottomValue; 6760e0dd02 2010-11-26 kinaba: } 6760e0dd02 2010-11-26 kinaba: override Value eval_( Str e, Table ctx, bool ctxMod ) 6760e0dd02 2010-11-26 kinaba: { 203e4cb208 2010-11-27 kinaba: return this.lift(super.eval_(e,ctx,ctxMod), ctx, e.pos); 6760e0dd02 2010-11-26 kinaba: } 6760e0dd02 2010-11-26 kinaba: override Value eval_( Int e, Table ctx, bool ctxMod ) 6760e0dd02 2010-11-26 kinaba: { 203e4cb208 2010-11-27 kinaba: return this.lift(super.eval_(e,ctx,ctxMod), ctx, e.pos); 6760e0dd02 2010-11-26 kinaba: } 6760e0dd02 2010-11-26 kinaba: override Value eval_( Var e, Table ctx, bool ctxMod ) 6760e0dd02 2010-11-26 kinaba: { 203e4cb208 2010-11-27 kinaba: if( ctx.has(e.name, layerID()) ) 203e4cb208 2010-11-27 kinaba: return ctx.get(e.name, layerID()); a795c97dc3 2010-11-27 kinaba: Value v; a795c97dc3 2010-11-27 kinaba: try { v = ctx.get(e.name, ValueLayer, e.pos); } a795c97dc3 2010-11-27 kinaba: catch ( RuntimeException ) { a795c97dc3 2010-11-27 kinaba: throw genex!RuntimeException(e.pos, e.name~" not found in layer "~layerID()~" nor "~ValueLayer); a795c97dc3 2010-11-27 kinaba: } a795c97dc3 2010-11-27 kinaba: return this.lift(v, ctx, e.pos); ba11f1d551 2010-11-23 kinaba: } ba11f1d551 2010-11-23 kinaba: } ba11f1d551 2010-11-23 kinaba: 203e4cb208 2010-11-27 kinaba: // Macro layer. For optimization, if AST didn't change it returns null 6760e0dd02 2010-11-26 kinaba: class MacroLayerEval : LayerEval ba11f1d551 2010-11-23 kinaba: { 203e4cb208 2010-11-27 kinaba: override Layer layerID() 6760e0dd02 2010-11-26 kinaba: { 6760e0dd02 2010-11-26 kinaba: return MacroLayer; 203e4cb208 2010-11-27 kinaba: } 203e4cb208 2010-11-27 kinaba: override Value evalToNonNull( AST e, Table ctx, bool ctxMod = CascadeCtx ) 203e4cb208 2010-11-27 kinaba: { 203e4cb208 2010-11-27 kinaba: Value v = this.eval(e, ctx, ctxMod); 203e4cb208 2010-11-27 kinaba: return v is null ? ast2table(e) : v; 6760e0dd02 2010-11-26 kinaba: } 6760e0dd02 2010-11-26 kinaba: override Value eval_( Die e, Table ctx, bool ctxMod ) 6760e0dd02 2010-11-26 kinaba: { 6760e0dd02 2010-11-26 kinaba: return null; 6760e0dd02 2010-11-26 kinaba: } 6760e0dd02 2010-11-26 kinaba: override Value eval_( Str e, Table ctx, bool ctxMod ) 6760e0dd02 2010-11-26 kinaba: { 6760e0dd02 2010-11-26 kinaba: return null; 6760e0dd02 2010-11-26 kinaba: } 6760e0dd02 2010-11-26 kinaba: override Value eval_( Int e, Table ctx, bool ctxMod ) 6760e0dd02 2010-11-26 kinaba: { 6760e0dd02 2010-11-26 kinaba: return null; 6760e0dd02 2010-11-26 kinaba: } 6760e0dd02 2010-11-26 kinaba: override Value eval_( Var e, Table ctx, bool ctxMod ) 6760e0dd02 2010-11-26 kinaba: { 203e4cb208 2010-11-27 kinaba: if( ctx.has(e.name, layerID()) ) 203e4cb208 2010-11-27 kinaba: return ctx.get(e.name, layerID(), e.pos); 203e4cb208 2010-11-27 kinaba: return null; 6760e0dd02 2010-11-26 kinaba: } 6760e0dd02 2010-11-26 kinaba: override Value eval_( Lay e, Table ctx, bool ctxMod ) ba11f1d551 2010-11-23 kinaba: { 203e4cb208 2010-11-27 kinaba: return getLayerEval(e.layer).eval(e.expr,ctx); ba11f1d551 2010-11-23 kinaba: } 6760e0dd02 2010-11-26 kinaba: override Value eval_( Let e, Table ctx, bool ctxMod ) ba11f1d551 2010-11-23 kinaba: { 203e4cb208 2010-11-27 kinaba: if( !ctxMod ) 203e4cb208 2010-11-27 kinaba: ctx = new Table(ctx, Table.Kind.NotPropagateSet); 203e4cb208 2010-11-27 kinaba: a795c97dc3 2010-11-27 kinaba: Value ai = this.eval(e.vdef, ctx); 203e4cb208 2010-11-27 kinaba: ctx.set(e.name, NoopLayer, null); 203e4cb208 2010-11-27 kinaba: Value ae = this.eval(e.expr, ctx, OverwriteCtx); 203e4cb208 2010-11-27 kinaba: 203e4cb208 2010-11-27 kinaba: if( ai is null && ae is null ) return null; a795c97dc3 2010-11-27 kinaba: if( ai is null ) ai = ast2table(e.vdef); 6760e0dd02 2010-11-26 kinaba: if( ae is null ) ae = ast2table(e.expr); 203e4cb208 2010-11-27 kinaba: 6760e0dd02 2010-11-26 kinaba: return ast2table(e, delegate Value (AST _){ a795c97dc3 2010-11-27 kinaba: if(_ is e.vdef) { return ai; } 6760e0dd02 2010-11-26 kinaba: if(_ is e.expr) { return ae; } 6760e0dd02 2010-11-26 kinaba: assert(false); 6760e0dd02 2010-11-26 kinaba: }); 552d43f567 2010-11-26 kinaba: } 6760e0dd02 2010-11-26 kinaba: override Value eval_( App e, Table ctx, bool ctxMod ) 552d43f567 2010-11-26 kinaba: { 203e4cb208 2010-11-27 kinaba: Value f = this.eval( e.fun, ctx ); 6760e0dd02 2010-11-26 kinaba: if(auto ff = cast(FunValue)f) 6760e0dd02 2010-11-26 kinaba: return this.invokeFunction(ff, e.args, ctx, e.pos, getNameIfPossible(e.fun)); 203e4cb208 2010-11-27 kinaba: else 203e4cb208 2010-11-27 kinaba: { 6760e0dd02 2010-11-26 kinaba: bool allNull = (f is null); 6760e0dd02 2010-11-26 kinaba: Value[] vas; 203e4cb208 2010-11-27 kinaba: foreach(a; e.args) 203e4cb208 2010-11-27 kinaba: { 6760e0dd02 2010-11-26 kinaba: Value va = this.eval(a, ctx, CascadeCtx); 6760e0dd02 2010-11-26 kinaba: if(va !is null) allNull = false; 6760e0dd02 2010-11-26 kinaba: vas ~= va; 6760e0dd02 2010-11-26 kinaba: } 6760e0dd02 2010-11-26 kinaba: if( allNull ) 6760e0dd02 2010-11-26 kinaba: return null; 6760e0dd02 2010-11-26 kinaba: return ast2table(e, delegate Value (AST _){ 6760e0dd02 2010-11-26 kinaba: if(_ is e.fun) return (f is null ? ast2table(e.fun) : f); 6760e0dd02 2010-11-26 kinaba: foreach(i,a; e.args) if(_ is a) return (vas[i] is null ? ast2table(a) : vas[i]); 6760e0dd02 2010-11-26 kinaba: assert(false); 6760e0dd02 2010-11-26 kinaba: }); 552d43f567 2010-11-26 kinaba: } 6760e0dd02 2010-11-26 kinaba: } 6760e0dd02 2010-11-26 kinaba: override Value eval_( Fun e, Table ctx, bool ctxMod ) 6760e0dd02 2010-11-26 kinaba: { 203e4cb208 2010-11-27 kinaba: ctx = new Table(ctx, Table.Kind.NotPropagateSet); 6760e0dd02 2010-11-26 kinaba: foreach(p; e.params) 203e4cb208 2010-11-27 kinaba: ctx.set(p.name, NoopLayer, null); 203e4cb208 2010-11-27 kinaba: Value af = this.eval(e.funbody, ctx); 6760e0dd02 2010-11-26 kinaba: if( af is null ) 6760e0dd02 2010-11-26 kinaba: return null; 6760e0dd02 2010-11-26 kinaba: return ast2table(e, (AST _){if(_ is e.funbody)return af; assert(false);}); 6760e0dd02 2010-11-26 kinaba: } 6760e0dd02 2010-11-26 kinaba: } 6760e0dd02 2010-11-26 kinaba: 203e4cb208 2010-11-27 kinaba: /// (rawmacro) layer. almost same as @macro, but the Layer expression becomes AST, too. 6760e0dd02 2010-11-26 kinaba: class RawMacroLayerEval : MacroLayerEval 6760e0dd02 2010-11-26 kinaba: { 6760e0dd02 2010-11-26 kinaba: override Value eval_( Lay e, Table ctx, bool ctxMod ) 6760e0dd02 2010-11-26 kinaba: { 203e4cb208 2010-11-27 kinaba: Value ae = this.eval(e.expr, ctx); 6760e0dd02 2010-11-26 kinaba: return ae is null ? null 6760e0dd02 2010-11-26 kinaba: : ast2table(e, delegate Value (AST _){if(_ is e.expr)return ae; assert(false);}); 6ac127ddd0 2010-11-23 kinaba: } ba11f1d551 2010-11-23 kinaba: } ba11f1d551 2010-11-23 kinaba: 203e4cb208 2010-11-27 kinaba: private: // short utils 6760e0dd02 2010-11-26 kinaba: ba11f1d551 2010-11-23 kinaba: string getNameIfPossible(AST e) ba11f1d551 2010-11-23 kinaba: { ba11f1d551 2010-11-23 kinaba: if(auto v = cast(Var)e) ba11f1d551 2010-11-23 kinaba: return v.name; ba11f1d551 2010-11-23 kinaba: return ""; ba11f1d551 2010-11-23 kinaba: } ba11f1d551 2010-11-23 kinaba: 203e4cb208 2010-11-27 kinaba: AST runMacro(AST e, Table ctx, bool ctxMod=LayerEval.CascadeCtx) 203e4cb208 2010-11-27 kinaba: { 203e4cb208 2010-11-27 kinaba: Value v = getLayerEval(RawMacroLayer).eval(e, ctx, ctxMod); 203e4cb208 2010-11-27 kinaba: return (v is null ? e : polemy2d!(AST)(v, e.pos)); 203e4cb208 2010-11-27 kinaba: } 203e4cb208 2010-11-27 kinaba: 203e4cb208 2010-11-27 kinaba: private: 6ac127ddd0 2010-11-23 kinaba: Value createNewFunction(Fun e, Table ctx) 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: class UserDefinedFunValue : FunValue 3f6f41b558 2010-11-20 kinaba: { 20be503cae 2010-11-24 kinaba: Fun ast; 20be503cae 2010-11-24 kinaba: Table defCtx; 6ac127ddd0 2010-11-23 kinaba: override const(Parameter[]) params() { return ast.params; } 20be503cae 2010-11-24 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; } 153a14cec0 2010-11-24 kinaba: override string toString() const 153a14cec0 2010-11-24 kinaba: { return sprintf!"(function:%x:%x)"(cast(void*)ast, cast(void*)defCtx); } 20be503cae 2010-11-24 kinaba: override int opCmp(Object rhs) { 20be503cae 2010-11-24 kinaba: if(auto r = cast(UserDefinedFunValue)rhs) { b993a8ad16 2010-11-24 kinaba: if(auto c = typeid(void*).compare(cast(void*)ast, cast(void*)r.ast)) b993a8ad16 2010-11-24 kinaba: return c; b993a8ad16 2010-11-24 kinaba: if(auto c = typeid(void*).compare(cast(void*)defCtx, cast(void*)r.defCtx)) b993a8ad16 2010-11-24 kinaba: return c; b993a8ad16 2010-11-24 kinaba: return 0;// [TODO] avoid using pointer value... 20be503cae 2010-11-24 kinaba: } 153a14cec0 2010-11-24 kinaba: if(auto r = cast(Value)rhs) return typeid(this).opCmp(typeid(r)); 20be503cae 2010-11-24 kinaba: throw genex!RuntimeException("comparison with value and something other"); 20be503cae 2010-11-24 kinaba: } b993a8ad16 2010-11-24 kinaba: override hash_t toHash() { b993a8ad16 2010-11-24 kinaba: return (cast(hash_t)cast(void*)ast) + (cast(hash_t)cast(void*)defCtx); b993a8ad16 2010-11-24 kinaba: } 20be503cae 2010-11-24 kinaba: 552d43f567 2010-11-26 kinaba: AST[void*] mandeCache; b993a8ad16 2010-11-24 kinaba: static class MemokeyType b993a8ad16 2010-11-24 kinaba: { 203e4cb208 2010-11-27 kinaba: void* a; Layer b; Table c; 203e4cb208 2010-11-27 kinaba: mixin SimpleClass; b993a8ad16 2010-11-24 kinaba: } b993a8ad16 2010-11-24 kinaba: static Tuple!(Value,int)[MemokeyType] memo; b993a8ad16 2010-11-24 kinaba: b97bd4f713 2010-11-23 kinaba: override Value invoke(Layer lay, Table ctx, LexPosition pos) 3f6f41b558 2010-11-20 kinaba: { 203e4cb208 2010-11-27 kinaba: auto evlay = getLayerEval(lay); 203e4cb208 2010-11-27 kinaba: auto nonMemoizedRun = (){ return evlay.macroAndEval(ast.funbody, ctx); }; b993a8ad16 2010-11-24 kinaba: b993a8ad16 2010-11-24 kinaba: if( !isUserDefinedLayer(lay) ) b993a8ad16 2010-11-24 kinaba: return nonMemoizedRun(); b993a8ad16 2010-11-24 kinaba: 203e4cb208 2010-11-27 kinaba: // automatic memoized co-recursive execution 203e4cb208 2010-11-27 kinaba: MemokeyType memokey = new MemokeyType(cast(void*)ast, lay, ctx); b993a8ad16 2010-11-24 kinaba: if(auto p = memokey in memo) ba11f1d551 2010-11-23 kinaba: { b993a8ad16 2010-11-24 kinaba: (*p)[1] ++; b993a8ad16 2010-11-24 kinaba: return (*p)[0]; 2134cd44cc 2010-11-23 kinaba: } ba11f1d551 2010-11-23 kinaba: else 005474ba5b 2010-11-27 kinaba: memo[memokey] = tuple(cast(Value)new BottomValue, 0); b993a8ad16 2010-11-24 kinaba: b993a8ad16 2010-11-24 kinaba: Value r = nonMemoizedRun(); b993a8ad16 2010-11-24 kinaba: b993a8ad16 2010-11-24 kinaba: int touched = memo[memokey][1]; b993a8ad16 2010-11-24 kinaba: memo[memokey] = tuple(r, 12345678); b993a8ad16 2010-11-24 kinaba: return r; 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: b97bd4f713 2010-11-23 kinaba: /// Add primitive function to the global context b97bd4f713 2010-11-23 kinaba: void addPrimitive(R,T...)(string name, Layer defLay, R delegate (T) dg) 6ac127ddd0 2010-11-23 kinaba: { 6ac127ddd0 2010-11-23 kinaba: class NativeFunValue : FunValue 1c01f44f52 2010-11-13 kinaba: { 6ac127ddd0 2010-11-23 kinaba: override const(Parameter[]) params() { return params_data; } b97bd4f713 2010-11-23 kinaba: override Table definitionContext() { return theContext; } b97bd4f713 2010-11-23 kinaba: b97bd4f713 2010-11-23 kinaba: override string toString() { return sprintf!"(native:%x)"(dg.funcptr); } b97bd4f713 2010-11-23 kinaba: override int opCmp(Object rhs) { b97bd4f713 2010-11-23 kinaba: if(auto r = cast(NativeFunValue)rhs) return typeid(typeof(dg)).compare(&dg,&r.dg); b97bd4f713 2010-11-23 kinaba: if(auto r = cast(Value)rhs) return typeid(this).opCmp(typeid(r)); 153a14cec0 2010-11-24 kinaba: throw genex!RuntimeException("comparison with value and something other"); b97bd4f713 2010-11-23 kinaba: } b993a8ad16 2010-11-24 kinaba: override hash_t toHash() const { b993a8ad16 2010-11-24 kinaba: return typeid(dg).getHash(&dg); b993a8ad16 2010-11-24 kinaba: } b97bd4f713 2010-11-23 kinaba: b97bd4f713 2010-11-23 kinaba: R delegate(T) dg; b97bd4f713 2010-11-23 kinaba: Parameter[] params_data; b97bd4f713 2010-11-23 kinaba: b97bd4f713 2010-11-23 kinaba: this(R delegate(T) dg) b97bd4f713 2010-11-23 kinaba: { b97bd4f713 2010-11-23 kinaba: this.dg = dg; 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: } b97bd4f713 2010-11-23 kinaba: b97bd4f713 2010-11-23 kinaba: override Value invoke(Layer lay, Table ctx, LexPosition pos) 6ac127ddd0 2010-11-23 kinaba: { b97bd4f713 2010-11-23 kinaba: if( lay != defLay ) 153a14cec0 2010-11-24 kinaba: throw genex!RuntimeException(pos, 153a14cec0 2010-11-24 kinaba: text("only ", defLay, " layer can call native function: ", name)); 6ac127ddd0 2010-11-23 kinaba: T typed_args; 6ac127ddd0 2010-11-23 kinaba: foreach(i, Ti; T) { 005474ba5b 2010-11-27 kinaba: Value vi = ctx.get(text(i), ValueLayer, pos); 005474ba5b 2010-11-27 kinaba: typed_args[i] = cast(Ti) vi; 6ac127ddd0 2010-11-23 kinaba: if( typed_args[i] is null ) 153a14cec0 2010-11-24 kinaba: throw genex!RuntimeException(pos, 005474ba5b 2010-11-27 kinaba: sprintf!"type mismatch on the argument %d of native function %s. %s required but %s passed."(i+1,name,typeid(Ti),vi)); 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: } 6ac127ddd0 2010-11-23 kinaba: } 1c01f44f52 2010-11-13 kinaba: } b97bd4f713 2010-11-23 kinaba: theContext.set(name, defLay, new NativeFunValue(dg)); 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: } 6ac127ddd0 2010-11-23 kinaba: 203e4cb208 2010-11-27 kinaba: version(unittest) 203e4cb208 2010-11-27 kinaba: import polemy.runtime; 005474ba5b 2010-11-27 kinaba: 005474ba5b 2010-11-27 kinaba: unittest 005474ba5b 2010-11-27 kinaba: { 005474ba5b 2010-11-27 kinaba: auto e = new Evaluator; 005474ba5b 2010-11-27 kinaba: enrollRuntimeLibrary(e); 005474ba5b 2010-11-27 kinaba: assert_eq( e.evalString(` 005474ba5b 2010-11-27 kinaba: @@foo(x){x*2}; 005474ba5b 2010-11-27 kinaba: @foo "+" (x,y){x}; 005474ba5b 2010-11-27 kinaba: @foo(3+4) 005474ba5b 2010-11-27 kinaba: `), new IntValue(6) ); 005474ba5b 2010-11-27 kinaba: } 203e4cb208 2010-11-27 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; 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: } 203e4cb208 2010-11-27 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)) ); ba11f1d551 2010-11-23 kinaba: assert_eq( e.globalContext.get("x",ValueLayer), new IntValue(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); ba11f1d551 2010-11-23 kinaba: assert_eq( e.evalString(`let x=1; let y=(let x=2); x`), new IntValue(1) ); ba11f1d551 2010-11-23 kinaba: assert_eq( e.evalString(`let x=1; let y=(let x=2;fun(){x}); y()`), new IntValue(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 }; 3ae09b8cbf 2010-11-24 kinaba: @ 3 incr(x) {@value( if @ 3(x)+1< 3 then @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)) ); 0f02103885 2010-11-09 kinaba: } 0f02103885 2010-11-09 kinaba: 0f02103885 2010-11-09 kinaba: unittest 0f02103885 2010-11-09 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: `) ); 0f02103885 2010-11-09 kinaba: } 0f02103885 2010-11-09 kinaba: unittest 0f02103885 2010-11-09 kinaba: { f9c31f3cd8 2010-11-24 kinaba: auto e = new Evaluator; f9c31f3cd8 2010-11-24 kinaba: enrollRuntimeLibrary(e); f7e9e77316 2010-11-26 kinaba: assert_throw!RuntimeException( e.evalString(`case 1`) ); f9c31f3cd8 2010-11-24 kinaba: assert_nothrow( e.evalString(`case 1 when 1: 2`) ); f8684f4d69 2010-11-26 kinaba: f8684f4d69 2010-11-26 kinaba: // this is a shorthand for f8684f4d69 2010-11-26 kinaba: // @macro x = fun(){} in @macro(x) f8684f4d69 2010-11-26 kinaba: // so it is ok to fail, but it is really incovenient on REPL f8684f4d69 2010-11-26 kinaba: assert_nothrow( e.evalString(`@macro x=fun(){}`) ); f7e9e77316 2010-11-26 kinaba: } f7e9e77316 2010-11-26 kinaba: f7e9e77316 2010-11-26 kinaba: unittest f7e9e77316 2010-11-26 kinaba: { f7e9e77316 2010-11-26 kinaba: auto e = new Evaluator; f7e9e77316 2010-11-26 kinaba: enrollRuntimeLibrary(e); f7e9e77316 2010-11-26 kinaba: assert_throw!RuntimeException( e.evalString(`...`) ); 203e4cb208 2010-11-27 kinaba: assert_eq( e.evalString(`@@foo(x){x}; @foo(...)`), new BottomValue ); 423f308350 2010-11-07 kinaba: }