melbourne 1.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.
Files changed (113) hide show
  1. data/HISTORY +3 -0
  2. data/LICENSE +27 -0
  3. data/README.rdoc +38 -0
  4. data/Rakefile +38 -0
  5. data/VERSION.yml +4 -0
  6. data/ext/melbourne/bstring-license.txt +29 -0
  7. data/ext/melbourne/bstrlib.c +2918 -0
  8. data/ext/melbourne/bstrlib.h +302 -0
  9. data/ext/melbourne/extconf.rb +76 -0
  10. data/ext/melbourne/grammar.cpp +11885 -0
  11. data/ext/melbourne/grammar.hpp +14 -0
  12. data/ext/melbourne/grammar.y +6013 -0
  13. data/ext/melbourne/internal.hpp +137 -0
  14. data/ext/melbourne/lex.c.tab +136 -0
  15. data/ext/melbourne/local_state.hpp +41 -0
  16. data/ext/melbourne/melbourne.cpp +37 -0
  17. data/ext/melbourne/node.hpp +262 -0
  18. data/ext/melbourne/node_types.cpp +245 -0
  19. data/ext/melbourne/node_types.hpp +135 -0
  20. data/ext/melbourne/node_types.rb +190 -0
  21. data/ext/melbourne/quark.cpp +52 -0
  22. data/ext/melbourne/quark.hpp +14 -0
  23. data/ext/melbourne/symbols.cpp +219 -0
  24. data/ext/melbourne/symbols.hpp +116 -0
  25. data/ext/melbourne/var_table.cpp +113 -0
  26. data/ext/melbourne/var_table.hpp +33 -0
  27. data/ext/melbourne/visitor.cpp +1052 -0
  28. data/ext/melbourne/visitor.hpp +20 -0
  29. data/lib/melbourne/ast/constants.rb +128 -0
  30. data/lib/melbourne/ast/control_flow.rb +382 -0
  31. data/lib/melbourne/ast/data.rb +19 -0
  32. data/lib/melbourne/ast/definitions.rb +561 -0
  33. data/lib/melbourne/ast/exceptions.rb +182 -0
  34. data/lib/melbourne/ast/file.rb +15 -0
  35. data/lib/melbourne/ast/grapher.rb +75 -0
  36. data/lib/melbourne/ast/literals.rb +268 -0
  37. data/lib/melbourne/ast/node.rb +21 -0
  38. data/lib/melbourne/ast/operators.rb +117 -0
  39. data/lib/melbourne/ast/self.rb +17 -0
  40. data/lib/melbourne/ast/sends.rb +451 -0
  41. data/lib/melbourne/ast/values.rb +74 -0
  42. data/lib/melbourne/ast/variables.rb +251 -0
  43. data/lib/melbourne/ast.rb +22 -0
  44. data/lib/melbourne/parser.rb +38 -0
  45. data/lib/melbourne/processor.rb +460 -0
  46. data/lib/melbourne.rb +46 -0
  47. data/spec/helpers/ast/node.rb +15 -0
  48. data/spec/helpers/ast/reduced_graph.rb +64 -0
  49. data/spec/lib/parser/alias_spec.rb +97 -0
  50. data/spec/lib/parser/and_spec.rb +63 -0
  51. data/spec/lib/parser/array_spec.rb +157 -0
  52. data/spec/lib/parser/attrasgn_spec.rb +401 -0
  53. data/spec/lib/parser/back_ref_spec.rb +20 -0
  54. data/spec/lib/parser/call_spec.rb +958 -0
  55. data/spec/lib/parser/case_spec.rb +577 -0
  56. data/spec/lib/parser/cdecl_spec.rb +108 -0
  57. data/spec/lib/parser/class_spec.rb +221 -0
  58. data/spec/lib/parser/colon2_spec.rb +13 -0
  59. data/spec/lib/parser/colon3_spec.rb +12 -0
  60. data/spec/lib/parser/const_spec.rb +12 -0
  61. data/spec/lib/parser/cvar_spec.rb +55 -0
  62. data/spec/lib/parser/cvasgn_spec.rb +71 -0
  63. data/spec/lib/parser/cvdecl_spec.rb +31 -0
  64. data/spec/lib/parser/defined_spec.rb +353 -0
  65. data/spec/lib/parser/defn_spec.rb +1409 -0
  66. data/spec/lib/parser/defs_spec.rb +247 -0
  67. data/spec/lib/parser/dot2_spec.rb +29 -0
  68. data/spec/lib/parser/dot3_spec.rb +29 -0
  69. data/spec/lib/parser/dregx_spec.rb +127 -0
  70. data/spec/lib/parser/dstr_spec.rb +453 -0
  71. data/spec/lib/parser/dsym_spec.rb +31 -0
  72. data/spec/lib/parser/dxstr_spec.rb +31 -0
  73. data/spec/lib/parser/ensure_spec.rb +279 -0
  74. data/spec/lib/parser/false_spec.rb +12 -0
  75. data/spec/lib/parser/flip2_spec.rb +138 -0
  76. data/spec/lib/parser/flip3_spec.rb +100 -0
  77. data/spec/lib/parser/for_spec.rb +279 -0
  78. data/spec/lib/parser/gasgn_spec.rb +34 -0
  79. data/spec/lib/parser/gvar_spec.rb +33 -0
  80. data/spec/lib/parser/hash_spec.rb +77 -0
  81. data/spec/lib/parser/iasgn_spec.rb +54 -0
  82. data/spec/lib/parser/if_spec.rb +439 -0
  83. data/spec/lib/parser/iter_spec.rb +2582 -0
  84. data/spec/lib/parser/lasgn_spec.rb +1066 -0
  85. data/spec/lib/parser/lit_spec.rb +75 -0
  86. data/spec/lib/parser/masgn_spec.rb +1970 -0
  87. data/spec/lib/parser/match2_spec.rb +47 -0
  88. data/spec/lib/parser/match3_spec.rb +54 -0
  89. data/spec/lib/parser/match_spec.rb +19 -0
  90. data/spec/lib/parser/module_spec.rb +102 -0
  91. data/spec/lib/parser/nil_spec.rb +13 -0
  92. data/spec/lib/parser/not_spec.rb +39 -0
  93. data/spec/lib/parser/nth_ref_spec.rb +12 -0
  94. data/spec/lib/parser/op_asgn_spec.rb +619 -0
  95. data/spec/lib/parser/or_spec.rb +155 -0
  96. data/spec/lib/parser/postexe_spec.rb +31 -0
  97. data/spec/lib/parser/regex_spec.rb +52 -0
  98. data/spec/lib/parser/rescue_spec.rb +1028 -0
  99. data/spec/lib/parser/return_spec.rb +151 -0
  100. data/spec/lib/parser/sclass_spec.rb +172 -0
  101. data/spec/lib/parser/str_spec.rb +162 -0
  102. data/spec/lib/parser/super_spec.rb +276 -0
  103. data/spec/lib/parser/true_spec.rb +12 -0
  104. data/spec/lib/parser/undef_spec.rb +222 -0
  105. data/spec/lib/parser/until_spec.rb +286 -0
  106. data/spec/lib/parser/valias_spec.rb +12 -0
  107. data/spec/lib/parser/while_spec.rb +458 -0
  108. data/spec/lib/parser/xstr_spec.rb +12 -0
  109. data/spec/lib/parser/yield_spec.rb +202 -0
  110. data/spec/lib/parser/zsuper_spec.rb +101 -0
  111. data/spec/matchers/parse_as.rb +27 -0
  112. data/spec/spec_helper.rb +10 -0
  113. metadata +168 -0
@@ -0,0 +1,561 @@
1
+ module Melbourne
2
+
3
+ module AST
4
+
5
+ # An +alias+ statement as in:
6
+ #
7
+ # alias x y
8
+ #
9
+ class Alias < Node
10
+
11
+ # The element that is aliased
12
+ #
13
+ attr_accessor :to
14
+
15
+ # The alias that is defined for the element
16
+ #
17
+ attr_accessor :from
18
+
19
+ def initialize(line, to, from) #:nodoc:
20
+ @line = line
21
+ @to = to
22
+ @from = from
23
+ end
24
+
25
+ end
26
+
27
+ # TODO: document!
28
+ class VAlias < Alias #:nodoc:
29
+
30
+ end
31
+
32
+ # An +undef+ statement as in:
33
+ #
34
+ # undef :x
35
+ #
36
+ class Undef < Node
37
+
38
+ # The name of the +undef+'d element
39
+ #
40
+ attr_accessor :name
41
+
42
+ def initialize(line, sym) #:nodoc:
43
+ @line = line
44
+ @name = sym
45
+ end
46
+
47
+ end
48
+
49
+ # A code block as in:
50
+ #
51
+ # begin
52
+ # end
53
+ #
54
+ # but also as in (implicit block):
55
+ #
56
+ # a = 1; b = 2
57
+ #
58
+ class Block < Node
59
+
60
+ # The statements inside of the block
61
+ #
62
+ attr_accessor :array
63
+
64
+ def initialize(line, array) #:nodoc:
65
+ @line = line
66
+ @array = array
67
+ end
68
+
69
+ # TODO: document!
70
+ def strip_arguments #:nodoc:
71
+ if @array.first.kind_of? FormalArguments
72
+ node = @array.shift
73
+ if @array.first.kind_of? BlockArgument
74
+ node.block_arg = @array.shift
75
+ end
76
+ return node
77
+ end
78
+ end
79
+
80
+ end
81
+
82
+ # TODO: document!
83
+ class ClosedScope < Node #:nodoc:
84
+
85
+ attr_accessor :body
86
+
87
+ end
88
+
89
+ # A method definition as in:
90
+ #
91
+ # def method
92
+ # end
93
+ #
94
+ class Define < ClosedScope
95
+
96
+ # The name of the defined method
97
+ #
98
+ attr_accessor :name
99
+
100
+ # The arguments of the defined method
101
+ #
102
+ attr_accessor :arguments
103
+
104
+ def initialize(line, name, block) #:nodoc:
105
+ @line = line
106
+ @name = name
107
+ @arguments = block.strip_arguments
108
+ block.array << Nil.new(line) if block.array.empty?
109
+ @body = block
110
+ end
111
+
112
+ end
113
+
114
+ # A singleton method definition as in:
115
+ #
116
+ # def object.method
117
+ # end
118
+ #
119
+ class DefineSingleton < Node
120
+
121
+ # The receiver of the definition
122
+ #
123
+ attr_accessor :name
124
+
125
+ # The body of the defined method
126
+ #
127
+ attr_accessor :body
128
+
129
+ def initialize(line, receiver, name, block) #:nodoc:
130
+ @line = line
131
+ @receiver = receiver
132
+ @body = DefineSingletonScope.new line, name, block
133
+ end
134
+
135
+ end
136
+
137
+ # The scope a singletion method definition opens. This is the actual body of +Melbourne::AST::DefineSingleton+s
138
+ #
139
+ class DefineSingletonScope < Define
140
+
141
+ def initialize(line, name, block) #:nodoc:
142
+ super line, name, block
143
+ end
144
+
145
+ end
146
+
147
+ # The formal arguments of a method definition as in:
148
+ #
149
+ # def method(x) # x is a formal argument of the method
150
+ # end
151
+ #
152
+ class FormalArguments < Node
153
+
154
+ # The names of the arguments
155
+ #
156
+ attr_accessor :names
157
+
158
+ # The names of the required arguments
159
+ #
160
+ attr_accessor :required
161
+
162
+ # The names of the optional arguments
163
+ #
164
+ attr_accessor :optional
165
+
166
+ # The arguments of the method that have default values
167
+ #
168
+ attr_accessor :defaults
169
+
170
+ # The splat (<tt>*some</tt>) arguments of the method
171
+ #
172
+ attr_accessor :splat
173
+
174
+ # The block argument if there is one
175
+ #
176
+ attr_accessor :block_arg
177
+
178
+ def initialize(line, args, defaults, splat) #:nodoc:
179
+ @line = line
180
+ @defaults = nil
181
+ @block_arg = nil
182
+
183
+ if defaults
184
+ defaults = DefaultArguments.new line, defaults
185
+ @defaults = defaults
186
+ @optional = defaults.names
187
+
188
+ stop = defaults.names.first
189
+ last = args.each_with_index { |a, i| break i if a == stop }
190
+ @required = args[0, last]
191
+ else
192
+ @required = args.dup
193
+ @optional = []
194
+ end
195
+
196
+ if splat.kind_of? Symbol
197
+ args << splat
198
+ elsif splat
199
+ splat = :@unnamed_splat
200
+ args << splat
201
+ end
202
+ @names = args
203
+ @splat = splat
204
+ end
205
+
206
+ def block_arg=(node) #:nodoc:
207
+ @names << node.name
208
+ @block_arg = node
209
+ end
210
+
211
+ # Gets the arity of the method. The arity is the number of required arguments the method defines.
212
+ #
213
+ # === Example
214
+ #
215
+ # def method(a, b = 1) # arity is 1 as the second argument is optional
216
+ # end
217
+ #
218
+ def arity
219
+ @required.size
220
+ end
221
+
222
+ # Gets the number of required arguments the method defines.
223
+ #
224
+ def required_args
225
+ @required.size
226
+ end
227
+
228
+ # Gets the total number of all arguments the method defines.
229
+ #
230
+ def total_args
231
+ @required.size + @optional.size
232
+ end
233
+
234
+ # TODO: document!
235
+ def splat_index #:nodoc:
236
+ if @splat
237
+ index = @names.size
238
+ index -= 1 if @block_arg
239
+ index -= 1 if @splat.kind_of? Symbol
240
+ index
241
+ end
242
+ end
243
+
244
+ end
245
+
246
+ # Defaults arguments of a method. This of node also contains the actual statements that define the defaults.
247
+ #
248
+ class DefaultArguments < Node
249
+
250
+ # The statements that define the defaults (these are usually Melbourne::AST::LocalVariableAssignment nodes)
251
+ #
252
+ attr_accessor :arguments
253
+
254
+ # The names of the arguments
255
+ #
256
+ attr_accessor :names
257
+
258
+ def initialize(line, block) #:nodoc:
259
+ @line = line
260
+ array = block.array
261
+ @names = array.map { |a| a.name }
262
+ @arguments = array
263
+ end
264
+
265
+ end
266
+
267
+ module LocalVariable #:nodoc:
268
+
269
+ attr_accessor :variable
270
+
271
+ end
272
+
273
+ # A block argument as in:
274
+ #
275
+ # def method(&block)
276
+ # end
277
+ #
278
+ class BlockArgument < Node
279
+
280
+ include LocalVariable
281
+
282
+ # The name of the block argument
283
+ #
284
+ attr_accessor :name
285
+
286
+ def initialize(line, name) #:nodoc:
287
+ @line = line
288
+ @name = name
289
+ end
290
+
291
+ end
292
+
293
+ # A class as in:
294
+ #
295
+ # class X; end
296
+ #
297
+ class Class < Node
298
+
299
+ # The name of the +class+
300
+ #
301
+ attr_accessor :name
302
+
303
+ # The superclass of the +class+
304
+ #
305
+ attr_accessor :superclass
306
+
307
+ # The body of the +class+
308
+ #
309
+ attr_accessor :body
310
+
311
+ def initialize(line, name, superclass, body) #:nodoc:
312
+ @line = line
313
+
314
+ @superclass = superclass ? superclass : Nil.new(line)
315
+
316
+ if name.kind_of? Symbol
317
+ @name = ClassName.new line, name, @superclass
318
+ else
319
+ @name = ScopedClassName.new line, name, @superclass
320
+ end
321
+
322
+ if body
323
+ @body = ClassScope.new line, @name, body
324
+ else
325
+ @body = EmptyBody.new line
326
+ end
327
+ end
328
+
329
+ end
330
+
331
+ # The scope a class definition opens. This is the actual body of +Melbourne::AST::Class+es
332
+ #
333
+ class ClassScope < ClosedScope
334
+
335
+ def initialize(line, name, body) #:nodoc:
336
+ @line = line
337
+ @name = name.name
338
+ @body = body
339
+ end
340
+
341
+ end
342
+
343
+ # A class name as in:
344
+ #
345
+ # class X; end
346
+ #
347
+ class ClassName < Node
348
+
349
+ # The actual name of the class
350
+ #
351
+ attr_accessor :name
352
+
353
+ # TODO: document!
354
+ attr_accessor :superclass #:nodoc:
355
+
356
+ def initialize(line, name, superclass) #:nodoc:
357
+ @line = line
358
+ @name = name
359
+ @superclass = superclass
360
+ end
361
+
362
+ end
363
+
364
+ # A scoped class name as in:
365
+ #
366
+ # class X::Y; end
367
+ #
368
+ class ScopedClassName < ClassName
369
+
370
+ # The parent of the scoped class name; for a class <tt>class X::Y; end</tt> the scoped class name is +Y+ and the parent is +X+
371
+ #
372
+ attr_accessor :parent
373
+
374
+ def initialize(line, parent, superclass) #:nodoc:
375
+ @line = line
376
+ @name = parent.name
377
+ @parent = parent.parent
378
+ @superclass = superclass
379
+ end
380
+
381
+ end
382
+
383
+ # A module as in:
384
+ #
385
+ # module M; end
386
+ #
387
+ class Module < Node
388
+
389
+ # The name of the module
390
+ #
391
+ attr_accessor :name
392
+
393
+ # The body of the module
394
+ #
395
+ attr_accessor :body
396
+
397
+ def initialize(line, name, body) #:nodoc:
398
+ @line = line
399
+
400
+ if name.kind_of? Symbol
401
+ @name = ModuleName.new line, name
402
+ else
403
+ @name = ScopedModuleName.new line, name
404
+ end
405
+
406
+ if body
407
+ @body = ModuleScope.new line, @name, body
408
+ else
409
+ @body = EmptyBody.new line
410
+ end
411
+ end
412
+
413
+ end
414
+
415
+ # The body of a class that has no body as in:
416
+ #
417
+ # class X; end
418
+ #
419
+ class EmptyBody < Node
420
+
421
+ end
422
+
423
+ # The name of a module
424
+ #
425
+ class ModuleName < Node
426
+
427
+ # The actual name of the module
428
+ #
429
+ attr_accessor :name
430
+
431
+ def initialize(line, name) #:nodoc:
432
+ @line = line
433
+ @name = name
434
+ end
435
+
436
+ end
437
+
438
+ # A scoped module name as in:
439
+ #
440
+ # module X::M; end
441
+ #
442
+ class ScopedModuleName < ModuleName
443
+
444
+ # The parent of the scoped module name; for a module <tt>module X::M; end</tt> the scoped module name is +Y+ and the parent is +X+
445
+ #
446
+ attr_accessor :parent
447
+
448
+ def initialize(line, parent) #:nodoc:
449
+ @line = line
450
+ @name = parent.name
451
+ @parent = parent.parent
452
+ end
453
+
454
+ end
455
+
456
+ # The scope a module definition opens. This is the actual body of +Melbourne::AST::Module+s
457
+ #
458
+ class ModuleScope < ClosedScope
459
+
460
+ def initialize(line, name, body) #:nodoc:
461
+ @line = line
462
+ @name = name.name
463
+ @body = body
464
+ end
465
+
466
+ end
467
+
468
+ # A singleton class as in:
469
+ #
470
+ # class X
471
+ # class << self
472
+ # end
473
+ # end
474
+ #
475
+ class SClass < Node
476
+
477
+ # The receiver (for <tt>class << self</tt>, +self+ is the receiver)
478
+ #
479
+ attr_accessor :receiver
480
+
481
+ def initialize(line, receiver, body) #:nodoc:
482
+ @line = line
483
+ @receiver = receiver
484
+ @body = SClassScope.new line, body
485
+ end
486
+
487
+ end
488
+
489
+ # The scope a singleton class definition opens. This is the actual body of +Melbourne::AST::SClass+s
490
+ #
491
+ class SClassScope < ClosedScope
492
+
493
+ def initialize(line, body) #:nodoc:
494
+ @line = line
495
+ @body = body
496
+ @name = nil
497
+ end
498
+
499
+ end
500
+
501
+ # TODO: document!
502
+ class Container < ClosedScope #:nodoc:
503
+
504
+ attr_accessor :file, :name, :variable_scope
505
+
506
+ def initialize(body)
507
+ @body = body || Nil.new(1)
508
+ end
509
+
510
+ end
511
+
512
+ # TODO: document!
513
+ class EvalExpression < Container #:nodoc:
514
+
515
+ def initialize(body)
516
+ super body
517
+ @name = :__eval_script__
518
+ end
519
+
520
+ end
521
+
522
+ # TODO: document!
523
+ class Snippit < Container #:nodoc:
524
+
525
+ def initialize(body)
526
+ super body
527
+ @name = :__snippit__
528
+ end
529
+
530
+ end
531
+
532
+ # TODO: document!
533
+ class Script < Container #:nodoc:
534
+
535
+ def initialize(body)
536
+ super body
537
+ @name = :__script__
538
+ end
539
+
540
+ end
541
+
542
+ # A <tt>defined?</tt> statement as in:
543
+ #
544
+ # defined? a
545
+ #
546
+ class Defined < Node
547
+
548
+ # The expression passed to <tt>defined?</tt>
549
+ #
550
+ attr_accessor :expression
551
+
552
+ def initialize(line, expr) #:nodoc:
553
+ @line = line
554
+ @expression = expr
555
+ end
556
+
557
+ end
558
+
559
+ end
560
+
561
+ end
@@ -0,0 +1,182 @@
1
+ module Melbourne
2
+
3
+ module AST
4
+
5
+ # A +begin+ statement as in:
6
+ #
7
+ # begin
8
+ # do
9
+ # rescue
10
+ # puts 'error'
11
+ # end
12
+ #
13
+ class Begin < Node
14
+
15
+ # The +rescue+ statement to the +begin+ statement id there is any
16
+ #
17
+ attr_accessor :rescue
18
+
19
+ def initialize(line, body) #:nodoc:
20
+ @line = line
21
+ @rescue = body
22
+ end
23
+
24
+ end
25
+
26
+ EnsureType = 1
27
+
28
+ # An +ensure+ statement as in:
29
+ #
30
+ # begin
31
+ # do
32
+ # rescue
33
+ # puts 'error'
34
+ # ensure
35
+ # clean
36
+ # end
37
+ #
38
+ class Ensure < Node
39
+
40
+ # The body of the +ensure+ statement
41
+ #
42
+ attr_accessor :body
43
+
44
+ # A literal if one is defined as the only statement in the +ensure+ statement
45
+ #
46
+ attr_accessor :ensure
47
+
48
+ def initialize(line, body, ensr) #:nodoc:
49
+ @line = line
50
+ @body = body || Nil.new(line)
51
+ @ensure = ensr
52
+ end
53
+
54
+ end
55
+
56
+ RescueType = 0
57
+
58
+ # A +rescue+ statement as in:
59
+ #
60
+ # begin
61
+ # do
62
+ # rescue
63
+ # puts 'error'
64
+ # end
65
+ #
66
+ class Rescue < Node
67
+
68
+ # The body of the +rescue+ block
69
+ #
70
+ attr_accessor :body
71
+
72
+ # The exception or other element that is rescued from
73
+ #
74
+ attr_accessor :rescue
75
+
76
+ # The +else+ block of the +rescue+ block (+else+ is an alias for +ensure+ here)
77
+ #
78
+ attr_accessor :else
79
+
80
+ def initialize(line, body, rescue_body, else_body) #:nodoc:
81
+ @line = line
82
+ @body = body
83
+ @rescue = rescue_body
84
+ @else = else_body
85
+ end
86
+
87
+ end
88
+
89
+ # A +rescue+ condition as in:
90
+ #
91
+ # begin
92
+ # do
93
+ # rescue RuntimeError => e
94
+ # puts 'error'
95
+ # end
96
+ #
97
+ class RescueCondition < Node
98
+
99
+ # The actual conditions of rescue condition
100
+ #
101
+ attr_accessor :conditions
102
+
103
+ # Assignments in the rescue condition (e.g. <tt>RuntimeError => e</tt>, where +e+ is assigned)
104
+ #
105
+ attr_accessor :assignment
106
+
107
+ # The body os the +rescue+ block
108
+ #
109
+ attr_accessor :body
110
+
111
+ # TODO: document!
112
+ attr_accessor :next #:nodoc:
113
+
114
+ # TODO: document!
115
+ attr_accessor :splat #:nodoc:
116
+
117
+ def initialize(line, conditions, body, nxt) #:nodoc:
118
+ @line = line
119
+ @next = nxt
120
+ @splat = nil
121
+ @assignment = nil
122
+
123
+ case conditions
124
+ when ArrayLiteral
125
+ @conditions = conditions
126
+ when ConcatArgs
127
+ @conditions = conditions.array
128
+ @splat = RescueSplat.new line, conditions.rest
129
+ when SplatValue
130
+ @splat = RescueSplat.new line, conditions.value
131
+ when nil
132
+ condition = ConstFind.new line, :StandardError
133
+ @conditions = ArrayLiteral.new line, [condition]
134
+ end
135
+
136
+ case body
137
+ when Block
138
+ @assignment = body.array.shift if assignment? body.array.first
139
+ @body = body
140
+ when nil
141
+ @body = Nil.new line
142
+ else
143
+ if assignment? body
144
+ @assignment = body
145
+ @body = Nil.new line
146
+ else
147
+ @body = body
148
+ end
149
+ end
150
+ end
151
+
152
+ # TODO: document!
153
+ def assignment?(node) #:nodoc:
154
+ case node
155
+ when VariableAssignment
156
+ value = node.value
157
+ when AttributeAssignment
158
+ value = node.arguments.array.last
159
+ else
160
+ return false
161
+ end
162
+
163
+ return true if value.kind_of? GlobalVariableAccess and value.name == :$!
164
+ end
165
+
166
+ end
167
+
168
+ # TODO: document!
169
+ class RescueSplat < Node #:nodoc:
170
+
171
+ attr_accessor :value
172
+
173
+ def initialize(line, value)
174
+ @line = line
175
+ @value = value
176
+ end
177
+
178
+ end
179
+
180
+ end
181
+
182
+ end