Diff
Not logged in

Differences From Artifact [f1d2e31afdaaee9d]:

To Artifact [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