Differences From Artifact [d315cdb0d9e5cf48]:
- File
polemy/eval.d
- 2010-11-13 03:55:17 - part of checkin [c368edbcb1] on branch trunk - @@lay(x) { ... } declaration and value rising. (user: kinaba) [annotate]
To Artifact [a63938dc88b0c424]:
- File
polemy/eval.d
- 2010-11-13 04:32:12 - part of checkin [8474ae68d9] on branch trunk - rising mechanism (user: kinaba) [annotate]
8 8 import polemy._common;
9 9 import polemy.lex : LexPosition;
10 10 import polemy.ast;
11 11 import polemy.parse;
12 12 import polemy.value;
13 13 import std.typecons;
14 14 import std.stdio;
15 +
16 +// [todo] move to value.d
17 +
18 +FunValue nativef(Value delegate(immutable LexPosition pos, Layer lay, Value[] args) dg)
19 +{
20 + return new FunValue(dg);
21 +}
22 +
23 +FunValue native(R,T...)(R delegate (T) dg)
24 +{
25 + return nativef( delegate Value(immutable LexPosition pos, Layer lay, Value[] args) {
26 + if( lay != "@v" )
27 + throw genex!RuntimeException(pos, "only @v layer can call native function");
28 + if( T.length != args.length )
29 + throw genex!RuntimeException(pos, "argument number mismatch!");
30 + T typed_args;
31 + foreach(i, Ti; T)
32 + {
33 + typed_args[i] = cast(Ti) args[i];
34 + if( typed_args[i] is null )
35 + throw genex!RuntimeException(pos, sprintf!"type mismatch on the argument %d"(i));
36 + }
37 + try {
38 + return dg(typed_args);
39 + } catch( RuntimeException e ) {
40 + throw e.pos is null ? new RuntimeException(pos, e.msg, e.file, e.line) : e;
41 + }
42 + });
43 +}
15 44
16 45 ///
17 46 Table createGlobalContext()
18 47 {
19 48 auto ctx = new Table;
20 - // [TODO] autogenerate these typechecks
21 - ctx.set("+", "@v", new FunValue(delegate Value(immutable LexPosition pos, Layer lay, Value[] args){
22 - if( args.length != 2 )
23 - throw genex!RuntimeException(pos, "+ takes two arguments!!");
24 - if( auto x = cast(IntValue)args[0] )
25 - if( auto y = cast(IntValue)args[1] )
26 - return new IntValue(x.data+y.data);
27 - throw genex!RuntimeException(pos, "cannot add non-integers");
28 - }));
29 - ctx.set("-", "@v", new FunValue(delegate Value(immutable LexPosition pos, Layer lay, Value[] args){
30 - if( args.length != 2 )
31 - throw genex!RuntimeException(pos, "- takes two arguments!!");
32 - if( auto x = cast(IntValue)args[0] )
33 - if( auto y = cast(IntValue)args[1] )
34 - return new IntValue(x.data-y.data);
35 - throw genex!RuntimeException(pos, "cannot subtract non-integers");
36 - }));
37 - ctx.set("*", "@v", new FunValue(delegate Value(immutable LexPosition pos, Layer lay, Value[] args){
38 - if( args.length != 2 )
39 - throw genex!RuntimeException(pos, "* takes two arguments!!");
40 - if( auto x = cast(IntValue)args[0] )
41 - if( auto y = cast(IntValue)args[1] )
42 - return new IntValue(x.data*y.data);
43 - throw genex!RuntimeException(pos, "cannot multiply non-integers");
44 - }));
45 - ctx.set("/", "@v", new FunValue(delegate Value(immutable LexPosition pos, Layer lay, Value[] args){
46 - if( args.length != 2 )
47 - throw genex!RuntimeException(pos, "/ takes two arguments!!");
48 - if( auto x = cast(IntValue)args[0] )
49 - if( auto y = cast(IntValue)args[1] )
50 - return new IntValue(x.data/y.data);
51 - throw genex!RuntimeException(pos, "cannot divide non-integers");
52 - }));
53 - ctx.set("<", "@v", new FunValue(delegate Value(immutable LexPosition pos, Layer lay, Value[] args){
54 - if( args.length != 2 )
55 - throw genex!RuntimeException(pos, "< takes two arguments!!");
56 - if( auto x = cast(IntValue)args[0] )
57 - if( auto y = cast(IntValue)args[1] )
58 - return new IntValue(BigInt(to!int(x.data < y.data)));
59 - throw genex!RuntimeException(pos, "cannot compare non-integers");
60 - }));
61 - ctx.set(">", "@v", new FunValue(delegate Value(immutable LexPosition pos, Layer lay, Value[] args){
62 - if( args.length != 2 )
63 - throw genex!RuntimeException(pos, "> takes two arguments!!");
64 - if( auto x = cast(IntValue)args[0] )
65 - if( auto y = cast(IntValue)args[1] )
66 - return new IntValue(BigInt(to!int(x.data>y.data)));
67 - throw genex!RuntimeException(pos, "cannot compare non-integers");
68 - }));
49 + ctx.set("+", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(lhs.data + rhs.data);} ));
50 + ctx.set("-", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(lhs.data - rhs.data);} ));
51 + ctx.set("*", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(lhs.data * rhs.data);} ));
52 + ctx.set("/", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(lhs.data / rhs.data);} ));
53 + ctx.set("%", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(lhs.data % rhs.data);} ));
54 + ctx.set("<", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(BigInt(lhs.data < rhs.data ? 1: 0));} ));
55 + ctx.set(">", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(BigInt(lhs.data > rhs.data ? 1: 0));} ));
56 + ctx.set("<=", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(BigInt(lhs.data <= rhs.data ? 1: 0));} ));
57 + ctx.set(">=", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(BigInt(lhs.data >= rhs.data ? 1: 0));} ));
58 + ctx.set("==", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(BigInt(lhs.data == rhs.data ? 1: 0));} ));
59 + ctx.set("!=", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(BigInt(lhs.data != rhs.data ? 1: 0));} ));
69 60 ctx.set("print", "@v", new FunValue(delegate Value(immutable LexPosition pos, Layer lay, Value[] args){
70 61 foreach(a; args)
71 62 write(a);
72 63 writeln("");
73 64 return new IntValue(BigInt(178));
74 65 }));
75 66 ctx.set("if", "@v", new FunValue(delegate Value(immutable LexPosition pos, Layer lay, Value[] args){
................................................................................
105 96 Table ctx = createGlobalContext();
106 97 return typeof(return)(eval(e, ctx, false, "@v"), ctx);
107 98 }
108 99
109 100 /// Entry point of this module
110 101 /// If splitCtx = true, then inner variable declaration do not overwrite ctx.
111 102 /// lay is the layer ID for evaluation (standard value semantics uses "@v").
112 -import std.typetuple;
103 +
113 104 Value eval(AST e, Table ctx, bool splitCtx, Layer lay)
114 105 {
115 106 return e.match(
116 107 (StrLiteral e)
117 108 {
118 109 Value v = new StrValue(e.data);
119 110 if( lay == "@v" )
120 111 return v;
121 - else
112 + else // rise
122 113 return (cast(FunValue)ctx.get(lay, "(system)", e.pos)).call(e.pos, "@v", [v]);
123 114 },
124 115 (IntLiteral e)
125 116 {
126 117 Value v = new IntValue(e.data);
127 118 if( lay == "@v" )
128 119 return v;
129 - else // are these "@v"s appropriate???
120 + else // rise
130 121 return (cast(FunValue)ctx.get(lay, "(system)", e.pos)).call(e.pos, "@v", [v]);
131 122 },
132 123 (VarExpression e)
133 124 {
134 125 try {
135 126 return ctx.get(e.var, lay, e.pos);
136 127 } catch( RuntimeException ) {
137 - // rise
128 + // rise from @v
138 129 return (cast(FunValue)ctx.get(lay, "(system)", e.pos)).call(e.pos, "@v",
139 130 [ctx.get(e.var, "@v", e.pos)]
140 131 );
141 132 }
142 133 },
143 134 (LayeredExpression e)
144 135 {
................................................................................
163 154 args ~= eval(a, ctx, true, lay);
164 155 return f.call(e.pos, lay, args);
165 156 }
166 157 throw genex!RuntimeException(e.pos, "Non-funcion is applied");
167 158 },
168 159 (FunLiteral e)
169 160 {
161 + // funvalue need not be rised
170 162 return new FunValue(delegate Value(immutable LexPosition pos, string lay, Value[] args){
171 163 if( e.params.length != args.length )
172 164 throw genex!RuntimeException(e.pos, sprintf!"Argument Number Mismatch (%d required but %d given)"
173 165 (e.params.length, args.length));
174 166 Table ctxNeo = new Table(ctx, Table.Kind.NotPropagateSet);
175 167 foreach(i,p; e.params)
176 168 ctxNeo.set(p.name, lay, args[i]);