pavone@8: var mainModule; pavone@8: pavone@8: function toobj(val) pavone@8: { pavone@8: switch(typeof val) pavone@8: { pavone@8: case 'boolean': pavone@8: if(val) { pavone@8: return mainModule.strue; pavone@8: } else { pavone@8: return mainModule.sfalse; pavone@8: } pavone@8: case 'number': pavone@8: return mainModule.snumber(val); pavone@8: } pavone@8: throw new Error("can't make val into object"); pavone@8: } pavone@8: pavone@10: function setP(o, p, val) pavone@10: { pavone@10: o[p] = val; pavone@10: return o; pavone@10: } pavone@10: pavone@10: function getP(o, p) pavone@10: { pavone@10: return o[p]; pavone@10: } pavone@10: pavone@8: op.prototype.toJS = function(symbols, isReceiver) { pavone@8: var ret = '(' + this.left.toJS(symbols) +' '+ (this.op == '=' ? '==' : this.op) +' '+ this.right.toJS(symbols) + ')'; pavone@8: if (isReceiver) { pavone@8: ret = 'toobj' + ret; pavone@8: } pavone@8: return ret; pavone@8: }; pavone@8: pavone@8: symbol.prototype.toJS = function(symbols) { pavone@8: var name = this.cleanName(); pavone@8: if (name == 'self') { pavone@8: return symbols.selfVar(); pavone@8: } pavone@8: name = name.replace("_", "UN_").replace(":", "CN_").replace("!", "EX_").replace('?', 'QS_').replace('@', 'AT_'); pavone@8: var reserved = {'true': true, 'false': true, 'this': true, 'if': true, 'else': true, 'NaN': true}; pavone@8: if (name in reserved) { pavone@8: name = 's' + name; pavone@8: } pavone@8: return name; pavone@8: } pavone@8: pavone@8: intlit.prototype.toJS = function(symbols) { pavone@8: return this.val.toString(); pavone@8: } pavone@8: pavone@8: floatlit.prototype.toJS = function(symbols) { pavone@8: return this.val.toString(); pavone@8: } pavone@8: pavone@8: strlit.prototype.toJS = function(symbols) { pavone@8: return '"' + this.val.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n').replace('\r', '\\r') + '"'; pavone@8: } pavone@8: pavone@8: funcall.prototype.toJS = function(symbols) { pavone@8: var name = this.name[this.name.length-1] == ':' ? this.name.substr(0, this.name.length-1) : this.name; pavone@12: if (name == 'foreign') { pavone@12: if ((this.args[0] instanceof lambda) || (this.args[0] instanceof object)) { pavone@12: return null; pavone@12: } else if(this.args[0] instanceof symbol) { pavone@12: return this.args[0].name; pavone@12: } else { pavone@12: throw new Error("Unexpected AST type for foreign:"); pavone@12: } pavone@12: } pavone@8: var args = this.args.slice(0, this.args.length); pavone@8: if (this.receiver) { pavone@8: args.splice(0, 0, this.receiver); pavone@8: } pavone@8: var funinfo = symbols.find(name); pavone@8: if (!funinfo) { pavone@8: var receiver = args[0]; pavone@8: args.splice(0, 1); pavone@8: for (var i in args) { pavone@8: args[i] = args[i].toJS(symbols); pavone@8: } pavone@8: return receiver.toJS(symbols, true) + '.' + (new symbol(name)).toJS(symbols) + '(' + args.join(', ') + ')'; pavone@8: } pavone@8: switch(funinfo.type) pavone@8: { pavone@8: case 'self': pavone@8: if (args.length < funinfo.def.args.length || funinfo.def.args[0].name != 'self') { pavone@8: var receiver = new symbol('self'); pavone@8: } else { pavone@8: var receiver = args[0]; pavone@8: args.splice(0, 1); pavone@8: } pavone@8: for (var i in args) { pavone@8: args[i] = args[i].toJS(symbols); pavone@8: } pavone@8: return receiver.toJS(symbols, true) + '.' + (new symbol(name)).toJS(symbols) + '(' + args.join(', ') + ')'; pavone@8: case 'parent': pavone@8: var ret = 'this'; pavone@8: for (var i = 0; i < funinfo.depth; ++i) { pavone@8: ret += '.parent'; pavone@8: } pavone@8: for (var i in args) { pavone@8: args[i] = args[i].toJS(symbols); pavone@8: } pavone@8: ret += (new symbol(name)).toJS(symbols) + '(' + args.join(', ') + ')'; pavone@8: return ret; pavone@8: case 'local': pavone@8: case 'upvar': pavone@8: case 'foreign': pavone@8: for (var i in args) { pavone@8: args[i] = args[i].toJS(symbols); pavone@8: } pavone@8: return (new symbol(name)).toJS(symbols) + '(' + args.join(', ') + ')'; pavone@8: } pavone@8: } pavone@8: pavone@8: object.prototype.toJS = function(symbols) { pavone@8: var messages = this.messages; pavone@8: symbols = new osymbols(symbols); pavone@8: var compiled = [] pavone@8: for (var i in messages) { pavone@8: var js = messages[i].toJSObject(symbols); pavone@8: if (js) { pavone@8: compiled.push(indent(js)); pavone@8: } pavone@8: } pavone@8: return '{\n\tparent: ' + symbols.parentObject() + ',\n\t' + compiled.join(',\n\t') + '\n}'; pavone@8: } pavone@8: pavone@8: object.prototype.toJSModule = function() { pavone@8: return '(function () {\n\tvar module = ' + indent(this.toJS(null)) + ';\n\treturn module;\n})' pavone@8: } pavone@8: pavone@8: lambda.prototype.toJS = function(symbols) { pavone@8: var args = this.args ? this.args.slice(0, this.args.length) : []; pavone@8: if (args.length && args[0].cleanName() == 'self') { pavone@8: args.splice(0, 1); pavone@8: } pavone@8: var exprs = this.expressions; pavone@8: symbols = new lsymbols(symbols); pavone@8: for (var i in args) { pavone@8: symbols.defineVar(args[i].cleanName(), null); pavone@8: args[i] = args[i].toJS(symbols); pavone@8: } pavone@8: var compiled = [] pavone@8: for (var i in exprs) { pavone@8: var js = exprs[i].toJS(symbols); pavone@8: if (js) { pavone@8: compiled.push(indent(js)); pavone@8: } pavone@8: } pavone@8: exprs = compiled; pavone@8: if (exprs.length) { pavone@8: exprs[exprs.length-1] = 'return ' + exprs[exprs.length-1] + ';'; pavone@8: } pavone@8: return 'function (' + args.join(', ') + ') {\n\t' + (symbols.needsSelfVar ? 'var self = this;\n\t' : '') + exprs.join(';\n\t') + '\n}' pavone@8: }; pavone@8: lambda.prototype.toJSModule = lambda.prototype.toJS pavone@8: pavone@8: assignment.prototype.toJS = function(symbols) { pavone@8: var existing = symbols.find(this.symbol.name); pavone@8: var prefix = ''; pavone@8: if (!existing) { pavone@8: symbols.defineVar(this.symbol.name, this.expression); pavone@8: prefix = 'var '; pavone@8: } else { pavone@8: switch (existing.type) pavone@8: { pavone@8: case 'self': pavone@8: prefix = 'this.'; pavone@8: break; pavone@8: case 'parent': pavone@8: prefix = 'this.'; pavone@8: for (var i = 0; i < existing.depth; ++i) { pavone@8: prefix += 'parent.'; pavone@8: } pavone@8: break; pavone@8: } pavone@8: } pavone@12: var val = this.expression.toJS(symbols); pavone@12: if (val === null) { pavone@8: return null; pavone@8: } pavone@12: return prefix + this.symbol.toJS(symbols) + ' = ' + val; pavone@8: }; pavone@8: assignment.prototype.toJSObject = function(symbols) { pavone@8: symbols.defineMsg(this.symbol.name, this.expression); pavone@12: var val = this.expression.toJS(symbols); pavone@12: if (val === null) { pavone@8: return null; pavone@8: } pavone@12: return this.symbol.toJS(symbols) + ': ' + val; pavone@8: };