Mercurial > repos > tabletprog
view compiler.js @ 42:4e983fe32047
Fix closures as methods so that private vars work
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 12 Jul 2012 20:14:15 -0700 |
parents | e7be612fd3ae |
children | 18ab96287c3a |
line wrap: on
line source
function indent(str) { return str.split('\n').join('\n\t'); } var toplevel = new topsymbols(); function topsymbols() { this.names = 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; } }); }); } else { this.names = {}; } } topsymbols.prototype.find = function(name) { if (!this.names) { throw new Error('data not ready'); } if (name in this.names) { return { type: 'toplevel', def: null }; } return null; } topsymbols.prototype.getEnvType = function() { return 'void'; } function osymbols(parent) { this.parent = parent; this.names = {}; this.needsenv = false; } osymbols.prototype.find = function(name, nestedcall) { if (name in this.names) { if (this.names[name] instanceof funcall && this.names[name].name == 'foreign:') { return { type: 'foreign', def: this.names[name] }; } return { type: 'self', def: this.names[name], }; } else if(this.parent) { var ret = this.parent.find(name, nestedcall); if (ret) { if(ret.type == 'self') { ret.type = 'parent'; ret.depth = 1; } else if(ret.type == 'parent') { ret.depth++; } else if(ret.type == 'closedover' || ret.type == 'upvar') { this.needsenv = true; } } return ret; } return null; }; osymbols.prototype.defineMsg = function(name, def) { this.names[name] = def; } osymbols.prototype.parentObject = function() { if (!this.parent) { return 'null'; } return 'this'; } osymbols.prototype.allSymbols = function(curlist, cursyms) { if (curlist === undefined) { curlist = []; cursyms = {}; } var keys = Object.keys(this.names).sort(); for (var i in keys) { if (!(keys[i] in cursyms)) { curlist.push(keys[i]); cursyms[keys[i]] = true; } } if (this.parent) { return this.parent.allSymbols(curlist, cursyms); } return curlist; } osymbols.prototype.getEnvType = function() { return this.parent.getEnvType(); } osymbols.prototype.envVar = function() { return this.parent.envVar(); } function lsymbols(parent) { this.parent = parent; this.names = {}; this.closedover = {}; this.declared = {}; this.needsSelfVar = false; this.passthruenv = false; this.envtype = 'void'; } lsymbols.prototype.find = function(name, nestedcall) { if (name in this.names) { if (this.names[name] instanceof funcall && this.names[name].name == 'foreign:') { return { type: 'foreign', def: this.names[name] }; } 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) { if (ret.type == 'closedover') { ret.type = 'upvar'; ret.depth = 1; } else if (ret.type == 'upvar') { if (Object(this.closedover).keys.length) { ret.depth++; } else { this.passthruenv = true; } } } return ret; } return null; }; lsymbols.prototype.defineVar = function(name, def) { this.names[name] = def; }; lsymbols.prototype.declareVar = function(name) { this.declared[name] = true; } lsymbols.prototype.selfVar = function() { if (this.parent && this.parent instanceof lsymbols) { this.parent.needsSelf(); return 'self'; } else { return 'this'; } }; lsymbols.prototype.needsSelf = function() { if (this.parent && this.parent instanceof lsymbols) { this.parent.needsSelf(); } else { this.needsSelfVar = true; } }; lsymbols.prototype.allSymbols = osymbols.prototype.allSymbols; lsymbols.prototype.parentEnvType = function() { if (!this.parent) { return 'void'; } return this.parent.getEnvType(); }; lsymbols.prototype.getEnvType = function() { if (this.passthruenv) { return this.parent.getEnvType(); } else { return this.envtype; } } lsymbols.prototype.envVar = function() { if (Object.keys(this.closedover).length) { return 'myenv'; } else if(this.passthruenv) { return 'env'; } return null; } var mainModule; 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"); } op.prototype.populateSymbols = function(symbols, isReceiver) { this.left.populateSymbols(symbols); this.right.populateSymbols(symbols); }; symbol.prototype.populateSymbols = function(symbols) { this.symbols = symbols; symbols.find(this.cleanName()); } intlit.prototype.populateSymbols = function(symbols) { } floatlit.prototype.populateSymbols = function(symbols) { } strlit.prototype.populateSymbols = function(symbols) { } listlit.prototype.populateSymbols = function(symbols) { for (var i = 0; i < this.val.length; i++) { this.val[i].populateSymbols(symbols); } } arraylit.prototype.populateSymbols = function(symbols) { for (var i = 0; i < this.val.length; i++) { this.val[i].populateSymbols(symbols); } } funcall.prototype.populateSymbols = function(symbols) { 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:"); } } this.symbols = symbols; for (var i in this.args) { this.args[i].populateSymbols(symbols); } if (this.receiver) { this.receiver.populateSymbols(symbols); } } funcall.prototype.populateSymbolsObject = function(symbols) { this.populateSymbols(symbols.parent); } object.prototype.populateSymbols = function(symbols) { symbols = new osymbols(symbols); for (var i in this.messages) { this.messages[i].populateSymbolsObject(symbols); } this.symbols = symbols; } lambda.prototype.populateSymbols = function(symbols) { 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); for (var i in args) { symbols.defineVar(args[i].cleanName(), null); args[i].populateSymbols(symbols); } for (var i in exprs) { exprs[i].populateSymbols(symbols); } this.symbols = symbols; }; assignment.prototype.populateSymbols = function(symbols) { var existing = symbols.find(this.symbol.name); if (!existing) { symbols.defineVar(this.symbol.name, this.expression); } this.symbol.populateSymbols(symbols); this.expression.populateSymbols(symbols); this.symbols = symbols; }; assignment.prototype.populateSymbolsObject = function(symbols) { if (this.expression instanceof lambda || (this.expression instanceof funcall & this.expression.name == 'foreign:')) { symbols.defineMsg(this.symbol.name, this.expression); } else { symbols.defineMsg(this.symbol.name, new getter(null)); symbols.defineMsg(this.symbol.name + '!', new setter(null)); } this.symbol.populateSymbols(symbols); this.expression.populateSymbols(symbols); this.symbols = symbols; }; function setter(fun) { this.fun = fun; } setter.prototype.args = [new symbol('self'), new symbol('newval')]; function getter(fun) { this.fun = fun; } getter.prototype.args = [new symbol('self')];