Diff
Not logged in

Differences From Artifact [6d85ee04f34c61b7]:

To Artifact [43e26264d772abeb]:


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 }