mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-02-18 03:21:20 -05:00
the existential operator can now be used infix as well
This commit is contained in:
@@ -179,6 +179,7 @@ rule
|
|||||||
| Expression '||' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
| Expression '||' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||||
| Expression AND Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
| Expression AND Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||||
| Expression OR Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
| Expression OR Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||||
|
| Expression '?' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||||
|
|
||||||
| Expression '-=' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
| Expression '-=' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||||
| Expression '+=' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
| Expression '+=' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||||
|
|||||||
@@ -556,7 +556,7 @@ module CoffeeScript
|
|||||||
:not => '!'
|
:not => '!'
|
||||||
}
|
}
|
||||||
CHAINABLE = [:<, :>, :>=, :<=, :===, :'!===']
|
CHAINABLE = [:<, :>, :>=, :<=, :===, :'!===']
|
||||||
CONDITIONALS = [:'||=', :'&&=', :'?=']
|
ASSIGNMENT = [:'||=', :'&&=', :'?=']
|
||||||
PREFIX_OPERATORS = [:typeof, :delete]
|
PREFIX_OPERATORS = [:typeof, :delete]
|
||||||
|
|
||||||
def initialize(operator, first, second=nil, flip=false)
|
def initialize(operator, first, second=nil, flip=false)
|
||||||
@@ -574,8 +574,9 @@ module CoffeeScript
|
|||||||
|
|
||||||
def compile_node(o)
|
def compile_node(o)
|
||||||
return write(compile_chain(o)) if chainable? && @first.unwrap.is_a?(OpNode) && @first.unwrap.chainable?
|
return write(compile_chain(o)) if chainable? && @first.unwrap.is_a?(OpNode) && @first.unwrap.chainable?
|
||||||
return write(compile_conditional(o)) if CONDITIONALS.include?(@operator.to_sym)
|
return write(compile_assignment(o)) if ASSIGNMENT.include?(@operator.to_sym)
|
||||||
return write(compile_unary(o)) if unary?
|
return write(compile_unary(o)) if unary?
|
||||||
|
return write(compile_existence(o)) if @operator == '?'
|
||||||
write("#{@first.compile(o)} #{@operator} #{@second.compile(o)}")
|
write("#{@first.compile(o)} #{@operator} #{@second.compile(o)}")
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -588,17 +589,22 @@ module CoffeeScript
|
|||||||
@first.second = ParentheticalNode.new(AssignNode.new(temp, shared))
|
@first.second = ParentheticalNode.new(AssignNode.new(temp, shared))
|
||||||
shared = temp
|
shared = temp
|
||||||
end
|
end
|
||||||
write("(#{@first.compile(o)}) && (#{shared.compile(o)} #{@operator} #{@second.compile(o)})")
|
"(#{@first.compile(o)}) && (#{shared.compile(o)} #{@operator} #{@second.compile(o)})"
|
||||||
end
|
end
|
||||||
|
|
||||||
def compile_conditional(o)
|
def compile_assignment(o)
|
||||||
first, second = @first.compile(o), @second.compile(o)
|
first, second = @first.compile(o), @second.compile(o)
|
||||||
o[:scope].find(first) if @first.unwrap.is_a?(Value)
|
o[:scope].find(first) if @first.unwrap.is_a?(Value)
|
||||||
sym = @operator[0..1]
|
sym = @operator[0..1]
|
||||||
return "#{first} = (#{first} !== undefined && #{first} !== null) ? #{first} : #{second}" if @operator == '?='
|
return "#{first} = #{ExistenceNode.compile_test(first)} ? #{first} : #{second}" if @operator == '?='
|
||||||
"#{first} = #{first} #{sym} #{second}"
|
"#{first} = #{first} #{sym} #{second}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def compile_existence(o)
|
||||||
|
first, second = @first.compile(o), @second.compile(o)
|
||||||
|
"#{ExistenceNode.compile_test(first)} ? #{first} : #{second}"
|
||||||
|
end
|
||||||
|
|
||||||
def compile_unary(o)
|
def compile_unary(o)
|
||||||
space = PREFIX_OPERATORS.include?(@operator.to_sym) ? ' ' : ''
|
space = PREFIX_OPERATORS.include?(@operator.to_sym) ? ' ' : ''
|
||||||
parts = [@operator.to_s, space, @first.compile(o)]
|
parts = [@operator.to_s, space, @first.compile(o)]
|
||||||
@@ -890,13 +896,16 @@ module CoffeeScript
|
|||||||
class ExistenceNode < Node
|
class ExistenceNode < Node
|
||||||
children :expression
|
children :expression
|
||||||
|
|
||||||
|
def self.compile_test(variable)
|
||||||
|
"(typeof #{variable} !== \"undefined\" && #{variable} !== null)"
|
||||||
|
end
|
||||||
|
|
||||||
def initialize(expression)
|
def initialize(expression)
|
||||||
@expression = expression
|
@expression = expression
|
||||||
end
|
end
|
||||||
|
|
||||||
def compile_node(o)
|
def compile_node(o)
|
||||||
val = @expression.compile(o)
|
write(ExistenceNode.compile_test(@expression.compile(o)))
|
||||||
write("(typeof #{val} !== \"undefined\" && #{val} !== null)")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
20
test/fixtures/execution/test_existence.coffee
vendored
20
test/fixtures/execution/test_existence.coffee
vendored
@@ -2,4 +2,22 @@ print(if my_special_variable? then false else true)
|
|||||||
|
|
||||||
my_special_variable: false
|
my_special_variable: false
|
||||||
|
|
||||||
print(if my_special_variable? then true else false)
|
print(if my_special_variable? then true else false)
|
||||||
|
|
||||||
|
|
||||||
|
# Existential assignment.
|
||||||
|
|
||||||
|
a: 5
|
||||||
|
a: null
|
||||||
|
a ?= 10
|
||||||
|
b ?= 10
|
||||||
|
|
||||||
|
print(a is 10 and b is 10)
|
||||||
|
|
||||||
|
|
||||||
|
# The existential operator.
|
||||||
|
|
||||||
|
z: null
|
||||||
|
x: z ? "EX"
|
||||||
|
|
||||||
|
print(z is null and x is "EX")
|
||||||
10
test/fixtures/execution/test_operations.coffee
vendored
10
test/fixtures/execution/test_operations.coffee
vendored
@@ -16,13 +16,3 @@ i: 0
|
|||||||
func: => i++
|
func: => i++
|
||||||
|
|
||||||
print(1 > func() < 1)
|
print(1 > func() < 1)
|
||||||
|
|
||||||
|
|
||||||
# The conditional assignment based on existence.
|
|
||||||
|
|
||||||
a: 5
|
|
||||||
a: null
|
|
||||||
a ?= 10
|
|
||||||
b ?= 10
|
|
||||||
|
|
||||||
print(a is 10 and b is 10)
|
|
||||||
Reference in New Issue
Block a user