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 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;