Check-in [b993a8ad16]
Not logged in
Overview
SHA1 Hash:b993a8ad168487e4bd482a1fbb2ff69ce7e010f9
Date: 2010-11-25 02:44:58
User: kinaba
Comment:auto memo and re-run feature of non @value/@macro layers re-re-re-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 [197c2cfb75326106] to [bc3c32f1d9aafc10].

256 256 override Table definitionContext() { return defCtx; } 257 257 258 258 this(Fun ast, Table defCtx) { this.ast=ast; this.defCtx=defCtx; } 259 259 override string toString() const 260 260 { return sprintf!"(function:%x:%x)"(cast(void*)ast, cast(void*)defCtx); } 261 261 override int opCmp(Object rhs) { 262 262 if(auto r = cast(UserDefinedFunValue)rhs) { 263 - auto a = cast(void*)this.ast; 264 - auto b = cast(void*)r.ast; 265 - if(a<b) return -1; 266 - if(a>b) return +1; // [TODO] avoid using pointer value... 267 - return this.defCtx.opCmp(r.defCtx); 263 + if(auto c = typeid(void*).compare(cast(void*)ast, cast(void*)r.ast)) 264 + return c; 265 + if(auto c = typeid(void*).compare(cast(void*)defCtx, cast(void*)r.defCtx)) 266 + return c; 267 + return 0;// [TODO] avoid using pointer value... 268 268 } 269 269 if(auto r = cast(Value)rhs) return typeid(this).opCmp(typeid(r)); 270 270 throw genex!RuntimeException("comparison with value and something other"); 271 271 } 272 - mixin SimpleToHash; 272 + override hash_t toHash() { 273 + return (cast(hash_t)cast(void*)ast) + (cast(hash_t)cast(void*)defCtx); 274 + } 273 275 274 - AST afterMacroAST; 276 + AST macroCache; 277 + static class MemokeyType 278 + { 279 + void* a; Layer b; Tuple!(string,Layer,Value)[] c; 280 + hash_t toHash() { 281 + hash_t h = structuralHash(a) + structuralHash(b); 282 + foreach(e; c) 283 + h += structuralHash(e[0])+structuralHash(e[1])+structuralHash(e[2]); 284 + return h; 285 + } 286 + mixin SimpleToString; 287 + mixin SimpleConstructor; 288 + mixin SimpleCompareWithoutToHash; 289 + } 290 + static Tuple!(Value,int)[MemokeyType] memo; 291 + 275 292 override Value invoke(Layer lay, Table ctx, LexPosition pos) 276 293 { 277 294 if( isASTLayer(lay) ) 278 295 return eval(ast.funbody, lay, ctx); 279 - if( afterMacroAST is null ) 296 + 297 + auto nonMemoizedRun = (){ 298 + if( macroCache is null ) 299 + { 300 + auto va = macroAndEval(e.funbody, lay, ctx); 301 + macroCache = va[1]; 302 + return va[0]; 303 + } 304 + else 305 + return eval(macroCache, lay, ctx); 306 + }; 307 + 308 + if( !isUserDefinedLayer(lay) ) 309 + return nonMemoizedRun(); 310 + 311 + MemokeyType memokey = new MemokeyType(cast(void*)ast, lay, ctx.direct_entries()); 312 + 313 + if(auto p = memokey in memo) 280 314 { 281 - auto va = macroAndEval(e.funbody, lay, ctx); 282 - afterMacroAST = va[1]; 283 - return va[0]; 315 + (*p)[1] ++; 316 + return (*p)[0]; 284 317 } 285 318 else 286 - return eval(afterMacroAST, lay, ctx); 319 + memo[memokey] = tuple(lift(new UndefinedValue, lay, ctx, pos), 0); 320 + 321 + Value r = nonMemoizedRun(); 322 + 323 + int touched = memo[memokey][1]; 324 + memo[memokey] = tuple(r, 12345678); 325 + //if(touched) {DBG("rerun :: ",r);r = nonMemoizedRun();} // twice!! 326 + return r; 287 327 } 288 328 } 289 329 return new UserDefinedFunValue(e,ctx); 290 330 } 291 331 292 332 public: 293 333 /// Add primitive function to the global context ................................................................................ 300 340 301 341 override string toString() { return sprintf!"(native:%x)"(dg.funcptr); } 302 342 override int opCmp(Object rhs) { 303 343 if(auto r = cast(NativeFunValue)rhs) return typeid(typeof(dg)).compare(&dg,&r.dg); 304 344 if(auto r = cast(Value)rhs) return typeid(this).opCmp(typeid(r)); 305 345 throw genex!RuntimeException("comparison with value and something other"); 306 346 } 307 - mixin SimpleToHash; 347 + override hash_t toHash() const { 348 + return typeid(dg).getHash(&dg); 349 + } 308 350 309 351 R delegate(T) dg; 310 352 Parameter[] params_data; 311 353 312 354 this(R delegate(T) dg) 313 355 { 314 356 this.dg = dg;

Modified polemy/failure.d from [2827b7df74d1df19] to [442c0afd591f3c6a].

49 49 template ExceptionWithPosition() 50 50 { 51 51 LexPosition pos; 52 52 this( LexPosition pos, string msg, string file=null, size_t line=0, Throwable next=null ) 53 53 { 54 54 string fullmsg = pos is null ? sprintf!("\n[??] %s")(msg) 55 55 : sprintf!("\n[%s] %s")(pos, msg); 56 - for(int i=0; i<callstack_pos.length || i<callstack_msg.length; ++i) 56 + foreach_reverse(i,_; callstack_pos) 57 57 { 58 - LexPosition p = (i<callstack_pos.length ? callstack_pos[i] : null); 59 - string m = (i<callstack_msg.length ? callstack_msg[i] : null); 58 + LexPosition p = callstack_pos[i]; 59 + string m = callstack_msg[i]; 60 60 fullmsg ~= p is null ? sprintf!("\n[??] %s")(m) 61 61 : sprintf!("\n[%s] %s")(p, m); 62 62 } 63 63 super(fullmsg, file, line, next); 64 64 this.pos = pos; 65 65 } 66 66 this( string msg, string file=null, size_t line=0, Throwable next=null )

Modified polemy/value.d from [dc69a053821951bd] to [6fa9c2c94c01b274].

18 18 } 19 19 20 20 /// 21 21 class IntValue : Value 22 22 { 23 23 BigInt data; 24 24 25 - this(bool n) { this.data = n?1:0; } 26 - this(int n) { this.data = n; } 27 - this(long n) { this.data = n; } 25 + this(bool n) { this.data = n?1:0; } 26 + this(int n) { this.data = n; } 27 + this(long n) { this.data = n; } 28 28 this(BigInt n) { this.data = n; } 29 29 this(string n) { this.data = BigInt(n); } 30 30 override string toString() const { return toDecimalString(cast(BigInt)data); } 31 31 override int opCmp(Object rhs) { 32 32 if(auto r = cast(IntValue)rhs) return data.opCmp(r.data); 33 33 if(auto r = cast(Value)rhs) return typeid(this).opCmp(typeid(r)); 34 34 throw genex!RuntimeException("comparison with value and somithing other"); ................................................................................ 79 79 class Table : Value 80 80 { 81 81 enum Kind {PropagateSet, NotPropagateSet}; 82 82 83 83 this( Table proto=null, Kind k = Kind.PropagateSet ) 84 84 { this.prototype = proto; this.kind = k; } 85 85 86 + /// Set the value v to the index i of layer lay 86 87 void set(string i, Layer lay, Value v) 87 88 { 88 89 if( setIfExist(i, lay, v) ) 89 90 return; 90 91 data[i][lay] = v; 91 92 } 92 93 94 + /// True if index i has value in layer lay 93 95 bool has(string i, Layer lay) const 94 96 { 95 97 if( i in data ) 96 98 return !!(lay in data[i]); 97 99 if( prototype is null ) 98 100 return false; 99 101 return prototype.has(i, lay); 100 102 } 101 103 104 + /// Return the value of index i at layer lay. Throws if it is not set 102 105 Value get(string i, Layer lay, LexPosition pos=null) 103 106 { 104 107 if( i in data ) { 105 108 // [TODO] consider forwarding to proto also in this case 106 109 if( lay !in data[i] ) 107 110 throw genex!RuntimeException(pos, sprintf!"'%s' is not set in %s layer"(i,lay)); 108 111 return data[i][lay]; 109 112 } 110 113 if( prototype is null ) 111 114 throw genex!RuntimeException(pos, sprintf!"'%s' not found in %s layer"(i,lay)); 112 115 return prototype.get(i, lay, pos); 113 116 } 114 117 118 + /// t.access!T(lay,a,b,...) returns t.get(a,lay).get(b,lay).... if exists 119 + /// and has type T. Returns null otherwise 115 120 T access(T,S...)( Layer lay, string path, S rest ) 116 121 { 117 122 static if( rest.length == 0 ) 118 123 { 119 124 if( this.has(path, lay) ) 120 125 return cast(T) this.get(path, lay); 121 126 } ................................................................................ 123 128 { 124 129 if(auto next = this.access!Table(lay,path)) 125 130 return next.access!T(lay,rest); 126 131 } 127 132 return null; 128 133 } 129 134 130 - string toStringWithoutParen() const 131 - { 132 - string result; 133 - bool first = true; 134 - foreach(k, l2d; data) 135 - foreach(l,d; l2d) 136 - { 137 - if(first) first=false; else result~=", "; 138 - result ~= k; 139 - if( l.empty ) 140 - result ~= "(emptylayer)"; 141 - else if( l != ValueLayer ) 142 - result ~= l; 143 - result ~= ":"; 144 - result ~= text(cast(Value)d); 145 - } 146 - if( prototype !is null ) 147 - { 148 - result ~= " / "; 149 - result ~= prototype.toStringWithoutParen(); 150 - } 151 - return result; 152 - } 153 - 154 - string toString() 155 - { 156 - if( isList() ) 157 - return text(toList()); 158 - return "{" ~ toStringWithoutParen() ~ "}"; 159 - } 160 - 161 -public: 162 135 /// Is this an empty table? 163 136 bool empty() 164 137 { 165 138 return data.length==0 && (prototype is null || prototype.empty); 166 139 } 167 140 168 141 /// Can be seen as a cons-list? ................................................................................ 190 163 else 191 164 throw genex!RuntimeException("this table is not a cons-list"); 192 165 } 193 166 if( t.empty ) 194 167 return result; 195 168 throw genex!RuntimeException("this table is not a cons-list"); 196 169 } 170 + 171 + /// Get the list of direct entries ignoring prototypes in sorted order 172 + Tuple!(string,Layer,Value)[] direct_entries() 173 + { 174 + Tuple!(string,Layer,Value)[] arr; 175 + foreach(k, l2d; data) 176 + foreach(l,d; l2d) 177 + arr ~= tuple(k,l,d); 178 + arr.sort(); 179 + return arr; 180 + } 181 + 182 + /// Get the whole list of observable entries in unspecified order 183 + Tuple!(string,Layer,Value)[] entries() 184 + { 185 + bool[string] hidden; 186 + Tuple!(string,Layer,Value)[] arr; 187 + enumerateEntries(hidden, arr); 188 + return arr; 189 + } 190 + 191 + private void enumerateEntries( ref bool[string] hidden, ref Tuple!(string,Layer,Value)[] arr ) 192 + { 193 + foreach(k, l2d; data) 194 + if( k !in hidden ) 195 + { 196 + foreach(l,d; l2d) 197 + arr ~= tuple(k,l,d); 198 + hidden[k] = true; 199 + } 200 + if(prototype !is null) 201 + prototype.enumerateEntries(hidden, arr); 202 + } 203 + 204 + override string toString() 205 + { 206 + if( isList() ) 207 + return text(toList()); 208 + return "{" ~ toStringWithoutParen() ~ "}"; 209 + } 210 + 211 + override int opCmp(Object rhs) 212 + { 213 + if(auto r = cast(Table)rhs) { 214 + Tuple!(string,Layer,Value)[] ls = this.entries(); 215 + Tuple!(string,Layer,Value)[] rs = r.entries(); 216 + if( ls.length != rs.length ) 217 + return (ls.length < rs.length ? -1 : +1); 218 + ls.sort(); 219 + rs.sort(); 220 + foreach(i,_; ls) 221 + if(auto c = ls[i].opCmp(rs[i])) 222 + return c; 223 + return 0; 224 + } 225 + if(auto r = cast(Value)rhs) return typeid(this).opCmp(typeid(r)); 226 + throw genex!RuntimeException("comparison with value and somithing other"); 227 + } 228 + 229 + override hash_t toHash() 230 + { 231 + Tuple!(string,Layer,Value)[] ls = this.entries(); 232 + ls.sort(); 233 + hash_t h; 234 + foreach(e; ls) 235 + h += structuralHash(e[0])+structuralHash(e[1])+structuralHash(e[2]); 236 + return h; 237 + } 197 238 198 239 private: 199 240 Table prototype; 200 241 Kind kind; 201 242 Value[Layer][string] data; 243 + 244 + string toStringWithoutParen() const 245 + { 246 + string result; 247 + bool first = true; 248 + foreach(k, l2d; data) 249 + foreach(l,d; l2d) 250 + { 251 + if(first) first=false; else result~=", "; 252 + result ~= k; 253 + if( l.empty ) 254 + result ~= "(emptylayer)"; 255 + else if( l != ValueLayer ) 256 + result ~= l; 257 + result ~= ":"; 258 + result ~= text(cast(Value)d); 259 + } 260 + if( prototype !is null ) 261 + { 262 + result ~= " / "; 263 + result ~= prototype.toStringWithoutParen(); 264 + } 265 + return result; 266 + } 202 267 203 268 bool setIfExist(string i, Layer lay, Value v) 204 269 { 205 270 if( i in data ) 206 271 { 207 272 data[i][lay] = v; 208 273 return true;

Modified sample/type.pmy from [f80a12af3228ea33] to [12b974146da19906].

20 20 def mergeType(a,b) { 21 21 if( a == "undefined" ): ( if(b=="undefined"):"error" else b ) else ( a ) 22 22 }; 23 23 24 24 @type "if" = fun(c,t,e) {@value( 25 25 if(@type(c)=="int" ): mergeType(@type(t()), @type(e())) else : "error" 26 26 )}; 27 + 28 +def fib(x) 29 +{ 30 + if x<2 then 1 else fib(x-1) + fib(x-2) 31 +}; 32 + 33 +print( @type(fib(10)) );

Modified tricks/tricks.d from [cc1b586b87325960] to [00969146488cc3dc].

95 95 // shiyo- desu. Don't use in this way. 96 96 // Tamp tries to call new Tomp(real) (because it only sees Tomp's members), 97 97 // but it fails because Tomp takes (int,string,real). 98 98 assert( !__traits(compiles, { 99 99 class Tamp : Tomp { mixin SimpleConstructor; } 100 100 }) ); 101 101 } 102 + 103 +hash_t structuralHash(T)(T x) 104 +{ 105 + alias SC_Unqual!(T) UCT; 106 + 107 + static if(is(UCT == class)) 108 + return (cast(UCT)x).toHash(); 109 + else 110 + static if(SC_HasGoodHash!(UCT)) 111 + { return typeid(UCT).getHash(&x); } 112 + else 113 + static if(is(UCT T == T[])) 114 + { hash_t h; foreach(e; x) h+=structuralHash(e); return h; } 115 + else 116 + static if(is(UCT == struct)) 117 + static if(__traits(compiles, std.bigint.BigInt)) 118 + static if(is(UCT == std.bigint.BigInt)) 119 + return cast(hash_t) x.toInt(); 120 + else 121 + static assert(false, "should not use struct.toHash"); 122 + else 123 + static assert(false, "should not use struct.toHash"); 124 + else 125 + static assert(false, "nonhashable datatype "~UCT.stringof); 126 +} 127 + 128 +alias std.traits.Unqual SC_Unqual; 129 + 130 +template SC_HasGoodHash(T) 131 +{ 132 + enum SC_HasGoodHash = 133 + is(T : bool) || isNumeric!(T) || isSomeString!(T) || isSomeChar!(T) || isPointer!(T); 134 +} 102 135 103 136 /// Mixing-in the MOST-DERIVED-member-wise comparator for a class 137 +/// BE SURE THAT THIS IS CONSISTENT WITH opCmp and opEquals 104 138 105 139 template SimpleToHash() 106 140 { 107 141 override hash_t toHash() const /// member-by-member hash 108 142 { 109 143 hash_t h = 0; 110 144 foreach(mem; this.tupleof) 111 - h += typeid(mem).getHash(&mem); 145 + h += structuralHash(mem); 112 146 return h; 113 147 } 114 148 } 149 + 150 +/// Mixing-in the MOST-DERIVED-member-wise comparator for a class 151 + 152 +template SimpleCompareWithoutToHash() 153 +{ 154 + override bool opEquals(Object rhs) const /// member-by-member equality 155 + { 156 + return opCmp(rhs) == 0; 157 + } 158 + 159 + override int opCmp(Object rhs_) const /// member-by-member compare 160 + { 161 + if( rhs_ is null ) 162 + return -1; 163 + if( auto rhs = cast(typeof(this))rhs_ ) 164 + { 165 + foreach(i,_; this.tupleof) 166 + { 167 + static if(is(typeof(_) == struct)) 168 + auto c = (cast(SC_Unqual!(typeof(_)))this.tupleof[i]).opCmp(rhs.tupleof[i]); 169 + else 170 + auto c = typeid(_).compare(&this.tupleof[i],&rhs.tupleof[i]); 171 + if(c) 172 + return c; 173 + } 174 + return 0; 175 + } 176 + return typeid(this).opCmp(typeid(rhs_)); 177 + } 178 +} 115 179 116 180 /// Mixing-in the MOST-DERIVED-member-wise comparator for a class 117 181 118 182 /*mixin*/ 119 183 template SimpleCompare() 120 184 { 121 - override bool opEquals(Object rhs_) const /// member-by-member equality 122 - { 123 - if( auto rhs = cast(typeof(this))rhs_ ) 124 - { 125 - foreach(i,_; this.tupleof) 126 - if( this.tupleof[i] != (cast(const)rhs).tupleof[i] ) 127 - return false; 128 - return true; 129 - } 130 - assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), typeid(rhs_))); 131 - } 132 - 133 185 mixin SimpleToHash; 134 - 135 - override int opCmp(Object rhs_) const /// member-by-member compare 136 - { 137 - if( auto rhs = cast(typeof(this))rhs_ ) 138 - { 139 - foreach(i,_; this.tupleof) 140 - if( this.tupleof[i] != (cast(const)rhs).tupleof[i] ) { 141 - auto a = (cast(SC_Unqual!(typeof(this)))this).tupleof[i]; 142 - auto b = rhs.tupleof[i]; 143 - return a < b ? -1 : +1; 144 - } 145 -// not work well for structures??????? 146 -// if(auto c = typeid(_).compare(&this.tupleof[i],&rhs.tupleof[i])) 147 -// return c; 148 - return 0; 149 - } 150 - assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), typeid(rhs_))); 151 - } 186 + mixin SimpleCompareWithoutToHash; 152 187 } 153 188 154 -alias std.traits.Unqual SC_Unqual; 155 - 156 189 unittest 157 190 { 158 191 class Temp 159 192 { 160 193 int x; 161 194 string y; 162 195 mixin SimpleConstructor; ................................................................................ 173 206 class TempDummy 174 207 { 175 208 int x; 176 209 string y; 177 210 mixin SimpleConstructor; 178 211 mixin SimpleCompare; 179 212 } 180 - assert_throw!AssertError( new Temp(1,"foo") == new TempDummy(1,"foo") ); 181 - assert_throw!AssertError( new Temp(1,"foo") <= new TempDummy(1,"foo") ); 213 + assert_ne( new Temp(1,"foo"), new TempDummy(1,"foo") ); 214 + assert_nothrow( new Temp(1,"foo") <= new TempDummy(1,"foo") ); 182 215 } 183 216 184 217 /// Mixing-in a simple toString method 185 218 186 219 /*mixin*/ 187 220 template SimpleToString() 188 221 { ................................................................................ 222 255 template SimpleClass() 223 256 { 224 257 mixin SimpleConstructor; 225 258 mixin SimpleCompare; 226 259 mixin SimpleToString; 227 260 } 228 261 229 -/// Will be used for dynamic overload resolution pattern 262 +/// Utility 230 263 231 264 template firstParam(T) 232 265 { 233 266 alias ParameterTypeTuple!(T)[0] firstParam; 234 267 }