Diff
Not logged in

Differences From Artifact [0386a7dd31807f87]:

To Artifact [19366410c0eeb209]:


43 43 44 44 45 45 /// 46 46 abstract class FunValue : Value 47 47 { 48 48 const(Parameter[]) params(); 49 49 Table definitionContext(); 50 - Value invoke(in LexPosition pos, Layer lay, Table ctx); 51 -} 52 - 53 -import polemy.eval; // circular... 54 -version = MacroCache; 55 -//version = AutoMemoization; 56 -//version = AutoRerun; 57 - 58 -/// 59 -class UserDefinedFunValue : FunValue 60 -{ 61 - FunLiteral ast; 62 - Table defCtx; 63 - 64 - this(FunLiteral ast, Table defCtx) { this.ast=ast; this.defCtx=defCtx; } 65 - override string toString() const { return sprintf!"(function:%x:%x)"(cast(void*)ast, cast(void*)defCtx); } 66 - override bool opEquals(Object rhs_) const /// member-by-member equality 67 - { 68 - if( auto rhs = cast(typeof(this))rhs_ ) 69 - return this.ast==rhs.ast && this.defCtx==rhs.defCtx; 70 - assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), typeid(rhs_))); 71 - } 72 - override hash_t toHash() const /// member-by-member hash 73 - { 74 - return typeid(this.ast).getHash(&this.ast) + typeid(this.defCtx).getHash(&this.defCtx); 75 - } 76 - override int opCmp(Object rhs_) /// member-by-member compare 77 - { 78 - if( auto rhs = cast(typeof(this))rhs_ ) 79 - { 80 - if(auto i = this.ast.opCmp(rhs.ast)) 81 - return i; 82 - return this.defCtx.opCmp(rhs.defCtx); 83 - } 84 - assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), typeid(rhs_))); 85 - } 86 - 87 - private AST preprocessed_funbody; 88 - private Value[Value[]][Layer] memo; 89 - 90 - override const(Parameter[]) params() { return ast.params; } 91 - override Table definitionContext() { return defCtx; } 92 - override Value invoke(in LexPosition pos, Layer lay, Table ctx) 93 - { 94 - // TODO: only auto raised ones need memo? no? 95 - // how can we integrate re-run ?? 96 - version(AutoMemoization) 97 - { 98 - Value[] memokey; 99 - if( lay != ValueLayer && lay != MacroLayer ) 100 - { 101 - foreach(i,p; ast.params) 102 - memokey ~= ctx.get(p.name, lay); // lay? 103 - if( auto memolay = lay in memo ) 104 - if( auto pv = memokey in *memolay ) 105 - return *pv; 106 - memo[lay][memokey] = lift(ast.pos,new UndValue,lay,ctx); 107 - } 108 - } 109 - 110 - // @macro run!!! 111 - if( lay == MacroLayer ) 112 - return macroEval(ast.funbody, ctx, false); 113 - 114 - version(MacroCache) { 115 - if( preprocessed_funbody is null ) { 116 - // .prototype!, forced macro cannot access parameters 117 - ctx.kill = true; scope(exit)ctx.kill=false; 118 - preprocessed_funbody = tableToAST(ValueLayer,macroEval(ast.funbody, ctx, true)); 119 - } 120 - } else { 121 - if( preprocessed_funbody is null ) { 122 - // .prototype!, forced macro cannot access parameters 123 - ctx.kill = true; scope(exit)ctx.kill=false; 124 - preprocessed_funbody = tableToAST(ValueLayer,macroEval(ast.funbody, ctx, true)); 125 - } 126 - } 127 - 128 - auto v = eval(preprocessed_funbody, ctx, true, lay); 129 - version(AutoMemoization) 130 - { 131 - if( lay != ValueLayer && lay != MacroLayer ) 132 - { 133 - memo[lay][memokey] = v; 134 - version(AutoReRun) 135 - memo[lay][memokey] = eval(preprocessed_funbody, ctx, true, lay); // re-Run!! 136 - } 137 - } 138 - return v; 139 - } 140 -} 141 - 142 -/// 143 -abstract class NativeFunValue : FunValue 144 -{ 145 - Parameter[] params_data; 146 - override const(Parameter[]) params() { return params_data; } 147 - override Table definitionContext() { return new Table; } // todo: cache overrie 148 -} 149 - 150 -/// Named Constructor for FunValue 151 - 152 -FunValue native(R,T...)(R delegate (T) dg) 153 -{ 154 - return new class NativeFunValue { 155 - this() 156 - { 157 - foreach(i, Ti; T) 158 - params_data ~= new Parameter(text(i), []); 159 - } 160 - override Value invoke(in LexPosition pos, Layer lay, Table ctx) 161 - { 162 - if( lay != ValueLayer ) 163 - throw genex!RuntimeException(pos, "only "~ValueLayer~" layer can call native function"); 164 - T typed_args; 165 - foreach(i, Ti; T) { 166 - typed_args[i] = cast(Ti) ctx.get(text(i), ValueLayer); 167 - if( typed_args[i] is null ) 168 - throw genex!RuntimeException(pos, sprintf!"type mismatch on the argument %d"(i+1)); 169 - } 170 - try { 171 - return dg(typed_args); 172 - } catch( RuntimeException e ) { 173 - throw e.pos is null ? new RuntimeException(pos, e.msg, e.file, e.line) : e; 174 - } 175 - } 176 - }; 50 + Value invoke(LexPosition pos, Layer lay, Table ctx); 177 51 } 178 52 179 53 /// Context (variable environment) 180 54 /// Simlar to prototype chain of ECMAScript etc. 181 55 /// But extended with the notion of "Layer" 182 56 183 57 class Table : Value ................................................................................ 184 58 { 185 59 enum Kind {PropagateSet, NotPropagateSet}; 186 60 bool kill = false; // to refactor 187 61 188 62 this( Table proto=null, Kind k = Kind.PropagateSet ) 189 63 { this.prototype = proto; this.kind = k; } 190 64 191 - void set(string i, Layer lay, Value v, in LexPosition pos=null) 65 + void set(string i, Layer lay, Value v, LexPosition pos=null) 192 66 { 193 67 if( setIfExist(i, lay, v) ) 194 68 return; 195 69 data[i][lay] = v; 196 70 } 197 71 198 - bool has(string i, Layer lay, in LexPosition pos=null) 72 + bool has(string i, Layer lay) const 199 73 { 200 74 if( i in data ) { 201 75 if( lay !in data[i] ) 202 76 return false; 203 77 if(kill) 204 78 return false; 205 79 return true; 206 80 } 207 81 if( prototype is null ) 208 82 return false; 209 - return prototype.has(i, lay, pos); 83 + return prototype.has(i, lay); 210 84 } 211 85 212 - Value get(string i, Layer lay, in LexPosition pos=null) 86 + Value get(string i, Layer lay, LexPosition pos=null) 213 87 { 214 88 if( i in data ) { 215 89 // [TODO] consider forwarding to proto also in this case 216 90 if( lay !in data[i] ) 217 91 throw genex!RuntimeException(pos, sprintf!"'%s' is not set in layer %s"(i,lay)); 218 92 if(kill) 219 93 throw genex!RuntimeException(pos, sprintf!"'%s' is killed in macro"(i)); ................................................................................ 244 118 string result; 245 119 bool first = true; 246 120 foreach(k, l2d; data) 247 121 foreach(l,d; l2d) 248 122 { 249 123 if(first) first=false; else result~=", "; 250 124 result ~= k; 251 - result ~= l; 125 + if( l.empty ) 126 + result ~= "(emptylayer)"; 127 + else if( l != ValueLayer ) 128 + result ~= l; 252 129 result ~= ":"; 253 130 result ~= text(cast(Value)d); 254 131 } 255 132 if( prototype !is null ) 256 133 { 257 134 result ~= " / "; 258 135 result ~= prototype.toStringWithoutParen(); ................................................................................ 371 248 if( nodeType is null ) 372 249 throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST {is:(not string)}"); 373 250 auto pos = extractPos(t); 374 251 switch(nodeType.data) 375 252 { 376 253 case "int": 377 254 if(auto v = t.access!IntValue(theLayer, "data")) 378 - return new IntLiteral(pos, v.data); 255 + return new Int(pos, v.data); 379 256 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"int", data:(not int)}`); 380 257 case "str": 381 258 if(auto v = t.access!StrValue(theLayer, "data")) 382 - return new StrLiteral(pos, v.data); 259 + return new Str(pos, v.data); 383 260 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"str", data:(not string)}`); 384 261 case "var": 385 262 if(auto v = t.access!StrValue(theLayer, "name")) 386 - return new VarExpression(pos, v.data); 263 + return new Var(pos, v.data); 387 264 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"var", name:(not string)}`); 388 265 case "lay": 389 266 if(auto v = t.access!StrValue(theLayer, "layer")) 390 267 if(auto e = t.access!Table(theLayer, "expr")) 391 - return new LayExpression(pos, v.data, tableToAST(theLayer,e)); 268 + return new Lay(pos, v.data, tableToAST(theLayer,e)); 392 269 else 393 270 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"lay", expr:(not table)}`); 394 271 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"lay", layer:(not string)}`); 395 272 case "let": 396 273 if(auto n = t.access!StrValue(theLayer, "name")) 397 274 if(auto e = t.access!Table(theLayer, "init")) 398 275 if(auto b = t.access!Table(theLayer, "expr")) ................................................................................ 399 276 { 400 277 string nn = n.data; 401 278 auto ee = tableToAST(theLayer, e); 402 279 auto bb = tableToAST(theLayer, b); 403 280 Layer lay=""; 404 281 if(auto l = t.access!StrValue(theLayer, "layer")) 405 282 lay = l.data; 406 - return new LetExpression(pos, nn, lay, ee, bb); 283 + return new Let(pos, nn, lay, ee, bb); 407 284 } 408 285 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"let", name:"???", init:"???", expr:"???"}`); 409 286 case "app": 410 287 if(auto f = t.access!Table(theLayer, "fun")) 411 288 if(auto a = t.access!Table(theLayer, "args")) 412 - return new FuncallExpression(pos, tableToAST(theLayer,f), tableToASTList(theLayer,a)); 289 + return new App(pos, tableToAST(theLayer,f), tableToASTList(theLayer,a)); 413 290 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"app", fun:???, args:???}`); 414 291 case "fun": 415 292 if(auto p = t.access!Table(theLayer, "params")) 416 293 if(auto b = t.access!Table(theLayer, "funbody")) 417 294 { 418 295 Parameter[] ps; 419 296 foreach(v; tableAsConsList(theLayer, p)) ................................................................................ 436 313 Layer[] emp; 437 314 ps ~= new Parameter(ss.data, emp); 438 315 continue; 439 316 } 440 317 throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {bad fun params %s}`(v)); 441 318 } 442 319 auto bb = tableToAST(theLayer, b); 443 - return new FunLiteral(pos,ps,bb); 320 + return new Fun(pos,ps,bb); 444 321 } 445 322 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"fun", param:???, body:???}`); 446 323 default: 447 324 throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {is: "%s"} unknown`(nodeType.data)); 448 325 } 449 326 } 327 + 328 +Table makeCons(Value a, Value d) 329 +{ 330 + Table t = new Table; 331 + t.set("car", ValueLayer, a); 332 + t.set("cdr", ValueLayer, d); 333 + return t; 334 +} 335 + 336 +Table fromPos(LexPosition pos) 337 +{ 338 + Table t = new Table; 339 + if( pos !is null ) { 340 + t.set("filename", ValueLayer, new StrValue(pos.filename)); 341 + t.set("lineno", ValueLayer, new IntValue(BigInt(pos.lineno))); 342 + t.set("column", ValueLayer, new IntValue(BigInt(pos.column))); 343 + } else { 344 + t.set("filename", ValueLayer, new StrValue("nullpos")); 345 + t.set("lineno", ValueLayer, new IntValue(BigInt(0))); 346 + t.set("column", ValueLayer, new IntValue(BigInt(0))); 347 + } 348 + return t; 349 +}