Mercurial > repos > tabletprog
comparison jsbackend.js @ 95:926b65fe92b4
Do some cleanup on JS backend
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 24 Jul 2012 19:13:38 -0700 |
parents | 668f533e5284 |
children | 648659961e0e |
comparison
equal
deleted
inserted
replaced
90:b5152f5ac138 | 95:926b65fe92b4 |
---|---|
43 } | 43 } |
44 return obj; | 44 return obj; |
45 } | 45 } |
46 | 46 |
47 op.prototype.toJS = function(isReceiver) { | 47 op.prototype.toJS = function(isReceiver) { |
48 var ret = '(' + this.left.toJS() +' '+ (this.op == '=' ? '==' : this.op) +' '+ this.right.toJS() + ')'; | 48 var opmap = {'=': '==', '.': '+'}; |
49 if (isReceiver) { | 49 var ret = '(' + this.left.toJS() +' '+ (this.op in opmap ? opmap[this.op] : this.op) +' '+ this.right.toJS() + ')'; |
50 ret = 'toobj' + ret; | |
51 } | |
52 return ret; | 50 return ret; |
53 }; | 51 }; |
54 | 52 |
55 function escapeJSName(name) | 53 function escapeJSName(name) |
56 { | 54 { |
78 pre = 'this'; | 76 pre = 'this'; |
79 for (var i = 0; i < funinfo.depth; ++i) { | 77 for (var i = 0; i < funinfo.depth; ++i) { |
80 pre += '.parent'; | 78 pre += '.parent'; |
81 } | 79 } |
82 } else if (info.type == 'toplevel') { | 80 } else if (info.type == 'toplevel') { |
83 pre = 'modules.'; | 81 return toplevel.moduleVar(name); |
84 modules[name] = false; | |
85 } | 82 } |
86 return pre + escapeJSName(name); | 83 return pre + escapeJSName(name); |
87 } | 84 } |
88 | 85 |
89 intlit.prototype.toJS = function() { | 86 intlit.prototype.toJS = function() { |
120 var args = this.args.slice(0, this.args.length); | 117 var args = this.args.slice(0, this.args.length); |
121 if (this.receiver) { | 118 if (this.receiver) { |
122 args.splice(0, 0, this.receiver); | 119 args.splice(0, 0, this.receiver); |
123 } | 120 } |
124 var funinfo = this.symbols.find(name); | 121 var funinfo = this.symbols.find(name); |
125 if (!funinfo || funinfo.def instanceof setter) { | 122 if (!funinfo || funinfo.def instanceof setter || funinfo.type == 'toplevel') { |
126 var receiver = args[0]; | 123 var receiver = args[0]; |
127 args.splice(0, 1); | 124 args.splice(0, 1); |
128 for (var i in args) { | 125 for (var i in args) { |
129 args[i] = args[i].toJS(); | 126 args[i] = args[i].toJS(); |
130 } | 127 } |
131 var rJS = receiver.toJS(true); | 128 var rJS = (funinfo ? '' : 'toobj(') + receiver.toJS(true) + (funinfo ? '' : ')') ; |
132 if ((name[name.length-1] == '!' && args.length == 1) || (funinfo && funinfo.def instanceof setter)) { | 129 if ((name[name.length-1] == '!' && args.length == 1) || (funinfo && funinfo.def instanceof setter)) { |
133 return '(' + rJS + '.' + escapeJSName(name.substr(0, name.length-1)) + ' = ' + args[0] + ', ' + rJS + ')'; | 130 return '(' + rJS + '.' + escapeJSName(name.substr(0, name.length-1)) + ' = ' + args[0] + ', ' + rJS + ')'; |
134 } else { | 131 } else { |
135 var callee = rJS + '.' + escapeJSName(name); | 132 var callee = rJS + '.' + escapeJSName(name); |
136 var callCode = callee + '(' + args.join(', ') + ')'; | |
137 if (args.length == 0) { | 133 if (args.length == 0) { |
138 return '(' + callee + ' instanceof Function ? ' + callCode + ' : ' + callee + ')'; | 134 return callee; |
139 } else { | 135 } else { |
140 return callCode; | 136 return callee + '(' + args.join(', ') + ')'; |
141 } | 137 } |
142 } | 138 } |
143 } | 139 } |
144 var ret = ''; | 140 var ret = ''; |
145 switch(funinfo.type) | 141 switch(funinfo.type) |
212 return pre+'{\n\tparent: ' + this.symbols.parentObject() + ',\n\t' + compiled.join(',\n\t') + '\n}'+post; | 208 return pre+'{\n\tparent: ' + this.symbols.parentObject() + ',\n\t' + compiled.join(',\n\t') + '\n}'+post; |
213 } | 209 } |
214 | 210 |
215 object.prototype.toJSModule = function() { | 211 object.prototype.toJSModule = function() { |
216 this.populateSymbols(toplevel); | 212 this.populateSymbols(toplevel); |
217 return '(function () {\n\tvar module = ' + indent(this.toJS()) + ';\n\treturn module;\n})' | 213 return '(function () {\n\tvar module = ' + indent(this.toJS()) + ';\n\treturn module;\n})();' |
218 } | 214 } |
219 | 215 |
220 lambda.prototype.toJS = function() { | 216 lambda.prototype.toJS = function() { |
221 var args = this.args ? this.args.slice(0, this.args.length) : []; | 217 var args = this.args ? this.args.slice(0, this.args.length) : []; |
222 if (args.length && args[0].cleanName() == 'self') { | 218 if (args.length && args[0].cleanName() == 'self') { |
237 if (exprs.length) { | 233 if (exprs.length) { |
238 exprs[exprs.length-1] = 'return ' + exprs[exprs.length-1] + ';'; | 234 exprs[exprs.length-1] = 'return ' + exprs[exprs.length-1] + ';'; |
239 } | 235 } |
240 return 'function (' + args.join(', ') + ') {\n\t' + (this.symbols.needsSelfVar ? 'var self = this;\n\t' : '') + exprs.join(';\n\t') + '\n}' | 236 return 'function (' + args.join(', ') + ') {\n\t' + (this.symbols.needsSelfVar ? 'var self = this;\n\t' : '') + exprs.join(';\n\t') + '\n}' |
241 }; | 237 }; |
238 lambda.prototype.nonSelfArgs = function() { | |
239 var args = this.args ? this.args.slice(0, this.args.length) : []; | |
240 if (args.length && args[0].cleanName() == 'self') { | |
241 args.splice(0, 1); | |
242 } | |
243 return args; | |
244 }; | |
242 lambda.prototype.toJSModule = function() { | 245 lambda.prototype.toJSModule = function() { |
243 this.populateSymbols(toplevel); | 246 this.populateSymbols(toplevel); |
244 return this.toJS(); | 247 return this.toJS() + '();'; |
248 } | |
249 | |
250 modulefile.prototype.toJSModule = function(){ | |
251 return this.ast.toJSModule(); | |
252 }; | |
253 | |
254 function processUsedToplevelJS(toplevel) | |
255 { | |
256 var alwaysused = ['true', 'false']; | |
257 var ret = ''; | |
258 var modulenum = 0; | |
259 var visited = {}; | |
260 for (var i in alwaysused) { | |
261 toplevel.used[alwaysused[i]] = true; | |
262 } | |
263 var newused = Object.keys(toplevel.used); | |
264 var allused = newused; | |
265 while (newused.length) { | |
266 for (var i in newused) { | |
267 toplevel.names[newused[i]].populateSymbols(toplevel); | |
268 visited[newused[i]] = true; | |
269 } | |
270 newused = []; | |
271 for (var symbol in toplevel.used) { | |
272 if (!(symbol in visited)) { | |
273 newused.push(symbol); | |
274 allused.push(symbol); | |
275 } | |
276 } | |
277 } | |
278 | |
279 for (var i = allused.length-1; i >= 0; i--) { | |
280 var symbol = allused[i]; | |
281 ret += 'var ' + toplevel.moduleVar(symbol) + ' = ' + toplevel.names[symbol].toJSModule() + '\n'; | |
282 } | |
283 return ret; | |
284 } | |
285 | |
286 function makeJSProg(mainmodule) | |
287 { | |
288 return processUsedToplevelJS(toplevel) + 'main_module = ' + mainmodule.toJSModule() + '\n' + | |
289 'Number.prototype.__defineGetter__("string", function() { return "" + this; });\n' + | |
290 'String.prototype.__defineGetter__("string", function() { return this; });\n' + | |
291 'String.prototype.__defineGetter__("print", function() { write(this); });\n' + | |
292 'Array.prototype.foreach = function(action) { var ret = module_false; for (var i = 0; i < this.length; i++) { ret = action(i, this[i]) }; return ret; };\n' + | |
293 'Function.prototype.whileCN_do = function(action) { var ret = module_false; while(toobj(this()) == module_true) { ret = action(); } return ret; };\n' + | |
294 'function toobj(val) {\n' + | |
295 ' return (typeof val == "boolean") ? (val ? module_true : module_false) : val;\n' + | |
296 '}\n' + | |
297 'var m = main_module.main;\n' + | |
298 'if (m instanceof Function) {\n' + | |
299 ' m(arguments);\n' + | |
300 '}\n'; | |
245 } | 301 } |
246 | 302 |
247 assignment.prototype.toJS = function() { | 303 assignment.prototype.toJS = function() { |
248 var existing = this.symbols.find(this.symbol.name); | 304 var existing = this.symbols.find(this.symbol.name); |
249 var prefix = ''; | 305 var prefix = ''; |
267 if (val === null) { | 323 if (val === null) { |
268 return null; | 324 return null; |
269 } | 325 } |
270 return prefix + this.symbol.toJS() + ' = ' + val; | 326 return prefix + this.symbol.toJS() + ' = ' + val; |
271 }; | 327 }; |
328 function removeInitialFunction(str) | |
329 { | |
330 var f = 'function'; | |
331 str = str.trim(); | |
332 if (str.substr(0, f.length) == f) { | |
333 return str.substr(f.length); | |
334 } | |
335 return str; | |
336 } | |
272 assignment.prototype.toJSObject = function() { | 337 assignment.prototype.toJSObject = function() { |
273 var val = this.expression.toJS(); | 338 var val = this.expression.toJS(); |
274 if (val === null) { | 339 if (val === null) { |
275 return null; | 340 return null; |
276 } | 341 } |
342 if (this.expression instanceof lambda) { | |
343 var args = this.expression.nonSelfArgs(); | |
344 if (args.length == 0) { | |
345 return 'get ' + escapeJSName(this.symbol.name) + removeInitialFunction(val); | |
346 } else if(args.length == 1 && this.symbol.name[this.symbol.name.length-1] == '!') { | |
347 return 'set ' + escapeJSName(this.symbol.name.substr(0, this.symbol.name.length-1)) + removeInitialFunction(val); | |
348 } | |
349 } | |
277 return escapeJSName(this.symbol.name) + ': ' + val; | 350 return escapeJSName(this.symbol.name) + ': ' + val; |
278 }; | 351 }; |