ruby2js 2.1.24 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +91 -50
- data/lib/ruby2js/converter/args.rb +10 -0
- data/lib/ruby2js/converter/block.rb +1 -1
- data/lib/ruby2js/converter/case.rb +1 -1
- data/lib/ruby2js/converter/casgn.rb +6 -1
- data/lib/ruby2js/converter/class.rb +7 -2
- data/lib/ruby2js/converter/class2.rb +167 -0
- data/lib/ruby2js/converter/def.rb +54 -6
- data/lib/ruby2js/converter/defs.rb +11 -5
- data/lib/ruby2js/converter/dstr.rb +26 -0
- data/lib/ruby2js/converter/for.rb +3 -3
- data/lib/ruby2js/converter/hash.rb +31 -6
- data/lib/ruby2js/converter/if.rb +1 -1
- data/lib/ruby2js/converter/ivasgn.rb +5 -2
- data/lib/ruby2js/converter/masgn.rb +41 -4
- data/lib/ruby2js/converter/send.rb +71 -10
- data/lib/ruby2js/converter/super.rb +21 -8
- data/lib/ruby2js/converter/vasgn.rb +5 -1
- data/lib/ruby2js/converter/while.rb +13 -0
- data/lib/ruby2js/converter.rb +32 -5
- data/lib/ruby2js/es2015/strict.rb +3 -0
- data/lib/ruby2js/es2015.rb +5 -0
- data/lib/ruby2js/es2016/strict.rb +3 -0
- data/lib/ruby2js/es2016.rb +5 -0
- data/lib/ruby2js/es2017/strict.rb +3 -0
- data/lib/ruby2js/es2017.rb +5 -0
- data/lib/ruby2js/execjs.rb +1 -1
- data/lib/ruby2js/filter/camelCase.rb +1 -1
- data/lib/ruby2js/filter/functions.rb +49 -2
- data/lib/ruby2js/filter/vue.rb +66 -45
- data/lib/ruby2js/strict.rb +3 -0
- data/lib/ruby2js/version.rb +3 -3
- data/lib/ruby2js.rb +41 -0
- data/ruby2js.gemspec +3 -1
- metadata +10 -6
- data/lib/ruby2js/filter/angular-resource.rb +0 -25
- data/lib/ruby2js/filter/angular-route.rb +0 -44
- data/lib/ruby2js/filter/angularrb.rb +0 -604
- data/lib/ruby2js/filter/strict.rb +0 -20
@@ -56,8 +56,8 @@ module Ruby2JS
|
|
56
56
|
# hoist get/set comments to definition of property
|
57
57
|
if right.type == :hash
|
58
58
|
right.children.each do |pair|
|
59
|
-
|
60
|
-
if pair.children.last.type
|
59
|
+
next unless Parser::AST::Node === pair.children.last
|
60
|
+
if [:block, :def, :async].include? pair.children.last.type
|
61
61
|
if @comments[pair.children.last]
|
62
62
|
(puts ''; singleton = false) if singleton
|
63
63
|
comments(pair.children.last).each do |comment|
|
@@ -68,15 +68,40 @@ module Ruby2JS
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
|
+
# check to see if es2015 anonymous function syntax can be used
|
72
|
+
anonfn = (es2015 and right and right.type == :block)
|
73
|
+
if anonfn
|
74
|
+
receiver, method = right.children[0].children
|
75
|
+
if receiver
|
76
|
+
unless method == :new and receiver.children == [nil, :Proc]
|
77
|
+
anonfn = false
|
78
|
+
end
|
79
|
+
elsif not [:lambda, :proc].include? method
|
80
|
+
anonfn = false
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
71
84
|
if
|
85
|
+
anonfn and
|
72
86
|
left.children.first.to_s =~ /\A[a-zA-Z_$][a-zA-Z_$0-9]*\Z/
|
73
87
|
then
|
74
|
-
|
88
|
+
@prop = left.children.first
|
89
|
+
parse right, :method
|
75
90
|
else
|
76
|
-
|
91
|
+
if not [:str, :sym].include? left.type and es2015
|
92
|
+
put '['
|
93
|
+
parse left
|
94
|
+
put ']'
|
95
|
+
elsif
|
96
|
+
left.children.first.to_s =~ /\A[a-zA-Z_$][a-zA-Z_$0-9]*\Z/
|
97
|
+
then
|
98
|
+
put left.children.first
|
99
|
+
else
|
100
|
+
parse left
|
101
|
+
end
|
102
|
+
|
103
|
+
put ': '; parse right
|
77
104
|
end
|
78
|
-
|
79
|
-
put ': '; parse right
|
80
105
|
end
|
81
106
|
|
82
107
|
ensure
|
data/lib/ruby2js/converter/if.rb
CHANGED
@@ -50,7 +50,7 @@ module Ruby2JS
|
|
50
50
|
if scope
|
51
51
|
vars = @vars.select {|key, value| value == :pending}.keys
|
52
52
|
unless vars.empty?
|
53
|
-
insert mark, "var #{vars.join(', ')}#{@sep}"
|
53
|
+
insert mark, "#{es2015 ? 'let' : 'var'} #{vars.join(', ')}#{@sep}"
|
54
54
|
vars.each {|var| @vars[var] = true}
|
55
55
|
end
|
56
56
|
end
|
@@ -4,8 +4,11 @@ module Ruby2JS
|
|
4
4
|
# (ivasgn :@a
|
5
5
|
# (int 1))
|
6
6
|
|
7
|
-
handle :ivasgn do |var, expression|
|
8
|
-
put "#{ var.to_s.sub('@', 'this._') }
|
7
|
+
handle :ivasgn do |var, expression=nil|
|
8
|
+
put "#{ var.to_s.sub('@', 'this._') }"
|
9
|
+
if expression
|
10
|
+
put " = "; parse expression
|
11
|
+
end
|
9
12
|
end
|
10
13
|
end
|
11
14
|
end
|
@@ -10,11 +10,48 @@ module Ruby2JS
|
|
10
10
|
# (int 2)))
|
11
11
|
|
12
12
|
handle :masgn do |lhs, rhs|
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
if es2015
|
14
|
+
walk = lambda do |node|
|
15
|
+
results = []
|
16
|
+
node.children.each do |var|
|
17
|
+
if var.type == :lvasgn
|
18
|
+
results << var
|
19
|
+
elsif var.type == :mlhs or var.type == :splat
|
20
|
+
results += walk[var]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
results
|
24
|
+
end
|
25
|
+
|
26
|
+
vars = walk[lhs]
|
27
|
+
newvars = vars.select {|var| not @vars.include? var.children[0]}
|
28
|
+
|
29
|
+
if newvars.length > 0
|
30
|
+
if vars == newvars
|
31
|
+
put 'let '
|
32
|
+
else
|
33
|
+
put "let #{newvars.map {|var| var.children.last}.join(', ')}#{@sep}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
newvars.each do |var|
|
38
|
+
@vars[var.children.last] ||= (@scope ? true : :pending)
|
39
|
+
end
|
40
|
+
|
41
|
+
put '['
|
42
|
+
lhs.children.each_with_index do |child, index|
|
43
|
+
put ", " unless index == 0
|
44
|
+
parse child
|
45
|
+
end
|
46
|
+
put "] = "
|
47
|
+
parse rhs
|
48
|
+
else
|
49
|
+
block = []
|
50
|
+
lhs.children.zip rhs.children.zip do |var, val|
|
51
|
+
block << s(var.type, *var.children, *val)
|
52
|
+
end
|
53
|
+
parse s(:begin, *block), @state
|
16
54
|
end
|
17
|
-
parse s(:begin, *block), @state
|
18
55
|
end
|
19
56
|
end
|
20
57
|
end
|
@@ -9,11 +9,11 @@ module Ruby2JS
|
|
9
9
|
# (sendw nil :puts
|
10
10
|
# (int 1))
|
11
11
|
|
12
|
-
# Note: attr and
|
12
|
+
# Note: attr, sendw, and await are only generated by filters. Attr forces
|
13
13
|
# interpretation as an attribute vs a function call with zero parameters.
|
14
14
|
# Sendw forces parameters to be placed on separate lines.
|
15
15
|
|
16
|
-
handle :send, :sendw, :attr, :call do |receiver, method, *args|
|
16
|
+
handle :send, :sendw, :await, :attr, :call do |receiver, method, *args|
|
17
17
|
ast = @ast
|
18
18
|
|
19
19
|
# strip '!' and '?' decorations
|
@@ -21,13 +21,13 @@ module Ruby2JS
|
|
21
21
|
|
22
22
|
# three ways to define anonymous functions
|
23
23
|
if method == :new and receiver and receiver.children == [nil, :Proc]
|
24
|
-
return parse args.first
|
24
|
+
return parse args.first, @state
|
25
25
|
elsif not receiver and [:lambda, :proc].include? method
|
26
26
|
if method == :lambda
|
27
27
|
return parse s(args.first.type, *args.first.children[0..-2],
|
28
|
-
s(:autoreturn, args.first.children[-1]))
|
28
|
+
s(:autoreturn, args.first.children[-1])), @state
|
29
29
|
else
|
30
|
-
return parse args.first
|
30
|
+
return parse args.first, @state
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
@@ -35,12 +35,59 @@ module Ruby2JS
|
|
35
35
|
if [:call, :[]].include? method and receiver and receiver.type == :block
|
36
36
|
t2,m2,*args2 = receiver.children.first.children
|
37
37
|
if not t2 and [:lambda, :proc].include? m2 and args2.length == 0
|
38
|
-
(@state == :statement ? group(receiver) : parse(receiver))
|
38
|
+
(es2015 || @state == :statement ? group(receiver) : parse(receiver))
|
39
39
|
put '('; parse_all(*args, join: ', '); put ')'
|
40
40
|
return
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
+
# async/await support
|
45
|
+
if es2017 and receiver == nil and args.length == 1
|
46
|
+
if method == :async
|
47
|
+
if args.first.type == :def
|
48
|
+
# async def f(x) {...}
|
49
|
+
return parse args.first.updated :async
|
50
|
+
|
51
|
+
elsif args.first.type == :defs
|
52
|
+
# async def o.m(x) {...}
|
53
|
+
return parse args.first.updated :asyncs
|
54
|
+
|
55
|
+
elsif args.first.type == :block
|
56
|
+
block = args.first
|
57
|
+
|
58
|
+
if block.children[0].children.last == :lambda
|
59
|
+
# async lambda {|x| ... }
|
60
|
+
# async -> (x) { ... }
|
61
|
+
return parse block.updated(:async, [nil, block.children[1],
|
62
|
+
s(:autoreturn, block.children[2])])
|
63
|
+
|
64
|
+
elsif block.children[0].children.last == :proc
|
65
|
+
# async proc {|x| ... }
|
66
|
+
return parse block.updated(:async, [nil, *block.children[1..-1]])
|
67
|
+
|
68
|
+
elsif
|
69
|
+
block.children[0].children[1] == :new and
|
70
|
+
block.children[0].children[0] == s(:const, nil, :Proc)
|
71
|
+
then
|
72
|
+
# async Proc.new {|x| ... }
|
73
|
+
return parse block.updated(:async, [nil, *block.children[1..-1]])
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
elsif method == :await
|
78
|
+
if args.first.type == :send
|
79
|
+
# await f(x)
|
80
|
+
return parse args.first.updated(:await)
|
81
|
+
|
82
|
+
elsif args.first.type == :block
|
83
|
+
# await f(x) { ... }
|
84
|
+
block = args.first
|
85
|
+
return parse block.updated nil, [block.children[0].updated(:await),
|
86
|
+
*block.children[1..-1]]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
44
91
|
op_index = operator_index method
|
45
92
|
if op_index != -1
|
46
93
|
target = args.first
|
@@ -76,6 +123,13 @@ module Ruby2JS
|
|
76
123
|
parse receiver; put '['; parse_all(*args[0..-2], join: ', '); put '] = '
|
77
124
|
parse args[-1]
|
78
125
|
|
126
|
+
elsif method == :** and not es2016
|
127
|
+
put 'Math.pow('
|
128
|
+
parse receiver
|
129
|
+
put ', '
|
130
|
+
parse args.first
|
131
|
+
put ')'
|
132
|
+
|
79
133
|
elsif [:-@, :+@, :~, '~'].include? method
|
80
134
|
put method.to_s[0]; parse receiver
|
81
135
|
|
@@ -99,7 +153,7 @@ module Ruby2JS
|
|
99
153
|
elsif method =~ /=$/
|
100
154
|
parse receiver
|
101
155
|
put "#{ '.' if receiver }#{ method.to_s.sub(/=$/, ' =') } "
|
102
|
-
parse args.first
|
156
|
+
parse args.first, (@state == :method ? :method : :expression)
|
103
157
|
|
104
158
|
elsif method == :new
|
105
159
|
if receiver
|
@@ -166,6 +220,8 @@ module Ruby2JS
|
|
166
220
|
put 'typeof '; parse args.first
|
167
221
|
|
168
222
|
else
|
223
|
+
put 'await ' if @ast.type == :await
|
224
|
+
|
169
225
|
if not ast.is_method?
|
170
226
|
if receiver
|
171
227
|
(group_receiver ? group(receiver) : parse(receiver))
|
@@ -173,7 +229,7 @@ module Ruby2JS
|
|
173
229
|
else
|
174
230
|
parse ast.updated(:lvasgn, [method]), @state
|
175
231
|
end
|
176
|
-
elsif args.
|
232
|
+
elsif args.any? {|arg| arg.type == :splat} and not es2015
|
177
233
|
parse s(:send, s(:attr, receiver, method), :apply,
|
178
234
|
(receiver || s(:nil)), s(:array, *args))
|
179
235
|
else
|
@@ -206,11 +262,16 @@ module Ruby2JS
|
|
206
262
|
# build up chain of conditional evaluations
|
207
263
|
until stack.empty?
|
208
264
|
node = stack.pop
|
209
|
-
|
210
|
-
|
265
|
+
expr = node.updated(:send, [expr, *node.children[1..-1]])
|
266
|
+
result = s(:and, result, expr)
|
211
267
|
end
|
212
268
|
|
213
269
|
parse result
|
214
270
|
end
|
271
|
+
|
272
|
+
handle :splat do |expr|
|
273
|
+
put '...'
|
274
|
+
parse expr
|
275
|
+
end
|
215
276
|
end
|
216
277
|
end
|
@@ -6,7 +6,7 @@ module Ruby2JS
|
|
6
6
|
# (super ...)
|
7
7
|
|
8
8
|
handle :super, :zsuper do |*args|
|
9
|
-
unless @
|
9
|
+
unless @instance_method and @class_parent
|
10
10
|
raise NotImplementedError, "super outside of a method"
|
11
11
|
end
|
12
12
|
|
@@ -21,15 +21,28 @@ module Ruby2JS
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
|
24
|
+
if es2015
|
25
|
+
if @instance_method.children[0] == :constructor
|
26
|
+
put 'super'
|
27
|
+
else
|
28
|
+
put 'super.'
|
29
|
+
put @instance_method.children[0]
|
30
|
+
end
|
25
31
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
32
|
+
put '('
|
33
|
+
parse s(:args, *args)
|
34
|
+
put ')'
|
35
|
+
else
|
36
|
+
parse @class_parent
|
30
37
|
|
31
|
-
|
32
|
-
|
38
|
+
# what to call
|
39
|
+
if @instance_method.type != :constructor
|
40
|
+
puts ".prototype.#{ @instance_method.children[1].to_s.chomp('=') }"
|
41
|
+
end
|
42
|
+
|
43
|
+
if args
|
44
|
+
put '.call('; parse_all s(:self), *args, join: ', '; put ')'
|
45
|
+
end
|
33
46
|
end
|
34
47
|
end
|
35
48
|
end
|
@@ -9,6 +9,19 @@ module Ruby2JS
|
|
9
9
|
begin
|
10
10
|
next_token, @next_token = @next_token, :continue
|
11
11
|
|
12
|
+
# handle while loops that assign a variable
|
13
|
+
while condition.type == :begin and condition.children.length == 1
|
14
|
+
condition = condition.children.first
|
15
|
+
end
|
16
|
+
|
17
|
+
if condition.type == :lvasgn
|
18
|
+
var = condition.children[0]
|
19
|
+
unless @vars[var]
|
20
|
+
put "#{es2015 ? 'let' : 'var'} #{var}#@sep"
|
21
|
+
@vars[var] = true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
12
25
|
put 'while ('; parse condition; puts ') {'; scope block; sput '}'
|
13
26
|
ensure
|
14
27
|
@next_token = next_token
|
data/lib/ruby2js/converter.rb
CHANGED
@@ -5,8 +5,9 @@ module Ruby2JS
|
|
5
5
|
attr_accessor :ast
|
6
6
|
|
7
7
|
LOGICAL = :and, :not, :or
|
8
|
-
OPERATORS = [:[], :[]=], [:not, :!], [:*, :/, :%], [:+, :-],
|
9
|
-
[:&], [:^, :|], [:<=, :<, :>, :>=], [:==, :!=, :===, :"!=="],
|
8
|
+
OPERATORS = [:[], :[]=], [:not, :!], [:**], [:*, :/, :%], [:+, :-],
|
9
|
+
[:>>, :<<], [:&], [:^, :|], [:<=, :<, :>, :>=], [:==, :!=, :===, :"!=="],
|
10
|
+
[:and, :or]
|
10
11
|
|
11
12
|
INVERT_OP = {
|
12
13
|
:< => :>=,
|
@@ -44,6 +45,9 @@ module Ruby2JS
|
|
44
45
|
@prototype = nil
|
45
46
|
@class_parent = nil
|
46
47
|
@class_name = nil
|
48
|
+
|
49
|
+
@eslevel = :es5
|
50
|
+
@strict = false
|
47
51
|
end
|
48
52
|
|
49
53
|
def width=(width)
|
@@ -52,6 +56,14 @@ module Ruby2JS
|
|
52
56
|
|
53
57
|
def convert
|
54
58
|
parse( @ast, :statement )
|
59
|
+
|
60
|
+
if @strict
|
61
|
+
if @sep == '; '
|
62
|
+
@lines.first.unshift "\"use strict\"#@sep"
|
63
|
+
else
|
64
|
+
@lines.unshift Line.new('"use strict";')
|
65
|
+
end
|
66
|
+
end
|
55
67
|
end
|
56
68
|
|
57
69
|
def operator_index op
|
@@ -73,6 +85,20 @@ module Ruby2JS
|
|
73
85
|
Parser::AST::Node.new(type, args)
|
74
86
|
end
|
75
87
|
|
88
|
+
attr_accessor :strict, :eslevel
|
89
|
+
|
90
|
+
def es2015
|
91
|
+
@eslevel >= 2015
|
92
|
+
end
|
93
|
+
|
94
|
+
def es2016
|
95
|
+
@eslevel >= 2016
|
96
|
+
end
|
97
|
+
|
98
|
+
def es2017
|
99
|
+
@eslevel >= 2017
|
100
|
+
end
|
101
|
+
|
76
102
|
@@handlers = []
|
77
103
|
def self.handle(*types, &block)
|
78
104
|
types.each do |type|
|
@@ -132,9 +158,9 @@ module Ruby2JS
|
|
132
158
|
end
|
133
159
|
|
134
160
|
def parse_all(*args)
|
135
|
-
options = (Hash === args.last) ? args.pop : {}
|
136
|
-
sep = options[:join].to_s
|
137
|
-
state = options[:state] || :expression
|
161
|
+
@options = (Hash === args.last) ? args.pop : {}
|
162
|
+
sep = @options[:join].to_s
|
163
|
+
state = @options[:state] || :expression
|
138
164
|
|
139
165
|
args.each_with_index do |arg, index|
|
140
166
|
put sep unless index == 0
|
@@ -211,6 +237,7 @@ require 'ruby2js/converter/break'
|
|
211
237
|
require 'ruby2js/converter/case'
|
212
238
|
require 'ruby2js/converter/casgn'
|
213
239
|
require 'ruby2js/converter/class'
|
240
|
+
require 'ruby2js/converter/class2'
|
214
241
|
require 'ruby2js/converter/const'
|
215
242
|
require 'ruby2js/converter/cvar'
|
216
243
|
require 'ruby2js/converter/cvasgn'
|
data/lib/ruby2js/execjs.rb
CHANGED
@@ -17,7 +17,7 @@ module Ruby2JS
|
|
17
17
|
if node.children[0] == nil and WHITELIST.include? node.children[1].to_s
|
18
18
|
super
|
19
19
|
elsif node.children[1] =~ /_.*\w$/
|
20
|
-
super S(
|
20
|
+
super S(:send , node.children[0],
|
21
21
|
camelCase(node.children[1]), *node.children[2..-1])
|
22
22
|
else
|
23
23
|
super
|
@@ -47,8 +47,12 @@ module Ruby2JS
|
|
47
47
|
process S(:call, target, :toString, *args)
|
48
48
|
|
49
49
|
elsif method == :Array and target == nil
|
50
|
-
|
51
|
-
:
|
50
|
+
if es2015
|
51
|
+
process S(:send, s(:const, nil, :Array), :from, *args)
|
52
|
+
else
|
53
|
+
process S(:send, s(:attr, s(:attr, s(:const, nil, :Array),
|
54
|
+
:prototype), :slice), :call, *args)
|
55
|
+
end
|
52
56
|
|
53
57
|
elsif method == :to_i
|
54
58
|
process node.updated :send, [nil, :parseInt, target, *args]
|
@@ -368,6 +372,49 @@ module Ruby2JS
|
|
368
372
|
:step, step])
|
369
373
|
process node.updated(nil, [call, *node.children[1..-1]])
|
370
374
|
|
375
|
+
elsif
|
376
|
+
# (a..b).each {|v| ...}
|
377
|
+
call.children[1] == :each and
|
378
|
+
call.children[0].type == :begin and
|
379
|
+
call.children[0].children.length == 1 and
|
380
|
+
[:irange, :erange].include? call.children[0].children[0].type and
|
381
|
+
node.children[1].children.length == 1
|
382
|
+
then
|
383
|
+
s(:for, s(:lvasgn, node.children[1].children[0].children[0]),
|
384
|
+
call.children[0].children[0], node.children[2])
|
385
|
+
|
386
|
+
elsif
|
387
|
+
[:each, :each_value].include? call.children[1] and
|
388
|
+
node.children[1].children.length == 1
|
389
|
+
then
|
390
|
+
if es2015
|
391
|
+
process node.updated(:for_of,
|
392
|
+
[s(:lvasgn, node.children[1].children[0].children[0]),
|
393
|
+
node.children[0].children[0], node.children[2]])
|
394
|
+
else
|
395
|
+
process node.updated(nil, [s(:send, call.children[0],
|
396
|
+
:forEach), *node.children[1..2]])
|
397
|
+
end
|
398
|
+
|
399
|
+
elsif
|
400
|
+
call.children[1] == :each_key and
|
401
|
+
[:each, :each_key].include? call.children[1] and
|
402
|
+
node.children[1].children.length == 1
|
403
|
+
then
|
404
|
+
process node.updated(:for,
|
405
|
+
[s(:lvasgn, node.children[1].children[0].children[0]),
|
406
|
+
node.children[0].children[0], node.children[2]])
|
407
|
+
|
408
|
+
elsif es2015 and call.children[1] == :inject
|
409
|
+
process node.updated(:send, [call.children[0], :reduce,
|
410
|
+
s(:block, s(:send, nil, :lambda), *node.children[1..2]),
|
411
|
+
*call.children[2..-1]])
|
412
|
+
|
413
|
+
elsif es2017 and call.children[1] == :each_pair
|
414
|
+
process node.updated(nil, [s(:send, s(:send, s(:const, nil, :Object),
|
415
|
+
:entries, call.children[0]), :forEach), s(:args, s(:mlhs,
|
416
|
+
*node.children[1].children)), node.children[2]])
|
417
|
+
|
371
418
|
else
|
372
419
|
super
|
373
420
|
end
|