changeset 42:4e983fe32047

Fix closures as methods so that private vars work
author Mike Pavone <pavone@retrodev.com>
date Thu, 12 Jul 2012 20:14:15 -0700
parents 0558dad9d061
children 27a2167663dd
files cbackend.js compiler.js parser.js samples/private
diffstat 4 files changed, 63 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/cbackend.js	Wed Jul 11 21:57:38 2012 -0700
+++ b/cbackend.js	Thu Jul 12 20:14:15 2012 -0700
@@ -55,12 +55,8 @@
 	return name;
 }
 
-symbol.prototype.toC = function() {
-	var name = this.cleanName();
-	var info = this.symbols.find(name);
-	if (!info) {
-		throw new Error('symbol ' + name + ' not found');
-	}
+function getSymbolPrefix(info)
+{
 	var pre = '';
 	switch(info.type) {
 	case 'self':
@@ -78,6 +74,13 @@
 			pre += 'parent->';
 		}
 		break;
+	case 'recupvar':
+		if (info.subtype == 'object') {
+			pre = 'self->env->';
+		} else {
+			//TODO: fill this case in if necessary
+		}
+		pre += getSymbolPrefix(info.parent);
 	case 'toplevel':
 		pre = 'modules.';
 		modules[name] = false;
@@ -85,7 +88,17 @@
 	case 'closedover':
 		pre = 'myenv->';
 	}
-	return pre + escapeCName(name);
+	return pre;
+}
+
+symbol.prototype.toC = function() {
+	var name = this.cleanName();
+	var info = this.symbols.find(name);
+	if (!info) {
+		throw new Error('symbol ' + name + ' not found');
+	}
+	
+	return getSymbolPrefix(info) + escapeCName(name);
 }
 
 var declaredInts = {};
@@ -146,7 +159,7 @@
 	if (this.receiver) {
 		args.splice(0, 0, this.receiver);
 	}
-		var method = false;
+	var method = false;
 	var funinfo = this.symbols.find(name);
 	if (!funinfo || funinfo.def instanceof setter) {
 		method = true;
@@ -154,7 +167,8 @@
 		switch(funinfo.type)
 		{
 		case 'self':
-			if (args.length < funinfo.def.args.length || funinfo.def.args[0].name != 'self') {
+			
+			if (args.length < funinfo.def.args.length || !funinfo.def.args.length || funinfo.def.args[0].name != 'self') {
 				args.splice(0, 0, new symbol('self', this.symbols));
 			} else {
 				args.splice(0, 1);
@@ -207,6 +221,9 @@
 cObject.prototype.addProperty = function(propname, value, type) {
 	if (type != undefined) {
 		this.properties.push([propname, type]);
+		if (value !== null) {
+			this.values.push(value);
+		}
 	} else {
 		var escaped = escapeCName(propname);
 		this.addMessage(propname, {
@@ -288,6 +305,10 @@
 	var values = [];
 	var imports = []
 	var me = new cObject('object_' + nextobject++);
+	if (this.symbols.needsenv) {
+		me.addProperty('env', this.symbols.envVar(), 'struct ' + this.symbols.getEnvType() + ' * ');
+		me.hasenv = true;
+	}
 	for (var i in messages) {
 		if (messages[i] instanceof funcall) {
 			if (messages[i].name == 'import:' && messages[i].args.length == 1) {
@@ -308,6 +329,7 @@
 			messages[i].toCObject(me);
 		}
 	}
+	
 	forwarddec += me.toEarlyCDef();
 	toplevelcode += me.toCDef();
 	return me.toCInstance();
@@ -491,7 +513,7 @@
 	}
 	
 	if (Object.keys(this.symbols.closedover).length) {
-		forwarddec += 'typedef struct {\n';
+		forwarddec += 'typedef struct lambda_' + mynum + '_env {\n';
 		for (var varname in this.symbols.closedover) {
 			forwarddec += '\tobject * ' + escapeCName(varname) + ';\n';
 		}
@@ -515,16 +537,20 @@
 	}
 	toplevelcode += args.join('') + '\tva_end(args);\n' + exprs.join(';\n\t') + '\n}\n';
 	
-	if (this.symbols.parentEnvType() != 'void') {
-		if (this.symbols.passthruenv) {
-			var envvar = 'env';
-		} else {
-			var envvar = 'myenv';
+	if (this.selftype) {
+		return 'lambda_' + mynum;
+	} else {
+		if (this.symbols.parentEnvType() != 'void') {
+			if (this.symbols.passthruenv) {
+				var envvar = 'env';
+			} else {
+				var envvar = 'myenv';
+			}
+			return 'make_closure(' + envvar + ', lambda_' + mynum + ')';
+		} else {	
+			toplevelcode += 'closure lambda_obj_' + mynum + ' = {{&lambda_meta, NULL}, NULL, lambda_' + mynum + '};\n';
+			return '((object *)&lambda_obj_' + mynum + ')';
 		}
-		return 'make_closure(' + envvar + ', lambda_' + mynum + ')';
-	} else {	
-		toplevelcode += 'closure lambda_obj_' + mynum + ' = {{&lambda_meta, NULL}, NULL, lambda_' + mynum + '};\n';
-		return '((object *)&lambda_obj_' + mynum + ')';
 	}
 };
 lambda.prototype.toCObject = function(typename) {
@@ -571,7 +597,7 @@
 		}
 		cobj.addMessage(this.symbol.name, {
 			vars: messagevars,
-			lines: [paramget + 'return ccall(' + val + ', ' + params.length + (params.length ? ', ' : '') + params.join(', ') + ');']
+			lines: [paramget + 'return ' + val + '(' + (cobj.hasenv ? 'self->env' : 'NULL') + ', ' + params.length + (params.length ? ', ' : '') + params.join(', ') + ');']
 		});
 	} else {
 		cobj.addProperty(this.symbol.name, val);
--- a/compiler.js	Wed Jul 11 21:57:38 2012 -0700
+++ b/compiler.js	Thu Jul 12 20:14:15 2012 -0700
@@ -45,8 +45,9 @@
 {
 	this.parent = parent;
 	this.names = {};
+	this.needsenv = false;
 }
-osymbols.prototype.find = function(name) {
+osymbols.prototype.find = function(name, nestedcall) {
 	if (name in this.names) {
 		if (this.names[name] instanceof funcall && this.names[name].name == 'foreign:') {
 			return {
@@ -59,13 +60,15 @@
 			def: this.names[name],
 		};
 	} else if(this.parent) {
-		var ret = this.parent.find(name);
+		var ret = this.parent.find(name, nestedcall);
 		if (ret) {
 			if(ret.type == 'self') {
 				ret.type = 'parent';
 				ret.depth = 1;
 			} else if(ret.type == 'parent') {
 				ret.depth++;
+			} else if(ret.type == 'closedover' || ret.type == 'upvar') {
+				this.needsenv = true;
 			}
 		}
 		return ret;
@@ -101,6 +104,9 @@
 osymbols.prototype.getEnvType = function() {
 	return this.parent.getEnvType();
 }
+osymbols.prototype.envVar = function() {
+	return this.parent.envVar();
+}
 
 function lsymbols(parent)
 {
@@ -187,6 +193,14 @@
 		return this.envtype;
 	}
 }
+lsymbols.prototype.envVar = function() {
+	if (Object.keys(this.closedover).length) {
+		return 'myenv';
+	} else if(this.passthruenv) {
+		return 'env';
+	}
+	return null;
+}
 
 var mainModule;
 
--- a/parser.js	Wed Jul 11 21:57:38 2012 -0700
+++ b/parser.js	Thu Jul 12 20:14:15 2012 -0700
@@ -54,7 +54,7 @@
 
 function lambda(args, expressions)
 {
-	this.args = args;
+	this.args = args ? args : [];
 	this.expressions = expressions;
 }
 
Binary file samples/private has changed