diff compiler.js @ 84:9811040704ac

Add support for llMessage:withVars:andCode and llProperty:withType for specifying low level code without having to stick C inside the compiler. Redo array built-in type to use this feature.
author Mike Pavone <pavone@retrodev.com>
date Sat, 21 Jul 2012 22:30:21 -0700
parents 8a9b96888b7d
children 926b65fe92b4
line wrap: on
line diff
--- a/compiler.js	Sat Jul 21 22:29:16 2012 -0700
+++ b/compiler.js	Sat Jul 21 22:30:21 2012 -0700
@@ -78,11 +78,12 @@
 {
 	this.parent = parent;
 	this.names = {};
+	this.llnames = {};
 	this.needsenv = false;
 	this.typename = null;
 	this.needsparent = false;
 }
-osymbols.prototype.find = function(name, nestedcall) {
+osymbols.prototype.find = function(name, nestedcall, allowll) {
 	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:') {
@@ -93,11 +94,18 @@
 		}
 		var ret = {
 			type: 'self',
+			isll: false,
 			def: this.names[name],
 			selftype: this.typename
 		};
+	} else if(allowll && name in this.llnames) {
+		return {
+			type: 'self',
+			isll: true,
+			selftype: this.typename
+		};
 	} else if(this.parent) {
-		var ret = this.parent.find(name, nestedcall);
+		var ret = this.parent.find(name, nestedcall, allowll);
 		if (ret) {
 			if(ret.type == 'self') {
 				ret.type = 'parent';
@@ -119,6 +127,9 @@
 osymbols.prototype.defineMsg = function(name, def) {
 	this.names[name] = def;
 }
+osymbols.prototype.defineLLProperty = function(name) {
+	this.llnames[name] = true;
+}
 osymbols.prototype.parentObject = function() {
 	if (!this.parent) {
 		return 'null';
@@ -160,7 +171,7 @@
 	this.envtype = 'void';
 	this.needsParentEnv = false;
 }
-lsymbols.prototype.find = function(name, nestedcall) {
+lsymbols.prototype.find = function(name, nestedcall, allowll) {
 	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:') {
@@ -187,7 +198,7 @@
 			}
 		}
 	} else if(this.parent) {
-		var ret = this.parent.find(name, true);
+		var ret = this.parent.find(name, true, allowll);
 		if (ret) {
 			if (ret.type == 'closedover') {
 				ret.type = 'upvar';
@@ -317,6 +328,31 @@
 		} else {
 			throw new Error("Unexpected AST type for foreign:");
 		}
+	} else if (this.name == 'llProperty:withType:') {
+		if (this.args[0] instanceof symbol) {
+			if ((this.args[1] instanceof symbol) || (this.args[1] instanceof funcall)) {
+				symbols.defineLLProperty(this.args[0].name);
+				return;
+			} else {
+				throw new Error("Second argument to llProperty:withType: must be a symbol or funcall");
+			}
+		} else {
+			throw new Error("First argument to llProperty:withType: must be a symbol");
+		}
+	} else if (this.name == 'llMessage:withVars:andCode:') {
+		if (this.args[0] instanceof symbol) {
+			if (this.args[1] instanceof lambda) {
+				if (this.args[2] instanceof lambda) {
+					symbols.defineMsg(this.args[0].name, this.args[2]);
+				} else {
+					throw new Error("Third argument to llMessage:withVars:andCode: must be a lambda");
+				}
+			} else {
+				throw new Error("Second argument to llMessage:withVars:andCode: must be a lambda");
+			}
+		} else {
+			throw new Error("First argument to llMessage:withVars:andCode: must be a symbol");
+		}
 	}
 	this.symbols = symbols;
 	var name = this.name[this.name.length-1] == ':' ? this.name.substr(0, this.name.length-1) : this.name;
@@ -333,11 +369,11 @@
 }
 
 funcall.prototype.populateSymbolsObject = function(symbols) {
-	this.populateSymbols(symbols.parent);
+	this.populateSymbols(symbols);
 }
 
 object.prototype.populateSymbols = function(symbols) {
-	symbols = new osymbols(symbols);
+	var symbols = new osymbols(symbols);
 	for (var i in this.messages) {
 		this.messages[i].populateSymbolsObject(symbols);
 	}