diff --git a/lib/nodes.js b/lib/nodes.js index 2b51d292..16119bdf 100644 --- a/lib/nodes.js +++ b/lib/nodes.js @@ -467,7 +467,7 @@ this.soak = _arg2; this.args = _arg; Call.__super__.constructor.call(this); - this["new"] = ''; + this.isNew = false; this.isSuper = variable === 'super'; this.variable = this.isSuper ? null : variable; this.args || (this.args = []); @@ -478,7 +478,7 @@ __extends(Call, Base); Call.prototype.children = ['variable', 'args']; Call.prototype.newInstance = function() { - this["new"] = 'new '; + this.isNew = true; return this; }; Call.prototype.superReference = function(o) { @@ -506,7 +506,7 @@ rite = new Value(left); } rite = new Call(rite, this.args); - rite["new"] = this["new"]; + rite.isNew = this.isNew; left = new Literal("typeof " + (left.compile(o)) + " === \"function\""); return new If(left, new Value(rite), { soak: true @@ -563,7 +563,7 @@ } return _result; }).call(this)).join(', '); - return this.isSuper ? this.compileSuper(args, o) : this["new"] + this.variable.compile(o, LEVEL_ACCESS) + ("(" + args + ")"); + return this.isSuper ? this.compileSuper(args, o) : (this.isNew ? 'new ' : '') + this.variable.compile(o, LEVEL_ACCESS) + ("(" + args + ")"); }; Call.prototype.compileSuper = function(args, o) { return "" + (this.superReference(o)) + ".call(this" + (args.length ? ', ' : '') + args + ")"; @@ -574,7 +574,7 @@ if (this.isSuper) { return "" + (this.superReference(o)) + ".apply(this, " + splatargs + ")"; } - if (!this["new"]) { + if (!this.isNew) { base = new Value(this.variable); if ((name = base.properties.pop()) && base.isComplex()) { ref = o.scope.freeVariable('this'); @@ -949,7 +949,7 @@ if (obj.base instanceof Parens) { _ref4 = new Value(obj.unwrapAll()).cacheReference(o), obj = _ref4[0], idx = _ref4[1]; } else { - idx = isObject ? (obj.tags["this"] ? obj.properties[0].name : obj) : new Literal(0); + idx = isObject ? obj.tags["this"] ? obj.properties[0].name : obj : new Literal(0); } } acc = IDENTIFIER.test(idx.unwrap().value || 0); diff --git a/src/lexer.coffee b/src/lexer.coffee index 4eeb6ca5..2c75e04a 100644 --- a/src/lexer.coffee +++ b/src/lexer.coffee @@ -143,8 +143,9 @@ exports.Lexer = class Lexer when '"' return 0 unless string = @balancedString @chunk, [['"', '"'], ['#{', '}']] if 0 < string.indexOf '#{', 1 - then @interpolateString string.slice 1, -1 - else @token 'STRING', @escapeLines string + @interpolateString string.slice 1, -1 + else + @token 'STRING', @escapeLines string else return 0 @line += count string, '\n' @@ -158,8 +159,9 @@ exports.Lexer = class Lexer quote = heredoc.charAt 0 doc = @sanitizeHeredoc match[2], {quote, indent: null} if quote is '"' and 0 <= doc.indexOf '#{' - then @interpolateString doc, heredoc: yes - else @token 'STRING', @makeString doc, quote, yes + @interpolateString doc, heredoc: yes + else + @token 'STRING', @makeString doc, quote, yes @line += count heredoc, '\n' heredoc.length @@ -444,8 +446,9 @@ exports.Lexer = class Lexer for [tag, value], i in tokens @token '+', '+' if i if tag is 'TOKENS' - then @tokens.push value... - else @token 'STRING', @makeString value, '"', heredoc + @tokens.push value... + else + @token 'STRING', @makeString value, '"', heredoc @token ')', ')' if interpolated tokens diff --git a/src/nodes.coffee b/src/nodes.coffee index adc4d27d..3a625bb6 100644 --- a/src/nodes.coffee +++ b/src/nodes.coffee @@ -42,8 +42,9 @@ exports.Base = class Base node = @unfoldSoak(o) or this node.tab = o.indent if o.level is LEVEL_TOP or node.isPureStatement() or not node.isStatement(o) - then node.compileNode o - else node.compileClosure o + node.compileNode o + else + node.compileClosure o # Statements converted into expressions via closure-wrapping share a scope # object with their parent closure, to preserve the expected lexical scope. @@ -101,7 +102,7 @@ exports.Base = class Base containsPureStatement: -> @isPureStatement() or @contains (node, func) -> func(node) or if node instanceof While or node instanceof For - then (node) -> node instanceof Return + (node) -> node instanceof Return else func , (node) -> node.isPureStatement() @@ -407,14 +408,14 @@ exports.Call = class Call extends Base constructor: (variable, @args, @soak) -> super() - @new = '' + @isNew = false @isSuper = variable is 'super' @variable = if @isSuper then null else variable @args or= [] # Tag this invocation as creating a new instance. newInstance: -> - @new = 'new ' + @isNew = true this # Grab the reference to the superclass' implementation of the current method. @@ -424,8 +425,9 @@ exports.Call = class Call extends Base {name} = method throw SyntaxError 'cannot call super on an anonymous function.' unless name if method.klass - then "#{method.klass}.__super__.#{name}" - else "#{name}.__super__.constructor" + "#{method.klass}.__super__.#{name}" + else + "#{name}.__super__.constructor" # Soaked chained invocations unfold into if/else ternary structures. unfoldSoak: (o) -> @@ -437,7 +439,7 @@ exports.Call = class Call extends Base left = new Literal @superReference o rite = new Value left rite = new Call rite, @args - rite.new = @new + rite.isNew = @isNew left = new Literal "typeof #{ left.compile o } === \"function\"" return new If left, new Value(rite), soak: yes call = this @@ -453,19 +455,22 @@ exports.Call = class Call extends Base for call in list.reverse() if ifn if call.variable instanceof Call - then call.variable = ifn - else call.variable.base = ifn + call.variable = ifn + else + call.variable.base = ifn ifn = If.unfoldSoak o, call, 'variable' ifn # Compile a vanilla function call. compileNode: (o) -> @variable?.tags.front = @tags.front - return @compileSplat o for arg in @args when arg instanceof Splat + for arg in @args when arg instanceof Splat + return @compileSplat o args = (arg.compile o, LEVEL_LIST for arg in @args).join ', ' if @isSuper - then @compileSuper args, o - else @new + @variable.compile(o, LEVEL_ACCESS) + "(#{args})" + @compileSuper args, o + else + (if @isNew then 'new ' else '') + @variable.compile(o, LEVEL_ACCESS) + "(#{args})" # `super()` is converted into a call against the superclass's implementation # of the current function. @@ -479,7 +484,7 @@ exports.Call = class Call extends Base compileSplat: (o) -> splatargs = Splat.compileSplattedArray @args, o return "#{ @superReference o }.apply(this, #{splatargs})" if @isSuper - unless @new + unless @isNew base = new Value @variable if (name = base.properties.pop()) and base.isComplex() ref = o.scope.freeVariable 'this' @@ -564,10 +569,11 @@ exports.Obj = class Obj extends Base lastNoncom = last nonComments props = for prop, i in @properties join = if i is @properties.length - 1 - then '' + '' else if prop is lastNoncom or prop instanceof Comment - then '\n' - else ',\n' + '\n' + else + ',\n' indent = if prop instanceof Comment then '' else @idt 1 if prop instanceof Value and prop.tags.this prop = new Assign prop.properties[0].name, prop, 'object' @@ -594,8 +600,9 @@ exports.Obj = class Obj extends Base [key, val] = acc.cache o, LEVEL_LIST, ref ref = val key = if acc instanceof Literal and IDENTIFIER.test key - then '.' + key - else '[' + key + ']' + '.' + key + else + '[' + key + ']' code += "#{obj}#{key} = #{val}, " code += obj if o.level <= LEVEL_PAREN then code else "(#{code})" @@ -623,10 +630,12 @@ exports.Arr = class Arr extends Base for obj, i in @objects code = obj.compile o, LEVEL_LIST objects.push (if obj instanceof Comment - then "\n#{code}\n#{o.indent}" + "\n#{code}\n#{o.indent}" else if i is @objects.length - 1 - then code - else code + ', ') + code + else + code + ', ' + ) objects = objects.join '' if 0 < objects.indexOf '\n' "[\n#{o.indent}#{objects}\n#{@tab}]" @@ -778,8 +787,9 @@ exports.Assign = class Assign extends Base [obj, idx] = new Value(obj.unwrapAll()).cacheReference o else idx = if isObject - then (if obj.tags.this then obj.properties[0].name else obj) - else new Literal 0 + if obj.tags.this then obj.properties[0].name else obj + else + new Literal 0 acc = IDENTIFIER.test idx.unwrap().value or 0 value = new Value value value.properties.push new (if acc then Accessor else Index) idx @@ -800,8 +810,9 @@ exports.Assign = class Assign extends Base else # A shorthand `{a, b, @c} = val` pattern-match. if obj.base instanceof Parens - then [obj, idx] = new Value(obj.unwrapAll()).cacheReference o - else idx = if obj.tags.this then obj.properties[0].name else obj + [obj, idx] = new Value(obj.unwrapAll()).cacheReference o + else + idx = if obj.tags.this then obj.properties[0].name else obj if not splat and obj instanceof Splat val = new Literal obj.compileValue o, valVar, i, olength - i - 1 splat = true @@ -1070,8 +1081,9 @@ exports.Op = class Op extends Base @operator = op this else if @second - then new Parens(this).invert() - else super() + new Parens(this).invert() + else + super() unfoldSoak: (o) -> @operator in ['++', '--', 'delete'] and If.unfoldSoak o, this, 'first' @@ -1128,8 +1140,9 @@ exports.In = class In extends Base compileNode: (o) -> if @array instanceof Value and @array.isArray() - then @compileOrTest o - else @compileLoopTest o + @compileOrTest o + else + @compileLoopTest o compileOrTest: (o) -> [sub, ref] = @object.cache o, LEVEL_OP @@ -1211,8 +1224,9 @@ exports.Existence = class Existence extends Base compileNode: (o) -> code = @expression.compile o code = if IDENTIFIER.test(code) and not o.scope.check code - then "typeof #{code} !== \"undefined\" && #{code} !== null" - else "#{code} != null" + "typeof #{code} !== \"undefined\" && #{code} !== null" + else + "#{code} != null" if o.level <= LEVEL_COND then code else "(#{code})" #### Parens @@ -1294,12 +1308,14 @@ exports.For = class For extends Base vars = ivar + ' = ' + @from.compile o vars += ', ' + tail if tail isnt tvar cond = if +pvar - then "#{ivar} #{ if pvar < 0 then '>' else '<' }= #{tvar}" - else "#{pvar} < 0 ? #{ivar} >= #{tvar} : #{ivar} <= #{tvar}" + "#{ivar} #{ if pvar < 0 then '>' else '<' }= #{tvar}" + else + "#{pvar} < 0 ? #{ivar} >= #{tvar} : #{ivar} <= #{tvar}" else if name or @object and not @raw - then [sourcePart, svar] = @source.compileLoopReference o, 'ref' - else sourcePart = svar = @source.compile o, LEVEL_PAREN + [sourcePart, svar] = @source.compileLoopReference o, 'ref' + else + sourcePart = svar = @source.compile o, LEVEL_PAREN namePart = if @pattern new Assign(@name, new Literal "#{svar}[#{ivar}]").compile o, LEVEL_TOP else if name @@ -1431,8 +1447,9 @@ exports.If = class If extends Base ifPart = @tab + ifPart unless child return ifPart unless @elseBody ifPart + ' else ' + if @isChain - then @elseBodyNode().compile merge o, indent: @tab, chainChild: true - else "{\n#{ @elseBody.compile o, LEVEL_TOP }\n#{@tab}}" + @elseBodyNode().compile merge o, indent: @tab, chainChild: true + else + "{\n#{ @elseBody.compile o, LEVEL_TOP }\n#{@tab}}" # Compile the If as a conditional operator. compileExpression: (o) -> diff --git a/src/rewriter.coffee b/src/rewriter.coffee index 6178bc36..e6de981e 100644 --- a/src/rewriter.coffee +++ b/src/rewriter.coffee @@ -49,7 +49,7 @@ class exports.Rewriter return action.call this, token, i if levels is 0 and condition.call this, token, i return action.call this, token, i - 1 if not token or levels < 0 if token[0] in EXPRESSION_START - levels += 1 + levels += 1 else if token[0] in EXPRESSION_END levels -= 1 i += 1 @@ -64,8 +64,9 @@ class exports.Rewriter if after?[0] is 'INDENT' tokens.splice i + 2, 1 if before?[0] is 'OUTDENT' and post?[0] is 'TERMINATOR' - then tokens.splice i - 2, 1 - else tokens.splice i, 0, after + tokens.splice i - 2, 1 + else + tokens.splice i, 0, after else if prev and prev[0] not in ['TERMINATOR', 'INDENT', 'OUTDENT'] if post?[0] is 'TERMINATOR' and after?[0] is 'OUTDENT' tokens.splice i + 2, 0, tokens.splice(i, 2)... @@ -139,10 +140,11 @@ class exports.Rewriter stack[stack.length - 1]?[0] isnt '{') stack.push ['{'] idx = if ago1 is ')' - then start[1] + start[1] else if ago2 is '@' - then i - 2 - else i - 1 + i - 2 + else + i - 1 idx -= 2 if @tag(idx - 2) is 'HERECOMMENT' tok = ['{', '{', token[2]] tok.generated = yes