Mercurial > repos > tabletprog
diff jsbackend.js @ 126:a2d2d8e09291
Merge
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Mon, 05 Aug 2013 23:37:17 -0700 |
parents | a83989115028 |
children |
line wrap: on
line diff
--- a/jsbackend.js Mon Aug 05 23:36:18 2013 -0700 +++ b/jsbackend.js Mon Aug 05 23:37:17 2013 -0700 @@ -3,18 +3,7 @@ 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; } function importSym(obj, src, key) @@ -45,9 +34,13 @@ } op.prototype.toJS = function(isReceiver) { - var ret = '(' + this.left.toJS() +' '+ (this.op == '=' ? '==' : this.op) +' '+ this.right.toJS() + ')'; - if (isReceiver) { - ret = 'toobj' + ret; + if (this.op == '&&') { + var ret = 'toobj(' + this.left.toJS() + ').sif(' + this.right.toJS() + ')'; + } else if(this.op == '||') { + var ret = 'toobj(' + this.left.toJS() + ').ifnot(' + this.right.toJS() + ')'; + } else { + var opmap = {'=': '==', '.': '+'}; + var ret = '(' + this.left.toJS() +' '+ (this.op in opmap ? opmap[this.op] : this.op) +' '+ this.right.toJS() + ')'; } return ret; }; @@ -80,8 +73,7 @@ pre += '.parent'; } } else if (info.type == 'toplevel') { - pre = 'modules.'; - modules[name] = false; + return toplevel.moduleVar(name); } return pre + escapeJSName(name); } @@ -122,22 +114,21 @@ args.splice(0, 0, this.receiver); } var funinfo = this.symbols.find(name); - if (!funinfo || funinfo.def instanceof setter) { + if (!funinfo || funinfo.def instanceof setter || funinfo.type == 'toplevel') { var receiver = args[0]; args.splice(0, 1); for (var i in args) { args[i] = args[i].toJS(); } - var rJS = receiver.toJS(true); + var rJS = (funinfo ? '' : 'toobj(') + receiver.toJS(true) + (funinfo ? '' : ')') ; if ((name[name.length-1] == '!' && args.length == 1) || (funinfo && funinfo.def instanceof setter)) { return '(' + rJS + '.' + escapeJSName(name.substr(0, name.length-1)) + ' = ' + args[0] + ', ' + rJS + ')'; } else { var callee = rJS + '.' + escapeJSName(name); - var callCode = callee + '(' + args.join(', ') + ')'; if (args.length == 0) { - return '(' + callee + ' instanceof Function ? ' + callCode + ' : ' + callee + ')'; + return callee; } else { - return callCode; + return callee + '(' + args.join(', ') + ')'; } } } @@ -145,7 +136,7 @@ switch(funinfo.type) { case 'self': - if (args.length < funinfo.def.args.length || funinfo.def.args[0].name != 'self') { + if (args.length < funinfo.def.args.length || funinfo.def.args.length == 0 || funinfo.def.args[0].name != 'self') { var receiver = new symbol('self', this.symbols); } else { var receiver = args[0]; @@ -160,7 +151,8 @@ ret = receiver.toJS(true) + '.'; break; case 'parent': - ret = 'this'; + var receiver = new symbol('self', this.symbols); + ret = receiver.toJS(true); for (var i = 0; i < funinfo.depth; ++i) { ret += '.parent'; } @@ -214,7 +206,7 @@ object.prototype.toJSModule = function() { this.populateSymbols(toplevel); - return '(function () {\n\tvar module = ' + indent(this.toJS()) + ';\n\treturn module;\n})' + return '(function () {\n\tvar module = ' + indent(this.toJS()) + ';\n\treturn module;\n})();' } lambda.prototype.toJS = function() { @@ -239,40 +231,162 @@ } return 'function (' + args.join(', ') + ') {\n\t' + (this.symbols.needsSelfVar ? 'var self = this;\n\t' : '') + exprs.join(';\n\t') + '\n}' }; +lambda.prototype.nonSelfArgs = function() { + var args = this.args ? this.args.slice(0, this.args.length) : []; + if (args.length && args[0].cleanName() == 'self') { + args.splice(0, 1); + } + return args; +}; lambda.prototype.toJSModule = function() { this.populateSymbols(toplevel); - return this.toJS(); + return this.toJS() + '();'; +} + +modulefile.prototype.toJSModule = function(){ + return this.ast.toJSModule(); +}; + +function processUsedToplevelJS(toplevel) +{ + var alwaysused = ['true', 'false']; + var ret = ''; + var modulenum = 0; + var visited = {}; + for (var i = 0; i < alwaysused.length; i++) { + toplevel.used[alwaysused[i]] = true; + } + var newused = Object.keys(toplevel.used); + var allused = newused; + while (newused.length) { + for (var i = 0; i < newused.length; i++) { + console.log(i, newused[i]); + toplevel.names[newused[i]].populateSymbols(toplevel); + visited[newused[i]] = true; + } + newused = []; + for (var symbol in toplevel.used) { + if (!(symbol in visited)) { + newused.push(symbol); + allused.push(symbol); + } + } + } + + for (var i = allused.length-1; i >= 0; i--) { + var symbol = allused[i]; + ret += 'var ' + toplevel.moduleVar(symbol) + ' = ' + toplevel.names[symbol].toJSModule() + '\n'; + } + return ret; +} + +function asyncProcessTopLevelJS(toplevel, whenDone) +{ + var alwaysused = ['true', 'false']; + var ret = ''; + var modulenum = 0; + var visited = {}; + for (var i = 0; i < alwaysused.length; i++) { + toplevel.used[alwaysused[i]] = true; + } + var newused = Object.keys(toplevel.used); + var allused = newused; + var i = -1; + var handler = function() { + i++; + while(newused.length) + { + if (i < newused.length) { + visited[newused[i]] = true; + toplevel.names[newused[i]].popuplateSymbolsAsync(toplevel, handler); + return; + } else { + newused = []; + for (var symbol in toplevel.used) { + if (!(symbol in visited)) { + newused.push(symbol); + allused.push(symbol); + } + } + i = 0; + } + } + whenDone(); + }; + handler(); +} + +function makeJSProg(mainmodule) +{ + return processUsedToplevelJS(toplevel) + 'main_module = ' + mainmodule.toJSModule() + '\n' + + 'Number.prototype.__defineGetter__("string", function() { return "" + this; });\n' + + 'String.prototype.__defineGetter__("string", function() { return this; });\n' + + 'String.prototype.__defineGetter__("print", function() { write(this); });\n' + + 'Object.defineProperty(Array.prototype, "foreach", {value: function(action) { var ret = module_false; for (var i = 0; i < this.length; i++) { ret = action(i, this[i]) }; return ret; }});\n' + + 'Function.prototype.whileCN_do = function(action) { var ret = module_false; while(toobj(this()) == module_true) { ret = action(); } return ret; };\n' + + 'module_true.valueOf = function() { return true; }\n' + + 'module_false.valueOf = function() { return false; }\n' + + 'function toobj(val) {\n' + + ' return (typeof val == "boolean") ? (val ? module_true : module_false) : val;\n' + + '}\n' + + 'var m = main_module.main;\n' + + 'if (m instanceof Function) {\n' + + ' m(arguments);\n' + + '}\n'; } assignment.prototype.toJS = function() { var existing = this.symbols.find(this.symbol.name); var prefix = ''; - if (!existing) { + /*if (!existing) { prefix = 'var '; } else { switch (existing.type) { case 'self': - prefix = 'this.'; + var self = new symbol('self', this.symbols); + prefix = self.toJS() + '.'; break; case 'parent': - prefix = 'this.'; + var self = new symbol('self', this.symbols); + prefix = self.toJS() + '.'; for (var i = 0; i < existing.depth; ++i) { prefix += 'parent.'; } break; } - } + }*/ var val = this.expression.toJS(); if (val === null) { return null; } + if ((existing.type == 'local' || existing.type == 'closedover') && !existing.isdeclared) { + prefix = 'var '; + this.symbols.declareVar(this.symbol.name); + } return prefix + this.symbol.toJS() + ' = ' + val; }; +function removeInitialFunction(str) +{ + var f = 'function'; + str = str.trim(); + if (str.substr(0, f.length) == f) { + return str.substr(f.length); + } + return str; +} assignment.prototype.toJSObject = function() { var val = this.expression.toJS(); if (val === null) { return null; } + if (this.expression instanceof lambda) { + var args = this.expression.nonSelfArgs(); + if (args.length == 0) { + return 'get ' + escapeJSName(this.symbol.name) + removeInitialFunction(val); + } else if(args.length == 1 && this.symbol.name[this.symbol.name.length-1] == '!') { + return 'set ' + escapeJSName(this.symbol.name.substr(0, this.symbol.name.length-1)) + removeInitialFunction(val); + } + } return escapeJSName(this.symbol.name) + ': ' + val; };