@@ -8,38 +8,55 @@ class DefNode < ScopeNode
8
8
9
9
children :recvr , :mid , :args , :stmts
10
10
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
15
14
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
17
18
18
- @kwargs = args [ 1 ..-1 ] . select do |arg |
19
+ def keyword_args
20
+ @keyword_args ||= args [ 1 ..-1 ] . select do |arg |
19
21
[ :kwarg , :kwoptarg , :kwrestarg ] . include? arg . first
20
22
end
23
+ end
21
24
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
23
44
24
45
# 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
28
48
end
29
49
30
50
# splat args *splat
31
- if restarg = args [ 1 ..- 1 ] . find { | a | a . first == :restarg }
51
+ if rest_arg
32
52
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
38
55
end
39
56
end
40
57
41
58
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 )
43
60
end
44
61
45
62
in_scope do
@@ -61,13 +78,7 @@ def compile
61
78
62
79
line "#{ variable ( splat ) } = $slice.call(arguments, #{ argc } );" if splat
63
80
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
71
82
compile_keyword_args
72
83
73
84
# must do this after opt args incase opt arg uses yield
@@ -118,18 +129,40 @@ def compile
118
129
wrap '(' , ", nil) && '#{ mid } '" if expr?
119
130
end
120
131
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
+
121
141
def compile_keyword_args
122
- return if @kwargs . empty?
142
+ return if keyword_args . empty?
123
143
helper :hash2
124
144
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
+
128
161
line "if (!$kwargs.$$is_hash) {"
129
162
line " throw Opal.ArgumentError.$new('expecting keyword args');"
130
163
line "}"
131
164
132
- @kwargs . each do |kwarg |
165
+ keyword_args . each do |kwarg |
133
166
case kwarg . first
134
167
when :kwoptarg
135
168
arg_name = kwarg [ 1 ]
@@ -147,7 +180,7 @@ def compile_keyword_args
147
180
arg_name = kwarg [ 1 ]
148
181
var_name = variable ( arg_name . to_s )
149
182
150
- kwarg_names = @kwargs . select do |kw |
183
+ kwarg_names = keyword_args . select do |kw |
151
184
[ :kwoptarg , :kwarg ] . include? kw . first
152
185
end . map { |kw | "#{ kw [ 1 ] . to_s . inspect } : true" }
153
186
0 commit comments