ruby2js 1.0.0 → 1.1.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 +8 -8
- data/lib/ruby2js.rb +2 -2
- data/lib/ruby2js/converter.rb +68 -474
- data/lib/ruby2js/converter/andasgn.rb +12 -0
- data/lib/ruby2js/converter/arg.rb +14 -0
- data/lib/ruby2js/converter/args.rb +13 -0
- data/lib/ruby2js/converter/array.rb +33 -0
- data/lib/ruby2js/converter/begin.rb +13 -0
- data/lib/ruby2js/converter/block.rb +16 -0
- data/lib/ruby2js/converter/blockpass.rb +11 -0
- data/lib/ruby2js/converter/boolean.rb +11 -0
- data/lib/ruby2js/converter/break.rb +12 -0
- data/lib/ruby2js/converter/case.rb +23 -0
- data/lib/ruby2js/converter/casgn.rb +16 -0
- data/lib/ruby2js/converter/class.rb +75 -0
- data/lib/ruby2js/converter/const.rb +10 -0
- data/lib/ruby2js/converter/def.rb +91 -0
- data/lib/ruby2js/converter/defined.rb +15 -0
- data/lib/ruby2js/converter/dstr.rb +16 -0
- data/lib/ruby2js/converter/for.rb +19 -0
- data/lib/ruby2js/converter/hash.rb +24 -0
- data/lib/ruby2js/converter/if.rb +34 -0
- data/lib/ruby2js/converter/ivar.rb +10 -0
- data/lib/ruby2js/converter/ivasgn.rb +11 -0
- data/lib/ruby2js/converter/kwbegin.rb +44 -0
- data/lib/ruby2js/converter/literal.rb +12 -0
- data/lib/ruby2js/converter/logical.rb +43 -0
- data/lib/ruby2js/converter/masgn.rb +20 -0
- data/lib/ruby2js/converter/next.rb +12 -0
- data/lib/ruby2js/converter/nil.rb +10 -0
- data/lib/ruby2js/converter/opasgn.rb +20 -0
- data/lib/ruby2js/converter/orasgn.rb +12 -0
- data/lib/ruby2js/converter/regexp.rb +21 -0
- data/lib/ruby2js/converter/return.rb +15 -0
- data/lib/ruby2js/converter/self.rb +10 -0
- data/lib/ruby2js/converter/send.rb +98 -0
- data/lib/ruby2js/converter/sym.rb +10 -0
- data/lib/ruby2js/converter/undef.rb +12 -0
- data/lib/ruby2js/converter/until.rb +12 -0
- data/lib/ruby2js/converter/untilpost.rb +13 -0
- data/lib/ruby2js/converter/var.rb +11 -0
- data/lib/ruby2js/converter/vasgn.rb +41 -0
- data/lib/ruby2js/converter/while.rb +12 -0
- data/lib/ruby2js/converter/whilepost.rb +14 -0
- data/lib/ruby2js/converter/xstr.rb +16 -0
- data/lib/ruby2js/filter/angularrb.rb +1 -1
- data/lib/ruby2js/filter/jquery.rb +95 -1
- data/lib/ruby2js/version.rb +1 -1
- data/ruby2js.gemspec +3 -3
- metadata +44 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
M2MyOGI2ZTQxMWYwMjJlYjc4M2M1OGFjNGVhNmRhOGJkYTc3ZGFjNA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZWNmN2FhYmI4OTUyODhjMDI0MGQ3ZjJmZjA1NTczM2EzN2M2NmQ4Ng==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YWZjYzYxN2NlMjNhZWNmMGE1ODRlZjY3ODg0ZjQ3YjkxYzFhZDNmNWRiODUy
|
10
|
+
ZTI0MTExMTQwMjg5YTMzZDQyNjEzOTE5NjdlN2VkNDM3NjZhMjFiOTZhNjQy
|
11
|
+
YmZmYmNlNmIxZmMxNmI4NTk4Yjg5MTFkNjAzZjc5N2I0ZTQ3ZDk=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MzcwYTRlZjI0Mjc5ODM0ZmY5MzQwZDE1NDZlMDE0YzU0NmZjZmI0YTFkMjFl
|
14
|
+
OTE3ZWM5MjFhMDE3NzRjZWYyMTFiMjI4YzQxNDgzNTJiOTU1NWZiODc4ZmY4
|
15
|
+
YjViNmZiMmYzMWFhYTliNjk1NjAwMWIzY2JmOGYwNDFlOWE3Nzk=
|
data/lib/ruby2js.rb
CHANGED
@@ -17,7 +17,7 @@ module Ruby2JS
|
|
17
17
|
|
18
18
|
if Proc === source
|
19
19
|
file,line = source.source_location
|
20
|
-
source = File.read(file).untaint
|
20
|
+
source = File.read(file.dup.untaint).untaint
|
21
21
|
ast = find_block( parse(source), line )
|
22
22
|
elsif Parser::AST::Node === source
|
23
23
|
ast = source
|
@@ -49,7 +49,7 @@ module Ruby2JS
|
|
49
49
|
lines.each do |line|
|
50
50
|
if line.start_with? '}' or line.start_with? ']'
|
51
51
|
pre.sub!(/^ /,'')
|
52
|
-
line.sub!(
|
52
|
+
line.sub!(/([,;])$/,"\\1\n")
|
53
53
|
pending = true
|
54
54
|
else
|
55
55
|
pending = false
|
data/lib/ruby2js/converter.rb
CHANGED
@@ -14,6 +14,11 @@ module Ruby2JS
|
|
14
14
|
@nl = ''
|
15
15
|
@ws = ' '
|
16
16
|
@varstack = []
|
17
|
+
|
18
|
+
@handlers = {}
|
19
|
+
@@handlers.each do |name|
|
20
|
+
@handlers[name] = method("on_#{name}")
|
21
|
+
end
|
17
22
|
end
|
18
23
|
|
19
24
|
def enable_vertical_whitespace
|
@@ -34,9 +39,9 @@ module Ruby2JS
|
|
34
39
|
OPERATORS.index( OPERATORS.find{ |el| el.include? op } ) || -1
|
35
40
|
end
|
36
41
|
|
37
|
-
def scope( ast, args=
|
38
|
-
@varstack.push @vars
|
39
|
-
@vars =
|
42
|
+
def scope( ast, args=nil )
|
43
|
+
@varstack.push @vars.dup
|
44
|
+
@vars = args if args
|
40
45
|
parse( ast, :statement )
|
41
46
|
ensure
|
42
47
|
@vars = @varstack.pop
|
@@ -54,482 +59,26 @@ module Ruby2JS
|
|
54
59
|
selector.source_buffer.source[selector.end_pos] == '('
|
55
60
|
end
|
56
61
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
when :sym
|
66
|
-
ast.children.first.to_s.inspect
|
67
|
-
|
68
|
-
when :lvar, :gvar, :cvar
|
69
|
-
ast.children.first
|
70
|
-
|
71
|
-
when :true, :false
|
72
|
-
ast.type.to_s
|
73
|
-
|
74
|
-
when :nil
|
75
|
-
'null'
|
76
|
-
|
77
|
-
when :lvasgn
|
78
|
-
var, value = ast.children
|
79
|
-
output = value ? "#{ 'var ' unless @vars.keys.include? var }#{ var } = #{ parse value }" : var
|
80
|
-
@vars[var] = true
|
81
|
-
output
|
82
|
-
|
83
|
-
when :op_asgn
|
84
|
-
var, op, value = ast.children
|
85
|
-
|
86
|
-
if [:+, :-].include?(op) and value.type==:int and value.children==[1]
|
87
|
-
if state == :statement
|
88
|
-
"#{ parse var }#{ op }#{ op }"
|
89
|
-
else
|
90
|
-
"#{ op }#{ op }#{ parse var }"
|
91
|
-
end
|
92
|
-
else
|
93
|
-
"#{ parse var } #{ op }= #{ parse value }"
|
94
|
-
end
|
95
|
-
|
96
|
-
when :casgn
|
97
|
-
cbase, var, value = ast.children
|
98
|
-
var = "#{cbase}.var" if cbase
|
99
|
-
output = "const #{ var } = #{ parse value }"
|
100
|
-
@vars[var] = true
|
101
|
-
output
|
102
|
-
|
103
|
-
when :gvasgn
|
104
|
-
name, value = ast.children
|
105
|
-
"#{ name } = #{ parse value }"
|
106
|
-
|
107
|
-
when :ivasgn
|
108
|
-
name, expression = ast.children
|
109
|
-
"#{ name.to_s.sub('@', 'this._') } = #{ parse expression }"
|
110
|
-
|
111
|
-
when :or_asgn
|
112
|
-
var, value = ast.children
|
113
|
-
"#{ parse var } = #{parse var} || #{ parse value }"
|
114
|
-
|
115
|
-
when :and_asgn
|
116
|
-
var, value = ast.children
|
117
|
-
"#{ parse var } = #{parse var} && #{ parse value }"
|
118
|
-
|
119
|
-
when :ivar
|
120
|
-
name = ast.children.first
|
121
|
-
name.to_s.sub('@', 'this._')
|
122
|
-
|
123
|
-
when :hash
|
124
|
-
hashy = ast.children.map do |node|
|
125
|
-
left, right = node.children
|
126
|
-
key = parse left
|
127
|
-
key = $1 if key =~ /\A"([a-zA-Z_$][a-zA-Z_$0-9]*)"\Z/
|
128
|
-
"#{key}: #{parse right}"
|
129
|
-
end
|
130
|
-
"{#{ hashy.join(', ') }}"
|
131
|
-
|
132
|
-
when :regexp
|
133
|
-
str, opt = ast.children
|
134
|
-
if str.children.first.include? '/'
|
135
|
-
if opt.children.empty?
|
136
|
-
"new RegExp(#{ str.children.first.inspect })"
|
137
|
-
else
|
138
|
-
"new RegExp(#{ str.children.first.inspect }, #{ opt.children.join.inspect})"
|
139
|
-
end
|
140
|
-
else
|
141
|
-
"/#{ str.children.first }/#{ opt.children.join }"
|
142
|
-
end
|
143
|
-
|
144
|
-
when :array
|
145
|
-
splat = ast.children.rindex { |a| a.type == :splat }
|
146
|
-
if splat
|
147
|
-
items = ast.children
|
148
|
-
item = items[splat].children.first
|
149
|
-
if items.length == 1
|
150
|
-
parse item
|
151
|
-
elsif splat == items.length - 1
|
152
|
-
parse s(:send, s(:array, *items[0..-2]), :concat, item)
|
153
|
-
elsif splat == 0
|
154
|
-
parse s(:send, item, :concat, s(:array, *items[1..-1]))
|
155
|
-
else
|
156
|
-
parse s(:send,
|
157
|
-
s(:send, s(:array, *items[0..splat-1]), :concat, item),
|
158
|
-
:concat, s(:array, *items[splat+1..-1]))
|
159
|
-
end
|
160
|
-
else
|
161
|
-
list = ast.children.map { |a| parse a }
|
162
|
-
if list.join(', ').length < 80
|
163
|
-
"[#{ list.join(', ') }]"
|
164
|
-
else
|
165
|
-
"[\n#{ list.join(",\n") }\n]"
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
when :begin
|
170
|
-
ast.children.map{ |e| parse e, :statement }.join(@sep)
|
171
|
-
|
172
|
-
when :return
|
173
|
-
"return #{ parse ast.children.first }"
|
174
|
-
|
175
|
-
when *LOGICAL
|
176
|
-
left, right = ast.children
|
177
|
-
left = left.children.first if left and left.type == :begin
|
178
|
-
right = right.children.first if right.type == :begin
|
179
|
-
op_index = operator_index ast.type
|
180
|
-
lgroup = LOGICAL.include?( left.type ) && op_index <= operator_index( left.type )
|
181
|
-
left = parse left
|
182
|
-
left = "(#{ left })" if lgroup
|
183
|
-
rgroup = LOGICAL.include?( right.type ) && op_index <= operator_index( right.type ) if right.children.length > 0
|
184
|
-
right = parse right
|
185
|
-
right = "(#{ right })" if rgroup
|
186
|
-
|
187
|
-
case ast.type
|
188
|
-
when :and
|
189
|
-
"#{ left } && #{ right }"
|
190
|
-
when :or
|
191
|
-
"#{ left } || #{ right }"
|
192
|
-
else
|
193
|
-
"!#{ left }"
|
194
|
-
end
|
195
|
-
|
196
|
-
when :send, :attr
|
197
|
-
receiver, method, *args = ast.children
|
198
|
-
if method =~ /\w[!?]$/
|
199
|
-
raise NotImplementedError, "invalid method name #{ method }"
|
200
|
-
end
|
201
|
-
|
202
|
-
if method == :new and receiver and receiver.children == [nil, :Proc]
|
203
|
-
return parse args.first
|
204
|
-
elsif not receiver and [:lambda, :proc].include? method
|
205
|
-
return parse args.first
|
206
|
-
end
|
207
|
-
|
208
|
-
op_index = operator_index method
|
209
|
-
if op_index != -1
|
210
|
-
target = args.first
|
211
|
-
target = target.children.first if target and target.type == :begin
|
212
|
-
receiver = receiver.children.first if receiver.type == :begin
|
213
|
-
end
|
214
|
-
|
215
|
-
group_receiver = receiver.type == :send && op_index <= operator_index( receiver.children[1] ) if receiver
|
216
|
-
group_target = target.type == :send && op_index <= operator_index( target.children[1] ) if target
|
217
|
-
|
218
|
-
if method == :!
|
219
|
-
if receiver.type == :defined?
|
220
|
-
parse s(:undefined?, *receiver.children)
|
221
|
-
else
|
222
|
-
group_receiver ||= (receiver.type != :send && receiver.children.length > 1)
|
223
|
-
"!#{ group_receiver ? group(receiver) : parse(receiver) }"
|
224
|
-
end
|
225
|
-
|
226
|
-
elsif method == :[]
|
227
|
-
"#{ parse receiver }[#{ args.map {|arg| parse arg}.join(', ') }]"
|
228
|
-
|
229
|
-
elsif method == :-@ or method == :+@
|
230
|
-
"#{ method.to_s[0] }#{ parse receiver }"
|
231
|
-
|
232
|
-
elsif method == :=~
|
233
|
-
"#{ parse args.first }.test(#{ parse receiver })"
|
234
|
-
|
235
|
-
elsif method == :!~
|
236
|
-
"!#{ parse args.first }.test(#{ parse receiver })"
|
237
|
-
|
238
|
-
elsif OPERATORS.flatten.include? method
|
239
|
-
"#{ group_receiver ? group(receiver) : parse(receiver) } #{ method } #{ group_target ? group(target) : parse(target) }"
|
240
|
-
|
241
|
-
elsif method =~ /=$/
|
242
|
-
"#{ parse receiver }#{ '.' if receiver }#{ method.to_s.sub(/=$/, ' =') } #{ parse args.first }"
|
243
|
-
|
244
|
-
elsif method == :new and receiver
|
245
|
-
args = args.map {|a| parse a}.join(', ')
|
246
|
-
"new #{ parse receiver }(#{ args })"
|
247
|
-
|
248
|
-
elsif method == :raise and receiver == nil
|
249
|
-
if args.length == 1
|
250
|
-
"throw #{ parse args.first }"
|
251
|
-
else
|
252
|
-
"throw new #{ parse args.first }(#{ parse args[1] })"
|
253
|
-
end
|
254
|
-
|
255
|
-
elsif method == :typeof and receiver == nil
|
256
|
-
"typeof #{ parse args.first }"
|
257
|
-
|
258
|
-
else
|
259
|
-
if args.length == 0 and not is_method?(ast)
|
260
|
-
"#{ parse receiver }#{ '.' if receiver }#{ method }"
|
261
|
-
elsif args.length > 0 and args.last.type == :splat
|
262
|
-
parse s(:send, s(:attr, receiver, method), :apply, receiver,
|
263
|
-
s(:send, s(:array, *args[0..-2]), :concat,
|
264
|
-
args[-1].children.first))
|
265
|
-
else
|
266
|
-
args = args.map {|a| parse a}.join(', ')
|
267
|
-
"#{ parse receiver }#{ '.' if receiver }#{ method }(#{ args })"
|
268
|
-
end
|
269
|
-
end
|
270
|
-
|
271
|
-
when :const
|
272
|
-
receiver, name = ast.children
|
273
|
-
"#{ parse receiver }#{ '.' if receiver }#{ name }"
|
274
|
-
|
275
|
-
when :masgn
|
276
|
-
lhs, rhs = ast.children
|
277
|
-
block = []
|
278
|
-
lhs.children.zip rhs.children.zip do |var, val|
|
279
|
-
block << s(var.type, *var.children, *val)
|
280
|
-
end
|
281
|
-
parse s(:begin, *block)
|
282
|
-
|
283
|
-
when :if
|
284
|
-
condition, true_block, else_block = ast.children
|
285
|
-
if state == :statement
|
286
|
-
output = "if (#{ parse condition }) {#@nl#{ scope true_block }#@nl}"
|
287
|
-
while else_block and else_block.type == :if
|
288
|
-
condition, true_block, else_block = else_block.children
|
289
|
-
output << " else if (#{ parse condition }) {#@nl#{ scope true_block }#@nl}"
|
290
|
-
end
|
291
|
-
output << " else {#@nl#{ scope else_block }#@nl}" if else_block
|
292
|
-
output
|
293
|
-
else
|
294
|
-
"(#{ parse condition } ? #{ parse true_block } : #{ parse else_block })"
|
295
|
-
end
|
296
|
-
|
297
|
-
when :while
|
298
|
-
condition, block = ast.children
|
299
|
-
"while (#{ parse condition }) {#@nl#{ scope block }#@nl}"
|
300
|
-
|
301
|
-
when :until
|
302
|
-
condition, block = ast.children
|
303
|
-
parse s(:while, s(:send, condition, :!), block)
|
304
|
-
|
305
|
-
when :while_post
|
306
|
-
condition, block = ast.children
|
307
|
-
block = block.updated(:begin) if block.type == :kwbegin
|
308
|
-
"do {#@nl#{ scope block }#@nl} while (#{ parse condition })"
|
309
|
-
|
310
|
-
when :until_post
|
311
|
-
condition, block = ast.children
|
312
|
-
parse s(:while_post, s(:send, condition, :!), block)
|
313
|
-
|
314
|
-
when :for
|
315
|
-
var, expression, block = ast.children
|
316
|
-
parse s(:block,
|
317
|
-
s(:send, expression, :forEach),
|
318
|
-
s(:args, s(:arg, var.children.last)),
|
319
|
-
block);
|
320
|
-
|
321
|
-
when :case
|
322
|
-
expr, *whens, other = ast.children
|
323
|
-
|
324
|
-
whens.map! do |node|
|
325
|
-
*values, code = node.children
|
326
|
-
cases = values.map {|value| "case #{ parse value }:#@ws"}.join
|
327
|
-
"#{ cases }#{ parse code }#{@sep}break#@sep"
|
328
|
-
end
|
329
|
-
|
330
|
-
other = "#{@nl}default:#@ws#{ parse other }#@nl" if other
|
331
|
-
|
332
|
-
"switch (#{ parse expr }) {#@nl#{whens.join(@nl)}#{other}}"
|
333
|
-
|
334
|
-
when :block
|
335
|
-
call, args, block = ast.children
|
336
|
-
block ||= s(:begin)
|
337
|
-
function = s(:def, name, args, block)
|
338
|
-
parse s(:send, *call.children, function)
|
339
|
-
|
340
|
-
when :def
|
341
|
-
name, args, body = ast.children
|
342
|
-
body ||= s(:begin)
|
343
|
-
if name =~ /[!?]$/
|
344
|
-
raise NotImplementedError, "invalid method name #{ name }"
|
345
|
-
end
|
346
|
-
|
347
|
-
vars = {}
|
348
|
-
if args and !args.children.empty?
|
349
|
-
# splats
|
350
|
-
if args.children.last.type == :restarg
|
351
|
-
if args.children[-1].children.first
|
352
|
-
body = s(:begin, body) unless body.type == :begin
|
353
|
-
assign = s(:lvasgn, args.children[-1].children.first,
|
354
|
-
s(:send, s(:attr,
|
355
|
-
s(:attr, s(:const, nil, :Array), :prototype), :slice),
|
356
|
-
:call, s(:lvar, :arguments),
|
357
|
-
s(:int, args.children.length-1)))
|
358
|
-
body = s(:begin, assign, *body.children)
|
359
|
-
end
|
360
|
-
|
361
|
-
args = s(:args, *args.children[0..-2])
|
362
|
-
|
363
|
-
elsif args.children.last.type == :blockarg and
|
364
|
-
args.children.length > 1 and args.children[-2].type == :restarg
|
365
|
-
body = s(:begin, body) unless body.type == :begin
|
366
|
-
blk = args.children[-1].children.first
|
367
|
-
vararg = args.children[-2].children.first
|
368
|
-
last = s(:send, s(:attr, s(:lvar, :arguments), :length), :-,
|
369
|
-
s(:int, 1))
|
370
|
-
|
371
|
-
# set block argument to the last argument passed
|
372
|
-
assign2 = s(:lvasgn, blk, s(:send, s(:lvar, :arguments), :[], last))
|
373
|
-
|
374
|
-
if vararg
|
375
|
-
# extract arguments between those defined and the last
|
376
|
-
assign1 = s(:lvasgn, vararg, s(:send, s(:attr, s(:attr, s(:const,
|
377
|
-
nil, :Array), :prototype), :slice), :call, s(:lvar, :arguments),
|
378
|
-
s(:int, args.children.length-1), last))
|
379
|
-
# push block argument back onto args if not a function
|
380
|
-
pushback = s(:if, s(:send, s(:send, nil, :typeof, s(:lvar, blk)),
|
381
|
-
:"!==", s(:str, "function")), s(:begin, s(:send, s(:lvar,
|
382
|
-
vararg), :push, s(:lvar, blk)), s(:lvasgn, blk, s(:nil))), nil)
|
383
|
-
# set block argument to null if all arguments were defined
|
384
|
-
pushback = s(:if, s(:send, s(:attr, s(:lvar, :arguments),
|
385
|
-
:length), :<=, s(:int, args.children.length-2)), s(:lvasgn,
|
386
|
-
blk, s(:nil)), pushback)
|
387
|
-
# combine statements
|
388
|
-
body = s(:begin, assign1, assign2, pushback, *body.children)
|
389
|
-
else
|
390
|
-
# set block argument to null if all arguments were defined
|
391
|
-
ignore = s(:if, s(:send, s(:attr, s(:lvar, :arguments),
|
392
|
-
:length), :<=, s(:int, args.children.length-2)), s(:lvasgn,
|
393
|
-
blk, s(:nil)), nil)
|
394
|
-
body = s(:begin, assign2, ignore, *body.children)
|
395
|
-
end
|
396
|
-
|
397
|
-
args = s(:args, *args.children[0..-3])
|
398
|
-
end
|
399
|
-
|
400
|
-
# optional arguments
|
401
|
-
args.children.each_with_index do |arg, i|
|
402
|
-
if arg.type == :optarg
|
403
|
-
body = s(:begin, body) unless body.type == :begin
|
404
|
-
argname, value = arg.children
|
405
|
-
children = args.children.dup
|
406
|
-
children[i] = s(:arg, argname)
|
407
|
-
args = s(:args, *children)
|
408
|
-
body = s(:begin, body) unless body.type == :begin
|
409
|
-
default = s(:if, s(:send, s(:defined?, s(:lvar, argname)), :!),
|
410
|
-
s(:lvasgn, argname, value), nil)
|
411
|
-
body = s(:begin, default, *body.children)
|
412
|
-
end
|
413
|
-
vars[arg.children.first] = true
|
414
|
-
end
|
415
|
-
end
|
416
|
-
|
417
|
-
"function#{ " #{name}" if name }(#{ parse args }) {#@nl#{ scope body, vars}#{@nl unless body == s(:begin)}}"
|
418
|
-
|
419
|
-
when :class
|
420
|
-
name, inheritance, *body = ast.children
|
421
|
-
init = s(:def, :initialize, s(:args))
|
422
|
-
body.compact!
|
423
|
-
|
424
|
-
if body.length == 1 and body.first.type == :begin
|
425
|
-
body = body.first.children.dup
|
426
|
-
end
|
427
|
-
|
428
|
-
body.map! do |m|
|
429
|
-
if m.type == :def
|
430
|
-
if m.children.first == :initialize
|
431
|
-
# constructor: remove from body and overwrite init function
|
432
|
-
init = m
|
433
|
-
nil
|
434
|
-
else
|
435
|
-
# method: add to prototype
|
436
|
-
s(:send, s(:attr, name, :prototype), "#{m.children[0]}=",
|
437
|
-
s(:block, s(:send, nil, :proc), *m.children[1..-1]))
|
438
|
-
end
|
439
|
-
elsif m.type == :defs and m.children.first == s(:self)
|
440
|
-
# class method definition: add to prototype
|
441
|
-
s(:send, name, "#{m.children[1]}=",
|
442
|
-
s(:block, s(:send, nil, :proc), *m.children[2..-1]))
|
443
|
-
elsif m.type == :send and m.children.first == nil
|
444
|
-
# class method call
|
445
|
-
s(:send, name, *m.children[1..-1])
|
446
|
-
elsif m.type == :lvasgn
|
447
|
-
# class variable
|
448
|
-
s(:send, name, "#{m.children[0]}=", *m.children[1..-1])
|
449
|
-
elsif m.type == :casgn and m.children[0] == nil
|
450
|
-
# class constant
|
451
|
-
s(:send, name, "#{m.children[1]}=", *m.children[2..-1])
|
452
|
-
else
|
453
|
-
raise NotImplementedError, "class #{ m.type }"
|
454
|
-
end
|
455
|
-
end
|
456
|
-
|
457
|
-
if inheritance
|
458
|
-
body.unshift s(:send, name, :prototype=, s(:send, inheritance, :new))
|
459
|
-
end
|
460
|
-
|
461
|
-
# prepend constructor
|
462
|
-
body.unshift s(:def, parse(name), *init.children[1..-1])
|
463
|
-
|
464
|
-
parse s(:begin, *body.compact)
|
465
|
-
|
466
|
-
when :args
|
467
|
-
ast.children.map { |a| parse a }.join(', ')
|
468
|
-
|
469
|
-
when :arg, :blockarg
|
470
|
-
ast.children.first
|
471
|
-
|
472
|
-
when :block_pass
|
473
|
-
parse ast.children.first
|
474
|
-
|
475
|
-
when :dstr, :dsym
|
476
|
-
ast.children.map{ |s| parse s }.join(' + ')
|
477
|
-
|
478
|
-
when :xstr
|
479
|
-
if @binding
|
480
|
-
@binding.eval(ast.children.first.children.first).to_s
|
481
|
-
else
|
482
|
-
eval(ast.children.first.children.first).to_s
|
483
|
-
end
|
484
|
-
|
485
|
-
when :self
|
486
|
-
'this'
|
487
|
-
|
488
|
-
when :break
|
489
|
-
'break'
|
490
|
-
|
491
|
-
when :next
|
492
|
-
'continue'
|
493
|
-
|
494
|
-
when :defined?
|
495
|
-
"typeof #{ parse ast.children.first } !== 'undefined'"
|
496
|
-
|
497
|
-
when :undefined?
|
498
|
-
"typeof #{ parse ast.children.first } === 'undefined'"
|
499
|
-
|
500
|
-
when :undef
|
501
|
-
ast.children.map {|c| "delete #{c.children.last}"}.join @sep
|
502
|
-
|
503
|
-
when :kwbegin
|
504
|
-
block = ast.children.first
|
505
|
-
if block.type == :ensure
|
506
|
-
block, finally = block.children
|
507
|
-
else
|
508
|
-
finally = nil
|
509
|
-
end
|
510
|
-
|
511
|
-
if block and block.type == :rescue
|
512
|
-
body, recover, otherwise = block.children
|
513
|
-
raise NotImplementedError, "block else" if otherwise
|
514
|
-
exception, name, recovery = recover.children
|
515
|
-
raise NotImplementedError, parse(exception) if exception
|
516
|
-
else
|
517
|
-
body = block
|
518
|
-
end
|
62
|
+
@@handlers = []
|
63
|
+
def self.handle(*types, &block)
|
64
|
+
types.each do |type|
|
65
|
+
define_method("on_#{type}", block)
|
66
|
+
@@handlers << type
|
67
|
+
end
|
68
|
+
end
|
519
69
|
|
520
|
-
|
521
|
-
|
522
|
-
output += " finally {#@nl#{ parse finally }#@nl}" if finally
|
70
|
+
def parse(ast, state=:expression)
|
71
|
+
return ast unless ast
|
523
72
|
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
parse s(:begin, *ast.children)
|
528
|
-
end
|
73
|
+
@state = state
|
74
|
+
@ast = ast
|
75
|
+
handler = @handlers[ast.type]
|
529
76
|
|
530
|
-
|
77
|
+
unless handler
|
531
78
|
raise NotImplementedError, "unknown AST type #{ ast.type }"
|
532
79
|
end
|
80
|
+
|
81
|
+
handler.call(*ast.children) if handler
|
533
82
|
end
|
534
83
|
|
535
84
|
def group( ast )
|
@@ -537,3 +86,48 @@ module Ruby2JS
|
|
537
86
|
end
|
538
87
|
end
|
539
88
|
end
|
89
|
+
|
90
|
+
# see https://github.com/whitequark/parser/blob/master/doc/AST_FORMAT.md
|
91
|
+
|
92
|
+
require 'ruby2js/converter/andasgn'
|
93
|
+
require 'ruby2js/converter/arg'
|
94
|
+
require 'ruby2js/converter/args'
|
95
|
+
require 'ruby2js/converter/array'
|
96
|
+
require 'ruby2js/converter/begin'
|
97
|
+
require 'ruby2js/converter/block'
|
98
|
+
require 'ruby2js/converter/blockpass'
|
99
|
+
require 'ruby2js/converter/boolean'
|
100
|
+
require 'ruby2js/converter/break'
|
101
|
+
require 'ruby2js/converter/case'
|
102
|
+
require 'ruby2js/converter/casgn'
|
103
|
+
require 'ruby2js/converter/class'
|
104
|
+
require 'ruby2js/converter/const'
|
105
|
+
require 'ruby2js/converter/def'
|
106
|
+
require 'ruby2js/converter/defined'
|
107
|
+
require 'ruby2js/converter/dstr'
|
108
|
+
require 'ruby2js/converter/for'
|
109
|
+
require 'ruby2js/converter/hash'
|
110
|
+
require 'ruby2js/converter/if'
|
111
|
+
require 'ruby2js/converter/ivar'
|
112
|
+
require 'ruby2js/converter/ivasgn'
|
113
|
+
require 'ruby2js/converter/kwbegin'
|
114
|
+
require 'ruby2js/converter/literal'
|
115
|
+
require 'ruby2js/converter/logical'
|
116
|
+
require 'ruby2js/converter/masgn'
|
117
|
+
require 'ruby2js/converter/next'
|
118
|
+
require 'ruby2js/converter/nil'
|
119
|
+
require 'ruby2js/converter/opasgn'
|
120
|
+
require 'ruby2js/converter/orasgn'
|
121
|
+
require 'ruby2js/converter/regexp'
|
122
|
+
require 'ruby2js/converter/return'
|
123
|
+
require 'ruby2js/converter/self'
|
124
|
+
require 'ruby2js/converter/send'
|
125
|
+
require 'ruby2js/converter/sym'
|
126
|
+
require 'ruby2js/converter/undef'
|
127
|
+
require 'ruby2js/converter/until'
|
128
|
+
require 'ruby2js/converter/untilpost'
|
129
|
+
require 'ruby2js/converter/var'
|
130
|
+
require 'ruby2js/converter/vasgn'
|
131
|
+
require 'ruby2js/converter/while'
|
132
|
+
require 'ruby2js/converter/whilepost'
|
133
|
+
require 'ruby2js/converter/xstr'
|