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.
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'