removing the last traces of half-assignments. Issue #541.

This commit is contained in:
Jeremy Ashkenas 2010-07-29 21:23:49 -04:00
parent 980a663c19
commit b18d7fb550
11 changed files with 36 additions and 41 deletions

View File

@ -8,4 +8,4 @@ else
date = if friday then sue else jill date = if friday then sue else jill
options = or defaults options or= defaults

View File

@ -60,8 +60,8 @@ race = ->
race() race()
# Conditional assignment: # Conditional assignment:
good = or evil good or= evil
wine = and cheese wine and= cheese
# Nested property access and calls. # Nested property access and calls.
((moon.turn(360))).shapes[3].move({x: 45, y: 30}).position['top'].offset('x') ((moon.turn(360))).shapes[3].move({x: 45, y: 30}).position['top'].offset('x')

View File

@ -12,7 +12,7 @@ class LinkedList
# Create a new node object to wrap the data. # Create a new node object to wrap the data.
node = data: data, next: null node = data: data, next: null
current = this._head = or node current = this._head or= node
if this._head isnt node if this._head isnt node
(current = current.next) while current.next (current = current.next) while current.next

View File

@ -46,7 +46,7 @@ LotteryDraw =
ticket_list.each (ticket) -> ticket_list.each (ticket) ->
score = ticket.score result score = ticket.score result
return if score is 0 return if score is 0
winners[buyer] = or [] winners[buyer] or= []
winners[buyer].push [ticket, score] winners[buyer].push [ticket, score]
this.tickets = {} this.tickets = {}
winners winners

View File

@ -70,7 +70,7 @@
return this.literalToken(); return this.literalToken();
}; };
Lexer.prototype.identifierToken = function() { Lexer.prototype.identifierToken = function() {
var _d, close_index, forcedIdentifier, id, tag; var close_index, forcedIdentifier, id, tag;
if (!(id = this.match(IDENTIFIER, 1))) { if (!(id = this.match(IDENTIFIER, 1))) {
return false; return false;
} }
@ -86,9 +86,6 @@
if (id === 'all' && this.tag() === 'FOR') { if (id === 'all' && this.tag() === 'FOR') {
tag = 'ALL'; tag = 'ALL';
} }
if (('AND' === (_d = this.tag() === '=' && tag) || 'OR' === _d)) {
return this.tag(1, CONVERSIONS[id] + '=');
}
if (include(JS_FORBIDDEN, id)) { if (include(JS_FORBIDDEN, id)) {
if (forcedIdentifier) { if (forcedIdentifier) {
tag = 'STRING'; tag = 'STRING';

View File

@ -30,7 +30,7 @@ lexer = new Lexer
# Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison # Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison
# compiler. # compiler.
exports.compile = compile = (code, options) -> exports.compile = compile = (code, options) ->
options = or {} options or= {}
try try
(parser.parse lexer.tokenize code).compile options (parser.parse lexer.tokenize code).compile options
catch err catch err

View File

@ -156,7 +156,7 @@ printTokens = (tokens) ->
parseOptions = -> parseOptions = ->
optionParser = new optparse.OptionParser SWITCHES, BANNER optionParser = new optparse.OptionParser SWITCHES, BANNER
o = options = optionParser.parse(process.argv[2...process.argv.length]) o = options = optionParser.parse(process.argv[2...process.argv.length])
options.compile = or !!o.output options.compile or= !!o.output
options.run = not (o.compile or o.print or o.lint) options.run = not (o.compile or o.print or o.lint)
options.print = !! (o.print or (o.eval or o.stdio and o.compile)) options.print = !! (o.print or (o.eval or o.stdio and o.compile))
sources = options.arguments sources = options.arguments

View File

@ -88,8 +88,6 @@ exports.Lexer = class Lexer
tag = id.toUpperCase() if include(JS_KEYWORDS, id) or (not forcedIdentifier and include(COFFEE_KEYWORDS, id)) tag = id.toUpperCase() if include(JS_KEYWORDS, id) or (not forcedIdentifier and include(COFFEE_KEYWORDS, id))
tag = 'LEADING_WHEN' if tag is 'WHEN' and include LINE_BREAK, @tag() tag = 'LEADING_WHEN' if tag is 'WHEN' and include LINE_BREAK, @tag()
tag = 'ALL' if id is 'all' and @tag() is 'FOR' tag = 'ALL' if id is 'all' and @tag() is 'FOR'
if @tag() is '=' and tag in ['AND', 'OR']
return @tag 1, CONVERSIONS[id] + '='
if include(JS_FORBIDDEN, id) if include(JS_FORBIDDEN, id)
if forcedIdentifier if forcedIdentifier
tag = 'STRING' tag = 'STRING'
@ -259,7 +257,7 @@ exports.Lexer = class Lexer
value = match and match[1] value = match and match[1]
space = match and match[2] space = match and match[2]
@tagParameters() if value and value.match CODE @tagParameters() if value and value.match CODE
value = or @chunk.substr 0, 1 value or= @chunk.substr 0, 1
@i += value.length @i += value.length
prevSpaced = @prev() and @prev().spaced prevSpaced = @prev() and @prev().spaced
tag = value tag = value
@ -347,7 +345,7 @@ exports.Lexer = class Lexer
# contents of the string. This method allows us to have strings within # contents of the string. This method allows us to have strings within
# interpolations within strings, ad infinitum. # interpolations within strings, ad infinitum.
balancedString: (str, delimited, options) -> balancedString: (str, delimited, options) ->
options = or {} options or= {}
slash = delimited[0][0] is '/' slash = delimited[0][0] is '/'
levels = [] levels = []
i = 0 i = 0
@ -384,7 +382,7 @@ exports.Lexer = class Lexer
# new Lexer, tokenize the interpolated contents, and merge them into the # new Lexer, tokenize the interpolated contents, and merge them into the
# token stream. # token stream.
interpolateString: (str, options) -> interpolateString: (str, options) ->
options = or {} options or= {}
if str.length < 3 or not starts str, '"' if str.length < 3 or not starts str, '"'
@token 'STRING', str @token 'STRING', str
else else

View File

@ -112,7 +112,7 @@ exports.BaseNode = class BaseNode
# `toString` representation of the node, for inspecting the parse tree. # `toString` representation of the node, for inspecting the parse tree.
# This is what `coffee --nodes` prints out. # This is what `coffee --nodes` prints out.
toString: (idt, override) -> toString: (idt, override) ->
idt = or '' idt or= ''
children = (child.toString idt + TAB for child in @collectChildren()).join('') children = (child.toString idt + TAB for child in @collectChildren()).join('')
'\n' + idt + (override or @class) + children '\n' + idt + (override or @class) + children
@ -187,7 +187,7 @@ exports.Expressions = class Expressions extends BaseNode
# An **Expressions** is the only node that can serve as the root. # An **Expressions** is the only node that can serve as the root.
compile: (o) -> compile: (o) ->
o = or {} o or= {}
if o.scope then super(o) else @compileRoot(o) if o.scope then super(o) else @compileRoot(o)
compileNode: (o) -> compileNode: (o) ->
@ -290,7 +290,7 @@ exports.ValueNode = class ValueNode extends BaseNode
# A **ValueNode** has a base and a list of property accesses. # A **ValueNode** has a base and a list of property accesses.
constructor: (@base, @properties) -> constructor: (@base, @properties) ->
@properties = or [] @properties or= []
# Add a property access to the list. # Add a property access to the list.
push: (prop) -> push: (prop) ->
@ -345,7 +345,7 @@ exports.ValueNode = class ValueNode extends BaseNode
only = del o, 'onlyFirst' only = del o, 'onlyFirst'
op = del o, 'operation' op = del o, 'operation'
props = if only then @properties[0...@properties.length - 1] else @properties props = if only then @properties[0...@properties.length - 1] else @properties
o.chainRoot = or this o.chainRoot or= this
baseline = @base.compile o baseline = @base.compile o
baseline = "(#baseline)" if @hasProperties() and (@base instanceof ObjectNode or @isNumber()) baseline = "(#baseline)" if @hasProperties() and (@base instanceof ObjectNode or @isNumber())
complete = @last = baseline complete = @last = baseline
@ -397,7 +397,7 @@ exports.CallNode = class CallNode extends BaseNode
@isNew = false @isNew = false
@isSuper = variable is 'super' @isSuper = variable is 'super'
@variable = if @isSuper then null else variable @variable = if @isSuper then null else variable
@args = or [] @args or= []
@compileSplatArguments = (o) -> @compileSplatArguments = (o) ->
SplatNode.compileSplattedArray.call(this, @args, o) SplatNode.compileSplattedArray.call(this, @args, o)
@ -489,7 +489,7 @@ exports.AccessorNode = class AccessorNode extends BaseNode
compileNode: (o) -> compileNode: (o) ->
name = @name.compile o name = @name.compile o
o.chainRoot.wrapped = or @soakNode o.chainRoot.wrapped or= @soakNode
namePart = if name.match(IS_STRING) then "[#name]" else ".#name" namePart = if name.match(IS_STRING) then "[#name]" else ".#name"
@prototype + namePart @prototype + namePart
@ -504,7 +504,7 @@ exports.IndexNode = class IndexNode extends BaseNode
constructor: (@index) -> constructor: (@index) ->
compileNode: (o) -> compileNode: (o) ->
o.chainRoot.wrapped = or @soakNode o.chainRoot.wrapped or= @soakNode
idx = @index.compile o idx = @index.compile o
prefix = if @proto then '.prototype' else '' prefix = if @proto then '.prototype' else ''
"#prefix[#idx]" "#prefix[#idx]"
@ -554,7 +554,7 @@ exports.RangeNode = class RangeNode extends BaseNode
[from, to] = [parseInt(@fromNum, 10), parseInt(@toNum, 10)] [from, to] = [parseInt(@fromNum, 10), parseInt(@toNum, 10)]
idx = del o, 'index' idx = del o, 'index'
step = del o, 'step' step = del o, 'step'
step = and "#idx += #{step.compile(o)}" step and= "#idx += #{step.compile(o)}"
if from <= to if from <= to
"#idx = #from; #idx <#@equals #to; #{step or "#idx++"}" "#idx = #from; #idx <#@equals #to; #{step or "#idx++"}"
else else
@ -633,7 +633,7 @@ exports.ArrayNode = class ArrayNode extends BaseNode
children: ['objects'] children: ['objects']
constructor: (@objects) -> constructor: (@objects) ->
@objects = or [] @objects or= []
@compileSplatLiteral = (o) -> @compileSplatLiteral = (o) ->
SplatNode.compileSplattedArray.call(this, @objects, o) SplatNode.compileSplattedArray.call(this, @objects, o)
@ -668,7 +668,7 @@ exports.ClassNode = class ClassNode extends BaseNode
# Initialize a **ClassNode** with its name, an optional superclass, and a # Initialize a **ClassNode** with its name, an optional superclass, and a
# list of prototype property assignments. # list of prototype property assignments.
constructor: (@variable, @parent, @properties) -> constructor: (@variable, @parent, @properties) ->
@properties = or [] @properties or= []
@returns = false @returns = false
makeReturn: -> makeReturn: ->
@ -707,8 +707,8 @@ exports.ClassNode = class ClassNode extends BaseNode
continue continue
if func instanceof CodeNode and func.bound if func instanceof CodeNode and func.bound
func.bound = false func.bound = false
constScope = or new Scope(o.scope, constructor.body, constructor) constScope or= new Scope(o.scope, constructor.body, constructor)
me = or constScope.freeVariable() me or= constScope.freeVariable()
pname = pvar.compile(o) pname = pvar.compile(o)
constructor.body.push new ReturnNode literal 'this' if constructor.body.empty() constructor.body.push new ReturnNode literal 'this' if constructor.body.empty()
constructor.body.unshift literal "this.#{pname} = function(){ return #{className}.prototype.#{pname}.apply(#me, arguments); }" constructor.body.unshift literal "this.#{pname} = function(){ return #{className}.prototype.#{pname}.apply(#me, arguments); }"
@ -838,8 +838,8 @@ exports.CodeNode = class CodeNode extends BaseNode
children: ['params', 'body'] children: ['params', 'body']
constructor: (@params, @body, tag) -> constructor: (@params, @body, tag) ->
@params = or [] @params or= []
@body = or new Expressions @body or= new Expressions
@bound = tag is 'boundfunc' @bound = tag is 'boundfunc'
# Compilation creates a new scope unless explicitly asked to share with the # Compilation creates a new scope unless explicitly asked to share with the
@ -893,7 +893,7 @@ exports.CodeNode = class CodeNode extends BaseNode
traverseChildren: (crossScope, func) -> super(crossScope, func) if crossScope traverseChildren: (crossScope, func) -> super(crossScope, func) if crossScope
toString: (idt) -> toString: (idt) ->
idt = or '' idt or= ''
children = (child.toString(idt + TAB) for child in @collectChildren()).join('') children = (child.toString(idt + TAB) for child in @collectChildren()).join('')
"\n#idt#children" "\n#idt#children"
@ -1251,7 +1251,7 @@ exports.ForNode = class ForNode extends BaseNode
isStatement: -> yes isStatement: -> yes
constructor: (@body, source, @name, @index) -> constructor: (@body, source, @name, @index) ->
@index = or null @index or= null
@source = source.source @source = source.source
@guard = source.guard @guard = source.guard
@step = source.step @step = source.step
@ -1340,7 +1340,7 @@ exports.IfNode = class IfNode extends BaseNode
children: ['condition', 'switchSubject', 'body', 'elseBody', 'assigner'] children: ['condition', 'switchSubject', 'body', 'elseBody', 'assigner']
constructor: (@condition, @body, @tags) -> constructor: (@condition, @body, @tags) ->
@tags = or {} @tags or= {}
@condition = new OpNode('!', new ParentheticalNode(@condition)) if @tags.invert @condition = new OpNode('!', new ParentheticalNode(@condition)) if @tags.invert
@elseBody = null @elseBody = null
@isChain = false @isChain = false
@ -1386,7 +1386,7 @@ exports.IfNode = class IfNode extends BaseNode
# The **IfNode** only compiles into a statement if either of its bodies needs # The **IfNode** only compiles into a statement if either of its bodies needs
# to be a statement. Otherwise a ternary is safe. # to be a statement. Otherwise a ternary is safe.
isStatement: -> isStatement: ->
@statement = or !!(@tags.statement or @bodyNode().isStatement() or (@elseBody and @elseBodyNode().isStatement())) @statement or= !!(@tags.statement or @bodyNode().isStatement() or (@elseBody and @elseBodyNode().isStatement()))
compileCondition: (o) -> compileCondition: (o) ->
(cond.compile(o) for cond in flatten([@condition])).join(' || ') (cond.compile(o) for cond in flatten([@condition])).join(' || ')
@ -1396,8 +1396,8 @@ exports.IfNode = class IfNode extends BaseNode
makeReturn: -> makeReturn: ->
if @isStatement() if @isStatement()
@body = and @ensureExpressions(@body.makeReturn()) @body and= @ensureExpressions(@body.makeReturn())
@elseBody = and @ensureExpressions(@elseBody.makeReturn()) @elseBody and= @ensureExpressions(@elseBody.makeReturn())
this this
else else
new ReturnNode this new ReturnNode this

View File

@ -239,7 +239,7 @@ exports.Rewriter = class Rewriter
@scanTokens (prev, token, post, i) => @scanTokens (prev, token, post, i) =>
for pair in pairs for pair in pairs
[open, close] = pair [open, close] = pair
levels[open] = or 0 levels[open] or= 0
if token[0] is open if token[0] is open
openLine[open] = token[2] if levels[open] == 0 openLine[open] = token[2] if levels[open] == 0
levels[open] += 1 levels[open] += 1

View File

@ -68,14 +68,14 @@ ok x*+y is -50
# Half-operators. # Half-operators.
one = two = null one = two = null
one = or 1 one or= 1
two = or 2 two or= 2
ok one is 1 ok one is 1
ok two is 2 ok two is 2
one = and 'one' one and= 'one'
two = and 'two' two and= 'two'
ok one is 'one' ok one is 'one'
ok two is 'two' ok two is 'two'