changeset 68:3a169ebb3224

Change strategy for handling true and false to avoid some initialization order problems and improve performance. Add support for negative integer literals. Update samples to reflect true/false change.
author Mike Pavone <pavone@retrodev.com>
date Sat, 14 Jul 2012 16:14:01 -0700
parents 42d5660b30b4
children ba032565c7a5
files cbackend.js compiler.js modules/false.tp modules/true.tp parser.js samples/fib.tp samples/iterfib.tp samples/recursive_closure.tp tpc.js
diffstat 9 files changed, 86 insertions(+), 62 deletions(-) [+]
line wrap: on
line diff
--- a/cbackend.js	Sat Jul 14 13:31:05 2012 -0700
+++ b/cbackend.js	Sat Jul 14 16:14:01 2012 -0700
@@ -96,7 +96,8 @@
 		throw new Error('symbol ' + name + ' not found');
 	}
 	if (info.type == 'toplevel') {
-		return info.def.modulevar;
+		
+		return toplevel.moduleVar(name);
 	}
 	return getSymbolPrefix(info, this.symbols) + escapeCName(name);
 }
@@ -104,9 +105,9 @@
 var declaredInts = {};
 
 intlit.prototype.toC = function() {
-	var str = this.val.toString();
+	var str = this.val < 0 ? 'neg_' + (0-this.val).toString() : this.val.toString();
 	if (!(this.val in declaredInts)) {
-		toplevelcode += 'obj_int32 int32_' + str + ' = {{&obj_int32_meta, NULL}, ' + str + '};\n';
+		toplevelcode += 'obj_int32 int32_' + str + ' = {{&obj_int32_meta, NULL}, ' + this.val.toString() + '};\n';
 		declaredInts[this.val] = true;
 	}
 	return '((object *)&int32_' + str + ')';
@@ -266,6 +267,7 @@
 	}
 }
 
+cObject.prototype.populateSymbols = function() {};
 
 cObject.prototype.toEarlyCDef = function() {
 	this.checkInitMsg();
@@ -400,9 +402,9 @@
 		lines: [
 			'argb = va_arg(args, ' + objtype + ' *);',
 			'if (self->num ' + cop + ' argb->num) {',
-			'	return mcall(METHOD_ID_TRUE, 1, main_module);',
+			'	return ' + toplevel.moduleVar('true') + ';',
 			'}',
-			'return mcall(METHOD_ID_FALSE, 1, main_module);'
+			'return ' + toplevel.moduleVar('false') + ';',
 		]
 	});
 }
@@ -449,7 +451,7 @@
 			'if (index->num >= 0 && index->num < self->size) {',
 			'	return self->data[index->num];',
 			'}',
-			'return mcall(METHOD_ID_FALSE, 1, main_module);'
+			'return ' + toplevel.moduleVar('false') + ';'
 		]
 	});
 	array.addMessage('set', {
@@ -528,9 +530,9 @@
 		lines: [
 			'argb = va_arg(args, string *);',
 			'if (self->length == argb->length && self->bytes == argb->bytes && !memcmp(self->data, argb->data, self->bytes)) {',
-			'	return mcall(METHOD_ID_TRUE, 1, main_module);',
+			'	return ' + toplevel.moduleVar('true') + ';',
 			'}',
-			'return mcall(METHOD_ID_FALSE, 1, main_module);'
+			'return ' + toplevel.moduleVar('false') + ';',
 		]
 	});
 	string.addMessage('NEQ_', {
@@ -538,9 +540,9 @@
 		lines: [
 			'argb = va_arg(args, string *);',
 			'if (self->length != argb->length || self->bytes != argb->bytes || memcmp(self->data, argb->data, self->bytes)) {',
-			'	return mcall(METHOD_ID_TRUE, 1, main_module);',
+			'	return ' + toplevel.moduleVar('true') + ';',
 			'}',
-			'return mcall(METHOD_ID_FALSE, 1, main_module);'
+			'return ' + toplevel.moduleVar('false') + ';',
 		]
 	});
 	string.addMessage('print', {
@@ -586,12 +588,11 @@
 	clos.addProperty('env', null, 'void *');
 	clos.addProperty('func', null, 'closure_func');
 	clos.addMessage('while:do', {
-		vars: {action: 'lambda *', valtrue: 'object *', ret: 'object *'},
+		vars: {action: 'lambda *', ret: 'object *'},
 		lines: [
 			'action = va_arg(args, lambda *);',
-			'valtrue = mcall(METHOD_ID_TRUE, 1, main_module);',
-			'ret = valtrue;',
-			'while(valtrue == ccall(self, 0)) {',
+			'ret = ' + toplevel.moduleVar('true') + ';',
+			'while(' + toplevel.moduleVar('true') + ' == ccall(self, 0)) {',
 			'	ccall(action, 0);',
 			'}',
 			'return ret;'
@@ -710,22 +711,55 @@
 	toplevel.names['os'] = os;
 }
 
+modulefile.prototype.populateSymbols = function (toplevel) {
+	if (!this.ast) {
+		this.ast = parseFile(this.path + '/' + this.file);
+		this.ast.populateSymbols(toplevel);
+	}
+};
+
 modulefile.prototype.toC = function(){
-	var ast = parseFile(this.path + '/' + this.file);
-	ast.populateSymbols(toplevel);
-	return ast.toCModuleInstance();
+	this.populateSymbols(toplevel);
+	return this.ast.toCModuleInstance();
 };
 
 function processUsedToplevel(toplevel)
-{
+{	
+	var alwaysused = ['true', 'false'];
 	var ret = '';
 	var modulenum = 0;
-	for (var symbol in toplevel.used) {
-		toplevel.names[symbol].modulevar = 'module_' + (modulenum++);
-		toplevelcode += 'object * ' + toplevel.names[symbol].modulevar + ';\n';
+	var newused = Object.keys(toplevel.used);
+	var allused = newused;
+	var visited = {};
+	for (var i in alwaysused) {
+		forwarddec += 'object * ' + toplevel.moduleVar(alwaysused[i]) + ';\n';
+		toplevel.names[alwaysused[i]].populateSymbols(toplevel);
+		visited[alwaysused[i]] = true;
 	}
-	for (var symbol in toplevel.used) {
-		ret += '\t' + toplevel.names[symbol].modulevar + ' = ' + toplevel.names[symbol].toC() + ';\n';
+	while (newused.length) {
+		for (var i in newused) {
+			debugprint('//---module', newused[i], '--- populate symbols');
+			forwarddec += 'object * ' + toplevel.moduleVar(newused[i]) + ';\n';
+			toplevel.names[newused[i]].populateSymbols(toplevel);
+			visited[newused[i]] = true;
+		}
+		newused = [];
+		for (var symbol in toplevel.used) {
+			if (!(symbol in visited)) {
+				debugprint('//found new usage of module', symbol);
+				newused.push(symbol);
+				allused.push(symbol);
+			}
+		}
+	}
+	for (var i in alwaysused) {
+		allused.push(alwaysused[i]);
+	}
+		
+	for (var i = allused.length-1; i >= 0; i--) {
+		var symbol = allused[i];
+		debugprint('//---module', symbol, '--- compile');
+		ret += '\t' + toplevel.moduleVar(symbol) + ' = ' + toplevel.names[symbol].toC() + ';\n';
 	}
 	return ret;
 }
@@ -746,8 +780,6 @@
 	var rest = 'object * mainModule() {\n' + moduleinit + '\tmain_module = ' + obj.toCModuleInstance() + ';\n\treturn main_module;\n}\n';
 	return '#include "runtime/proghead.inc"\n' +
 		'#define METHOD_ID_MAIN ' + getMethodId('main') + '\n' +
-		'#define METHOD_ID_TRUE ' + getMethodId('true') + '\n' +
-		'#define METHOD_ID_FALSE ' + getMethodId('false') + '\n' +
 		forwarddec + toplevelcode + rest + '#include "runtime/progfoot.inc"\n';
 }
 
--- a/compiler.js	Sat Jul 14 13:31:05 2012 -0700
+++ b/compiler.js	Sat Jul 14 16:14:01 2012 -0700
@@ -16,6 +16,7 @@
 {
 	this.names = null;
 	this.used = {};
+	this.nextmodulenum = 0;
 	var self = this;
 	if (typeof window === "object") {
 		get('/src/', function(data) {
@@ -36,7 +37,7 @@
 			var results = os.system("ls", [moduledirs[dirnum]]).split('\n');
 			for (var i in results) {
 				var tpidx = results[i].indexOf('.tp')
-				if (tpidx > -1) {
+				if (tpidx > 0 && tpidx == results[i].length - 3) {
 					this.names[results[i].substr(0, tpidx)] = new modulefile(moduledirs[dirnum], results[i]);
 				}
 			}
@@ -60,6 +61,18 @@
 topsymbols.prototype.getEnvType = function() {
 	return 'void';
 }
+topsymbols.prototype.moduleVar = function(name) {
+	if (!(name in this.names)) {
+		throw new Error('symbol ' + name + ' not found at toplevel');
+	}
+	if (name == 'true' || name == 'false') {
+		return 'module_' + name;
+	}
+	if (!this.names[name].modulevar) {
+		this.names[name].modulevar = 'module_' + this.nextmodulenum++
+	}
+	return this.names[name].modulevar;
+}
 
 function osymbols(parent)
 {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/false.tp	Sat Jul 14 16:14:01 2012 -0700
@@ -0,0 +1,6 @@
+#{
+	if:else <- :self trueblock :elseblock {
+		elseblock:
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/true.tp	Sat Jul 14 16:14:01 2012 -0700
@@ -0,0 +1,6 @@
+#{
+	if:else <- :self trueblock :elseblock {
+		trueblock:
+	}
+}
+
--- a/parser.js	Sat Jul 14 13:31:05 2012 -0700
+++ b/parser.js	Sat Jul 14 16:14:01 2012 -0700
@@ -82,7 +82,7 @@
 'float = digits:[0-9]+ "." decimals:[0-9]+ { return new floatlit(parseFloat(digits.join("") + "." + decimals.join(""))); };' +
 'binary = "0b" digits:[01]+ { return new intlit(parseInt(digits.join(""), 2)); };' +
 'hex = "0x" digits:[0-9a-fA-F]+ { return new intlit(parseInt(digits.join(""), 16)); };' +
-'int = digits:[0-9]+ { return new intlit(parseInt(digits.join(""), 10)); };' +
+'int = sign:"-"? digits:[0-9]+ { return new intlit(parseInt(sign + digits.join(""), 10)); };' +
 'string = "\\"" text:(strpart/escape)* "\\"" { return new strlit(text.join("")); };' +
 'strpart = text:[^\\"\\\\]+ { return text.join(""); };' + 
 'escape = "\\\\" char:[nt\\"r\\\\] { if (char == "n") { return "\\n"; } if (char == "r") { return "\\r"; } return char; };' +
--- a/samples/fib.tp	Sat Jul 14 13:31:05 2012 -0700
+++ b/samples/fib.tp	Sat Jul 14 16:14:01 2012 -0700
@@ -1,16 +1,4 @@
 #{
-true <- #{
-  if:else <- :self trueblock :elseblock {
-    trueblock:
-  }
-}
-
-false <- #{
-  if:else <- :self trueblock :elseblock {
-    elseblock:
-  }
-}
-
 fib <- :n {
   if: n < 2 {
     1
--- a/samples/iterfib.tp	Sat Jul 14 13:31:05 2012 -0700
+++ b/samples/iterfib.tp	Sat Jul 14 16:14:01 2012 -0700
@@ -1,15 +1,4 @@
 #{
-true <- #{
-  if:else <- :self trueblock :elseblock {
-    trueblock:
-  }
-}
-
-false <- #{
-  if:else <- :self trueblock :elseblock {
-    elseblock:
-  }
-}
 
 fib <- :n {
   last <- 0
--- a/samples/recursive_closure.tp	Sat Jul 14 13:31:05 2012 -0700
+++ b/samples/recursive_closure.tp	Sat Jul 14 16:14:01 2012 -0700
@@ -1,15 +1,4 @@
 #{
-	true <- #{
-	  if:else <- :self trueblock :elseblock {
-		trueblock:
-	  }
-	}
-
-	false <- #{
-	  if:else <- :self trueblock :elseblock {
-		elseblock:
-	  }
-	}
 	main <- {
 		foo <- :n {
 			if: n < 10 {
--- a/tpc.js	Sat Jul 14 13:31:05 2012 -0700
+++ b/tpc.js	Sat Jul 14 16:14:01 2012 -0700
@@ -49,12 +49,13 @@
 	print('usage: d8 tpc.js -- filename');
 	quit(1);
 }
-	
+includes.push(basedir + 'modules');
 compileFile(file, basedir, includes, debugmode);
 
 
 function parseFile(filename)
 {
+	debugprint('//parsing', filename);
 	var text = read(filename);
 	try {
 		var parsed = parser.parse(text);