Differences From Artifact [97875541a42dbc7a]:
- File
polemy/eval.d
- 2010-11-20 16:35:14 - part of checkin [3464a035ec] on branch trunk - source code cleanup (user: kinaba) [annotate]
To Artifact [27ad20bc14df9938]:
- File
polemy/eval.d
- 2010-11-21 08:18:05 - part of checkin [a5fe6233c1] on branch trunk - layered parameters implemented (user: kinaba) [annotate]
26 26 ctx.set("&&", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(BigInt((lhs.data!=0) && (rhs.data!=0) ? 1:0));} ));
27 27 ctx.set("<", "@v", native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs < rhs ? 1: 0));} ));
28 28 ctx.set(">", "@v", native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs > rhs ? 1: 0));} ));
29 29 ctx.set("<=", "@v", native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs <= rhs ? 1: 0));} ));
30 30 ctx.set(">=", "@v", native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs >= rhs ? 1: 0));} ));
31 31 ctx.set("==", "@v", native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs == rhs ? 1: 0));} ));
32 32 ctx.set("!=", "@v", native( (Value lhs, Value rhs){return new IntValue(BigInt(lhs != rhs ? 1: 0));} ));
33 - ctx.set("print", "@v", new FunValue(delegate Value(immutable LexPosition pos, Layer lay, Value[] args){
34 - foreach(a; args)
35 - write(a);
36 - writeln("");
33 + ctx.set("print", "@v", native( (Value a){
34 + writeln(a);
37 35 return new IntValue(BigInt(178));
38 36 }));
39 - ctx.set("if", "@v", new FunValue(delegate Value(immutable LexPosition pos, Layer lay, Value[] args){
40 - if( args.length != 3 )
41 - throw genex!RuntimeException(pos, "if takes three arguments!!");
42 - if( auto x = cast(IntValue)args[0] )
43 - if( auto ft = cast(FunValue)args[1] )
44 - if( auto fe = cast(FunValue)args[2] )
45 - return (x.data == 0 ? fe : ft).call(pos,lay,[]);
46 - throw genex!RuntimeException(pos, "type mismatch in if");
37 + ctx.set("if", "@v", native( (IntValue x, FunValue ft, FunValue fe){
38 + auto toRun = (x.data==0 ? fe : ft);
39 + return toRun.invoke(null, "@v", toRun.definitionContext());
40 +// return toRun.invoke(pos, lay, toRun.definitionContext());
47 41 }));
48 42 ctx.set("_isint", "@v", native( (Value v){return new IntValue(BigInt(cast(IntValue)v is null ? 0 : 1));} ));
49 43 ctx.set("_isstr", "@v", native( (Value v){return new IntValue(BigInt(cast(StrValue)v is null ? 0 : 1));} ));
50 44 ctx.set("_isfun", "@v", native( (Value v){return new IntValue(BigInt(cast(FunValue)v is null ? 0 : 1));} ));
51 45 ctx.set("_isundefined", "@v", native( (Value v){return new IntValue(BigInt(cast(UndValue)v is null ? 0 : 1));} ));
52 46 ctx.set("_istable", "@v", native( (Value v){return new IntValue(BigInt(cast(Table)v is null ? 0 : 1));} ));
53 47 ctx.set(".", "@v", native( (Table t, StrValue s){
................................................................................
84 78 /// Entry point of this module
85 79
86 80 Tuple!(Value,"val",Table,"ctx") eval(AST e)
87 81 {
88 82 Table ctx = createGlobalContext();
89 83 return typeof(return)(eval(e, ctx, false, "@v"), ctx);
90 84 }
85 +
86 +Value invokeFunction(in LexPosition pos, Value _f, AST[] args, Table callerCtx, Layer lay, bool AlwaysMacro=false)
87 +{
88 + if(auto f = cast(FunValue)_f)
89 + {
90 + Table ctx = new Table(f.definitionContext(), Table.Kind.NotPropagateSet);
91 + foreach(i,p; f.params())
92 + if( p.layers.empty )
93 + if(lay=="@macro")
94 + ctx.set(p.name, lay, macroEval(args[i], callerCtx, AlwaysMacro));
95 + else
96 + ctx.set(p.name, lay, eval(args[i], callerCtx, true, lay));
97 + else
98 + foreach(argLay; p.layers)
99 + if(argLay=="@macro")
100 + ctx.set(p.name, argLay, macroEval(args[i], callerCtx, AlwaysMacro));
101 + else
102 + ctx.set(p.name, argLay, eval(args[i], callerCtx, true, argLay));
103 + return f.invoke(pos, lay, ctx);
104 + }
105 + throw genex!RuntimeException(pos, "tried to call non-function");
106 +}
107 +
108 +Value lift(in LexPosition pos, Value v, Layer lay, Table callerCtx)
109 +{
110 + // similar to invoke Function, but with only one argument bound to @v
111 + Value _f = callerCtx.get(lay, "(system)", pos);
112 + if(auto f = cast(FunValue)_f)
113 + {
114 + Table ctx = new Table(f.definitionContext(), Table.Kind.NotPropagateSet);
115 + auto ps = f.params();
116 + if( ps.length != 1 )
117 + throw genex!RuntimeException(pos, "lift function must take exactly one argument at @v layer");
118 + if( ps[0].layers.length==0 || ps[0].layers.length==1 && ps[0].layers[0]=="@v" )
119 + {
120 + ctx.set(ps[0].name, "@v", v);
121 + return f.invoke(pos, "@v", ctx);
122 + }
123 + else
124 + throw genex!RuntimeException(pos, "lift function must take exactly one argument at @v layer");
125 + }
126 + throw genex!RuntimeException(pos, "tried to call non-function");
127 +}
91 128
92 129 /// Entry point of this module
93 130 /// If splitCtx = true, then inner variable declaration do not overwrite ctx.
94 131 /// lay is the layer ID for evaluation (standard value semantics uses "@v").
95 132
96 133 Value eval(AST e, Table ctx, bool splitCtx, Layer lay)
97 134 {
98 135 return e.match(
99 136 (StrLiteral e)
100 137 {
101 138 Value v = new StrValue(e.data);
102 139 if( lay == "@v" )
103 140 return v;
104 - else // rise
105 - return (cast(FunValue)ctx.get(lay, "(system)", e.pos)).call(e.pos, "@v", [v]);
141 + else
142 + return lift(e.pos,v,lay,ctx);
106 143 },
107 144 (IntLiteral e)
108 145 {
109 146 Value v = new IntValue(e.data);
110 147 if( lay == "@v" )
111 148 return v;
112 149 else // rise
113 - return (cast(FunValue)ctx.get(lay, "(system)", e.pos)).call(e.pos, "@v", [v]);
150 + return lift(e.pos,v,lay,ctx);
114 151 },
115 152 (VarExpression e)
116 153 {
117 154 if( lay == "@v" )
118 155 return ctx.get(e.var, lay, e.pos);
119 156 try {
120 157 return ctx.get(e.var, lay, e.pos);
121 158 } catch( Throwable ) { // [TODO] more precise...
122 - // rise from @v
123 - return (cast(FunValue)ctx.get(lay, "(system)", e.pos)).call(e.pos, "@v",
124 - [ctx.get(e.var, "@v", e.pos)]
125 - );
159 + return lift(e.pos, ctx.get(e.var, "@v", e.pos), lay, ctx);
126 160 }
127 161 },
128 162 (LayeredExpression e)
129 163 {
130 164 if( e.lay == "@macro" )
131 165 return macroEval(e.expr, ctx, false);
132 166 else
................................................................................
140 174 ctx = new Table(ctx, Table.Kind.NotPropagateSet);
141 175 Value v = eval(e.init, ctx, true, lay);
142 176 ctx.set(e.var, (e.layer.length ? e.layer : lay), v, e.pos);
143 177 return eval(e.expr, ctx, false, lay);
144 178 },
145 179 (FuncallExpression e)
146 180 {
147 - Value _f = eval(e.fun, ctx, true, lay);
148 - if( auto f = cast(FunValue)_f ) {
149 - Value[] args;
150 - foreach(a; e.args)
151 - args ~= eval(a, ctx, true, lay);
152 - return f.call(e.pos, lay, args);
153 - }
154 - throw genex!RuntimeException(e.pos, "Non-funcion is applied");
181 + return invokeFunction(e.pos, eval(e.fun, ctx, true, lay), e.args, ctx, lay);
155 182 },
156 183 (FunLiteral e)
157 184 {
158 185 Value[Value[]][Layer] memo;
159 186 AST macroMemo = null; // cache
160 187
161 188 // funvalue need not be rised
162 189 // no, need to be rised !! suppose @t(fib)("int")
163 - return new FunValue(delegate Value(immutable LexPosition pos, string lay, Value[] args){
164 - // TODO: only auto raised ones need memo? no?
165 - // auto memoization
166 - if( lay != "@v" && lay != "@macro" )
167 - {
168 - if( auto memolay = lay in memo )
169 - if( auto pv = args in *memolay )
170 - return *pv;
171 - memo[lay][args] = (cast(FunValue)ctx.get(lay, "(system)", e.pos)).call(e.pos, "@v",
172 - [new UndValue]
173 - );
174 - }
175 -
176 - if( e.params.length != args.length )
177 - throw genex!RuntimeException(e.pos, sprintf!"Argument Number Mismatch (%d required but %d given)"
178 - (e.params.length, args.length));
179 - Table ctxNeo = new Table(ctx, Table.Kind.NotPropagateSet);
180 - foreach(i,p; e.params)
181 - ctxNeo.set(p.name, lay, args[i]);
182 -
183 - // @macro run!!!
184 - if( lay == "@macro" )
185 - return macroEval(e.funbody, ctxNeo, false);
186 - if( macroMemo is null )
187 - macroMemo = tableToAST("@v",macroEval(e.funbody, ctxNeo, true));
188 - auto v = eval(macroMemo, ctxNeo, true, lay);
189 -
190 - //auto v = eval(e.funbody, ctxNeo, true, lay);
191 - // auto memoization
192 - if( lay != "@v" && lay != "@macro" )
193 - memo[lay][args] = v;
194 - return v;
195 - });
190 + return new UserDefinedFunValue(e, ctx);
196 191 },
197 192 delegate Value (AST e)
198 193 {
199 194 throw genex!RuntimeException(e.pos, sprintf!"Unknown Kind of Expression %s"(typeid(e)));
200 195 }
201 196 );
202 197 }
................................................................................
248 243 t.set("is", theLayer, new StrValue("lay"));
249 244 t.set("layer", theLayer, new StrValue(e.lay));
250 245 t.set("expr", theLayer, macroEval(e.expr,ctx,AlwaysMacro));
251 246 return cast(Value)t;
252 247 }
253 248 else
254 249 {
255 - return eval(e.expr, ctx, true, e.lay);
250 + if( e.lay == "@macro" )
251 + return macroEval(e.expr, ctx, false);
252 + else
253 + return eval(e.expr, ctx, true, e.lay);
256 254 }
257 255 },
258 256 (LetExpression e)
259 257 {
260 258 Table t = new Table;
261 259 t.set("pos", theLayer, pos);
262 260 t.set("is", theLayer, new StrValue("let"));
................................................................................
265 263 t.set("expr", theLayer, macroEval(e.expr,ctx,AlwaysMacro));
266 264 return t;
267 265 },
268 266 (FuncallExpression e)
269 267 {
270 268 Value _f = macroEval(e.fun,ctx,AlwaysMacro);
271 269
272 - // copy & pase from normal eval
273 - // [TODO] sync with @layerd parameters.
274 - if( auto f = cast(FunValue)_f ) {
275 - Value[] args;
276 - foreach(a; e.args)
277 - args ~= macroEval(a, ctx, AlwaysMacro);
278 - return f.call(e.pos, "@macro", args); // explicit @macro is the best???
279 - }
270 + if( auto f = cast(FunValue)_f )
271 + return invokeFunction(e.pos, f, e.args, ctx, "@macro", AlwaysMacro);
280 272
281 273 Table t = new Table;
282 274 t.set("pos", theLayer, pos);
283 275 t.set("is", theLayer, new StrValue("app"));
284 276 t.set("fun", theLayer, _f);
285 277 Table args = new Table;
286 278 foreach_reverse(a; e.args) {
................................................................................
386 378 // there was a bug that declaration in the first line of function definition
387 379 // cannot be recursive
388 380 assert_nothrow( evalString(`def foo() {
389 381 def bar(y) { if(y<1) {0} else {bar(0)} };
390 382 bar(1)
391 383 }; foo()`) );
392 384 }
385 +