mutant-melbourne 2.0.1

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 (64) hide show
  1. data/LICENSE +25 -0
  2. data/README.md +69 -0
  3. data/Rakefile +14 -0
  4. data/ext/melbourne/.gitignore +3 -0
  5. data/ext/melbourne/bstring-license.txt +29 -0
  6. data/ext/melbourne/bstrlib.c +2687 -0
  7. data/ext/melbourne/bstrlib.h +267 -0
  8. data/ext/melbourne/encoding_compat.cpp +188 -0
  9. data/ext/melbourne/encoding_compat.hpp +57 -0
  10. data/ext/melbourne/extconf.rb +87 -0
  11. data/ext/melbourne/grammar18.cpp +11280 -0
  12. data/ext/melbourne/grammar18.hpp +13 -0
  13. data/ext/melbourne/grammar18.y +6088 -0
  14. data/ext/melbourne/grammar19.cpp +12420 -0
  15. data/ext/melbourne/grammar19.hpp +11 -0
  16. data/ext/melbourne/grammar19.y +7113 -0
  17. data/ext/melbourne/lex.c.blt +152 -0
  18. data/ext/melbourne/lex.c.tab +136 -0
  19. data/ext/melbourne/local_state.hpp +43 -0
  20. data/ext/melbourne/melbourne.cpp +88 -0
  21. data/ext/melbourne/melbourne.hpp +19 -0
  22. data/ext/melbourne/node18.hpp +262 -0
  23. data/ext/melbourne/node19.hpp +271 -0
  24. data/ext/melbourne/node_types.rb +304 -0
  25. data/ext/melbourne/node_types18.cpp +255 -0
  26. data/ext/melbourne/node_types18.hpp +129 -0
  27. data/ext/melbourne/node_types19.cpp +249 -0
  28. data/ext/melbourne/node_types19.hpp +126 -0
  29. data/ext/melbourne/parser_state18.hpp +181 -0
  30. data/ext/melbourne/parser_state19.hpp +251 -0
  31. data/ext/melbourne/quark.cpp +42 -0
  32. data/ext/melbourne/quark.hpp +45 -0
  33. data/ext/melbourne/symbols.cpp +224 -0
  34. data/ext/melbourne/symbols.hpp +119 -0
  35. data/ext/melbourne/var_table18.cpp +83 -0
  36. data/ext/melbourne/var_table18.hpp +33 -0
  37. data/ext/melbourne/var_table19.cpp +65 -0
  38. data/ext/melbourne/var_table19.hpp +35 -0
  39. data/ext/melbourne/visitor18.cpp +963 -0
  40. data/ext/melbourne/visitor18.hpp +12 -0
  41. data/ext/melbourne/visitor19.cpp +960 -0
  42. data/ext/melbourne/visitor19.hpp +15 -0
  43. data/lib/compiler/ast/constants.rb +81 -0
  44. data/lib/compiler/ast/control_flow.rb +290 -0
  45. data/lib/compiler/ast/data.rb +14 -0
  46. data/lib/compiler/ast/definitions.rb +749 -0
  47. data/lib/compiler/ast/encoding.rb +18 -0
  48. data/lib/compiler/ast/exceptions.rb +138 -0
  49. data/lib/compiler/ast/file.rb +11 -0
  50. data/lib/compiler/ast/grapher.rb +89 -0
  51. data/lib/compiler/ast/literals.rb +207 -0
  52. data/lib/compiler/ast/node.rb +362 -0
  53. data/lib/compiler/ast/operators.rb +106 -0
  54. data/lib/compiler/ast/self.rb +15 -0
  55. data/lib/compiler/ast/sends.rb +615 -0
  56. data/lib/compiler/ast/transforms.rb +298 -0
  57. data/lib/compiler/ast/values.rb +88 -0
  58. data/lib/compiler/ast/variables.rb +351 -0
  59. data/lib/compiler/ast.rb +20 -0
  60. data/lib/compiler/locals.rb +109 -0
  61. data/lib/melbourne/processor.rb +651 -0
  62. data/lib/melbourne/version.rb +3 -0
  63. data/lib/melbourne.rb +143 -0
  64. metadata +112 -0
@@ -0,0 +1,298 @@
1
+ # -*- encoding: us-ascii -*-
2
+
3
+ module Rubinius
4
+ module AST
5
+ module Transforms
6
+ def self.register(category, name, klass)
7
+ transform_map[name] = klass
8
+ category_map[category] << klass
9
+ end
10
+
11
+ def self.transform_map
12
+ @transform_map ||= { }
13
+ end
14
+
15
+ def self.category_map
16
+ @category_map ||= Hash.new { |h, k| h[k] = [] }
17
+ end
18
+
19
+ def self.[](name)
20
+ transform_map[name]
21
+ end
22
+
23
+ def self.category(name)
24
+ if name == :all
25
+ category_map.values.flatten
26
+ else
27
+ category_map[name]
28
+ end
29
+ end
30
+ end
31
+
32
+ ##
33
+ # Handles block_given?
34
+ class BlockGiven < Send
35
+ transform :default, :block_given, "VM instruction for block_given?, iterator?"
36
+
37
+ def self.match?(line, receiver, name, arguments, privately)
38
+ if receiver.kind_of? Self and (name == :block_given? or name == :iterator?)
39
+ new line, receiver, name, privately
40
+ end
41
+ end
42
+ end
43
+
44
+ class AccessUndefined < Send
45
+ transform :kernel, :access_undefined, "VM instruction for undefined"
46
+
47
+ def self.match?(line, receiver, name, arguments, privately)
48
+ if privately and name == :undefined
49
+ new line, receiver, name, privately
50
+ end
51
+ end
52
+ end
53
+
54
+ ##
55
+ # Handles Rubinius.primitive
56
+ class SendPrimitive < SendWithArguments
57
+ transform :default, :primitive, "Rubinius.primitive"
58
+
59
+ def self.match?(line, receiver, name, arguments, privately)
60
+ match_send? receiver, :Rubinius, name, :primitive
61
+ end
62
+ end
63
+
64
+ ##
65
+ # Handles Rubinius.check_frozen
66
+ class CheckFrozen < SendWithArguments
67
+ transform :default, :frozen, "Rubinius.check_frozen"
68
+
69
+ def self.match?(line, receiver, name, arguments, privately)
70
+ match_send? receiver, :Rubinius, name, :check_frozen
71
+ end
72
+ end
73
+
74
+ ##
75
+ # Handles Rubinius.invoke_primitive
76
+ #
77
+ class InvokePrimitive < SendWithArguments
78
+ transform :default, :invoke_primitive, "Rubinius.invoke_primitive"
79
+
80
+ def self.match?(line, receiver, name, arguments, privately)
81
+ match_send? receiver, :Rubinius, name, :invoke_primitive
82
+ end
83
+ end
84
+
85
+ ##
86
+ # Handles Rubinius.call_custom
87
+ #
88
+ class CallCustom < SendWithArguments
89
+ transform :default, :call_custom, "Rubinius.call_custom"
90
+
91
+ def self.match?(line, receiver, name, arguments, privately)
92
+ match_send? receiver, :Rubinius, name, :call_custom
93
+ end
94
+ end
95
+
96
+ ##
97
+ # Handles Rubinius.single_block_arg
98
+ #
99
+ # Given the following code:
100
+ #
101
+ # m { |x| ... }
102
+ #
103
+ # In Ruby 1.8, this has the following semantics:
104
+ #
105
+ # * x == nil if no values are yielded
106
+ # * x == val if one value is yielded
107
+ # * x == [p, q, r, ...] if more than one value is yielded
108
+ # * x == [a, b, c, ...] if one Array is yielded
109
+ #
110
+ # In Ruby 1.9, this has the following semantics:
111
+ #
112
+ # * x == nil if no values are yielded
113
+ # * x == val if one value is yielded
114
+ # * x == p if yield(p, q, r, ...)
115
+ # * x == [a, b, c, ...] if one Array is yielded
116
+ #
117
+ # However, in Ruby 1.9, the Enumerator code manually implements the 1.8
118
+ # block argument semantics. This transform exposes the VM instruction we
119
+ # use in 1.8 mode (cast_for_single_block_arg) so we can use it in 1.9 mode
120
+ # for Enumerator.
121
+ #
122
+ class SingleBlockArg < SendWithArguments
123
+ transform :default, :single_block_arg, "Rubinius.single_block_arg"
124
+
125
+ def self.match?(line, receiver, name, arguments, privately)
126
+ match_send? receiver, :Rubinius, name, :single_block_arg
127
+ end
128
+ end
129
+
130
+ ##
131
+ # Handles Rubinius.asm
132
+ #
133
+ class InlineAssembly < SendWithArguments
134
+ transform :default, :assembly, "Rubinius.asm"
135
+
136
+ def self.match?(line, receiver, name, arguments, privately)
137
+ match_send? receiver, :Rubinius, name, :asm
138
+ end
139
+ end
140
+
141
+ ##
142
+ # Handles Rubinius.privately
143
+ #
144
+ class SendPrivately < Send
145
+ transform :kernel, :privately, "Rubinius.privately"
146
+
147
+ def self.match?(line, receiver, name, arguments, privately)
148
+ if match_send? receiver, :Rubinius, name, :privately
149
+ new line, receiver, name, privately
150
+ end
151
+ end
152
+
153
+ def block=(iter)
154
+ @block = iter.body
155
+ end
156
+
157
+ def map_sends
158
+ walk do |result, node|
159
+ case node
160
+ when Send, SendWithArguments
161
+ node.privately = true
162
+ end
163
+
164
+ result
165
+ end
166
+ end
167
+ end
168
+
169
+ ##
170
+ # Emits fast VM instructions for certain methods.
171
+ #
172
+ class SendFastMath < SendWithArguments
173
+ transform :default, :fast_math, "VM instructions for math, relational methods"
174
+
175
+ Operators = {
176
+ :+ => :meta_send_op_plus,
177
+ :- => :meta_send_op_minus,
178
+ :== => :meta_send_op_equal,
179
+ :=== => :meta_send_op_tequal,
180
+ :< => :meta_send_op_lt,
181
+ :> => :meta_send_op_gt
182
+ }
183
+
184
+ def self.match?(line, receiver, name, arguments, privately)
185
+ return false unless op = Operators[name]
186
+ if match_arguments? arguments, 1
187
+ node = new line, receiver, name, arguments
188
+ node.operator = op
189
+ node
190
+ end
191
+ end
192
+
193
+ attr_accessor :operator
194
+ end
195
+
196
+ ##
197
+ # Emits a fast path for #new
198
+ #
199
+ class SendFastNew < SendWithArguments
200
+ transform :default, :fast_new, "Fast SomeClass.new path"
201
+
202
+ # FIXME duplicated from kernel/common/compiled_code.rb
203
+ KernelMethodSerial = 47
204
+
205
+ def self.match?(line, receiver, name, arguments, privately)
206
+ # ignore vcall style
207
+ return false if !arguments and privately
208
+ name == :new
209
+ end
210
+ end
211
+
212
+ ##
213
+ # Emits "safe" names for certain fundamental core library methods
214
+ #
215
+ class SendKernelMethod < SendWithArguments
216
+ transform :kernel, :kernel_methods, "Safe names for fundamental methods"
217
+
218
+ Methods = {
219
+ :/ => :divide,
220
+ :__slash__ => :/,
221
+ :class => :__class__
222
+ }
223
+
224
+ Arguments = {
225
+ :/ => 1,
226
+ :__slash__ => 1,
227
+ :class => 0
228
+ }
229
+
230
+ def self.match?(line, receiver, name, arguments, privately)
231
+ return false unless rename = Methods[name]
232
+ if match_arguments? arguments, Arguments[name]
233
+ new line, receiver, rename, arguments, privately
234
+ end
235
+ end
236
+ end
237
+
238
+ ##
239
+ # Maps various methods to VM instructions
240
+ #
241
+ class SendInstructionMethod < SendWithArguments
242
+ transform :default, :fast_system, "VM instructions for certain methods"
243
+
244
+ Methods = {
245
+ :__kind_of__ => :kind_of,
246
+ :__instance_of__ => :instance_of,
247
+ :__nil__ => :is_nil,
248
+ }
249
+
250
+ Arguments = {
251
+ :__kind_of__ => 1,
252
+ :__instance_of__ => 1,
253
+ :__nil__ => 0,
254
+ }
255
+
256
+ def self.match?(line, receiver, name, arguments, privately)
257
+ return false unless rename = Methods[name]
258
+ if match_arguments? arguments, Arguments[name]
259
+ new line, receiver, rename, arguments, privately
260
+ end
261
+ end
262
+ end
263
+
264
+ ##
265
+ # Speeds up certain forms of Type.coerce_to
266
+ #
267
+ class SendFastCoerceTo < SendWithArguments
268
+ transform :default, :fast_coerce, "Fast Rubinius::Type.coerce_to path"
269
+
270
+ def self.match?(line, receiver, name, arguments, privately)
271
+ methods = [:coerce_to, :check_convert_type, :try_convert]
272
+ receiver.kind_of?(TypeConstant) && methods.include?(name) &&
273
+ arguments.body.size == 3
274
+ end
275
+ end
276
+
277
+ ##
278
+ # Handles loop do ... end
279
+ #
280
+ class SendLoop < Send
281
+ transform :magic, :loop, "loop do ... end"
282
+
283
+ def self.match?(line, receiver, name, arguments, privately)
284
+ if receiver.kind_of? Self and name == :loop
285
+ new line, receiver, name, privately
286
+ end
287
+ end
288
+
289
+ def block=(iter)
290
+ if iter.kind_of? BlockPass
291
+ @blockarg = iter
292
+ else
293
+ @block = iter.body
294
+ end
295
+ end
296
+ end
297
+ end
298
+ end
@@ -0,0 +1,88 @@
1
+ # -*- encoding: us-ascii -*-
2
+
3
+ module Rubinius
4
+ module AST
5
+ class SplatValue < Node
6
+ attr_accessor :value
7
+
8
+ def initialize(line, value)
9
+ @line = line
10
+ @value = value
11
+ end
12
+
13
+ def to_sexp
14
+ [:splat, @value.to_sexp]
15
+ end
16
+ end
17
+
18
+ class ConcatArgs < Node
19
+ attr_accessor :array, :rest
20
+
21
+ def initialize(line, array, rest)
22
+ @line = line
23
+ @array = array
24
+ @rest = rest
25
+ end
26
+
27
+ def to_sexp
28
+ [:argscat, @array.to_sexp, @rest.to_sexp]
29
+ end
30
+ end
31
+
32
+ class PushArgs < Node
33
+ attr_accessor :arguments, :value
34
+
35
+ def initialize(line, arguments, value)
36
+ @line = line
37
+ @arguments = arguments
38
+ @value = value
39
+ end
40
+
41
+ def to_sexp
42
+ [:argspush, @arguments.to_sexp, @value.to_sexp]
43
+ end
44
+ end
45
+
46
+
47
+ class SValue < Node
48
+ attr_accessor :value
49
+
50
+ def initialize(line, value)
51
+ @line = line
52
+ @value = value
53
+ end
54
+
55
+ def to_sexp
56
+ [:svalue, @value.to_sexp]
57
+ end
58
+ end
59
+
60
+ class ToArray < Node
61
+ attr_accessor :value
62
+
63
+ def initialize(line, value)
64
+ @line = line
65
+ @value = value
66
+ end
67
+
68
+ def to_sexp
69
+ [:to_ary, @value.to_sexp]
70
+ end
71
+ end
72
+
73
+ class ToString < Node
74
+ attr_accessor :value
75
+
76
+ def initialize(line, value)
77
+ @line = line
78
+ @value = value
79
+ end
80
+
81
+ def to_sexp
82
+ sexp = [:evstr]
83
+ sexp << @value.to_sexp if @value
84
+ sexp
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,351 @@
1
+ # -*- encoding: us-ascii -*-
2
+
3
+ module Rubinius
4
+ module AST
5
+ class BackRef < Node
6
+ attr_accessor :kind
7
+
8
+ def initialize(line, ref)
9
+ @line = line
10
+ @kind = ref
11
+ end
12
+
13
+ Kinds = {
14
+ :~ => 0,
15
+ :& => 1,
16
+ :"`" => 2,
17
+ :"'" => 3,
18
+ :+ => 4
19
+ }
20
+
21
+ def mode
22
+ unless mode = Kinds[@kind]
23
+ raise "Unknown backref: #{@kind}"
24
+ end
25
+
26
+ mode
27
+ end
28
+
29
+ def to_sexp
30
+ [:back_ref, @kind]
31
+ end
32
+ end
33
+
34
+ class NthRef < Node
35
+ attr_accessor :which
36
+
37
+ def initialize(line, ref)
38
+ @line = line
39
+ @which = ref
40
+ end
41
+
42
+ Mode = 5
43
+
44
+ def to_sexp
45
+ [:nth_ref, @which]
46
+ end
47
+ end
48
+
49
+ class VariableAccess < Node
50
+ attr_accessor :name
51
+
52
+ def initialize(line, name)
53
+ @line = line
54
+ @name = name
55
+ end
56
+ end
57
+
58
+ class VariableAssignment < Node
59
+ attr_accessor :name, :value
60
+
61
+ def initialize(line, name, value)
62
+ @line = line
63
+ @name = name
64
+ @value = value
65
+ end
66
+
67
+ def defined(g)
68
+ g.push_literal "assignment"
69
+ end
70
+
71
+ def to_sexp
72
+ sexp = [sexp_name, @name]
73
+ sexp << @value.to_sexp if @value
74
+ sexp
75
+ end
76
+ end
77
+
78
+ class ClassVariableAccess < VariableAccess
79
+ def to_sexp
80
+ [:cvar, @name]
81
+ end
82
+ end
83
+
84
+ class ClassVariableAssignment < VariableAssignment
85
+ def sexp_name
86
+ :cvasgn
87
+ end
88
+ end
89
+
90
+ class ClassVariableDeclaration < ClassVariableAssignment
91
+ def sexp_name
92
+ :cvdecl
93
+ end
94
+ end
95
+
96
+ class CurrentException < Node
97
+ def to_sexp
98
+ [:gvar, :$!]
99
+ end
100
+ end
101
+
102
+ class GlobalVariableAccess < VariableAccess
103
+ EnglishBackrefs = {
104
+ :$LAST_MATCH_INFO => :~,
105
+ :$MATCH => :&,
106
+ :$PREMATCH => :'`',
107
+ :$POSTMATCH => :"'",
108
+ :$LAST_PAREN_MATCH => :+,
109
+ }
110
+
111
+ def self.for_name(line, name)
112
+ case name
113
+ when :$!
114
+ CurrentException.new(line)
115
+ when :$~
116
+ BackRef.new(line, :~)
117
+ else
118
+ if backref = EnglishBackrefs[name]
119
+ BackRef.new(line, backref)
120
+ else
121
+ new(line, name)
122
+ end
123
+ end
124
+ end
125
+
126
+ def to_sexp
127
+ [:gvar, @name]
128
+ end
129
+ end
130
+
131
+ class GlobalVariableAssignment < VariableAssignment
132
+ def sexp_name
133
+ :gasgn
134
+ end
135
+ end
136
+
137
+ class SplatAssignment < Node
138
+ attr_accessor :value
139
+
140
+ def initialize(line, value)
141
+ @line = line
142
+ @value = value
143
+ end
144
+
145
+ def to_sexp
146
+ [:splat_assign, @value.to_sexp]
147
+ end
148
+ end
149
+
150
+ class SplatArray < SplatAssignment
151
+ def initialize(line, value, size)
152
+ @line = line
153
+ @value = value
154
+ @size = size
155
+ end
156
+
157
+ def to_sexp
158
+ [:splat, @value.to_sexp]
159
+ end
160
+ end
161
+
162
+ class SplatWrapped < SplatAssignment
163
+ def to_sexp
164
+ [:splat, @value.to_sexp]
165
+ end
166
+ end
167
+
168
+ class EmptySplat < Node
169
+ def initialize(line, size)
170
+ @line = line
171
+ @size = size
172
+ end
173
+
174
+ def to_sexp
175
+ [:splat]
176
+ end
177
+ end
178
+
179
+ class InstanceVariableAccess < VariableAccess
180
+ def to_sexp
181
+ [:ivar, @name]
182
+ end
183
+ end
184
+
185
+ class InstanceVariableAssignment < VariableAssignment
186
+ def sexp_name
187
+ :iasgn
188
+ end
189
+ end
190
+
191
+ class LocalVariableAccess < VariableAccess
192
+ include LocalVariable
193
+
194
+ def initialize(line, name)
195
+ @line = line
196
+ @name = name
197
+ @variable = nil
198
+ end
199
+
200
+ def to_sexp
201
+ [:lvar, @name]
202
+ end
203
+ end
204
+
205
+ class LocalVariableAssignment < VariableAssignment
206
+ include LocalVariable
207
+
208
+ def initialize(line, name, value)
209
+ @line = line
210
+ @name = name
211
+ @value = value
212
+ @variable = nil
213
+ end
214
+
215
+ def sexp_name
216
+ :lasgn
217
+ end
218
+ end
219
+
220
+ class PostArg < Node
221
+ attr_accessor :into, :rest
222
+
223
+ def initialize(line, into, rest)
224
+ @line = line
225
+ @into = into
226
+ @rest = rest
227
+ end
228
+ end
229
+
230
+ class MultipleAssignment < Node
231
+ attr_accessor :left, :right, :splat, :block
232
+
233
+ def initialize(line, left, right, splat)
234
+ @line = line
235
+ @left = left
236
+ @right = right
237
+ @splat = nil
238
+ @block = nil # support for |&b|
239
+ @post = nil # in `a,*b,c`, c is in post.
240
+
241
+ if Rubinius.ruby18?
242
+ @fixed = right.kind_of?(ArrayLiteral) ? true : false
243
+ elsif splat.kind_of?(PostArg)
244
+ @fixed = false
245
+ @post = splat.rest
246
+ splat = splat.into
247
+ elsif right.kind_of?(ArrayLiteral)
248
+ @fixed = right.body.size > 1
249
+ else
250
+ @fixed = false
251
+ end
252
+
253
+ if splat.kind_of? Node
254
+ if @left
255
+ if right
256
+ @splat = SplatAssignment.new line, splat
257
+ else
258
+ @splat = SplatWrapped.new line, splat
259
+ end
260
+ elsif @fixed
261
+ @splat = SplatArray.new line, splat, right.body.size
262
+ elsif right.kind_of? SplatValue
263
+ @splat = splat
264
+ else
265
+ @splat = SplatWrapped.new line, splat
266
+ end
267
+ elsif splat
268
+ # We need a node for eg { |*| } and { |a, *| }
269
+ size = @fixed ? right.body.size : 0
270
+ @splat = EmptySplat.new line, size
271
+ end
272
+ end
273
+
274
+ def pad_short(g)
275
+ short = @left.body.size - @right.body.size
276
+ if short > 0
277
+ short.times { g.push :nil }
278
+ g.make_array 0 if @splat
279
+ end
280
+ end
281
+
282
+ def pop_excess(g)
283
+ excess = @right.body.size - @left.body.size
284
+ excess.times { g.pop } if excess > 0
285
+ end
286
+
287
+ def make_array(g)
288
+ size = @right.body.size - @left.body.size
289
+ g.make_array size if size >= 0
290
+ end
291
+
292
+ def rotate(g)
293
+ if @splat
294
+ size = @left.body.size + 1
295
+ else
296
+ size = @right.body.size
297
+ end
298
+ g.rotate size
299
+ end
300
+
301
+ def iter_arguments
302
+ @iter_arguments = true
303
+ end
304
+
305
+ def declare_local_scope(scope)
306
+ # Fix the scope for locals introduced by the left. We
307
+ # do this before running the code for the right so that
308
+ # right side sees the proper scoping of the locals on the left.
309
+
310
+ if @left
311
+ @left.body.each do |var|
312
+ case var
313
+ when LocalVariable
314
+ scope.assign_local_reference var
315
+ when MultipleAssignment
316
+ var.declare_local_scope(scope)
317
+ end
318
+ end
319
+ end
320
+
321
+ if @splat and @splat.kind_of?(SplatAssignment)
322
+ if @splat.value.kind_of?(LocalVariable)
323
+ scope.assign_local_reference @splat.value
324
+ end
325
+ end
326
+ end
327
+
328
+ def to_sexp
329
+ left = @left ? @left.to_sexp : [:array]
330
+ left << [:splat, @splat.to_sexp] if @splat
331
+ left << @block.to_sexp if @block
332
+
333
+ sexp = [:masgn, left]
334
+ sexp << @right.to_sexp if @right
335
+ sexp
336
+ end
337
+ end
338
+
339
+ class PatternVariable < Node
340
+ include LocalVariable
341
+
342
+ attr_accessor :name, :value
343
+
344
+ def initialize(line, name)
345
+ @line = line
346
+ @name = name
347
+ @variable = nil
348
+ end
349
+ end
350
+ end
351
+ end