Diff
Not logged in

Differences From Artifact [c82fe33ef6c72ef2]:

To Artifact [0a7ac481ec249b42]:


4 4 * 5 5 * Evaluator for Polemy programming language. 6 6 */ 7 7 module polemy.eval; 8 8 import polemy._common; 9 9 import polemy.ast; 10 10 import polemy.runtime; 11 + 12 +Context createGlobalContext() 13 +{ 14 + auto ctx = new Context; 15 + ctx.add("+", new PrimitiveFunction(delegate Value(Value[] args){ 16 + if( args.length != 2 ) 17 + throw new PolemyRuntimeException("+ takes two arguments!!"); // TODO improve this message 18 + if( auto x = cast(IntValue)args[0] ) 19 + if( auto y = cast(IntValue)args[1] ) 20 + return new IntValue(x.data+y.data); 21 + throw new PolemyRuntimeException("cannot add non-integers"); // TODO improve this message 22 + })); 23 + ctx.add("-", new PrimitiveFunction(delegate Value(Value[] args){ 24 + if( args.length != 2 ) 25 + throw new PolemyRuntimeException("- takes two arguments!!"); // TODO improve this message 26 + if( auto x = cast(IntValue)args[0] ) 27 + if( auto y = cast(IntValue)args[1] ) 28 + return new IntValue(x.data-y.data); 29 + throw new PolemyRuntimeException("cannot add non-integers"); // TODO improve this message 30 + })); 31 + ctx.add("*", new PrimitiveFunction(delegate Value(Value[] args){ 32 + if( args.length != 2 ) 33 + throw new PolemyRuntimeException("* takes two arguments!!"); // TODO improve this message 34 + if( auto x = cast(IntValue)args[0] ) 35 + if( auto y = cast(IntValue)args[1] ) 36 + return new IntValue(x.data*y.data); 37 + throw new PolemyRuntimeException("cannot add non-integers"); // TODO improve this message 38 + })); 39 + ctx.add("/", new PrimitiveFunction(delegate Value(Value[] args){ 40 + if( args.length != 2 ) 41 + throw new PolemyRuntimeException("/ takes two arguments!!"); // TODO improve this message 42 + if( auto x = cast(IntValue)args[0] ) 43 + if( auto y = cast(IntValue)args[1] ) 44 + return new IntValue(x.data/y.data); 45 + throw new PolemyRuntimeException("cannot add non-integers"); // TODO improve this message 46 + })); 47 + return ctx; 48 +} 11 49 12 50 Context eval(Program prog) 13 51 { 14 - return eval(prog, new Context); 52 + return eval(prog, createGlobalContext()); 15 53 } 16 54 17 55 Context eval(Program prog, Context ctx) 18 56 { 19 57 foreach(s; prog) 20 58 ctx = eval(s, ctx); 21 59 return ctx; ................................................................................ 51 89 } 52 90 else 53 91 if( auto e = cast(VarExpression)_e ) 54 92 { 55 93 return ctx[e.var]; 56 94 } 57 95 else 58 - if( auto e = cast(BinOpExpression)_e ) 96 + if( auto e = cast(AssignExpression)_e ) 59 97 { 60 - if( e.op == "=" ) 98 + if( auto ev = cast(VarExpression)e.lhs ) 61 99 { 62 - if( auto ev = cast(VarExpression)e.lhs ) 63 - { 64 - Value r = eval(e.rhs, ctx); 65 - ctx[ev.var] = r; 66 - return r; 67 - } 68 - throw new PolemyRuntimeException(sprintf!"Lhs of assignment must be a variable: %s"(e.pos)); 100 + Value r = eval(e.rhs, ctx); 101 + ctx[ev.var] = r; 102 + return r; 69 103 } 70 - 71 - Value l = eval(e.lhs, ctx); 72 - Value r = eval(e.rhs, ctx); 73 - if( auto lv = cast(IntValue)l ) 74 - if( auto rv = cast(IntValue)r ) 75 - final switch(e.op) 76 - { 77 - case "+": return new IntValue(lv.data+rv.data); 78 - case "-": return new IntValue(lv.data-rv.data); 79 - case "*": return new IntValue(lv.data*rv.data); 80 - case "/": return new IntValue(lv.data/rv.data); 81 - } 82 - else 83 - throw new PolemyRuntimeException(sprintf!"rhs of %s must be an integer but was %s at [%s]"(e.op, typeid(r), e.rhs.pos)); 84 - else 85 - throw new PolemyRuntimeException(sprintf!"lhs of %s must be an integer but was %s at [%s]"(e.op, typeid(l), e.lhs.pos)); 104 + throw new PolemyRuntimeException(sprintf!"Lhs of assignment must be a variable: %s"(e.pos)); 105 + } 106 + else 107 + if( auto e = cast(FuncallExpression)_e ) 108 + { 109 + Value _f = eval(e.fun, ctx); 110 + if( auto f = cast(FunValue)_f ) { 111 + Value[] args; 112 + foreach(a; e.args) 113 + args ~= eval(a, ctx); 114 + return f.call(args); 115 + } else 116 + throw new PolemyRuntimeException(sprintf!"Non-funcion is applied at [%s]"(e.pos)); 86 117 } 87 118 throw new PolemyRuntimeException(sprintf!"Unknown Kind of Expression %s at [%s]"(typeid(_e), _e.pos)); 88 119 } 89 120 90 121 91 122 version(unittest) import polemy.parse; 92 123 version(unittest) import std.stdio;