diff cbackend.js @ 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
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);