Mercurial > repos > tabletprog
view compiler.js @ 293:2b045d5b673b
Add binding for sdl mouse motion event
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 24 Jul 2014 09:43:18 -0700 |
parents | 0dc7322590da |
children | d4df33596e7d |
line wrap: on
line source
var debugprint = function() {}; function indent(str) { return str.split('\n').join('\n\t'); } function modulefile(path, file) { this.path = path; this.file = file; } modulefile.prototype.populateSymbols = function (toplevel) { if (!this.ast) { this.ast = parseFile(this.path + '/' + this.file).macroexpand(toplevel.topenv); this.ast.populateSymbols(toplevel); } }; modulefile.prototype.popuplateSymbolsAsync = function(toplevel, whenDone) { if (!this.ast) { var self = this; get(this.path + '/' + this.file, function(data) { //TODO: macro expand in the async case 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 = null;//new topsymbols([]); function topsymbols(moduledirs, top) { if (!top) { top = new topenv(moduledirs); } this.topenv = top; this.moduledirs = moduledirs; this.names = null; this.used = {}; this.nextmodulenum = 0; this.onready = null; var self = this; if (typeof window === "object") { 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(); } }); }); } else { this.names = {}; for (var dirnum in moduledirs) { var results = os.system("ls", [moduledirs[dirnum]]).split('\n'); for (var i in results) { var tpidx = results[i].indexOf('.tp') if (tpidx > 0 && tpidx == results[i].length - 3) { this.names[results[i].substr(0, tpidx)] = new modulefile(moduledirs[dirnum], results[i]); } } } } } topsymbols.prototype.find = function(name) { debugprint('//topsymbols.find', name, name in this.names); if (!this.names) { throw new Error('data not ready'); } if (name in this.names) { this.used[name] = true; return { type: 'toplevel', def: this.names[name] }; } 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'); } if (name == 'true' || name == 'false' || name == 'list') { return 'module_' + name; } if (!this.names[name].modulevar) { 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, 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:') { return { type: 'foreign', def: this.names[name] }; } 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, allowll); if (ret) { if(ret.type == 'self') { ret.type = 'parent'; ret.depth = 1; this.needsparent = true; } else if(ret.type == 'parent') { this.needsparent = true; ret.depth++; } else if(ret.type == 'closedover' || ret.type == 'upvar') { this.needsenv = true; } } } else { return null; } debugprint('\t//symbol type:', ret ? ret.type : 'null'); return ret; }; 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'; } 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'; this.needsParentEnv = false; } 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:') { var ret = { type: 'foreign', def: this.names[name] }; } else { if (nestedcall && !(name in this.closedover)) { debugprint('//symbol', name, 'is now closed over'); this.closedover[name] = true; this.passthruenv = false; } if (name in this.closedover) { var ret = { type: 'closedover', def: this.names[name] }; } else { var ret = { type: 'local', def: this.names[name], isdeclared: (name in this.declared) }; } } } else if(this.parent) { var ret = this.parent.find(name, true, allowll); if (ret) { if (ret.type == 'closedover') { ret.type = 'upvar'; ret.depth = 0; } if (ret.type == 'upvar') { if (Object.keys(this.closedover).length) { ret.depth++; ret.startdepth = 1; this.needsParentEnv = true; } else { this.passthruenv = true; ret.startdepth = 0; /*if (ret.depth == 0) { ret.depth = 1; }*/ } } } } else { return null; } var type = ret ? ret.type : 'null'; debugprint('\t//symbol type:', type , type == 'upvar' ? 'depth: ' + ret.depth : ''); return ret; }; 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) { 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); }; symbol.prototype.populateSymbols = function(symbols) { this.symbols = symbols; var ret = symbols.find(this.cleanName()); if (ret && (ret.type == 'self' || ret.type == 'parent')) { symbols.find('self'); } } 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) { 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 == 'import:from:' && symbols instanceof osymbols && this.args.length == 2) { each(this.args[0].val, function(i, el) { if (!(el instanceof symbol)) { throw new Error('Names in import:from statement must be symbols'); } symbols.defineMsg(el.name, new lambda([], [])); }); } 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] instanceof symbol ? this.args[0].name : this.args[0].val); 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 or string"); } } else if (this.name == 'llMessage:withVars:andCode:' && symbols instanceof osymbols) { if (this.args[0] instanceof symbol || this.args[0] instanceof strlit) { 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; var funinfo = symbols.find(name); if (funinfo && (funinfo.type == 'self' || funinfo.type == 'parent')) { symbols.find('self'); } for (var i in this.args) { this.args[i].populateSymbols(symbols, undefined, isll); } if (this.receiver) { this.receiver.populateSymbols(symbols, undefined, isll); } } funcall.prototype.defineSymbolsObject = function(symbols) { } funcall.prototype.populateSymbolsObject = function(symbols) { this.populateSymbols(symbols); } object.prototype.populateSymbols = function(symbols) { var symbols = new osymbols(symbols); for (var i in this.messages) { this.messages[i].defineSymbolsObject(symbols); } for (var i in this.messages) { this.messages[i].populateSymbolsObject(symbols); } this.symbols = symbols; } 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); for (var i in args) { symbols.defineVar(args[i].cleanName(), null); args[i].populateSymbols(symbols); } if (isobject && (!args.length || args[0].cleanName() != 'self')) { symbols.defineVar('self', null); } for (var i in exprs) { exprs[i].populateSymbols(symbols); } this.symbols = symbols; }; assignment.prototype.populateSymbols = function(symbols) { debugprint('//assignment', this.symbol.name, 'populateSymbols'); var existing = symbols.find(this.symbol.name); if (!existing || existing.type == 'toplevel') { symbols.defineVar(this.symbol.name, this.expression); } this.symbol.populateSymbols(symbols); this.expression.populateSymbols(symbols); this.symbols = symbols; }; assignment.prototype.defineSymbolsObject = function(symbols) { debugprint('//messagedef', this.symbol.name, 'populateSymbols'); 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)); } }; assignment.prototype.populateSymbolsObject = function(symbols) { this.symbol.populateSymbols(symbols); this.expression.populateSymbols(symbols, true); 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')];