ruby2js 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +8 -8
  2. data/lib/ruby2js.rb +2 -2
  3. data/lib/ruby2js/converter.rb +68 -474
  4. data/lib/ruby2js/converter/andasgn.rb +12 -0
  5. data/lib/ruby2js/converter/arg.rb +14 -0
  6. data/lib/ruby2js/converter/args.rb +13 -0
  7. data/lib/ruby2js/converter/array.rb +33 -0
  8. data/lib/ruby2js/converter/begin.rb +13 -0
  9. data/lib/ruby2js/converter/block.rb +16 -0
  10. data/lib/ruby2js/converter/blockpass.rb +11 -0
  11. data/lib/ruby2js/converter/boolean.rb +11 -0
  12. data/lib/ruby2js/converter/break.rb +12 -0
  13. data/lib/ruby2js/converter/case.rb +23 -0
  14. data/lib/ruby2js/converter/casgn.rb +16 -0
  15. data/lib/ruby2js/converter/class.rb +75 -0
  16. data/lib/ruby2js/converter/const.rb +10 -0
  17. data/lib/ruby2js/converter/def.rb +91 -0
  18. data/lib/ruby2js/converter/defined.rb +15 -0
  19. data/lib/ruby2js/converter/dstr.rb +16 -0
  20. data/lib/ruby2js/converter/for.rb +19 -0
  21. data/lib/ruby2js/converter/hash.rb +24 -0
  22. data/lib/ruby2js/converter/if.rb +34 -0
  23. data/lib/ruby2js/converter/ivar.rb +10 -0
  24. data/lib/ruby2js/converter/ivasgn.rb +11 -0
  25. data/lib/ruby2js/converter/kwbegin.rb +44 -0
  26. data/lib/ruby2js/converter/literal.rb +12 -0
  27. data/lib/ruby2js/converter/logical.rb +43 -0
  28. data/lib/ruby2js/converter/masgn.rb +20 -0
  29. data/lib/ruby2js/converter/next.rb +12 -0
  30. data/lib/ruby2js/converter/nil.rb +10 -0
  31. data/lib/ruby2js/converter/opasgn.rb +20 -0
  32. data/lib/ruby2js/converter/orasgn.rb +12 -0
  33. data/lib/ruby2js/converter/regexp.rb +21 -0
  34. data/lib/ruby2js/converter/return.rb +15 -0
  35. data/lib/ruby2js/converter/self.rb +10 -0
  36. data/lib/ruby2js/converter/send.rb +98 -0
  37. data/lib/ruby2js/converter/sym.rb +10 -0
  38. data/lib/ruby2js/converter/undef.rb +12 -0
  39. data/lib/ruby2js/converter/until.rb +12 -0
  40. data/lib/ruby2js/converter/untilpost.rb +13 -0
  41. data/lib/ruby2js/converter/var.rb +11 -0
  42. data/lib/ruby2js/converter/vasgn.rb +41 -0
  43. data/lib/ruby2js/converter/while.rb +12 -0
  44. data/lib/ruby2js/converter/whilepost.rb +14 -0
  45. data/lib/ruby2js/converter/xstr.rb +16 -0
  46. data/lib/ruby2js/filter/angularrb.rb +1 -1
  47. data/lib/ruby2js/filter/jquery.rb +95 -1
  48. data/lib/ruby2js/version.rb +1 -1
  49. data/ruby2js.gemspec +3 -3
  50. metadata +44 -2
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NWUwYjJjY2RiMjE2MDhkMjdlMDVkODQ4MDFlNWUwYWZjODg3NjUwNA==
4
+ M2MyOGI2ZTQxMWYwMjJlYjc4M2M1OGFjNGVhNmRhOGJkYTc3ZGFjNA==
5
5
  data.tar.gz: !binary |-
6
- NGU5ZWI1ODU4MThkMTFjOTZjNDZmNDlkYzg2Mjc4NzIxMjNjZDk5MA==
6
+ ZWNmN2FhYmI4OTUyODhjMDI0MGQ3ZjJmZjA1NTczM2EzN2M2NmQ4Ng==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- ODA4MGVkMTZlZjU0MTA5YWM4YTg1OGNhMThlNTg0Nzc4NTViNjI2NDZhZDkx
10
- M2YyZmY2YTkxMTE5ZDM5OTA0OGQ4NmNmNzRkNjU2MWJiMjA3MGIwMmExZTFh
11
- YTM5OWE3MjExN2NhOGI2ZWJhYWNmYjFjYTc2Y2Y4OWZkYmQyOGY=
9
+ YWZjYzYxN2NlMjNhZWNmMGE1ODRlZjY3ODg0ZjQ3YjkxYzFhZDNmNWRiODUy
10
+ ZTI0MTExMTQwMjg5YTMzZDQyNjEzOTE5NjdlN2VkNDM3NjZhMjFiOTZhNjQy
11
+ YmZmYmNlNmIxZmMxNmI4NTk4Yjg5MTFkNjAzZjc5N2I0ZTQ3ZDk=
12
12
  data.tar.gz: !binary |-
13
- MjI0MzE3MmVmNzNjYzdiOWRjODFlYmRmYzA0NjNkY2U0YTdhZTViNTlhNGRj
14
- NzE5ZjY3NjI3NmE3NjhjNzY3MjFiNDEwMDU3M2RiYWU0YTg4MDA2ODhmZWM5
15
- YjM0NGM5ZWI2YTA4MWI3OTFiOGM0MTQ5YWE1NzlhNmJiNDU5NTg=
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!(/;$/,";\n")
52
+ line.sub!(/([,;])$/,"\\1\n")
53
53
  pending = true
54
54
  else
55
55
  pending = false
@@ -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 = @vars.merge(args)
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
- def parse(ast, state=:expression)
58
- return ast unless Parser::AST::Node === ast
59
-
60
- case ast.type
61
-
62
- when :int, :float, :str
63
- ast.children.first.inspect
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
- output = "try {#@nl#{ parse body }#@nl}"
521
- output += " catch (#{ parse name }) {#@nl#{ parse recovery }#@nl}" if recovery
522
- output += " finally {#@nl#{ parse finally }#@nl}" if finally
70
+ def parse(ast, state=:expression)
71
+ return ast unless ast
523
72
 
524
- if recovery or finally
525
- output
526
- else
527
- parse s(:begin, *ast.children)
528
- end
73
+ @state = state
74
+ @ast = ast
75
+ handler = @handlers[ast.type]
529
76
 
530
- else
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'