Differences From Artifact [c82fe33ef6c72ef2]:
- File
polemy/eval.d
- 2010-11-07 10:32:59 - part of checkin [4198578702e] on branch trunk - Changed several documentation comments into ddoc compatible ones. (user: kinaba) [annotate]
To Artifact [0a7ac481ec249b42]:
- File
polemy/eval.d
- 2010-11-07 12:20:47 - part of checkin [5d4cb856d8] on branch trunk - Added FuncallExpression (user: kinaba) [annotate]
4 * 4 *
5 * Evaluator for Polemy programming language. 5 * Evaluator for Polemy programming language.
6 */ 6 */
7 module polemy.eval; 7 module polemy.eval;
8 import polemy._common; 8 import polemy._common;
9 import polemy.ast; 9 import polemy.ast;
10 import polemy.runtime; 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!
> 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"); //
> 22 }));
> 23 ctx.add("-", new PrimitiveFunction(delegate Value(Value[] args){
> 24 if( args.length != 2 )
> 25 throw new PolemyRuntimeException("- takes two arguments!
> 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"); //
> 30 }));
> 31 ctx.add("*", new PrimitiveFunction(delegate Value(Value[] args){
> 32 if( args.length != 2 )
> 33 throw new PolemyRuntimeException("* takes two arguments!
> 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"); //
> 38 }));
> 39 ctx.add("/", new PrimitiveFunction(delegate Value(Value[] args){
> 40 if( args.length != 2 )
> 41 throw new PolemyRuntimeException("/ takes two arguments!
> 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"); //
> 46 }));
> 47 return ctx;
> 48 }
11 49
12 Context eval(Program prog) 50 Context eval(Program prog)
13 { 51 {
14 return eval(prog, new Context); | 52 return eval(prog, createGlobalContext());
15 } 53 }
16 54
17 Context eval(Program prog, Context ctx) 55 Context eval(Program prog, Context ctx)
18 { 56 {
19 foreach(s; prog) 57 foreach(s; prog)
20 ctx = eval(s, ctx); 58 ctx = eval(s, ctx);
21 return ctx; 59 return ctx;
................................................................................................................................................................................
51 } 89 }
52 else 90 else
53 if( auto e = cast(VarExpression)_e ) 91 if( auto e = cast(VarExpression)_e )
54 { 92 {
55 return ctx[e.var]; 93 return ctx[e.var];
56 } 94 }
57 else 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); | 100 Value r = eval(e.rhs, ctx);
65 ctx[ev.var] = r; | 101 ctx[ev.var] = r;
66 return r; | 102 return r;
67 } <
68 throw new PolemyRuntimeException(sprintf!"Lhs of assignm <
69 } 103 }
> 104 throw new PolemyRuntimeException(sprintf!"Lhs of assignment must
70 | 105 }
71 Value l = eval(e.lhs, ctx); <
72 Value r = eval(e.rhs, ctx); | 106 else
73 if( auto lv = cast(IntValue)l ) | 107 if( auto e = cast(FuncallExpression)_e )
74 if( auto rv = cast(IntValue)r ) <
75 final switch(e.op) <
76 { | 108 {
> 109 Value _f = eval(e.fun, ctx);
> 110 if( auto f = cast(FunValue)_f ) {
77 case "+": return new IntValue(lv.data+rv.data); | 111 Value[] args;
78 case "-": return new IntValue(lv.data-rv.data); | 112 foreach(a; e.args)
79 case "*": return new IntValue(lv.data*rv.data); | 113 args ~= eval(a, ctx);
80 case "/": return new IntValue(lv.data/rv.data); | 114 return f.call(args);
81 } <
82 else | 115 } else
83 throw new PolemyRuntimeException(sprintf!"rhs of | 116 throw new PolemyRuntimeException(sprintf!"Non-funcion is
84 else <
85 throw new PolemyRuntimeException(sprintf!"lhs of %s must <
86 } 117 }
87 throw new PolemyRuntimeException(sprintf!"Unknown Kind of Expression %s 118 throw new PolemyRuntimeException(sprintf!"Unknown Kind of Expression %s
88 } 119 }
89 120
90 121
91 version(unittest) import polemy.parse; 122 version(unittest) import polemy.parse;
92 version(unittest) import std.stdio; 123 version(unittest) import std.stdio;