Differences From Artifact [dc69a053821951bd]:
- File
polemy/value.d
- 2010-11-24 03:30:56 - part of checkin [20be503cae] on branch trunk - set up referece manual (user: kinaba) [annotate]
To Artifact [6fa9c2c94c01b274]:
- File
polemy/value.d
- 2010-11-24 17:44:58 - part of checkin [b993a8ad16] on branch trunk - auto memo and re-run feature of non @value/@macro layers re-re-re-implemented. (user: kinaba) [annotate]
18 } 18 }
19 19
20 /// 20 ///
21 class IntValue : Value 21 class IntValue : Value
22 { 22 {
23 BigInt data; 23 BigInt data;
24 24
25 this(bool n) { this.data = n?1:0; } | 25 this(bool n) { this.data = n?1:0; }
26 this(int n) { this.data = n; } | 26 this(int n) { this.data = n; }
27 this(long n) { this.data = n; } | 27 this(long n) { this.data = n; }
28 this(BigInt n) { this.data = n; } 28 this(BigInt n) { this.data = n; }
29 this(string n) { this.data = BigInt(n); } 29 this(string n) { this.data = BigInt(n); }
30 override string toString() const { return toDecimalString(cast(BigInt)da 30 override string toString() const { return toDecimalString(cast(BigInt)da
31 override int opCmp(Object rhs) { 31 override int opCmp(Object rhs) {
32 if(auto r = cast(IntValue)rhs) return data.opCmp(r.data); 32 if(auto r = cast(IntValue)rhs) return data.opCmp(r.data);
33 if(auto r = cast(Value)rhs) return typeid(this).opCmp(typeid( 33 if(auto r = cast(Value)rhs) return typeid(this).opCmp(typeid(
34 throw genex!RuntimeException("comparison with value and somithin 34 throw genex!RuntimeException("comparison with value and somithin
................................................................................................................................................................................
79 class Table : Value 79 class Table : Value
80 { 80 {
81 enum Kind {PropagateSet, NotPropagateSet}; 81 enum Kind {PropagateSet, NotPropagateSet};
82 82
83 this( Table proto=null, Kind k = Kind.PropagateSet ) 83 this( Table proto=null, Kind k = Kind.PropagateSet )
84 { this.prototype = proto; this.kind = k; } 84 { this.prototype = proto; this.kind = k; }
85 85
> 86 /// Set the value v to the index i of layer lay
86 void set(string i, Layer lay, Value v) 87 void set(string i, Layer lay, Value v)
87 { 88 {
88 if( setIfExist(i, lay, v) ) 89 if( setIfExist(i, lay, v) )
89 return; 90 return;
90 data[i][lay] = v; 91 data[i][lay] = v;
91 } 92 }
92 93
> 94 /// True if index i has value in layer lay
93 bool has(string i, Layer lay) const 95 bool has(string i, Layer lay) const
94 { 96 {
95 if( i in data ) 97 if( i in data )
96 return !!(lay in data[i]); 98 return !!(lay in data[i]);
97 if( prototype is null ) 99 if( prototype is null )
98 return false; 100 return false;
99 return prototype.has(i, lay); 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 Value get(string i, Layer lay, LexPosition pos=null) 105 Value get(string i, Layer lay, LexPosition pos=null)
103 { 106 {
104 if( i in data ) { 107 if( i in data ) {
105 // [TODO] consider forwarding to proto also in this case 108 // [TODO] consider forwarding to proto also in this case
106 if( lay !in data[i] ) 109 if( lay !in data[i] )
107 throw genex!RuntimeException(pos, sprintf!"'%s' 110 throw genex!RuntimeException(pos, sprintf!"'%s'
108 return data[i][lay]; 111 return data[i][lay];
109 } 112 }
110 if( prototype is null ) 113 if( prototype is null )
111 throw genex!RuntimeException(pos, sprintf!"'%s' not foun 114 throw genex!RuntimeException(pos, sprintf!"'%s' not foun
112 return prototype.get(i, lay, pos); 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 exist
> 119 /// and has type T. Returns null otherwise
115 T access(T,S...)( Layer lay, string path, S rest ) 120 T access(T,S...)( Layer lay, string path, S rest )
116 { 121 {
117 static if( rest.length == 0 ) 122 static if( rest.length == 0 )
118 { 123 {
119 if( this.has(path, lay) ) 124 if( this.has(path, lay) )
120 return cast(T) this.get(path, lay); 125 return cast(T) this.get(path, lay);
121 } 126 }
................................................................................................................................................................................
123 { 128 {
124 if(auto next = this.access!Table(lay,path)) 129 if(auto next = this.access!Table(lay,path))
125 return next.access!T(lay,rest); 130 return next.access!T(lay,rest);
126 } 131 }
127 return null; 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 /// Is this an empty table? 135 /// Is this an empty table?
163 bool empty() 136 bool empty()
164 { 137 {
165 return data.length==0 && (prototype is null || prototype.empty); 138 return data.length==0 && (prototype is null || prototype.empty);
166 } 139 }
167 140
168 /// Can be seen as a cons-list? 141 /// Can be seen as a cons-list?
................................................................................................................................................................................
190 else 163 else
191 throw genex!RuntimeException("this table is not 164 throw genex!RuntimeException("this table is not
192 } 165 }
193 if( t.empty ) 166 if( t.empty )
194 return result; 167 return result;
195 throw genex!RuntimeException("this table is not a cons-list"); 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!(strin
> 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 somithin
> 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])+structura
> 236 return h;
> 237 }
197 238
198 private: 239 private:
199 Table prototype; 240 Table prototype;
200 Kind kind; 241 Kind kind;
201 Value[Layer][string] data; 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 bool setIfExist(string i, Layer lay, Value v) 268 bool setIfExist(string i, Layer lay, Value v)
204 { 269 {
205 if( i in data ) 270 if( i in data )
206 { 271 {
207 data[i][lay] = v; 272 data[i][lay] = v;
208 return true; 273 return true;