mutant-melbourne 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
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