# HG changeset patch # User Mike Pavone # Date 1332717079 25200 # Node ID 132c7756860e33b8e9ec729cf7cf86c249922b60 # Parent 4dd99fde5f63ee9dee5c5744a27c594633aef61d Use populateSymbols to generate symbol tables during compilation rather than populating them as we go. This change allows us to refer to symbols defined later in the input stream and also gives the symbol table logic a single home that can be used both by the compiler and editor. diff -r 4dd99fde5f63 -r 132c7756860e jsbackend.js --- a/jsbackend.js Sun Mar 25 15:57:26 2012 -0700 +++ b/jsbackend.js Sun Mar 25 16:11:19 2012 -0700 @@ -27,18 +27,18 @@ return o[p]; } -op.prototype.toJS = function(symbols, isReceiver) { - var ret = '(' + this.left.toJS(symbols) +' '+ (this.op == '=' ? '==' : this.op) +' '+ this.right.toJS(symbols) + ')'; +op.prototype.toJS = function(isReceiver) { + var ret = '(' + this.left.toJS() +' '+ (this.op == '=' ? '==' : this.op) +' '+ this.right.toJS() + ')'; if (isReceiver) { ret = 'toobj' + ret; } return ret; }; -symbol.prototype.toJS = function(symbols) { +symbol.prototype.toJS = function() { var name = this.cleanName(); if (name == 'self') { - return symbols.selfVar(); + return this.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}; @@ -48,19 +48,19 @@ return name; } -intlit.prototype.toJS = function(symbols) { +intlit.prototype.toJS = function() { return this.val.toString(); } -floatlit.prototype.toJS = function(symbols) { +floatlit.prototype.toJS = function() { return this.val.toString(); } -strlit.prototype.toJS = function(symbols) { +strlit.prototype.toJS = function() { return '"' + this.val.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n').replace('\r', '\\r') + '"'; } -funcall.prototype.toJS = function(symbols) { +funcall.prototype.toJS = function() { var name = this.name[this.name.length-1] == ':' ? this.name.substr(0, this.name.length-1) : this.name; if (name == 'foreign') { if ((this.args[0] instanceof lambda) || (this.args[0] instanceof object)) { @@ -75,79 +75,77 @@ if (this.receiver) { args.splice(0, 0, this.receiver); } - var funinfo = symbols.find(name); + var funinfo = this.symbols.find(name); if (!funinfo) { var receiver = args[0]; args.splice(0, 1); for (var i in args) { - args[i] = args[i].toJS(symbols); + args[i] = args[i].toJS(); } - return receiver.toJS(symbols, true) + '.' + (new symbol(name)).toJS(symbols) + '(' + args.join(', ') + ')'; + return receiver.toJS(true) + '.' + (new symbol(name, this.symbols)).toJS() + '(' + 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'); + var receiver = new symbol('self', this.symbols); } else { var receiver = args[0]; args.splice(0, 1); } for (var i in args) { - args[i] = args[i].toJS(symbols); + args[i] = args[i].toJS(); } - return receiver.toJS(symbols, true) + '.' + (new symbol(name)).toJS(symbols) + '(' + args.join(', ') + ')'; + return receiver.toJS(true) + '.' + (new symbol(name, this.symbols)).toJS() + '(' + 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); + args[i] = args[i].toJS(); } - ret += (new symbol(name)).toJS(symbols) + '(' + args.join(', ') + ')'; + ret += (new symbol(name, this.symbols)).toJS() + '(' + args.join(', ') + ')'; return ret; case 'local': case 'upvar': case 'foreign': for (var i in args) { - args[i] = args[i].toJS(symbols); + args[i] = args[i].toJS(); } - return (new symbol(name)).toJS(symbols) + '(' + args.join(', ') + ')'; + return (new symbol(name, this.symbols)).toJS() + '(' + args.join(', ') + ')'; } } -object.prototype.toJS = function(symbols) { +object.prototype.toJS = function() { var messages = this.messages; - symbols = new osymbols(symbols); var compiled = [] for (var i in messages) { - var js = messages[i].toJSObject(symbols); + var js = messages[i].toJSObject(); if (js) { compiled.push(indent(js)); } } - return '{\n\tparent: ' + symbols.parentObject() + ',\n\t' + compiled.join(',\n\t') + '\n}'; + return '{\n\tparent: ' + this.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})' + this.populateSymbols(null); + return '(function () {\n\tvar module = ' + indent(this.toJS()) + ';\n\treturn module;\n})' } -lambda.prototype.toJS = function(symbols) { +lambda.prototype.toJS = function() { 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); + args[i] = args[i].toJS(); } var compiled = [] for (var i in exprs) { - var js = exprs[i].toJS(symbols); + var js = exprs[i].toJS(); if (js) { compiled.push(indent(js)); } @@ -156,15 +154,17 @@ 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}' + return 'function (' + args.join(', ') + ') {\n\t' + (this.symbols.needsSelfVar ? 'var self = this;\n\t' : '') + exprs.join(';\n\t') + '\n}' }; -lambda.prototype.toJSModule = lambda.prototype.toJS +lambda.prototype.toJSModule = function() { + this.populateSymbols(null); + return this.toJS(); +} -assignment.prototype.toJS = function(symbols) { - var existing = symbols.find(this.symbol.name); +assignment.prototype.toJS = function() { + var existing = this.symbols.find(this.symbol.name); var prefix = ''; if (!existing) { - symbols.defineVar(this.symbol.name, this.expression); prefix = 'var '; } else { switch (existing.type) @@ -180,17 +180,16 @@ break; } } - var val = this.expression.toJS(symbols); + var val = this.expression.toJS(); if (val === null) { return null; } - return prefix + this.symbol.toJS(symbols) + ' = ' + val; + return prefix + this.symbol.toJS() + ' = ' + val; }; -assignment.prototype.toJSObject = function(symbols) { - symbols.defineMsg(this.symbol.name, this.expression); - var val = this.expression.toJS(symbols); +assignment.prototype.toJSObject = function() { + var val = this.expression.toJS(); if (val === null) { return null; } - return this.symbol.toJS(symbols) + ': ' + val; + return this.symbol.toJS() + ': ' + val; }; diff -r 4dd99fde5f63 -r 132c7756860e parser.js --- a/parser.js Sun Mar 25 15:57:26 2012 -0700 +++ b/parser.js Sun Mar 25 16:11:19 2012 -0700 @@ -6,9 +6,10 @@ this.right = right; } -function symbol(name) +function symbol(name, symbols) { this.name = name; + this.symbols = symbols; } symbol.prototype.cleanName = function() { return this.name[0] == ':' ? this.name.substr(1) : this.name;