adding splats to function definitions
This commit is contained in:
parent
f299972713
commit
1d2bb3b2be
|
@ -39,7 +39,7 @@
|
||||||
<key>comment</key>
|
<key>comment</key>
|
||||||
<string>match stuff like: funcName: => … </string>
|
<string>match stuff like: funcName: => … </string>
|
||||||
<key>match</key>
|
<key>match</key>
|
||||||
<string>([a-zA-Z0-9_?.$]*)\s*(=|:)\s*([\w,\s]*?)\s*(=>)</string>
|
<string>([a-zA-Z0-9_?.$*]*)\s*(=|:)\s*([\w,\s]*?)\s*(=>)</string>
|
||||||
<key>name</key>
|
<key>name</key>
|
||||||
<string>meta.function.coffee</string>
|
<string>meta.function.coffee</string>
|
||||||
</dict>
|
</dict>
|
||||||
|
@ -60,7 +60,7 @@
|
||||||
<key>comment</key>
|
<key>comment</key>
|
||||||
<string>match stuff like: a => … </string>
|
<string>match stuff like: a => … </string>
|
||||||
<key>match</key>
|
<key>match</key>
|
||||||
<string>([a-zA-Z0-9_?., $]*)\s*(=>)</string>
|
<string>([a-zA-Z0-9_?., $*]*)\s*(=>)</string>
|
||||||
<key>name</key>
|
<key>name</key>
|
||||||
<string>meta.inline.function.coffee</string>
|
<string>meta.inline.function.coffee</string>
|
||||||
</dict>
|
</dict>
|
||||||
|
|
|
@ -5,7 +5,7 @@ token IF ELSE UNLESS
|
||||||
token NUMBER STRING REGEX
|
token NUMBER STRING REGEX
|
||||||
token TRUE FALSE YES NO ON OFF
|
token TRUE FALSE YES NO ON OFF
|
||||||
token IDENTIFIER PROPERTY_ACCESS
|
token IDENTIFIER PROPERTY_ACCESS
|
||||||
token CODE PARAM NEW RETURN
|
token CODE PARAM SPLAT NEW RETURN
|
||||||
token TRY CATCH FINALLY THROW
|
token TRY CATCH FINALLY THROW
|
||||||
token BREAK CONTINUE
|
token BREAK CONTINUE
|
||||||
token FOR IN WHILE
|
token FOR IN WHILE
|
||||||
|
@ -187,8 +187,13 @@ rule
|
||||||
|
|
||||||
# The parameters to a function definition.
|
# The parameters to a function definition.
|
||||||
ParamList:
|
ParamList:
|
||||||
PARAM { result = val }
|
Param { result = val }
|
||||||
| ParamList "," PARAM { result = val[0] << val[2] }
|
| ParamList "," Param { result = val[0] << val[2] }
|
||||||
|
;
|
||||||
|
|
||||||
|
Param:
|
||||||
|
PARAM
|
||||||
|
| SPLAT { result = SplatNode.new(val[0]) }
|
||||||
;
|
;
|
||||||
|
|
||||||
# Expressions that can be treated as values.
|
# Expressions that can be treated as values.
|
||||||
|
|
|
@ -190,15 +190,23 @@ module CoffeeScript
|
||||||
|
|
||||||
# A source of ambiguity in our grammar was parameter lists in function
|
# A source of ambiguity in our grammar was parameter lists in function
|
||||||
# definitions (as opposed to argument lists in function calls). Tag
|
# definitions (as opposed to argument lists in function calls). Tag
|
||||||
# parameter identifiers in order to avoid this.
|
# parameter identifiers in order to avoid this. Also, parameter lists can
|
||||||
|
# make use of splats.
|
||||||
def tag_parameters
|
def tag_parameters
|
||||||
index = 0
|
i = 0
|
||||||
loop do
|
loop do
|
||||||
tok = @tokens[index -= 1]
|
i -= 1
|
||||||
|
tok, prev = @tokens[i], @tokens[i - 1]
|
||||||
return if !tok
|
return if !tok
|
||||||
next if tok[0] == ','
|
next if tok[0] == ','
|
||||||
return if tok[0] != :IDENTIFIER
|
return if tok[0] != :IDENTIFIER
|
||||||
tok[0] = :PARAM
|
if prev && prev[0] == '*'
|
||||||
|
tok[0] = :SPLAT
|
||||||
|
@tokens.delete_at(i - 1)
|
||||||
|
i -= 1
|
||||||
|
else
|
||||||
|
tok[0] = :PARAM
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,11 @@ module CoffeeScript
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def unshift(node)
|
||||||
|
@expressions.unshift(node)
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
# If this Expressions consists of a single node, pull it back out.
|
# If this Expressions consists of a single node, pull it back out.
|
||||||
def unwrap
|
def unwrap
|
||||||
@expressions.length == 1 ? @expressions.first : self
|
@expressions.length == 1 ? @expressions.first : self
|
||||||
|
@ -389,7 +394,7 @@ module CoffeeScript
|
||||||
o[:scope].find(name) unless @variable.properties?
|
o[:scope].find(name) unless @variable.properties?
|
||||||
return write(@value.compile(o)) if @value.custom_assign?
|
return write(@value.compile(o)) if @value.custom_assign?
|
||||||
val = "#{name} = #{@value.compile(o)}"
|
val = "#{name} = #{@value.compile(o)}"
|
||||||
write(o[:return] && !@value.custom_return? ? "return (#{val})" : val)
|
write(o[:return] && !@value.custom_return? ? "#{o[:indent]}return (#{val})" : val)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -459,12 +464,35 @@ module CoffeeScript
|
||||||
o.delete(:no_wrap)
|
o.delete(:no_wrap)
|
||||||
name = o.delete(:immediate_assign)
|
name = o.delete(:immediate_assign)
|
||||||
@params.each {|id| o[:scope].parameter(id.to_s) }
|
@params.each {|id| o[:scope].parameter(id.to_s) }
|
||||||
|
if @params.last.is_a?(SplatNode)
|
||||||
|
splat = @params.pop
|
||||||
|
splat.index = @params.length
|
||||||
|
@body.unshift(splat)
|
||||||
|
end
|
||||||
code = @body.compile(o, :code)
|
code = @body.compile(o, :code)
|
||||||
name_part = name ? " #{name}" : ''
|
name_part = name ? " #{name}" : ''
|
||||||
write("function#{name_part}(#{@params.join(', ')}) {\n#{code}\n#{indent}}")
|
write("function#{name_part}(#{@params.join(', ')}) {\n#{code}\n#{indent}}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# A parameter splat in a function definition.
|
||||||
|
class SplatNode < Node
|
||||||
|
attr_accessor :index
|
||||||
|
attr_reader :name
|
||||||
|
|
||||||
|
def initialize(name)
|
||||||
|
@name = name
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
@name
|
||||||
|
end
|
||||||
|
|
||||||
|
def compile(o={})
|
||||||
|
"var #{@name} = Array.prototype.slice.call(arguments, #{@index})"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# An object literal.
|
# An object literal.
|
||||||
class ObjectNode < Node
|
class ObjectNode < Node
|
||||||
attr_reader :properties
|
attr_reader :properties
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
func: first, second, *rest =>
|
||||||
|
rest.join(' ')
|
||||||
|
|
||||||
|
result: func(1, 2, 3, 4, 5)
|
||||||
|
|
||||||
|
print(result is "3 4 5")
|
Loading…
Reference in New Issue