# HG changeset patch # User Mike Pavone # Date 1344442754 25200 # Node ID 9db0e3533b235a9dd774e4fa28f124e65bbc60dc # Parent b58b19c455ecbf8a12c42e2166a86da28e3d6f95 Some work on parameterized types diff -r b58b19c455ec -r 9db0e3533b23 types.js --- a/types.js Tue Aug 07 23:29:21 2012 -0700 +++ b/types.js Wed Aug 08 09:19:14 2012 -0700 @@ -64,11 +64,13 @@ this.satisfies_cache[type.id] = true; var ret = true; if (type.messages === undefined) { + print('type has no messages'); ret = false; } if (ret) { for (var msgname in this.messages) { if (!(msgname in type.messages) || !this.messages[msgname].satisfiedBy(type.messages[msgname])) { + print(msgname, 'missing in type'); ret = false; break; } @@ -95,7 +97,7 @@ }; objecttype.prototype.replaceParams = function(paramtypes, visited) { - if (visisted === undefined) { + if (visited === undefined) { visited = {}; } if (this.id in visited) { @@ -156,11 +158,13 @@ this.satisfies_cache[type.id] = true; var ret = true; if (!(type.callable) || this.params.length != type.params.length) { + print('type is not callable or param length mismatch'); ret = false; } if (ret) { for (var i in this.params) { if (i >= type.params.length || !this.params[i].satisfiedBy(type.params[i])) { + print('param ', i, ' is not satisfied'); ret = false; break; } @@ -169,6 +173,7 @@ if (ret) { for (var msgname in this.messages) { if (!(msgname in type.messages) || !this.messages[msgname].satisfiedBy(type.messages[msgname])) { + print('message', msgname, 'is not satisfied'); ret = false; break; } @@ -201,7 +206,7 @@ }; lambdatype.prototype.replaceParams = function(paramtypes, visited) { - if (visisted === undefined) { + if (visited === undefined) { visited = {}; } if (this.id in visited) { @@ -235,25 +240,25 @@ } uniontype.prototype.lazyinit = function() { - if (this.satisfies_cache = null) { + if (this.satisfies_cache == null) { this.satisfies_cache = {}; this.satisfies_cache[this.id] = true; this.messages = {}; - if (a.messages !== undefined && b.messages !== undefined) { - for (var msgname in a.messages) { - if (msgname in b.messages) { - this.messages[msgname] = mkunion(a.messages[msgname], b.messages[msgname]); + if (this.a.messages !== undefined && this.b.messages !== undefined) { + for (var msgname in this.a.messages) { + if (msgname in this.b.messages) { + this.messages[msgname] = mkunion(this.a.messages[msgname], this.b.messages[msgname]); } } } this.callable = false; - if (a.callable && b.callable && a.params.length == b.params.length) { + if (this.a.callable && this.b.callable && this.a.params.length == this.b.params.length) { this.callable = true; this.params = []; - for (var i = 0; i < a.params.length; i++) { - this.params.push(mkunion(a.params[i], b.params[i])); + for (var i = 0; i < this.a.params.length; i++) { + this.params.push(mkunion(this.a.params[i], this.b.params[i])); } - this.returntype = mkunion(a.returntype, b.returntype); + this.returntype = mkunion(this.a.returntype, this.b.returntype); } } }; @@ -278,11 +283,11 @@ if (indent.length > 6) { return 'max depth reached\n'; } - return indent + 'Union {\n\t' + indent + this.a.str() + '\t' + indent + this.b.str() + indent + '}\n'; + return indent + 'Union {\n\t' + indent + this.a.str(indent+'\t') + '\t' + indent + this.b.str(indent+'\t') + indent + '}\n'; }; uniontype.prototype.replaceParams = function(paramtypes, visited) { - if (visisted === undefined) { + if (visited === undefined) { visited = {}; } if (this.id in visited) { @@ -316,33 +321,49 @@ { this.type = type; this.params = params; + this.replaced = false; } -withtparams.prototype.satisfiedBy = function(type) { - return this.type.satisfiedBy(type); -}; - -withtparams.prototype.str = function(indent) { - return this.type.str(indent) + indent + '<' + this.params.map(function(p) { return p.str(indent); }).join(', ') + '>'; -}; - -withtparams.prototype.replaceParams = function(paramtypes) { - var replaced = false; - for (var i in this.params) { - var newp = this.params[i].replaceParams(paramtypes); - if (newp != this.params[i]) { - replaced = true; - this.params[i] = newp; +withtparams.prototype = { + satisfiedBy: function(type) { + this.lazyinit(); + return this.type.satisfiedBy(type); + }, + str: function(indent) { + if (indent === undefined) { + indent = ''; + } + if (indent.length > 6) { + return 'max depth reached\n'; } + return this.type.str(indent) + indent + '<' + this.params.map(function(p) { return p.str(indent); }).join(', ') + '>'; + }, + replaceParams: function(paramtypes) { + var replaced = false; + for (var i in this.params) { + var newp = this.params[i].replaceParams(paramtypes); + if (newp != this.params[i]) { + replaced = true; + this.params[i] = newp; + } + } + return this; + }, + lazyinit: function() { + if (!this.replaced) { + var childptypes = {}; + for (var i in this.type.typeparams) { + print(this.type.typeparams[i], 'is', this.params[i].str()); + childptypes[this.type.typeparams[i]] = this.params[i] + } + this.type = this.type.replaceParams(childptypes, {}); + this.replaced = true; + } + }, + get messages() { + this.lazyinit(); + return this.type.messages; } - if (replaced) { - var childptypes = {}; - for (var i in this.type.typeparams) { - childptypes[this.type.typeparams[i]] = this.params[i] - } - this.type = this.type.replaceParams(childptypes, {}); - } - return this; }; function typetest() @@ -373,7 +394,7 @@ var t = new typeparam('T', any); var q = new typeparam('Q', any); var head = new lambdatype(); - head.returnType = t; + head.returntype = t; tlnode.addMessage('head', head); var tail = new lambdatype(); var econs = new lambdatype();