changeset 100:9db0e3533b23

Some work on parameterized types
author Mike Pavone <pavone@retrodev.com>
date Wed, 08 Aug 2012 09:19:14 -0700
parents b58b19c455ec
children 5d15b91e738a
files types.js
diffstat 1 files changed, 58 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- 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();