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 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;