Mercurial > repos > tabletprog
diff jsbackend.js @ 8:04ae32e91598
Move compiler and test page related code out of parser.js
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Wed, 21 Mar 2012 20:33:39 -0700 |
parents | |
children | 37d7f60a8ea1 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jsbackend.js Wed Mar 21 20:33:39 2012 -0700 @@ -0,0 +1,175 @@ +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.toJS = function(symbols, isReceiver) { + var ret = '(' + this.left.toJS(symbols) +' '+ (this.op == '=' ? '==' : this.op) +' '+ this.right.toJS(symbols) + ')'; + if (isReceiver) { + ret = 'toobj' + ret; + } + return ret; +}; + +symbol.prototype.toJS = function(symbols) { + var name = this.cleanName(); + if (name == 'self') { + return symbols.selfVar(); + } + name = name.replace("_", "UN_").replace(":", "CN_").replace("!", "EX_").replace('?', 'QS_').replace('@', 'AT_'); + var reserved = {'true': true, 'false': true, 'this': true, 'if': true, 'else': true, 'NaN': true}; + if (name in reserved) { + name = 's' + name; + } + return name; +} + +intlit.prototype.toJS = function(symbols) { + return this.val.toString(); +} + +floatlit.prototype.toJS = function(symbols) { + return this.val.toString(); +} + +strlit.prototype.toJS = function(symbols) { + console.log('string:', this.val); + return '"' + this.val.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n').replace('\r', '\\r') + '"'; +} + +funcall.prototype.toJS = function(symbols) { + var name = this.name[this.name.length-1] == ':' ? this.name.substr(0, this.name.length-1) : this.name; + var args = this.args.slice(0, this.args.length); + if (this.receiver) { + args.splice(0, 0, this.receiver); + } + var funinfo = symbols.find(name); + if (!funinfo) { + var receiver = args[0]; + args.splice(0, 1); + for (var i in args) { + args[i] = args[i].toJS(symbols); + } + return receiver.toJS(symbols, true) + '.' + (new symbol(name)).toJS(symbols) + '(' + args.join(', ') + ')'; + } + switch(funinfo.type) + { + case 'self': + if (args.length < funinfo.def.args.length || funinfo.def.args[0].name != 'self') { + var receiver = new symbol('self'); + } else { + var receiver = args[0]; + args.splice(0, 1); + } + for (var i in args) { + args[i] = args[i].toJS(symbols); + } + return receiver.toJS(symbols, true) + '.' + (new symbol(name)).toJS(symbols) + '(' + args.join(', ') + ')'; + case 'parent': + var ret = 'this'; + for (var i = 0; i < funinfo.depth; ++i) { + ret += '.parent'; + } + for (var i in args) { + args[i] = args[i].toJS(symbols); + } + ret += (new symbol(name)).toJS(symbols) + '(' + args.join(', ') + ')'; + return ret; + case 'local': + case 'upvar': + case 'foreign': + for (var i in args) { + args[i] = args[i].toJS(symbols); + } + return (new symbol(name)).toJS(symbols) + '(' + args.join(', ') + ')'; + } +} + +object.prototype.toJS = function(symbols) { + var messages = this.messages; + symbols = new osymbols(symbols); + var compiled = [] + for (var i in messages) { + var js = messages[i].toJSObject(symbols); + if (js) { + compiled.push(indent(js)); + } + } + return '{\n\tparent: ' + symbols.parentObject() + ',\n\t' + compiled.join(',\n\t') + '\n}'; +} + +object.prototype.toJSModule = function() { + return '(function () {\n\tvar module = ' + indent(this.toJS(null)) + ';\n\treturn module;\n})' +} + +lambda.prototype.toJS = 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] = args[i].toJS(symbols); + } + var compiled = [] + for (var i in exprs) { + var js = exprs[i].toJS(symbols); + if (js) { + compiled.push(indent(js)); + } + } + exprs = compiled; + if (exprs.length) { + exprs[exprs.length-1] = 'return ' + exprs[exprs.length-1] + ';'; + } + return 'function (' + args.join(', ') + ') {\n\t' + (symbols.needsSelfVar ? 'var self = this;\n\t' : '') + exprs.join(';\n\t') + '\n}' +}; +lambda.prototype.toJSModule = lambda.prototype.toJS + +assignment.prototype.toJS = function(symbols) { + var existing = symbols.find(this.symbol.name); + var prefix = ''; + if (!existing) { + symbols.defineVar(this.symbol.name, this.expression); + prefix = 'var '; + } else { + switch (existing.type) + { + case 'self': + prefix = 'this.'; + break; + case 'parent': + prefix = 'this.'; + for (var i = 0; i < existing.depth; ++i) { + prefix += 'parent.'; + } + break; + } + } + if (this.expression instanceof funcall && this.expression.name == 'foreign:') { + return null; + } + return prefix + this.symbol.toJS(symbols) + ' = ' + this.expression.toJS(symbols); +}; +assignment.prototype.toJSObject = function(symbols) { + symbols.defineMsg(this.symbol.name, this.expression); + if (this.expression instanceof funcall && this.expression.name == 'foreign:') { + return null; + } + return this.symbol.toJS(symbols) + ': ' + this.expression.toJS(symbols); +};