Mercurial > repos > tabletprog
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); }