Check-in [a5fe6233c1]
Not logged in
Overview
SHA1 Hash:a5fe6233c190c89c9cae8608a34df26727136a7f
Date: 2010-11-21 17:18:05
User: kinaba
Comment:layered parameters implemented
Timelines: family | ancestors | descendants | both | trunk
Downloads: Tarball | ZIP archive
Other Links: files | file ages | manifest
Tags And Properties
Changes

Modified polemy/eval.d from [97875541a42dbc7a] to [27ad20bc14df9938].

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 +

Modified polemy/value.d from [f1d2e31afdaaee9d] to [f1a01bb8ba2daf26].

29 29 { 30 30 string data; 31 31 32 32 mixin SimpleClass; 33 33 override string toString() const { return data; } 34 34 } 35 35 36 -/// 37 -class FunValue : Value 38 -{ 39 - Value delegate(immutable LexPosition pos, string lay, Value[]) data; 40 - 41 - mixin SimpleConstructor; 42 - alias data call; 43 - override string toString() const { return sprintf!"(function:%s:%s)"(data.ptr,data.funcptr); } 44 -} 45 - 46 36 /// 47 37 class UndValue : Value 48 38 { 49 39 mixin SimpleClass; 50 40 override string toString() const { return "<undefined>"; } 51 41 } 52 42 53 -/// Named Constructor for FunValue 54 43 55 -FunValue nativef(Value delegate(immutable LexPosition pos, Layer lay, Value[] args) dg) 44 +/// 45 +abstract class FunValue : Value 46 +{ 47 + const(Parameter[]) params(); 48 + Table definitionContext(); 49 + Value invoke(in LexPosition pos, Layer lay, Table ctx); 50 +} 51 + 52 +import polemy.eval; // circular... 53 + 54 +/// 55 +class UserDefinedFunValue : FunValue 56 +{ 57 + FunLiteral ast; 58 + Table defCtx; 59 + override const(Parameter[]) params() { return ast.params; } 60 + override Table definitionContext() { return defCtx; } 61 + override Value invoke(in LexPosition pos, Layer lay, Table ctx) 62 + { 63 + // TODO: only auto raised ones need memo? no? 64 + // auto memoization 65 +/* 66 + if( lay != "@v" && lay != "@macro" ) 67 + { 68 + if( auto memolay = lay in memo ) 69 + if( auto pv = args in *memolay ) 70 + return *pv; 71 + memo[lay][args] = lift(e.pos,new UndValue,lay,ctx); 72 + } 73 + 74 +*/ 75 + // @macro run!!! 76 + if( lay == "@macro" ) 77 + return macroEval(ast.funbody, ctx, false); 78 +/*TODO memo*/ AST macroMemo; 79 + if( macroMemo is null ) { 80 + // .prototype!, forced macro cannot access parameters 81 + ctx.kill = true; scope(exit)ctx.kill=false; 82 + macroMemo = tableToAST("@v",macroEval(ast.funbody, ctx, true)); 83 + } 84 + auto v = eval(macroMemo, ctx, true, lay); 85 + 86 + //auto v = eval(e.funbody, ctxNeo, true, lay); 87 + // auto memoization 88 +// if( lay != "@v" && lay != "@macro" ) 89 +// memo[lay][args] = v; 90 + return v; 91 + } 92 + 93 + mixin SimpleClass; 94 + override string toString() const { return sprintf!"(function:%x:%x)"(cast(void*)ast, cast(void*)defCtx); } 95 +} 96 + 97 +/// 98 +abstract class NativeFunValue : FunValue 56 99 { 57 - return new FunValue(dg); 100 + Parameter[] params_data; 101 + override const(Parameter[]) params() { return params_data; } 102 + override Table definitionContext() { return new Table; } // todo: cache overrie 58 103 } 59 104 60 105 /// Named Constructor for FunValue 61 106 62 107 FunValue native(R,T...)(R delegate (T) dg) 63 108 { 64 - return nativef( delegate Value(immutable LexPosition pos, Layer lay, Value[] args) { 65 - if( lay != "@v" ) 66 - throw genex!RuntimeException(pos, "only @v layer can call native function"); 67 - if( T.length != args.length ) 68 - throw genex!RuntimeException(pos, "argument number mismatch!"); 69 - T typed_args; 70 - foreach(i, Ti; T) 109 + return new class NativeFunValue { 110 + this() 111 + { 112 + foreach(i, Ti; T) 113 + params_data ~= new Parameter(text(i), []); 114 + } 115 + override Value invoke(in LexPosition pos, Layer lay, Table ctx) 71 116 { 72 - typed_args[i] = cast(Ti) args[i]; 73 - if( typed_args[i] is null ) 74 - throw genex!RuntimeException(pos, sprintf!"type mismatch on the argument %d"(i+1)); 75 - } 76 - try { 77 - return dg(typed_args); 78 - } catch( RuntimeException e ) { 79 - throw e.pos is null ? new RuntimeException(pos, e.msg, e.file, e.line) : e; 117 + if( lay != "@v" ) 118 + throw genex!RuntimeException(pos, "only @v layer can call native function"); 119 + T typed_args; 120 + foreach(i, Ti; T) { 121 + typed_args[i] = cast(Ti) ctx.get(text(i), "@v"); 122 + if( typed_args[i] is null ) 123 + throw genex!RuntimeException(pos, sprintf!"type mismatch on the argument %d"(i+1)); 124 + } 125 + try { 126 + return dg(typed_args); 127 + } catch( RuntimeException e ) { 128 + throw e.pos is null ? new RuntimeException(pos, e.msg, e.file, e.line) : e; 129 + } 80 130 } 81 - }); 131 + }; 82 132 } 83 133 84 134 /// Layer ID 85 135 86 136 alias string Layer; 87 137 88 138 /// Context (variable environment) 89 139 /// Simlar to prototype chain of ECMAScript etc. 90 140 /// But extended with the notion of "Layer" 91 141 92 142 class Table : Value 93 143 { 94 144 enum Kind {PropagateSet, NotPropagateSet}; 145 + bool kill = false; // to refactor 95 146 96 147 this( Table proto=null, Kind k = Kind.PropagateSet ) 97 148 { this.prototype = proto; this.kind = k; } 98 149 99 150 void set(string i, Layer lay, Value v, in LexPosition pos=null) 100 151 { 101 152 if( setIfExist(i, lay, v) ) ................................................................................ 103 154 data[i][lay] = v; 104 155 } 105 156 106 157 bool has(string i, Layer lay, in LexPosition pos=null) 107 158 { 108 159 if( i in data ) { 109 160 if( lay !in data[i] ) 161 + return false; 162 + if(kill) 110 163 return false; 111 164 return true; 112 165 } 113 166 if( prototype is null ) 114 167 return false; 115 168 return prototype.has(i, lay, pos); 116 169 } ................................................................................ 117 170 118 171 Value get(string i, Layer lay, in LexPosition pos=null) 119 172 { 120 173 if( i in data ) { 121 174 // [TODO] consider forwarding to proto also in this case 122 175 if( lay !in data[i] ) 123 176 throw genex!RuntimeException(pos, sprintf!"variable %s is not set in layer %s"(i,lay)); 177 + if(kill) 178 + throw genex!RuntimeException(pos, sprintf!"variable %s is killed in macro"(i)); 124 179 return data[i][lay]; 125 180 } 126 181 if( prototype is null ) 127 182 throw new RuntimeException(pos, sprintf!"variable %s not found"(i)); 128 183 return prototype.get(i, lay, pos); 129 184 } 130 185

Modified sample/macro.pmy from [827dbc8186458d43] to [a38c7267da8f14a3].

47 47 print(maxNormal(printAndReturn(100),printAndReturn(200))); 48 48 print("--------------"); 49 49 print(maxBad(printAndReturn(100),printAndReturn(200))); 50 50 print("--------------"); 51 51 print( LetItBe( 1+2+3, it*it ) ); 52 52 print("--------------"); 53 53 print(pow10(2)); 54 - 55 54 }; 56 55 57 56 main()