Mercurial > repos > tabletprog
diff compiler.js @ 126:a2d2d8e09291
Merge
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Mon, 05 Aug 2013 23:37:17 -0700 |
parents | d715fb3c39ab |
children | d6e79885bd3b 18598163e3ef |
line wrap: on
line diff
--- a/compiler.js Mon Aug 05 23:36:18 2013 -0700 +++ b/compiler.js Mon Aug 05 23:37:17 2013 -0700 @@ -11,23 +11,57 @@ this.file = file; } +modulefile.prototype.populateSymbols = function (toplevel) { + if (!this.ast) { + this.ast = parseFile(this.path + '/' + this.file); + this.ast.populateSymbols(toplevel); + } +}; + +modulefile.prototype.popuplateSymbolsAsync = function(toplevel, whenDone) { + if (!this.ast) { + var self = this; + get(this.path + '/' + this.file, function(data) { + self.ast = parser.parse(data.responseText); + self.ast.populateSymbols(toplevel); + whenDone(); + }); + } else { + whenDone(); + } +}; + +function getfileshtml(path, data, names) +{ + var fakeEl = newEl("div", { + innerHTML: data.response + }); + each(qall('a', fakeEl), function(idx, a) { + var tpidx = a.textContent.indexOf('.tp'); + var modname = a.textContent.substr(0, tpidx); + if (tpidx > -1) { + names[modname] = new modulefile(path, modname + '.tp'); + } + }); +} + var toplevel = new topsymbols([]); function topsymbols(moduledirs) { this.names = null; this.used = {}; this.nextmodulenum = 0; + this.onready = null; var self = this; if (typeof window === "object") { - get('/src/', function(data) { - self.names = {}; - var fakeEl = newEl("div", { - innerHTML: data.response - }); - each(qall('a', fakeEl), function(idx, a) { - var tpidx = a.textContent.indexOf('.tp'); - if (tpidx > -1) { - self.names[a.textContent.substr(0, tpidx)] = true; + get('/modules/', function(data) { + var names = {} + getfileshtml('/modules', data, names); + get('/src/', function(data) { + getfileshtml('/src', data, names); + self.names = names; + if (self.onready) { + self.onready(); } }); }); @@ -57,10 +91,10 @@ }; } return null; -} +}; 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'); @@ -72,17 +106,33 @@ this.names[name].modulevar = 'module_' + this.nextmodulenum++ } return this.names[name].modulevar; -} +}; +topsymbols.prototype.onReady = function(fun) { + if (this.names) { + fun(); + return; + } + if (!this.onready) { + this.onready = fun; + } else { + var oldready = this.onready; + this.onready = function() { + oldready(); + fun(); + }; + } +}; function osymbols(parent) { 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 +143,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 +176,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 +220,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 +247,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'; @@ -262,22 +322,17 @@ function toobj(val) { - switch(typeof val) - { - case 'boolean': - if(val) { - return mainModule.strue; - } else { - return mainModule.sfalse; - } - case 'number': - return mainModule.snumber(val); - } - throw new Error("can't make val into object"); + return (typeof val == "boolean") ? (val ? module_true : module_false) : val; } op.prototype.populateSymbols = function(symbols, isReceiver) { this.left.populateSymbols(symbols); + if (this.op == '&&' || this.op == '||') { + //&& and || are syntactic sugar for if and ifnot with + //the second argument transformed into a lambda to + //achieve short-circuit evalutation + this.right = new lambda([], [this.right]); + } this.right.populateSymbols(symbols); }; @@ -311,12 +366,39 @@ } funcall.prototype.populateSymbols = function(symbols) { + var isll = false; if (this.name == 'foreign:') { if ((this.args[0] instanceof lambda) || (this.args[0] instanceof object) || (this.args[0] instanceof symbol)) { return; } 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]); + isll = true; + } 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; @@ -325,26 +407,29 @@ symbols.find('self'); } for (var i in this.args) { - this.args[i].populateSymbols(symbols); + this.args[i].populateSymbols(symbols, undefined, isll); } if (this.receiver) { - this.receiver.populateSymbols(symbols); + this.receiver.populateSymbols(symbols, undefined, isll); } } 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); } this.symbols = symbols; } - -lambda.prototype.populateSymbols = function(symbols, isobject) { +var lambdanum = 0; +lambda.prototype.populateSymbols = function(symbols, isobject, isll) { + if (!isll) { + this.name = 'lambda_' + lambdanum++; + } var args = this.args ? this.args.slice(0, this.args.length) : []; var exprs = this.expressions; var symbols = new lsymbols(symbols); @@ -394,3 +479,4 @@ this.fun = fun; } getter.prototype.args = [new symbol('self')]; +