Skip to content

Commit a932256

Browse files
committedDec 7, 2014
Support normal rest args and keyword args together
1 parent fd20330 commit a932256

File tree

1 file changed

+63
-30
lines changed

1 file changed

+63
-30
lines changed
 

Diff for: ‎lib/opal/nodes/def.rb

+63-30
Original file line numberDiff line numberDiff line change
@@ -8,38 +8,55 @@ class DefNode < ScopeNode
88

99
children :recvr, :mid, :args, :stmts
1010

11-
def compile
12-
jsid = mid_to_jsid mid.to_s
13-
params = nil
14-
scope_name = nil
11+
def opt_args
12+
@opt_args ||= args[1..-1].select { |arg| arg.first == :optarg }
13+
end
1514

16-
opt = args[1..-1].select { |a| a.first == :optarg }
15+
def rest_arg
16+
@rest_arg ||= args[1..-1].find { |arg| arg.first == :restarg }
17+
end
1718

18-
@kwargs = args[1..-1].select do |arg|
19+
def keyword_args
20+
@keyword_args ||= args[1..-1].select do |arg|
1921
[:kwarg, :kwoptarg, :kwrestarg].include? arg.first
2022
end
23+
end
2124

22-
argc = args.length - 1
25+
def block_arg
26+
@block_arg ||= args[1..-1].find { |arg| arg.first == :blockarg }
27+
end
28+
29+
def argc
30+
return @argc if @argc
31+
32+
@argc = args.length - 1
33+
@argc -= 1 if block_arg
34+
@argc -= 1 if rest_arg
35+
@argc -= keyword_args.size
36+
37+
@argc
38+
end
39+
40+
def compile
41+
jsid = mid_to_jsid mid.to_s
42+
params = nil
43+
scope_name = nil
2344

2445
# block name (&block)
25-
if given_block = args[1..-1].find { |a| a.first == :blockarg }
26-
block_name = variable(given_block[1]).to_sym
27-
argc -= 1
46+
if block_arg
47+
block_name = variable(block_arg[1]).to_sym
2848
end
2949

3050
# splat args *splat
31-
if restarg = args[1..-1].find { |a| a.first == :restarg }
51+
if rest_arg
3252
uses_splat = true
33-
if restarg[1]
34-
splat = restarg[1].to_sym
35-
argc -= 1
36-
else
37-
argc -= 1
53+
if rest_arg[1]
54+
splat = rest_arg[1].to_sym
3855
end
3956
end
4057

4158
if compiler.arity_check?
42-
arity_code = arity_check(args, opt, uses_splat, @kwargs, block_name, mid)
59+
arity_code = arity_check(args, opt_args, uses_splat, keyword_args, block_name, mid)
4360
end
4461

4562
in_scope do
@@ -61,13 +78,7 @@ def compile
6178

6279
line "#{variable(splat)} = $slice.call(arguments, #{argc});" if splat
6380

64-
opt.each do |o|
65-
next if o[2][2] == :undefined
66-
line "if (#{variable(o[1])} == null) {"
67-
line " #{variable(o[1])} = ", expr(o[2])
68-
line "}"
69-
end
70-
81+
compile_opt_args
7182
compile_keyword_args
7283

7384
# must do this after opt args incase opt arg uses yield
@@ -118,18 +129,40 @@ def compile
118129
wrap '(', ", nil) && '#{mid}'" if expr?
119130
end
120131

132+
def compile_opt_args
133+
opt_args.each do |arg|
134+
next if arg[2][2] == :undefined
135+
line "if (#{variable(arg[1])} == null) {"
136+
line " #{variable(arg[1])} = ", expr(arg[2])
137+
line "}"
138+
end
139+
end
140+
121141
def compile_keyword_args
122-
return if @kwargs.empty?
142+
return if keyword_args.empty?
123143
helper :hash2
124144

125-
line "if ($kwargs == null) {"
126-
line " $kwargs = $hash2([], {});"
127-
line "}"
145+
if rest_arg
146+
with_temp do |tmp|
147+
rest_arg_name = variable(rest_arg[1].to_sym)
148+
line "#{tmp} = #{rest_arg_name}[#{rest_arg_name}.length - 1];"
149+
line "if (#{tmp} == null || !#{tmp}.$$is_hash) {"
150+
line " $kwargs = $hash2([], {});"
151+
line "} else {"
152+
line " $kwargs = #{rest_arg_name}.pop();"
153+
line "}"
154+
end
155+
else
156+
line "if ($kwargs == null) {"
157+
line " $kwargs = $hash2([], {});"
158+
line "}"
159+
end
160+
128161
line "if (!$kwargs.$$is_hash) {"
129162
line " throw Opal.ArgumentError.$new('expecting keyword args');"
130163
line "}"
131164

132-
@kwargs.each do |kwarg|
165+
keyword_args.each do |kwarg|
133166
case kwarg.first
134167
when :kwoptarg
135168
arg_name = kwarg[1]
@@ -147,7 +180,7 @@ def compile_keyword_args
147180
arg_name = kwarg[1]
148181
var_name = variable(arg_name.to_s)
149182

150-
kwarg_names = @kwargs.select do |kw|
183+
kwarg_names = keyword_args.select do |kw|
151184
[:kwoptarg, :kwarg].include? kw.first
152185
end.map { |kw| "#{kw[1].to_s.inspect}: true" }
153186

0 commit comments

Comments
 (0)
Please sign in to comment.