Differences From Artifact [6d85ee04f34c61b7]:
- File
polemy/value.d
- 2010-11-23 10:09:03 - part of checkin [36c517dfc4] on branch trunk - refactored d-value and polemy-value conversion (user: kinaba) [annotate]
To Artifact [43e26264d772abeb]:
- File
polemy/value.d
- 2010-11-23 13:55:15 - part of checkin [2134cd44cc] on branch trunk - further clean-up for polemy2d (user: kinaba) [annotate]
75 75 /// Context (variable environment)
76 76 /// Simlar to prototype chain of ECMAScript etc.
77 77 /// But extended with the notion of "Layer"
78 78
79 79 class Table : Value
80 80 {
81 81 enum Kind {PropagateSet, NotPropagateSet};
82 - bool kill = false; // to refactor
83 82
84 83 this( Table proto=null, Kind k = Kind.PropagateSet )
85 84 { this.prototype = proto; this.kind = k; }
86 85
87 - void set(string i, Layer lay, Value v, LexPosition pos=null)
86 + void set(string i, Layer lay, Value v)
88 87 {
89 88 if( setIfExist(i, lay, v) )
90 89 return;
91 90 data[i][lay] = v;
92 91 }
93 92
94 93 bool has(string i, Layer lay) const
95 94 {
96 - if( i in data ) {
97 - if( lay !in data[i] )
98 - return false;
99 - if(kill)
100 - return false;
101 - return true;
102 - }
95 + if( i in data )
96 + return !!(lay in data[i]);
103 97 if( prototype is null )
104 98 return false;
105 99 return prototype.has(i, lay);
106 100 }
107 101
108 102 Value get(string i, Layer lay, LexPosition pos=null)
109 103 {
110 104 if( i in data ) {
111 105 // [TODO] consider forwarding to proto also in this case
112 106 if( lay !in data[i] )
113 - throw genex!RuntimeException(pos, sprintf!"'%s' is not set in layer %s"(i,lay));
114 - if(kill)
115 - throw genex!RuntimeException(pos, sprintf!"'%s' is killed in macro"(i));
107 + throw genex!RuntimeException(pos, sprintf!"'%s' is not set in %s layer"(i,lay));
116 108 return data[i][lay];
117 109 }
118 110 if( prototype is null )
119 - throw new RuntimeException(pos, sprintf!"'%s' not found"(i));
111 + throw genex!RuntimeException(pos, sprintf!"'%s' not found in %s layer"(i,lay));
120 112 return prototype.get(i, lay, pos);
121 113 }
122 114
123 115 T access(T,S...)( Layer lay, string path, S rest )
124 116 {
125 117 static if( rest.length == 0 )
126 118 {
................................................................................
155 147 {
156 148 result ~= " / ";
157 149 result ~= prototype.toStringWithoutParen();
158 150 }
159 151 return result;
160 152 }
161 153
162 - string toString() const
154 + string toString()
163 155 {
156 + if( isList() )
157 + return text(toList());
164 158 return "{" ~ toStringWithoutParen() ~ "}";
165 159 }
160 +
161 +public:
162 + /// Is this an empty table?
163 + bool empty()
164 + {
165 + return data.length==0 && (prototype is null || prototype.empty);
166 + }
167 +
168 + /// Can be seen as a cons-list?
169 + bool isList()
170 + {
171 + Table t = this;
172 + while(t.has("car", ValueLayer) && t.has("cdr", ValueLayer))
173 + if(auto tt = cast(Table)t.get("cdr", ValueLayer))
174 + t = tt;
175 + else
176 + return false;
177 + return t.empty;
178 + }
179 +
180 + /// Regard table as a cons-list and convert to an array
181 + Value[] toList()
182 + {
183 + Value[] result;
184 + Table t = this;
185 + while(t.has("car", ValueLayer) && t.has("cdr", ValueLayer))
186 + {
187 + result ~= t.get("car", ValueLayer);
188 + if(auto tt = cast(Table)t.get("cdr", ValueLayer))
189 + t = tt;
190 + else
191 + throw genex!RuntimeException("this table is not a cons-list");
192 + }
193 + if( t.empty )
194 + return result;
195 + throw genex!RuntimeException("this table is not a cons-list");
196 + }
166 197
167 198 private:
168 199 Table prototype;
169 200 Kind kind;
170 201 Value[Layer][string] data;
171 202
172 203 bool setIfExist(string i, Layer lay, Value v)
................................................................................
185 216 unittest
186 217 {
187 218 Table c0 = new Table;
188 219 Table c01 = new Table(c0, Table.Kind.NotPropagateSet);
189 220 Table c012 = new Table(c01, Table.Kind.PropagateSet);
190 221 Table c013 = new Table(c01, Table.Kind.PropagateSet);
191 222
192 - assert_nothrow( c012.set("x", ValueLayer, new IntValue(BigInt(12))) );
223 + assert_nothrow( c012.set("x", ValueLayer, new IntValue(12)) );
193 224 assert_throw!RuntimeException( c013.get("x", ValueLayer) );
194 - assert_nothrow( c013.set("x", ValueLayer, new IntValue(BigInt(13))) );
195 - assert_eq( c013.get("x", ValueLayer), new IntValue(BigInt(13)) );
196 - assert_eq( c012.get("x", ValueLayer), new IntValue(BigInt(12)) );
225 + assert_nothrow( c013.set("x", ValueLayer, new IntValue(13)) );
226 + assert_eq( c013.get("x", ValueLayer), new IntValue(13) );
227 + assert_eq( c012.get("x", ValueLayer), new IntValue(12) );
197 228 assert_throw!RuntimeException( c01.get("x", ValueLayer) );
198 229
199 - assert_nothrow( c01.set("y", ValueLayer, new IntValue(BigInt(1))) );
200 - assert_eq( c013.get("y", ValueLayer), new IntValue(BigInt(1)) );
201 - assert_eq( c012.get("y", ValueLayer), new IntValue(BigInt(1)) );
202 - assert_eq( c01.get("y", ValueLayer), new IntValue(BigInt(1)) );
230 + assert_nothrow( c01.set("y", ValueLayer, new IntValue(1)) );
231 + assert_eq( c013.get("y", ValueLayer), new IntValue(1) );
232 + assert_eq( c012.get("y", ValueLayer), new IntValue(1) );
233 + assert_eq( c01.get("y", ValueLayer), new IntValue(1) );
234 +
235 + assert_nothrow( c0.set("z", ValueLayer, new IntValue(0)) );
236 + assert_eq( c013.get("z", ValueLayer), new IntValue(0) );
237 + assert_eq( c012.get("z", ValueLayer), new IntValue(0) );
238 + assert_eq( c01.get("z", ValueLayer), new IntValue(0) );
239 + assert_eq( c0.get("z", ValueLayer), new IntValue(0) );
203 240
204 - assert_nothrow( c0.set("z", ValueLayer, new IntValue(BigInt(0))) );
205 - assert_eq( c013.get("z", ValueLayer), new IntValue(BigInt(0)) );
206 - assert_eq( c012.get("z", ValueLayer), new IntValue(BigInt(0)) );
207 - assert_eq( c01.get("z", ValueLayer), new IntValue(BigInt(0)) );
208 - assert_eq( c0.get("z", ValueLayer), new IntValue(BigInt(0)) );
241 + assert_nothrow( c012.set("y", ValueLayer, new IntValue(444)) );
242 + assert_eq( c013.get("y", ValueLayer), new IntValue(444) );
243 + assert_eq( c012.get("y", ValueLayer), new IntValue(444) );
244 + assert_eq( c01.get("y", ValueLayer), new IntValue(444) );
209 245
210 - assert_nothrow( c012.set("y", ValueLayer, new IntValue(BigInt(444))) );
211 - assert_eq( c013.get("y", ValueLayer), new IntValue(BigInt(444)) );
212 - assert_eq( c012.get("y", ValueLayer), new IntValue(BigInt(444)) );
213 - assert_eq( c01.get("y", ValueLayer), new IntValue(BigInt(444)) );
214 -
215 - assert_nothrow( c012.set("z", ValueLayer, new IntValue(BigInt(555))) );
216 - assert_eq( c013.get("z", ValueLayer), new IntValue(BigInt(0)) );
217 - assert_eq( c012.get("z", ValueLayer), new IntValue(BigInt(555)) );
218 - assert_eq( c01.get("z", ValueLayer), new IntValue(BigInt(0)) );
219 - assert_eq( c0.get("z", ValueLayer), new IntValue(BigInt(0)) );
246 + assert_nothrow( c012.set("z", ValueLayer, new IntValue(555)) );
247 + assert_eq( c013.get("z", ValueLayer), new IntValue(0) );
248 + assert_eq( c012.get("z", ValueLayer), new IntValue(555) );
249 + assert_eq( c01.get("z", ValueLayer), new IntValue(0) );
250 + assert_eq( c0.get("z", ValueLayer), new IntValue(0) );
220 251
221 252 // [TODO] define the semantics and test @layers
222 253 }