comparison types.js @ 101:5d15b91e738a

Fix paramerized types. Remove debug print calls.
author Mike Pavone <pavone@retrodev.com>
date Thu, 09 Aug 2012 08:09:14 -0700
parents 9db0e3533b23
children 92ff9630897a
comparison
equal deleted inserted replaced
100:9db0e3533b23 101:5d15b91e738a
62 } 62 }
63 //temporarily set cache entry to true to prevent infinite recursion 63 //temporarily set cache entry to true to prevent infinite recursion
64 this.satisfies_cache[type.id] = true; 64 this.satisfies_cache[type.id] = true;
65 var ret = true; 65 var ret = true;
66 if (type.messages === undefined) { 66 if (type.messages === undefined) {
67 print('type has no messages');
68 ret = false; 67 ret = false;
69 } 68 }
70 if (ret) { 69 if (ret) {
71 for (var msgname in this.messages) { 70 for (var msgname in this.messages) {
72 if (!(msgname in type.messages) || !this.messages[msgname].satisfiedBy(type.messages[msgname])) { 71 if (!(msgname in type.messages) || !this.messages[msgname].satisfiedBy(type.messages[msgname])) {
73 print(msgname, 'missing in type');
74 ret = false; 72 ret = false;
75 break; 73 break;
76 } 74 }
77 } 75 }
78 } 76 }
156 } 154 }
157 //temporarily set cache entry to true to prevent infinite recursion 155 //temporarily set cache entry to true to prevent infinite recursion
158 this.satisfies_cache[type.id] = true; 156 this.satisfies_cache[type.id] = true;
159 var ret = true; 157 var ret = true;
160 if (!(type.callable) || this.params.length != type.params.length) { 158 if (!(type.callable) || this.params.length != type.params.length) {
161 print('type is not callable or param length mismatch');
162 ret = false; 159 ret = false;
163 } 160 }
164 if (ret) { 161 if (ret) {
165 for (var i in this.params) { 162 for (var i in this.params) {
166 if (i >= type.params.length || !this.params[i].satisfiedBy(type.params[i])) { 163 if (i >= type.params.length || !this.params[i].satisfiedBy(type.params[i])) {
167 print('param ', i, ' is not satisfied');
168 ret = false; 164 ret = false;
169 break; 165 break;
170 } 166 }
171 } 167 }
172 } 168 }
173 if (ret) { 169 if (ret) {
174 for (var msgname in this.messages) { 170 for (var msgname in this.messages) {
175 if (!(msgname in type.messages) || !this.messages[msgname].satisfiedBy(type.messages[msgname])) { 171 if (!(msgname in type.messages) || !this.messages[msgname].satisfiedBy(type.messages[msgname])) {
176 print('message', msgname, 'is not satisfied');
177 ret = false; 172 ret = false;
178 break; 173 break;
179 } 174 }
180 } 175 }
181 } 176 }
211 } 206 }
212 if (this.id in visited) { 207 if (this.id in visited) {
213 return visited[this.id]; 208 return visited[this.id];
214 } 209 }
215 var me = visited[this.id] = this.clone(); 210 var me = visited[this.id] = this.clone();
216 for (var msgname in this.messages) { 211 for (var msgname in me.messages) {
217 me.messages[msgname] = me.messages[msgname].replaceParams(paramtypes, visited); 212 me.messages[msgname] = me.messages[msgname].replaceParams(paramtypes, visited);
218 } 213 }
214 for (var i in me.params) {
215 me.params[i] = me.params[i].replaceParams(paramtypes, visited);
216 }
217 me.returntype = me.returntype.replaceParams(paramtypes, visited);
219 return me; 218 return me;
220 }; 219 };
221 220
222 lambdatype.prototype.clone = function() { 221 lambdatype.prototype.clone = function() {
223 var clone = new lambdatype(); 222 var clone = new lambdatype();
237 this.b = b; 236 this.b = b;
238 this.id = nexttypeid++; 237 this.id = nexttypeid++;
239 this.satisfies_cache = null; 238 this.satisfies_cache = null;
240 } 239 }
241 240
242 uniontype.prototype.lazyinit = function() { 241 uniontype.prototype = {
243 if (this.satisfies_cache == null) { 242 lazyinit: function() {
244 this.satisfies_cache = {}; 243 if (this.satisfies_cache == null) {
245 this.satisfies_cache[this.id] = true; 244 this.satisfies_cache = {};
246 this.messages = {}; 245 this.satisfies_cache[this.id] = true;
247 if (this.a.messages !== undefined && this.b.messages !== undefined) { 246 this._messages = {};
248 for (var msgname in this.a.messages) { 247 if (this.a.messages !== undefined && this.b.messages !== undefined) {
249 if (msgname in this.b.messages) { 248 for (var msgname in this.a.messages) {
250 this.messages[msgname] = mkunion(this.a.messages[msgname], this.b.messages[msgname]); 249 if (msgname in this.b.messages) {
250 this._messages[msgname] = mkunion(this.a.messages[msgname], this.b.messages[msgname]);
251 }
251 } 252 }
252 } 253 }
253 } 254 this._callable = false;
254 this.callable = false; 255 if (this.a.callable && this.b.callable && this.a.params.length == this.b.params.length) {
255 if (this.a.callable && this.b.callable && this.a.params.length == this.b.params.length) { 256 this._callable = true;
256 this.callable = true; 257 this._params = [];
257 this.params = []; 258 for (var i = 0; i < this.a.params.length; i++) {
258 for (var i = 0; i < this.a.params.length; i++) { 259 this._params.push(mkunion(this.a.params[i], this.b.params[i]));
259 this.params.push(mkunion(this.a.params[i], this.b.params[i])); 260 }
260 } 261 this._returntype = mkunion(this.a.returntype, this.b.returntype);
261 this.returntype = mkunion(this.a.returntype, this.b.returntype); 262 }
262 } 263 }
263 } 264 },
264 }; 265 satisfiedBy: function(type)
265 266 {
266 uniontype.prototype.satisfiedBy = function(type) 267 this.lazyinit();
267 { 268 if (type.id in this.satisfies_cache) {
268 this.lazyinit(); 269 return this.satisfies_cache[type.id];
269 if (type.id in this.satisfies_cache) { 270 }
270 return this.satisfies_cache[type.id]; 271 this.satisfies_cache[type.id] = true;
271 } 272 var ret = this.a.satisfiedBy(type) || this.b.satisfiedBy(type);
272 this.satisfies_cache[type.id] = true; 273 this.satisfies_cache[type.id] = ret;
273 var ret = this.a.satisfiedBy(type) || this.b.satisfiedBy(type); 274 return ret;
274 this.satisfies_cache[type.id] = ret; 275 },
275 return ret; 276 str: function(indent)
276 }; 277 {
277 278 if (indent === undefined) {
278 uniontype.prototype.str = function(indent) 279 indent = '';
279 { 280 }
280 if (indent === undefined) { 281 if (indent.length > 6) {
281 indent = ''; 282 return 'max depth reached\n';
282 } 283 }
283 if (indent.length > 6) { 284 return indent + 'Union {\n\t' + indent + this.a.str(indent+'\t') + '\t' + indent + this.b.str(indent+'\t') + indent + '}\n';
284 return 'max depth reached\n'; 285 },
285 } 286 replaceParams: function(paramtypes, visited) {
286 return indent + 'Union {\n\t' + indent + this.a.str(indent+'\t') + '\t' + indent + this.b.str(indent+'\t') + indent + '}\n'; 287 if (visited === undefined) {
287 }; 288 visited = {};
288 289 }
289 uniontype.prototype.replaceParams = function(paramtypes, visited) { 290 if (this.id in visited) {
290 if (visited === undefined) { 291 return visited[this.id];
291 visited = {}; 292 }
292 } 293 var me = visited[this.id] = this.clone();
293 if (this.id in visited) { 294 me.a = me.a.replaceParams(paramtypes, visited);
294 return visited[this.id]; 295 me.b = me.b.replaceParams(paramtypes, visited);
295 } 296 return me;
296 var me = visited[this.id] = this.clone(); 297 },
297 me.a = me.a.replaceParams(paramtypes, visited); 298 clone: function() {
298 me.b = me.b.replaceParams(paramtypes, visited); 299 return new uniontype(this.a, this.b);
299 return me; 300 },
300 }; 301 get messages() {
301 302 this.lazyinit();
302 uniontype.prototype.clone = function() { 303 return this._messages;
303 return new uniontype(this.a, this.b); 304 },
305 get params() {
306 this.lazyinit();
307 return this._params;
308 },
309 get returntype() {
310 this.lazyinit();
311 return this._returntype;
312 },
313 get callable() {
314 this.lazyinit();
315 return this._callable;
316 }
304 }; 317 };
305 318
306 319
307 function mkunion(a, b) 320 function mkunion(a, b)
308 { 321 {
351 }, 364 },
352 lazyinit: function() { 365 lazyinit: function() {
353 if (!this.replaced) { 366 if (!this.replaced) {
354 var childptypes = {}; 367 var childptypes = {};
355 for (var i in this.type.typeparams) { 368 for (var i in this.type.typeparams) {
356 print(this.type.typeparams[i], 'is', this.params[i].str());
357 childptypes[this.type.typeparams[i]] = this.params[i] 369 childptypes[this.type.typeparams[i]] = this.params[i]
358 } 370 }
359 this.type = this.type.replaceParams(childptypes, {}); 371 this.type = this.type.replaceParams(childptypes, {});
360 this.replaced = true; 372 this.replaced = true;
361 } 373 }