converted the tests to use optional parentheses -- lot's of little subtleties to work out

This commit is contained in:
Jeremy Ashkenas 2010-01-24 23:40:45 -05:00
parent 70e3a6ef2f
commit a5d39efdd2
25 changed files with 106 additions and 101 deletions

View File

@ -55,7 +55,7 @@
<key>name</key>
<string>variable.parameter.function.coffee</string>
</dict>
<key>2</key>
<key>3</key>
<dict>
<key>name</key>
<string>storage.type.function.coffee</string>
@ -64,7 +64,7 @@
<key>comment</key>
<string>match stuff like: a =&gt; … </string>
<key>match</key>
<string>([a-zA-Z0-9_?., $*]*)\s*(=+&gt;)</string>
<string>([a-zA-Z0-9_?.$]*(,\s*[a-zA-Z0-9_?.$]+)*)\s*(=+&gt;)</string>
<key>name</key>
<string>meta.inline.function.coffee</string>
</dict>

View File

@ -163,7 +163,7 @@ module CoffeeScript
@line += indent.scan(MULTILINER).size
@i += indent.size
next_character = @chunk[MULTI_DENT, 4]
no_newlines = next_character == '.' || (last_value.to_s.match(NO_NEWLINE) && !last_value.match(CODE))
no_newlines = next_character == '.' || (last_value.to_s.match(NO_NEWLINE) && @tokens[-2][0] != '.' && !last_value.match(CODE))
return suppress_newlines(indent) if no_newlines
size = indent.scan(LAST_DENT).last.last.length
return newline_token(indent) if size == @indent
@ -242,13 +242,19 @@ module CoffeeScript
# make use of splats.
def tag_parameters
i = 0
tagged = false
loop do
i -= 1
tok = @tokens[i]
return if !tok
next if ['.', ','].include?(tok[0])
if ['.', ','].include?(tok[0])
tagged = false
next
end
return if tagged
return if tok[0] != :IDENTIFIER
tok[0] = :PARAM
tagged = true
end
end

View File

@ -17,9 +17,11 @@ module CoffeeScript
# Tokens that indicate the close of a clause of an expression.
EXPRESSION_CLOSE = [:CATCH, :WHEN, :ELSE, :FINALLY] + EXPRESSION_TAIL
# Tokens that, when immediately following an identifier, activate an
# implicit method call.
IMPLICIT_CALL = [:IDENTIFIER, :NUMBER, :STRING, :JS, :REGEX]
# Tokens pairs that, in immediate succession, indicate an implicit call.
IMPLICIT_FUNC = [:IDENTIFIER, :SUPER]
IMPLICIT_CALL = [:IDENTIFIER, :NUMBER, :STRING, :JS, :REGEX, :NEW, :PARAM,
:TRY, :DELETE, :INSTANCEOF, :TYPEOF, :SWITCH, :ARGUMENTS,
:TRUE, :FALSE, :YES, :NO, :ON, :OFF, '!', '!!', :NOT]
# The inverse mappings of token pairs we're trying to fix up.
INVERSES = BALANCED_PAIRS.inject({}) do |memo, pair|
@ -42,8 +44,8 @@ module CoffeeScript
remove_leading_newlines
remove_mid_expression_newlines
move_commas_outside_outdents
add_implicit_indentation
add_implicit_parentheses
add_implicit_indentation
ensure_balance(*BALANCED_PAIRS)
rewrite_closing_parens
@tokens
@ -156,7 +158,7 @@ module CoffeeScript
open = false
next 2
end
next 1 unless prev[0] == :IDENTIFIER && IMPLICIT_CALL.include?(token[0])
next 1 unless IMPLICIT_FUNC.include?(prev[0]) && IMPLICIT_CALL.include?(token[0])
@tokens.insert(i, ['(', Value.new('(', token[1].line)])
open = true
next 2

View File

@ -1,4 +1,4 @@
results: [1, 2, 3].map() x =>
x * x
print(results.join(' ') is '1 4 9')
print results.join(' ') is '1 4 9'

View File

@ -18,19 +18,19 @@ ThirdChild extends SecondChild
ThirdChild::func: string =>
super('three/') + string
result: (new ThirdChild()).func('four')
result: (new ThirdChild()).func 'four'
print(result is 'zero/one/two/three/four')
print result is 'zero/one/two/three/four'
TopClass: arg =>
this.prop: 'top-' + arg
SuperClass: arg =>
super('super-' + arg)
super 'super-' + arg
SubClass: =>
super('sub')
super 'sub'
SuperClass extends TopClass
SubClass extends SuperClass

View File

@ -2,7 +2,7 @@ identity_wrap: x => => x
result: identity_wrap(identity_wrap(true))()()
print(result)
print result
str: 'god'
@ -13,7 +13,7 @@ result: str.
reverse().
reverse()
print(result.join('') is 'dog')
print result.join('') is 'dog'
result: str
.split('')
@ -21,4 +21,4 @@ result: str
.reverse()
.reverse()
print(result.join('') is 'dog')
print result.join('') is 'dog'

View File

@ -3,26 +3,26 @@ b: -2
[a, b]: [b, a]
print(a is -2)
print(b is -1)
print a is -2
print b is -1
arr: [1, 2, 3]
[a, b, c]: arr
print(a is 1)
print(b is 2)
print(c is 3)
print a is 1
print b is 2
print c is 3
obj: {x: 10, y: 20, z: 30}
{x: a, y: b, z: c}: obj
print(a is 10)
print(b is 20)
print(c is 30)
print a is 10
print b is 20
print c is 30
person: {
@ -42,8 +42,8 @@ person: {
{name: a, family: {brother: {addresses: [one, {city: b}]}}}: person
print(a is "Bob")
print(b is "Moquasset NY, 10021")
print a is "Bob"
print b is "Moquasset NY, 10021"
test: {
@ -59,4 +59,4 @@ test: {
{person: {address: [ignore, addr...]}}: test
print(addr.join(', ') is "Street 101, Apt 101, City 101")
print addr.join(', ') is "Street 101, Apt 101, City 101"

View File

@ -3,7 +3,7 @@ func: =>
b: []
while a >= 0
b.push('o')
b.push 'o'
a--
c: {
@ -26,4 +26,4 @@ func: =>
c.single: c.list[1..1][0]
print(func() is '-')
print func() is '-'

View File

@ -12,7 +12,7 @@ a: null
a ?= 10
b ?= 10
print(a is 10 and b is 10)
print a is 10 and b is 10
# The existential operator.
@ -20,7 +20,7 @@ print(a is 10 and b is 10)
z: null
x: z ? "EX"
print(z is null and x is "EX")
print z is null and x is "EX"
# Only evaluate once.
@ -39,17 +39,17 @@ obj: {
prop: "hello"
}
print(obj?.prop is "hello")
print obj?.prop is "hello"
print(obj?.prop?.non?.existent?.property is undefined)
print obj?.prop?.non?.existent?.property is undefined
# Soaks and caches method calls as well.
arr: ["--", "----"]
print(arr.pop()?.length is 4)
print(arr.pop()?.length is 2)
print(arr.pop()?.length is undefined)
print(arr[0]?.length is undefined)
print(arr.pop()?.length?.non?.existent()?.property is undefined)
print arr.pop()?.length is 4
print arr.pop()?.length is 2
print arr.pop()?.length is undefined
print arr[0]?.length is undefined
print arr.pop()?.length?.non?.existent()?.property is undefined

View File

@ -9,7 +9,7 @@ findit: items =>
for item in items
return item if item is "bacon"
print(findit(items) is "bacon")
print findit(items) is "bacon"
# When when a closure wrapper is generated for expression conversion, make sure
@ -26,5 +26,5 @@ obj: {
this.num
}
print(obj.num is obj.func())
print(obj.num is obj.result)
print obj.num is obj.func()
print obj.num is obj.result

View File

@ -7,4 +7,4 @@ result: if a
if d
true
print(result)
print result

View File

@ -2,10 +2,10 @@ x: 1
y: {}
y.x: => 3
print(x is 1)
print(typeof(y.x) is 'function')
print(y.x() is 3)
print(y.x.name is 'x')
print x is 1
print typeof(y.x) is 'function'
print y.x() is 3
print y.x.name is 'x'
# The empty function should not cause a syntax error.
@ -40,9 +40,9 @@ memoize: fn =>
Math: {
Add: a, b => a + b
AnonymousAdd: (a, b => a + b)
FastAdd: memoize() a, b => a + b
FastAdd: memoize a, b => a + b
}
print(Math.Add(5, 5) is 10)
print(Math.AnonymousAdd(10, 10) is 20)
print(Math.FastAdd(20, 20) is 40)
print Math.Add(5, 5) is 10
print Math.AnonymousAdd(10, 10) is 20
print Math.FastAdd(20, 20) is 40

View File

@ -18,4 +18,4 @@ switch 'string'
code()
# comment
print(func())
print func()

View File

@ -3,7 +3,7 @@ a: """
on two lines
"""
print(a is "basic heredoc\non two lines")
print a is "basic heredoc\non two lines"
a: '''
@ -12,12 +12,12 @@ a: '''
c
'''
print(a is "a\n \"b\nc")
print a is "a\n \"b\nc"
a: '''one-liner'''
print(a is 'one-liner')
print a is 'one-liner'
a: """
@ -25,7 +25,7 @@ a: """
here
"""
print(a is "out\nhere")
print a is "out\nhere"
a: '''
@ -34,7 +34,7 @@ a: '''
c
'''
print(a is " a\n b\nc")
print a is " a\n b\nc"
a: '''
a
@ -43,4 +43,4 @@ a
b c
'''
print(a is "a\n\n\nb c")
print a is "a\n\n\nb c"

View File

@ -1,10 +1,10 @@
num: 1 + 2 + (a: 3)
print(num is 6)
print num is 6
result: if true
false
other: "result"
print(result is "result" and other is "result")
print result is "result" and other is "result"

View File

@ -1,37 +1,37 @@
a: [(x => x), (x => x * x)]
print(a.length is 2)
print a.length is 2
regex: /match/i
words: "I think there is a match in here."
print(!!words.match(regex))
print !!words.match(regex)
neg: (3 -4)
print(neg is -1)
print neg is -1
func: =>
return if true
print(func() is null)
print func() is null
str: "\\"
reg: /\\/
print(reg(str) and str is '\\')
print reg(str) and str is '\\'
i: 10
while i -= 1
print(i is 0)
print i is 0
money$: 'dollars'
print(money$ is 'dollars')
print money$ is 'dollars'

View File

@ -6,6 +6,6 @@ multi_liner:
single_liner:
[x, y] for y in [3..5] for x in [3..5]
print(multi_liner.length is single_liner.length)
print(5 is multi_liner[2][2][1])
print(5 is single_liner[2][2][1])
print multi_liner.length is single_liner.length
print 5 is multi_liner[2][2][1]
print 5 is single_liner[2][2][1]

View File

@ -3,4 +3,4 @@ six:
2 +
3
print(six is 6)
print six is 6

View File

@ -1,12 +1,12 @@
# CoffeeScript's operations should be chainable, like Python's.
print(500 > 50 > 5 > -5)
print 500 > 50 > 5 > -5
print(true is not false is true is not false)
print true is not false is true is not false
print(10 < 20 > 10)
print 10 < 20 > 10
print(50 > 10 > 5 is parseInt('5', 10))
print 50 > 10 > 5 is parseInt('5', 10)
# Make sure that each argument is only evaluated once, even if used
@ -15,4 +15,4 @@ print(50 > 10 > 5 is parseInt('5', 10))
i: 0
func: => i++
print(1 > func() < 1)
print 1 > func() < 1

View File

@ -5,16 +5,16 @@ negs: negs[0..2]
result: nums.concat(negs).join(', ')
print(result is '3, 6, 9, -20, -19, -18')
print result is '3, 6, 9, -20, -19, -18'
# Ensure that ranges are safe. This used to infinite loop:
j = 5
result: for j in [j..(j+3)]
j
print(result.join(' ') is '5 6 7 8')
print result.join(' ') is '5 6 7 8'
# With range comprehensions, you can loop in steps.
results: x for x in [0..25] by 5
print(results.join(' ') is '0 5 10 15 20 25')
print results.join(' ') is '0 5 10 15 20 25'

View File

@ -5,7 +5,7 @@ b: array[2...4]
result: a.concat(b).join(' ')
print(result is "7 8 9 2 3")
print result is "7 8 9 2 3"
countdown: [10..1].join(' ')
print(countdown is "10 9 8 7 6 5 4 3 2 1")
print countdown is "10 9 8 7 6 5 4 3 2 1"

View File

@ -1,9 +1,9 @@
func: first, second, rest... =>
rest.join(' ')
rest.join ' '
result: func(1, 2, 3, 4, 5)
result: func 1, 2, 3, 4, 5
print(result is "3 4 5")
print result is "3 4 5"
gold: silver: bronze: the_field: null
@ -27,9 +27,9 @@ contenders: [
"Usain Bolt"
]
medalists("Mighty Mouse", contenders...)
medalists "Mighty Mouse", contenders...
print(gold is "Mighty Mouse")
print(silver is "Michael Phelps")
print(bronze is "Liu Xiang")
print(the_field.length is 8)
print gold is "Mighty Mouse"
print silver is "Michael Phelps"
print bronze is "Liu Xiang"
print the_field.length is 8

View File

@ -1,7 +1,5 @@
array: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
array[5..10]: [0, 0, 0]
print(array.join(' ') is '0 1 2 3 4 0 0 0')
print array.join(' ') is '0 1 2 3 4 0 0 0'

View File

@ -14,8 +14,7 @@ result: switch num
when 11 then false
else false
print(result)
print result
func: num =>
switch num
@ -25,7 +24,7 @@ func: num =>
false
else false
print(func(2))
print(func(6))
print(!func(3))
print(!func(8))
print func(2)
print func(6)
print !func(3)
print !func(8)

View File

@ -1,17 +1,17 @@
i: 100
while i -= 1
print(i is 0)
print i is 0
i: 5
list: while i -= 1
i * 2
print(list.join(' ') is "8 6 4 2")
print list.join(' ') is "8 6 4 2"
i: 5
list: (i * 3 while i -= 1)
print(list.join(' ') is "12 9 6 3")
print list.join(' ') is "12 9 6 3"