changeset 54:976a0924e1d4

Fix closure over self var
author Mike Pavone <pavone@retrodev.com>
date Fri, 13 Jul 2012 19:22:39 -0700
parents 9482a0afe07c
children 93ddb4ad6fcb
files cbackend.js compiler.js tpc.js
diffstat 3 files changed, 65 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/cbackend.js	Fri Jul 13 18:31:32 2012 -0700
+++ b/cbackend.js	Fri Jul 13 19:22:39 2012 -0700
@@ -55,12 +55,13 @@
 	return name;
 }
 
-function getSymbolPrefix(info)
+function getSymbolPrefix(info, symbols)
 {
 	var pre = '';
 	switch(info.type) {
 	case 'self':
-		pre = 'self->';
+		
+		pre = (new symbol('self', symbols)).toC() + '->';
 		break;
 	case 'parent':
 		pre = 'self->';
@@ -96,7 +97,7 @@
 	if (info.type == 'toplevel') {
 		return info.def.modulevar;
 	}
-	return getSymbolPrefix(info) + escapeCName(name);
+	return getSymbolPrefix(info, this.symbols) + escapeCName(name);
 }
 
 var declaredInts = {};
@@ -253,7 +254,7 @@
 	for (var file in this.includes) {
 		includes += '#include ' + file + '\n';
 	}
-	var objdef =  'typedef struct {\n\tobject header;\n';
+	var objdef =  'typedef struct ' + this.name + ' {\n\tobject header;\n';
 	for (var i in this.properties) {
 		if (this.properties[i] instanceof Array) {
 			objdef += '\t' + this.properties[i][1] + ' ' + this.properties[i][0] + ';\n';
@@ -680,8 +681,10 @@
 		toplevelcode += builtins[i].toCDef();
 	}
 	addBuiltinModules(toplevel);
+	debugprint('//------POPULATING SYMBOLS-----');
 	obj.populateSymbols(toplevel);
 	var moduleinit = processUsedToplevel(toplevel);
+	debugprint('//------COMPILING AST-----');
 	var rest = 'object * mainModule() {\n' + moduleinit + '\tmain_module = ' + obj.toC() + ';\n\treturn main_module;\n}\n';
 	return '#include "runtime/proghead.inc"\n' +
 		'#define METHOD_ID_MAIN ' + getMethodId('main') + '\n' +
@@ -732,7 +735,11 @@
 	if (Object.keys(this.symbols.closedover).length) {
 		forwarddec += 'typedef struct lambda_' + mynum + '_env {\n';
 		for (var varname in this.symbols.closedover) {
-			forwarddec += '\tobject * ' + escapeCName(varname) + ';\n';
+			if (varname == 'self' && this.selftype) {
+				forwarddec += '\tstruct ' + this.selftype + ' * self;\n';
+			} else {
+				forwarddec += '\tobject * ' + escapeCName(varname) + ';\n';
+			}
 		}
 		forwarddec += '} lambda_' + mynum + '_env;\n'
 		
@@ -779,6 +786,7 @@
 }
 
 assignment.prototype.toC = function() {
+	debugprint('//assignment', this.symbol.name);
 	var existing = this.symbols.find(this.symbol.name);
 	var prefix = '';
 	var val = this.expression.toC();
@@ -788,10 +796,12 @@
 	if (existing.type == 'local' && !existing.isdeclared) {
 		prefix = 'object *';
 		this.symbols.declareVar(this.symbol.name);
+		debugprint('//declared var', this.symbol.name);
 	}
 	return prefix + this.symbol.toC() + ' = ' + val;
 };
 assignment.prototype.toCObject = function(cobj) {
+	debugprint('//message definition', this.symbol.name);
 	if (this.expression.toCObject) {
 		var val = this.expression.toCObject(cobj.name);
 	} else {
--- a/compiler.js	Fri Jul 13 18:31:32 2012 -0700
+++ b/compiler.js	Fri Jul 13 19:22:39 2012 -0700
@@ -1,3 +1,5 @@
+var debugprint = function() {};
+
 function indent(str)
 {
 	return str.split('\n').join('\n\t');
@@ -42,6 +44,7 @@
 	}
 }
 topsymbols.prototype.find = function(name) {
+	debugprint('//topsymbols.find', name, name in this.names);
 	if (!this.names) {
 		throw new Error('data not ready');
 	}
@@ -65,6 +68,7 @@
 	this.needsenv = false;
 }
 osymbols.prototype.find = function(name, nestedcall) {
+	debugprint('//osymbols.find', name + ', exists?:', name in this.names, ', nested?:', nestedcall);
 	if (name in this.names) {
 		if (this.names[name] instanceof funcall && this.names[name].name == 'foreign:') {
 			return {
@@ -72,7 +76,7 @@
 				def: this.names[name]
 			};
 		}
-		return {
+		var ret = {
 			type: 'self',
 			def: this.names[name],
 		};
@@ -88,9 +92,11 @@
 				this.needsenv = true;
 			}
 		}
-		return ret;
+	} else {
+		return null;
 	}
-	return null;
+	debugprint('\t//symbol type:', ret ? ret.type : 'null');
+	return ret;
 };
 osymbols.prototype.defineMsg = function(name, def) {
 	this.names[name] = def;
@@ -136,27 +142,30 @@
 	this.envtype = 'void';
 }
 lsymbols.prototype.find = function(name, nestedcall) {
+	debugprint('//lsymbols.find', name + ', exists?:', name in this.names, ', nested?:', nestedcall);
 	if (name in this.names) {
 		if (this.names[name] instanceof funcall && this.names[name].name == 'foreign:') {
-			return {
+			var ret = {
 				type: 'foreign',
 				def: this.names[name]
 			};
+		} else {
+			if (nestedcall) {
+				this.closedover[name] = true;
+			} 
+			if (name in this.closedover) {
+				var ret = {
+					type: 'closedover',
+					def: this.names[name]
+				};
+			} else {
+				var ret = {
+					type: 'local',
+					def: this.names[name],
+					isdeclared: (name in this.declared)
+				};
+			}
 		}
-		if (nestedcall) {
-			this.closedover[name] = true;
-		} 
-		if (name in this.closedover) {
-			return {
-				type: 'closedover',
-				def: this.names[name]
-			};
-		}
-		return {
-			type: 'local',
-			def: this.names[name],
-			isdeclared: (name in this.declared)
-		};
 	} else if(this.parent) {
 		var ret = this.parent.find(name, true);
 		if (ret) {
@@ -171,9 +180,11 @@
 				}
 			}
 		}
-		return ret;
+	} else {
+		return null;
 	}
-	return null;
+	debugprint('\t//symbol type:', ret ? ret.type : 'null');
+	return ret;
 };
 lsymbols.prototype.defineVar = function(name, def) {
 	this.names[name] = def;
@@ -244,7 +255,10 @@
 
 symbol.prototype.populateSymbols = function(symbols) {
 	this.symbols = symbols;
-	symbols.find(this.cleanName());
+	var ret = symbols.find(this.cleanName());
+	if (ret.type == 'self') {
+		symbols.find('self');
+	}
 }
 
 intlit.prototype.populateSymbols = function(symbols) {
@@ -297,17 +311,17 @@
 	this.symbols = symbols;
 }
 
-lambda.prototype.populateSymbols = function(symbols) {
+lambda.prototype.populateSymbols = function(symbols, isobject) {
 	var args = this.args ? this.args.slice(0, this.args.length) : [];
-	if (args.length && args[0].cleanName() == 'self') {
-		args.splice(0, 1);
-	}
 	var exprs = this.expressions;
-	symbols = new lsymbols(symbols);
+	var symbols = new lsymbols(symbols);
 	for (var i in args) {
 		symbols.defineVar(args[i].cleanName(), null);
 		args[i].populateSymbols(symbols);
 	}
+	if (isobject && (!args.length || args[0].cleanName() != 'self')) {
+		symbols.defineVar('self', null);
+	}
 	for (var i in exprs) {
 		exprs[i].populateSymbols(symbols);
 	}
@@ -331,7 +345,7 @@
 		symbols.defineMsg(this.symbol.name + '!', new setter(null));
 	}
 	this.symbol.populateSymbols(symbols);
-	this.expression.populateSymbols(symbols);
+	this.expression.populateSymbols(symbols, true);
 	this.symbols = symbols;
 };
 
--- a/tpc.js	Fri Jul 13 18:31:32 2012 -0700
+++ b/tpc.js	Fri Jul 13 19:22:39 2012 -0700
@@ -5,6 +5,7 @@
 var argtype = 'normal';
 var includes = [];
 var basedir = '';
+var debugmode = false;
 for (var i = 0; i < arguments.length; i++) {
 	switch (argtype) {
 	case 'normal':
@@ -13,6 +14,9 @@
 		case '-i':
 			argtype = arguments[i];
 			break;
+		case '-compilerdebug':
+			debugmode = true;
+			break;
 		default:
 			if (arguments[i].charAt(0) == '-') {
 				print("unrecognized switch", arguments[i]);
@@ -46,10 +50,10 @@
 	quit(1);
 }
 	
-compileFile(file, basedir, includes);
+compileFile(file, basedir, includes, debugmode);
 
 
-function compileFile(filename, basedir, includes)
+function compileFile(filename, basedir, includes, debugmode)
 {
 	var text = read(filename);
 	load(basedir + 'peg.js');
@@ -74,6 +78,9 @@
 		print(spacer + '^');
 		quit(1);
 	}
+	if (debugmode) {
+		debugprint = print;
+	}
 	var c = parsed.toCModule();
 	print(c);
 }