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.
- data/HISTORY +3 -0
- data/LICENSE +27 -0
- data/README.rdoc +38 -0
- data/Rakefile +38 -0
- data/VERSION.yml +4 -0
- data/ext/melbourne/bstring-license.txt +29 -0
- data/ext/melbourne/bstrlib.c +2918 -0
- data/ext/melbourne/bstrlib.h +302 -0
- data/ext/melbourne/extconf.rb +76 -0
- data/ext/melbourne/grammar.cpp +11885 -0
- data/ext/melbourne/grammar.hpp +14 -0
- data/ext/melbourne/grammar.y +6013 -0
- data/ext/melbourne/internal.hpp +137 -0
- data/ext/melbourne/lex.c.tab +136 -0
- data/ext/melbourne/local_state.hpp +41 -0
- data/ext/melbourne/melbourne.cpp +37 -0
- data/ext/melbourne/node.hpp +262 -0
- data/ext/melbourne/node_types.cpp +245 -0
- data/ext/melbourne/node_types.hpp +135 -0
- data/ext/melbourne/node_types.rb +190 -0
- data/ext/melbourne/quark.cpp +52 -0
- data/ext/melbourne/quark.hpp +14 -0
- data/ext/melbourne/symbols.cpp +219 -0
- data/ext/melbourne/symbols.hpp +116 -0
- data/ext/melbourne/var_table.cpp +113 -0
- data/ext/melbourne/var_table.hpp +33 -0
- data/ext/melbourne/visitor.cpp +1052 -0
- data/ext/melbourne/visitor.hpp +20 -0
- data/lib/melbourne/ast/constants.rb +128 -0
- data/lib/melbourne/ast/control_flow.rb +382 -0
- data/lib/melbourne/ast/data.rb +19 -0
- data/lib/melbourne/ast/definitions.rb +561 -0
- data/lib/melbourne/ast/exceptions.rb +182 -0
- data/lib/melbourne/ast/file.rb +15 -0
- data/lib/melbourne/ast/grapher.rb +75 -0
- data/lib/melbourne/ast/literals.rb +268 -0
- data/lib/melbourne/ast/node.rb +21 -0
- data/lib/melbourne/ast/operators.rb +117 -0
- data/lib/melbourne/ast/self.rb +17 -0
- data/lib/melbourne/ast/sends.rb +451 -0
- data/lib/melbourne/ast/values.rb +74 -0
- data/lib/melbourne/ast/variables.rb +251 -0
- data/lib/melbourne/ast.rb +22 -0
- data/lib/melbourne/parser.rb +38 -0
- data/lib/melbourne/processor.rb +460 -0
- data/lib/melbourne.rb +46 -0
- data/spec/helpers/ast/node.rb +15 -0
- data/spec/helpers/ast/reduced_graph.rb +64 -0
- data/spec/lib/parser/alias_spec.rb +97 -0
- data/spec/lib/parser/and_spec.rb +63 -0
- data/spec/lib/parser/array_spec.rb +157 -0
- data/spec/lib/parser/attrasgn_spec.rb +401 -0
- data/spec/lib/parser/back_ref_spec.rb +20 -0
- data/spec/lib/parser/call_spec.rb +958 -0
- data/spec/lib/parser/case_spec.rb +577 -0
- data/spec/lib/parser/cdecl_spec.rb +108 -0
- data/spec/lib/parser/class_spec.rb +221 -0
- data/spec/lib/parser/colon2_spec.rb +13 -0
- data/spec/lib/parser/colon3_spec.rb +12 -0
- data/spec/lib/parser/const_spec.rb +12 -0
- data/spec/lib/parser/cvar_spec.rb +55 -0
- data/spec/lib/parser/cvasgn_spec.rb +71 -0
- data/spec/lib/parser/cvdecl_spec.rb +31 -0
- data/spec/lib/parser/defined_spec.rb +353 -0
- data/spec/lib/parser/defn_spec.rb +1409 -0
- data/spec/lib/parser/defs_spec.rb +247 -0
- data/spec/lib/parser/dot2_spec.rb +29 -0
- data/spec/lib/parser/dot3_spec.rb +29 -0
- data/spec/lib/parser/dregx_spec.rb +127 -0
- data/spec/lib/parser/dstr_spec.rb +453 -0
- data/spec/lib/parser/dsym_spec.rb +31 -0
- data/spec/lib/parser/dxstr_spec.rb +31 -0
- data/spec/lib/parser/ensure_spec.rb +279 -0
- data/spec/lib/parser/false_spec.rb +12 -0
- data/spec/lib/parser/flip2_spec.rb +138 -0
- data/spec/lib/parser/flip3_spec.rb +100 -0
- data/spec/lib/parser/for_spec.rb +279 -0
- data/spec/lib/parser/gasgn_spec.rb +34 -0
- data/spec/lib/parser/gvar_spec.rb +33 -0
- data/spec/lib/parser/hash_spec.rb +77 -0
- data/spec/lib/parser/iasgn_spec.rb +54 -0
- data/spec/lib/parser/if_spec.rb +439 -0
- data/spec/lib/parser/iter_spec.rb +2582 -0
- data/spec/lib/parser/lasgn_spec.rb +1066 -0
- data/spec/lib/parser/lit_spec.rb +75 -0
- data/spec/lib/parser/masgn_spec.rb +1970 -0
- data/spec/lib/parser/match2_spec.rb +47 -0
- data/spec/lib/parser/match3_spec.rb +54 -0
- data/spec/lib/parser/match_spec.rb +19 -0
- data/spec/lib/parser/module_spec.rb +102 -0
- data/spec/lib/parser/nil_spec.rb +13 -0
- data/spec/lib/parser/not_spec.rb +39 -0
- data/spec/lib/parser/nth_ref_spec.rb +12 -0
- data/spec/lib/parser/op_asgn_spec.rb +619 -0
- data/spec/lib/parser/or_spec.rb +155 -0
- data/spec/lib/parser/postexe_spec.rb +31 -0
- data/spec/lib/parser/regex_spec.rb +52 -0
- data/spec/lib/parser/rescue_spec.rb +1028 -0
- data/spec/lib/parser/return_spec.rb +151 -0
- data/spec/lib/parser/sclass_spec.rb +172 -0
- data/spec/lib/parser/str_spec.rb +162 -0
- data/spec/lib/parser/super_spec.rb +276 -0
- data/spec/lib/parser/true_spec.rb +12 -0
- data/spec/lib/parser/undef_spec.rb +222 -0
- data/spec/lib/parser/until_spec.rb +286 -0
- data/spec/lib/parser/valias_spec.rb +12 -0
- data/spec/lib/parser/while_spec.rb +458 -0
- data/spec/lib/parser/xstr_spec.rb +12 -0
- data/spec/lib/parser/yield_spec.rb +202 -0
- data/spec/lib/parser/zsuper_spec.rb +101 -0
- data/spec/matchers/parse_as.rb +27 -0
- data/spec/spec_helper.rb +10 -0
- 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
|