From 19ed63129e9215399f3b5e6ec67750ddadc87b95 Mon Sep 17 00:00:00 2001 From: Chris Lloyd Date: Sun, 4 Apr 2010 16:59:44 +1000 Subject: [PATCH] Interpolated strings are expressions. --- lib/cake.js | 8 ++-- lib/coffee-script.js | 2 +- lib/command.js | 4 +- lib/grammar.js | 6 +-- lib/helpers.js | 2 +- lib/lexer.js | 35 ++++++++++------- lib/nodes.js | 92 ++++++++++++++++++++++---------------------- lib/optparse.js | 6 +-- lib/rewriter.js | 4 +- lib/scope.js | 2 +- src/lexer.coffee | 3 ++ 11 files changed, 87 insertions(+), 77 deletions(-) diff --git a/lib/cake.js b/lib/cake.js index 2064fdda..5c98fcfe 100755 --- a/lib/cake.js +++ b/lib/cake.js @@ -57,7 +57,7 @@ return path.exists('Cakefile', function(exists) { var _a, _b, _c, _d, arg, args; if (!(exists)) { - throw new Error("Cakefile not found in " + (process.cwd())); + throw new Error(("Cakefile not found in " + (process.cwd()))); } args = process.argv.slice(2, process.argv.length); CoffeeScript.run(fs.readFileSync('Cakefile'), { @@ -91,8 +91,8 @@ } return _b; }).call(this).join('') : ''; - desc = task.description ? "# " + (task.description) : ''; - puts("cake " + name + spaces + " " + desc); + desc = task.description ? ("# " + (task.description)) : ''; + puts(("cake " + name + spaces + " " + desc)); }} if (switches.length) { return puts(oparse.help()); @@ -100,7 +100,7 @@ }; // Print an error and exit when attempting to all an undefined task. no_such_task = function no_such_task(task) { - process.stdio.writeError("No such task: \"" + task + "\"\n"); + process.stdio.writeError(("No such task: \"" + task + "\"\n")); return process.exit(1); }; })(); diff --git a/lib/coffee-script.js b/lib/coffee-script.js index 68a89791..253c3833 100644 --- a/lib/coffee-script.js +++ b/lib/coffee-script.js @@ -34,7 +34,7 @@ return (parser.parse(lexer.tokenize(code))).compile(options); } catch (err) { if (options.source) { - err.message = "In " + (options.source) + ", " + (err.message); + err.message = ("In " + (options.source) + ", " + (err.message)); } throw err; } diff --git a/lib/command.js b/lib/command.js index 93b495da..6dc97e41 100644 --- a/lib/command.js +++ b/lib/command.js @@ -61,7 +61,7 @@ compile = function compile(source) { return path.exists(source, function(exists) { if (!(exists)) { - throw new Error("File not found: " + source); + throw new Error(("File not found: " + source)); } return fs.readFile(source, function(err, code) { return compile_script(source, code); @@ -221,7 +221,7 @@ }; // Print the `--version` message and exit. version = function version() { - puts("CoffeeScript version " + (CoffeeScript.VERSION)); + puts(("CoffeeScript version " + (CoffeeScript.VERSION))); return process.exit(0); }; })(); diff --git a/lib/grammar.js b/lib/grammar.js index 28b24e7a..67007ccf 100644 --- a/lib/grammar.js +++ b/lib/grammar.js @@ -33,8 +33,8 @@ if (!(action)) { return [pattern_string, '$$ = $1;', options]; } - action = (match = (action + '').match(unwrap)) ? match[1] : "(" + action + "())"; - return [pattern_string, "$$ = " + action + ";", options]; + action = (match = (action + '').match(unwrap)) ? match[1] : ("(" + action + "())"); + return [pattern_string, ("$$ = " + action + ";"), options]; }; // Grammatical Rules // ----------------- @@ -693,7 +693,7 @@ } } if (name === 'Root') { - alt[1] = "return " + (alt[1]); + alt[1] = ("return " + (alt[1])); } return alt; }).call(this)); diff --git a/lib/helpers.js b/lib/helpers.js index d262227f..e770597a 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -132,7 +132,7 @@ if (slash) { return false; } - throw new Error("SyntaxError: Unterminated " + (levels.pop()[0]) + " starting on line " + (this.line + 1)); + throw new Error(("SyntaxError: Unterminated " + (levels.pop()[0]) + " starting on line " + (this.line + 1))); } if (!i) { return false; diff --git a/lib/lexer.js b/lib/lexer.js index 416bf55b..7435ac80 100644 --- a/lib/lexer.js +++ b/lib/lexer.js @@ -185,7 +185,7 @@ } quote = match[1].substr(0, 1); doc = this.sanitize_heredoc(match[2] || match[4], quote); - this.interpolate_string("" + quote + doc + quote); + this.interpolate_string(("" + quote + doc + quote)); this.line += count(match[1], "\n"); this.i += match[1].length; return true; @@ -225,8 +225,8 @@ return '\\' + escaped; }); this.tokens = this.tokens.concat([['(', '('], ['NEW', 'new'], ['IDENTIFIER', 'RegExp'], ['CALL_START', '(']]); - this.interpolate_string("\"" + str + "\"", true); - this.tokens = this.tokens.concat([[',', ','], ['STRING', "\"" + flags + "\""], [')', ')'], [')', ')']]); + this.interpolate_string(("\"" + str + "\""), true); + this.tokens = this.tokens.concat([[',', ','], ['STRING', ("\"" + flags + "\"")], [')', ')'], [')', ')']]); } else { this.token('REGEX', regex); } @@ -412,7 +412,7 @@ Lexer.prototype.tag_half_assignment = function tag_half_assignment(tag) { var last; last = this.tokens.pop(); - this.tokens.push(["" + tag + "=", "" + tag + "=", last[2]]); + this.tokens.push([("" + tag + "="), ("" + tag + "="), last[2]]); return true; }; // A source of ambiguity in our grammar used to be parameter lists in function @@ -448,12 +448,12 @@ // The error for when you try to use a forbidden word in JavaScript as // an identifier. Lexer.prototype.identifier_error = function identifier_error(word) { - throw new Error("SyntaxError: Reserved word \"" + word + "\" on line " + (this.line + 1)); + throw new Error(("SyntaxError: Reserved word \"" + word + "\" on line " + (this.line + 1))); }; // The error for when you try to assign to a reserved word in JavaScript, // like "function" or "default". Lexer.prototype.assignment_error = function assignment_error() { - throw new Error("SyntaxError: Reserved word \"" + (this.value()) + "\" on line " + (this.line + 1) + " can't be assigned"); + throw new Error(("SyntaxError: Reserved word \"" + (this.value()) + "\" on line " + (this.line + 1) + " can't be assigned")); }; // Expand variables and expressions inside double-quoted strings using // [ECMA Harmony's interpolation syntax](http://wiki.ecmascript.org/doku.php?id=strawman:string_interpolation) @@ -464,7 +464,7 @@ // new Lexer, tokenize the interpolated contents, and merge them into the // token stream. Lexer.prototype.interpolate_string = function interpolate_string(str, escape_quotes) { - var _a, _b, _c, _d, _e, escaped, expr, group, i, inner, interp, lexer, match, nested, pi, quote, tag, token, tokens, value; + var _a, _b, _c, _d, _e, escaped, expr, group, i, inner, interp, interpolated, lexer, match, nested, pi, quote, tag, token, tokens, value; if (str.length < 3 || !starts(str, '"')) { return this.token('STRING', str); } else { @@ -482,28 +482,28 @@ group = _b[0]; interp = _b[1]; if (starts(interp, '@')) { - interp = "this." + (interp.substring(1)); + interp = ("this." + (interp.substring(1))); } if (pi < i) { - tokens.push(['STRING', "" + quote + (str.substring(pi, i)) + quote]); + tokens.push(['STRING', ("" + quote + (str.substring(pi, i)) + quote)]); } tokens.push(['IDENTIFIER', interp]); i += group.length - 1; pi = i + 1; } else if ((expr = balanced_string(str.substring(i), [['${', '}']]))) { if (pi < i) { - tokens.push(['STRING', "" + quote + (str.substring(pi, i)) + quote]); + tokens.push(['STRING', ("" + quote + (str.substring(pi, i)) + quote)]); } inner = expr.substring(2, expr.length - 1); if (inner.length) { - nested = lexer.tokenize("(" + inner + ")", { + nested = lexer.tokenize(("(" + inner + ")"), { rewrite: false, line: this.line }); nested.pop(); tokens.push(['TOKENS', nested]); } else { - tokens.push(['STRING', "" + quote + quote]); + tokens.push(['STRING', ("" + quote + quote)]); } i += expr.length - 1; pi = i + 1; @@ -511,11 +511,15 @@ i += 1; } if (pi < i && pi < str.length - 1) { - tokens.push(['STRING', "" + quote + (str.substring(pi, i)) + quote]); + tokens.push(['STRING', ("" + quote + (str.substring(pi, i)) + quote)]); } if (!(tokens[0][0] === 'STRING')) { tokens.unshift(['STRING', '""']); } + interpolated = tokens.length > 1; + if (interpolated) { + this.token('(', '('); + } _c = tokens; for (i = 0, _d = _c.length; i < _d; i++) { token = _c[i]; @@ -526,7 +530,7 @@ this.tokens = this.tokens.concat(value); } else if (tag === 'STRING' && escape_quotes) { escaped = value.substring(1, value.length - 1).replace(/"/g, '\\"'); - this.token(tag, "\"" + escaped + "\""); + this.token(tag, ("\"" + escaped + "\"")); } else { this.token(tag, value); } @@ -534,6 +538,9 @@ this.token('+', '+'); } } + if (interpolated) { + this.token(')', ')'); + } return tokens; } }; diff --git a/lib/nodes.js b/lib/nodes.js index c1d9f106..6999a763 100644 --- a/lib/nodes.js +++ b/lib/nodes.js @@ -284,10 +284,10 @@ var code; code = this.compile_node(o); if (o.scope.has_assignments(this)) { - code = "" + (this.tab) + "var " + (o.scope.compiled_assignments()) + ";\n" + code; + code = ("" + (this.tab) + "var " + (o.scope.compiled_assignments()) + ";\n" + code); } if (o.scope.has_declarations(this)) { - code = "" + (this.tab) + "var " + (o.scope.compiled_declarations()) + ";\n" + code; + code = ("" + (this.tab) + "var " + (o.scope.compiled_declarations()) + ";\n" + code); } return code; }; @@ -433,7 +433,7 @@ props = only ? this.properties.slice(0, this.properties.length - 1) : this.properties; baseline = this.base.compile(o); if (this.base instanceof ObjectNode && this.has_properties()) { - baseline = "(" + baseline + ")"; + baseline = ("(" + baseline + ")"); } complete = (this.last = baseline); _b = props; @@ -444,7 +444,7 @@ soaked = true; if (this.base instanceof CallNode && prop === props[0]) { temp = o.scope.free_variable(); - complete = "(" + temp + " = " + complete + ")" + this.SOAK + (baseline = temp + prop.compile(o)); + complete = ("(" + temp + " = " + complete + ")" + this.SOAK) + (baseline = temp + prop.compile(o)); } else { complete = complete + this.SOAK + (baseline += prop.compile(o)); } @@ -477,7 +477,7 @@ return this; }; CommentNode.prototype.compile_node = function compile_node(o) { - return "" + this.tab + "//" + this.lines.join("\n" + this.tab + "//"); + return ("" + this.tab + "//") + this.lines.join(("\n" + this.tab + "//")); }; return CommentNode; }).call(this); @@ -535,7 +535,7 @@ CallNode.prototype.compile_super = function compile_super(args, o) { var meth, methname; methname = o.scope.method.name; - meth = o.scope.method.proto ? "" + (o.scope.method.proto) + ".__superClass__." + methname : "" + (methname) + ".__superClass__.constructor"; + meth = o.scope.method.proto ? ("" + (o.scope.method.proto) + ".__superClass__." + methname) : ("" + (methname) + ".__superClass__.constructor"); return "" + (meth) + ".call(this" + (args.length ? ', ' : '') + args + ")"; }; // If you call a function with a splat, it's converted into a JavaScript @@ -547,7 +547,7 @@ if (obj.match(/\(/)) { temp = o.scope.free_variable(); obj = temp; - meth = "(" + temp + " = " + (this.variable.source) + ")" + (this.variable.last); + meth = ("(" + temp + " = " + (this.variable.source) + ")" + (this.variable.last)); } return "" + (this.prefix()) + (meth) + ".apply(" + obj + ", " + (this.compile_splat_arguments(o)) + ")"; }; @@ -668,12 +668,12 @@ } idx = del(o, 'index'); step = del(o, 'step'); - vars = "" + idx + " = " + this.from_var; + vars = ("" + idx + " = " + this.from_var); step = step ? step.compile(o) : '1'; equals = this.exclusive ? '' : '='; - intro = "(" + this.from_var + " <= " + this.to_var + " ? " + idx; - compare = "" + intro + " <" + equals + " " + this.to_var + " : " + idx + " >" + equals + " " + this.to_var + ")"; - incr = "" + intro + " += " + step + " : " + idx + " -= " + step + ")"; + intro = ("(" + this.from_var + " <= " + this.to_var + " ? " + idx); + compare = ("" + intro + " <" + equals + " " + this.to_var + " : " + idx + " >" + equals + " " + this.to_var + ")"); + incr = ("" + intro + " += " + step + " : " + idx + " -= " + step + ")"); return "" + vars + "; " + compare + "; " + incr; }; // When used as a value, expand the range into the equivalent array. In the @@ -778,15 +778,15 @@ if (obj instanceof SplatNode) { return this.compile_splat_literal(this.objects, o); } else if (obj instanceof CommentNode) { - objects.push("\n" + code + "\n" + o.indent); + objects.push(("\n" + code + "\n" + o.indent)); } else if (i === this.objects.length - 1) { objects.push(code); } else { - objects.push("" + code + ", "); + objects.push(("" + code + ", ")); } } objects = objects.join(''); - ending = objects.indexOf('\n') >= 0 ? "\n" + this.tab + "]" : ']'; + ending = objects.indexOf('\n') >= 0 ? ("\n" + this.tab + "]") : ']'; return "[" + objects + ending; }; return ArrayNode; @@ -903,14 +903,14 @@ } val = this.value.compile(o); if (this.context === 'object') { - return "" + name + ": " + val; + return ("" + name + ": " + val); } if (!(this.is_value() && this.variable.has_properties())) { o.scope.find(name); } - val = "" + name + " = " + val; + val = ("" + name + " = " + val); if (stmt) { - return "" + this.tab + val + ";"; + return ("" + this.tab + val + ";"); } if (top) { return val; @@ -926,7 +926,7 @@ var _a, _b, _c, access_class, assigns, code, i, idx, obj, oindex, olength, splat, val, val_var, value; val_var = o.scope.free_variable(); value = this.value.is_statement() ? ClosureNode.wrap(this.value) : this.value; - assigns = ["" + this.tab + val_var + " = " + (value.compile(o)) + ";"]; + assigns = [("" + this.tab + val_var + " = " + (value.compile(o)) + ";")]; o.top = true; o.as_statement = true; splat = false; @@ -945,7 +945,7 @@ splat = true; } else { if (typeof idx !== 'object') { - idx = literal(splat ? "" + (val_var) + ".length - " + (olength - idx) : idx); + idx = literal(splat ? ("" + (val_var) + ".length - " + (olength - idx)) : idx); } val = new ValueNode(literal(val_var), [new access_class(idx)]); } @@ -1029,11 +1029,11 @@ param = _i[_h]; (o.scope.parameter(param)); } - code = this.body.expressions.length ? "\n" + (this.body.compile_with_declarations(o)) + "\n" : ''; + code = this.body.expressions.length ? ("\n" + (this.body.compile_with_declarations(o)) + "\n") : ''; name_part = this.name ? ' ' + this.name : ''; - func = "function" + (this.bound ? '' : name_part) + "(" + (params.join(', ')) + ") {" + code + (this.idt(this.bound ? 1 : 0)) + "}"; + func = ("function" + (this.bound ? '' : name_part) + "(" + (params.join(', ')) + ") {" + code + (this.idt(this.bound ? 1 : 0)) + "}"); if (top && !this.bound) { - func = "(" + func + ")"; + func = ("(" + func + ")"); } if (!(this.bound)) { return func; @@ -1106,7 +1106,7 @@ _b = this.trailings; for (_a = 0, _c = _b.length; _a < _c; _a++) { trailing = _b[_a]; - o.scope.assign(trailing.compile(o), "arguments[arguments.length - " + this.trailings.length + " + " + i + "]"); + o.scope.assign(trailing.compile(o), ("arguments[arguments.length - " + this.trailings.length + " + " + i + "]")); i += 1; } return "" + name + " = " + (utility('slice')) + ".call(arguments, " + this.index + ", arguments.length - " + (this.trailings.length) + ")"; @@ -1115,7 +1115,7 @@ // from the right-hand-side's corresponding array. SplatNode.prototype.compile_value = function compile_value(o, name, index, trailings) { var trail; - trail = trailings ? ", " + (name) + ".length - " + trailings : ''; + trail = trailings ? (", " + (name) + ".length - " + trailings) : ''; return "" + (utility('slice')) + ".call(" + name + ", " + index + trail + ")"; }; // Utility function that converts arbitrary number of elements, mixed with @@ -1131,16 +1131,16 @@ if (!(arg instanceof SplatNode)) { prev = args[i - 1]; if (i === 1 && prev.substr(0, 1) === '[' && prev.substr(prev.length - 1, 1) === ']') { - args[i - 1] = "" + (prev.substr(0, prev.length - 1)) + ", " + code + "]"; + args[i - 1] = ("" + (prev.substr(0, prev.length - 1)) + ", " + code + "]"); continue; } else if (i > 1 && prev.substr(0, 9) === '.concat([' && prev.substr(prev.length - 2, 2) === '])') { - args[i - 1] = "" + (prev.substr(0, prev.length - 2)) + ", " + code + "])"; + args[i - 1] = ("" + (prev.substr(0, prev.length - 2)) + ", " + code + "])"); continue; } else { - code = "[" + code + "]"; + code = ("[" + code + "]"); } } - args.push(i === 0 ? code : ".concat(" + code + ")"); + args.push(i === 0 ? code : (".concat(" + code + ")")); i += 1; } return args.join(''); @@ -1181,14 +1181,14 @@ set = ''; if (!top) { rvar = o.scope.free_variable(); - set = "" + this.tab + rvar + " = [];\n"; + set = ("" + this.tab + rvar + " = [];\n"); if (this.body) { this.body = PushNode.wrap(rvar, this.body); } } - pre = "" + set + (this.tab) + "while (" + cond + ")"; + pre = ("" + set + (this.tab) + "while (" + cond + ")"); if (!this.body) { - return "" + pre + " null;" + post; + return ("" + pre + " null;" + post); } if (this.filter) { this.body = Expressions.wrap([new IfNode(this.filter, this.body)]); @@ -1277,7 +1277,7 @@ o.scope.find(first); } if (this.operator === '?=') { - return "" + first + " = " + (ExistenceNode.compile_test(o, this.first)) + " ? " + first + " : " + second; + return ("" + first + " = " + (ExistenceNode.compile_test(o, this.first)) + " ? " + first + " : " + second); } return "" + first + " = " + first + " " + (this.operator.substr(0, 2)) + " " + second; }; @@ -1329,9 +1329,9 @@ o.indent = this.idt(1); o.top = true; attempt_part = this.attempt.compile(o); - error_part = this.error ? " (" + (this.error.compile(o)) + ") " : ' '; - catch_part = this.recovery ? " catch" + error_part + "{\n" + (this.recovery.compile(o)) + "\n" + this.tab + "}" : ''; - finally_part = (this.ensure || '') && ' finally {\n' + this.ensure.compile(merge(o)) + "\n" + this.tab + "}"; + error_part = this.error ? (" (" + (this.error.compile(o)) + ") ") : ' '; + catch_part = this.recovery ? (" catch" + error_part + "{\n" + (this.recovery.compile(o)) + "\n" + this.tab + "}") : ''; + finally_part = (this.ensure || '') && ' finally {\n' + this.ensure.compile(merge(o)) + ("\n" + this.tab + "}"); return "" + (this.tab) + "try {\n" + attempt_part + "\n" + this.tab + "}" + catch_part + finally_part; }; return TryNode; @@ -1495,18 +1495,18 @@ index: ivar, step: this.step })); - for_part = "" + index_var + " = 0, " + for_part + ", " + index_var + "++"; + for_part = ("" + index_var + " = 0, " + for_part + ", " + index_var + "++"); } else { svar = scope.free_variable(); index_var = null; - source_part = "" + svar + " = " + (this.source.compile(o)) + ";\n" + this.tab; + source_part = ("" + svar + " = " + (this.source.compile(o)) + ";\n" + this.tab); if (name) { - var_part = "" + body_dent + name + " = " + svar + "[" + ivar + "];\n"; + var_part = ("" + body_dent + name + " = " + svar + "[" + ivar + "];\n"); } if (!this.object) { lvar = scope.free_variable(); - step_part = this.step ? "" + ivar + " += " + (this.step.compile(o)) : "" + ivar + "++"; - for_part = "" + ivar + " = 0, " + lvar + " = " + (svar) + ".length; " + ivar + " < " + lvar + "; " + step_part; + step_part = this.step ? ("" + ivar + " += " + (this.step.compile(o))) : ("" + ivar + "++"); + for_part = ("" + ivar + " = 0, " + lvar + " = " + (svar) + ".length; " + ivar + " < " + lvar + "; " + step_part); } } set_result = rvar ? this.idt() + rvar + ' = []; ' : this.idt(); @@ -1520,12 +1520,12 @@ body = PushNode.wrap(rvar, body); } this.filter ? (body = Expressions.wrap([new IfNode(this.filter, body)])) : null; - this.object ? (for_part = "" + ivar + " in " + svar + ") { if (" + (utility('hasProp')) + ".call(" + svar + ", " + ivar + ")") : null; + this.object ? (for_part = ("" + ivar + " in " + svar + ") { if (" + (utility('hasProp')) + ".call(" + svar + ", " + ivar + ")")) : null; body = body.compile(merge(o, { indent: body_dent, top: true })); - vars = range ? name : "" + name + ", " + ivar; + vars = range ? name : ("" + name + ", " + ivar); close = this.object ? '}}\n' : '}\n'; return "" + set_result + (source_part) + "for (" + for_part + ") {\n" + var_part + body + "\n" + this.tab + close + return_result; }; @@ -1655,16 +1655,16 @@ o.top = true; if_dent = child ? '' : this.idt(); com_dent = child ? this.idt() : ''; - prefix = this.comment ? "" + (this.comment.compile(cond_o)) + "\n" + com_dent : ''; + prefix = this.comment ? ("" + (this.comment.compile(cond_o)) + "\n" + com_dent) : ''; body = Expressions.wrap([this.body]).compile(o); - if_part = "" + prefix + (if_dent) + "if (" + (this.compile_condition(cond_o)) + ") {\n" + body + "\n" + this.tab + "}"; + if_part = ("" + prefix + (if_dent) + "if (" + (this.compile_condition(cond_o)) + ") {\n" + body + "\n" + this.tab + "}"); if (!(this.else_body)) { return if_part; } else_part = this.is_chain() ? ' else ' + this.else_body.compile(merge(o, { indent: this.idt(), chain_child: true - })) : " else {\n" + (Expressions.wrap([this.else_body]).compile(o)) + "\n" + this.tab + "}"; + })) : (" else {\n" + (Expressions.wrap([this.else_body]).compile(o)) + "\n" + this.tab + "}"); return "" + if_part + else_part; }; // Compile the IfNode as a ternary operator. @@ -1744,7 +1744,7 @@ // Helper for ensuring that utility functions are assigned at the top level. utility = function utility(name) { var ref; - ref = "__" + name; + ref = ("__" + name); Scope.root.assign(ref, UTILITIES[ref]); return ref; }; diff --git a/lib/optparse.js b/lib/optparse.js index 3eb7b1d3..f8454973 100755 --- a/lib/optparse.js +++ b/lib/optparse.js @@ -37,7 +37,7 @@ } } if (is_option && !matched_rule) { - throw new Error("unrecognized option: " + arg); + throw new Error(("unrecognized option: " + arg)); } if (!(is_option)) { options.arguments.push(arg); @@ -51,7 +51,7 @@ var _a, _b, _c, _d, _e, _f, _g, i, let_part, lines, rule, spaces; lines = ['Available options:']; if (this.banner) { - lines.unshift("" + this.banner + "\n"); + lines.unshift(("" + this.banner + "\n")); } _b = this.rules; for (_a = 0, _c = _b.length; _a < _c; _a++) { @@ -65,7 +65,7 @@ return _d; }).call(this).join('') : ''; let_part = rule.short_flag ? rule.short_flag + ', ' : ' '; - lines.push(" " + let_part + (rule.long_flag) + spaces + (rule.description)); + lines.push((" " + let_part + (rule.long_flag) + spaces + (rule.description))); } return "\n" + (lines.join('\n')) + "\n"; }; diff --git a/lib/rewriter.js b/lib/rewriter.js index 8a501a85..fc13a4cb 100644 --- a/lib/rewriter.js +++ b/lib/rewriter.js @@ -255,7 +255,7 @@ levels[open] -= 1; } if (levels[open] < 0) { - throw new Error("too many " + (token[1]) + " on line " + (token[2] + 1)); + throw new Error(("too many " + (token[1]) + " on line " + (token[2] + 1))); } } return 1; @@ -271,7 +271,7 @@ if (unclosed.length) { open = unclosed[0]; line = open_line[open] + 1; - throw new Error("unclosed " + open + " on line " + line); + throw new Error(("unclosed " + open + " on line " + line)); } }; // We'd like to support syntax like this: diff --git a/lib/scope.js b/lib/scope.js index b55ad5eb..f95bb335 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -120,7 +120,7 @@ _a = []; _b = this.variables; for (key in _b) { if (__hasProp.call(_b, key)) { val = _b[key]; - val.assigned ? _a.push("" + key + " = " + (val.value)) : null; + val.assigned ? _a.push(("" + key + " = " + (val.value))) : null; }} return _a; }; diff --git a/src/lexer.coffee b/src/lexer.coffee index c7a17701..36001cbc 100644 --- a/src/lexer.coffee +++ b/src/lexer.coffee @@ -376,6 +376,8 @@ exports.Lexer: class Lexer i: + 1 tokens.push ['STRING', "$quote${ str.substring(pi, i) }$quote"] if pi < i and pi < str.length - 1 tokens.unshift ['STRING', '""'] unless tokens[0][0] is 'STRING' + interpolated: tokens.length > 1 + @token '(', '(' if interpolated for token, i in tokens [tag, value]: token if tag is 'TOKENS' @@ -386,6 +388,7 @@ exports.Lexer: class Lexer else @token tag, value @token '+', '+' if i < tokens.length - 1 + @token ')', ')' if interpolated tokens # Helpers