added Python's chainable comparisons, like: 10 > 5 > 1

This commit is contained in:
Jeremy Ashkenas 2010-01-16 16:37:49 -05:00
parent c6c0c7d059
commit 9cb0564972
3 changed files with 31 additions and 2 deletions

View File

@ -26,7 +26,7 @@ module CoffeeScript
# Provide a quick implementation of a children method.
def self.children(*attributes)
attr_reader *attributes
attr_reader(*attributes)
attrs = attributes.map {|a| "[@#{a}]" }.join(', ')
class_eval "def children; [#{attrs}].flatten.compact; end"
end
@ -205,7 +205,7 @@ module CoffeeScript
def compile_node(o)
indent = statement? ? idt : ''
ending = statement? ? ';' : ''
write "#{indent}#{@value}#{ending}"
"#{indent}#{@value}#{ending}"
end
end
@ -355,6 +355,10 @@ module CoffeeScript
properties? && @properties.last.is_a?(SliceNode)
end
def unwrap
@properties.empty? ? @base : self
end
# Values are statements if their base is a statement.
def statement?
@base.is_a?(Node) && @base.statement? && !properties?
@ -550,6 +554,7 @@ module CoffeeScript
:isnt => "!==",
:not => '!'
}
CHAINABLE = [:<, :>, :>=, :<=, :===, :'!===']
CONDITIONALS = [:'||=', :'&&=']
PREFIX_OPERATORS = [:typeof, :delete]
@ -562,12 +567,23 @@ module CoffeeScript
@second.nil?
end
def chainable?
CHAINABLE.include?(operator.to_sym) && !unary?
end
def compile_node(o)
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_unary(o)) if unary?
write("#{@first.compile(o)} #{@operator} #{@second.compile(o)}")
end
# Mimic Python's chained comparisons. See:
# http://docs.python.org/reference/expressions.html#notin
def compile_chain(o)
write("(#{@first.compile(o)}) && (#{@first.unwrap.second.compile(o)} #{@operator} #{@second.compile(o)})")
end
def compile_conditional(o)
first, second = @first.compile(o), @second.compile(o)
sym = @operator[0..1]

View File

@ -55,6 +55,10 @@ module CoffeeScript
def statement_only?
false
end
def contains?
false
end
end
end

View File

@ -0,0 +1,9 @@
# CoffeeScript's operations should be chainable, like Python's.
print(500 > 50 > 5 > -5)
print(true is not false is true is not false)
print(10 < 20 > 10)
print(50 > 10 > 5 is parseInt('5', 10))