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,362 @@
1
+ # -*- encoding: us-ascii -*-
2
+
3
+ module Rubinius
4
+ module AST
5
+ class Node
6
+ attr_accessor :line
7
+
8
+ def self.transform(category, name, comment)
9
+ Transforms.register category, name, self
10
+ @transform_name = name
11
+ @transform_comment = comment
12
+ @transform_kind = :call
13
+ end
14
+
15
+ def self.transform_name
16
+ @transform_name
17
+ end
18
+
19
+ def self.transform_comment
20
+ @transform_comment
21
+ end
22
+
23
+ def self.transform_kind
24
+ @transform_kind
25
+ end
26
+
27
+ def self.transform_kind=(k)
28
+ @transform_kind = k
29
+ end
30
+
31
+ def self.match_send?(node, receiver, method, name)
32
+ node.kind_of? ConstantAccess and
33
+ node.name == receiver and
34
+ method == name
35
+ end
36
+
37
+ def self.match_arguments?(arguments, count)
38
+ case arguments
39
+ when ArrayLiteral
40
+ arguments.body.size == count
41
+ when nil
42
+ count == 0
43
+ else
44
+ false
45
+ end
46
+ end
47
+
48
+ def initialize(line)
49
+ @line = line
50
+ end
51
+
52
+ def pos(g)
53
+ g.set_line @line
54
+ end
55
+
56
+ def new_block_generator(g, arguments)
57
+ blk = g.class.new
58
+ blk.name = g.state.name || :__block__
59
+ blk.file = g.file
60
+ blk.for_block = true
61
+
62
+ blk.required_args = arguments.required_args
63
+ blk.post_args = arguments.post_args
64
+ blk.total_args = arguments.total_args
65
+
66
+ blk
67
+ end
68
+
69
+ def new_generator(g, name, arguments=nil)
70
+ meth = g.class.new
71
+ meth.name = name
72
+ meth.file = g.file
73
+
74
+ if arguments
75
+ meth.required_args = arguments.required_args
76
+ meth.post_args = arguments.post_args
77
+ meth.total_args = arguments.total_args
78
+ meth.splat_index = arguments.splat_index
79
+ end
80
+
81
+ meth
82
+ end
83
+
84
+ # This method implements a sort of tree iterator, yielding each Node
85
+ # instance to the provided block with the first argument to #walk. If
86
+ # the block returns a non-true value, the walk is terminated.
87
+ #
88
+ # This method is really an iterator, not a Visitor pattern.
89
+ def walk(arg=true, &block)
90
+ children do |child|
91
+ if ch_arg = block.call(arg, child)
92
+ child.walk(ch_arg, &block)
93
+ end
94
+ end
95
+ end
96
+
97
+ def ascii_graph
98
+ AsciiGrapher.new(self).print
99
+ end
100
+
101
+ def to_sexp
102
+ [:node, self.class.name]
103
+ end
104
+
105
+ # Yields each child of this Node to the block. Additionally, for any
106
+ # attribute that is an Array, yields each element that is a Node.
107
+ def children
108
+ instance_variables.each do |var|
109
+ child = instance_variable_get var
110
+ if child.kind_of? Node
111
+ yield child
112
+ elsif child.kind_of? Array
113
+ child.each { |x| yield x if x.kind_of? Node }
114
+ end
115
+ end
116
+ end
117
+
118
+ # The equivalent of Some::Module.demodulize.underscore in ActiveSupport.
119
+ # The code is shamelessly borrowed as well.
120
+ def self.node_name
121
+ @node_name ||=
122
+ begin
123
+ name = self.name.gsub(/^.*::/, '')
124
+ name.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
125
+ name.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
126
+ name.downcase!
127
+ name
128
+ end
129
+ end
130
+
131
+ def node_name
132
+ self.class.node_name
133
+ end
134
+
135
+ # Supports the Visitor pattern on a tree of Nodes. The +visitor+ should
136
+ # be an object that responds to methods named after the Node subclasses.
137
+ # The method called is determined by the #node_name method. Passes both
138
+ # the node and its parent so that the visitor can maintain nesting
139
+ # information if desired.
140
+ #
141
+ # The #visit implements a read-only traversal of the tree. To modify the
142
+ # tree, see the #transform methed.
143
+ def visit(visitor, parent=nil)
144
+ visitor.__send__ self.node_name, self, parent
145
+ children { |c| c.visit visitor, self }
146
+ end
147
+
148
+ # Called by #transform to update the child of a Node instance. The
149
+ # default just calls the attr_accessor for the child. However, Node
150
+ # subclasses that must synchronize other internal state can override
151
+ # this method.
152
+ def set_child(name, node)
153
+ send :"#{name}=", node
154
+ end
155
+
156
+ # Yields each attribute and its name to the block.
157
+ def attributes
158
+ instance_variables.each do |var|
159
+ child = instance_variable_get var
160
+ name = var.to_s[1..-1]
161
+ yield child, name
162
+ end
163
+ end
164
+
165
+ # A fixed-point algorithm for transforming an AST with a visitor. The
166
+ # traversal is top-down. The visitor object's method corresponding to
167
+ # each node (see #node_name) is called for each node, passing the node
168
+ # and its parent.
169
+ #
170
+ # To replace the node in the tree, the visitor method should return a
171
+ # new node; otherwise, return the existing node. The visitor is free to
172
+ # change values in the node, but substituting a node causes the entire
173
+ # tree to be walked repeatedly until no modifications are made.
174
+ def transform(visitor, parent=nil, state=nil)
175
+ state ||= TransformState.new
176
+
177
+ node = visitor.send :"node_#{node_name}", self, parent
178
+ state.modify unless equal? node
179
+
180
+ node.attributes do |attr, name|
181
+ if attr.kind_of? Node
182
+ child = attr.transform visitor, node, state
183
+ unless attr.equal? child
184
+ state.modify
185
+ node.set_child name, child
186
+ end
187
+ elsif attr.kind_of? Array
188
+ attr.each_with_index do |x, i|
189
+ if x.kind_of? Node
190
+ child = x.transform visitor, node, state
191
+ unless x.equal? child
192
+ state.modify
193
+ attr[i] = child
194
+ end
195
+ end
196
+ end
197
+ end
198
+ end
199
+
200
+ # Repeat the walk until the tree is not modified.
201
+ if parent.nil? and state.modified?
202
+ state.unmodify
203
+ node = transform visitor, nil, state
204
+ end
205
+
206
+ node
207
+ end
208
+
209
+ # Manage the state of the #transform method.
210
+ class TransformState
211
+ def initialized
212
+ @modified = false
213
+ end
214
+
215
+ def modified?
216
+ @modified
217
+ end
218
+
219
+ def modify
220
+ @modified = true
221
+ end
222
+
223
+ def unmodify
224
+ @modified = false
225
+ end
226
+ end
227
+ end
228
+
229
+ # In a perfect world, each AST node would fully encapsulate its state. But
230
+ # in the real world, some state exists across the AST rather than just in
231
+ # a node. For example, some nodes need to emit different bytecode when in
232
+ # a rescue.
233
+ #
234
+ # This class maintains state needed as the AST is walked to generate
235
+ # bytecode. An instance of State is pushed onto a stack in the Generator
236
+ # instance as each ClosedScope or Iter is entered, and popped when left.
237
+ class State
238
+ attr_reader :scope, :super, :eval
239
+
240
+ class << self
241
+ attr_accessor :flip_flops
242
+ end
243
+
244
+ self.flip_flops ||= 0
245
+
246
+ def initialize(scope)
247
+ @scope = scope
248
+ @ensure = 0
249
+ @block = 0
250
+ @masgn = 0
251
+ @loop = 0
252
+ @op_asgn = 0
253
+ @rescue = []
254
+ @name = []
255
+ end
256
+
257
+ def push_name(name)
258
+ @name.push name
259
+ end
260
+
261
+ def pop_name
262
+ @name.pop
263
+ end
264
+
265
+ def name
266
+ @name.last
267
+ end
268
+
269
+ def push_rescue(val)
270
+ @rescue.push(val)
271
+ end
272
+
273
+ def pop_rescue
274
+ @rescue.pop if rescue?
275
+ end
276
+
277
+ def rescue?
278
+ @rescue.last
279
+ end
280
+
281
+ def push_ensure
282
+ @ensure += 1
283
+ end
284
+
285
+ def pop_ensure
286
+ @ensure -= 1 if ensure?
287
+ end
288
+
289
+ def ensure?
290
+ @ensure > 0
291
+ end
292
+
293
+ def push_block
294
+ @block += 1
295
+ end
296
+
297
+ def pop_block
298
+ @block -= 1 if block?
299
+ end
300
+
301
+ def block?
302
+ @block > 0
303
+ end
304
+
305
+ def flip_flops
306
+ State.flip_flops
307
+ end
308
+
309
+ def push_flip_flop
310
+ State.flip_flops += 1
311
+ end
312
+
313
+ def push_masgn
314
+ @masgn += 1
315
+ end
316
+
317
+ def pop_masgn
318
+ @masgn -= 1 if masgn?
319
+ end
320
+
321
+ def masgn?
322
+ @masgn > 0
323
+ end
324
+
325
+ def push_op_asgn
326
+ @op_asgn += 1
327
+ end
328
+
329
+ def pop_op_asgn
330
+ @op_asgn -= 1 if op_asgn?
331
+ end
332
+
333
+ def op_asgn?
334
+ @op_asgn > 0
335
+ end
336
+
337
+ def push_super(scope)
338
+ @super = scope
339
+ end
340
+
341
+ alias_method :super?, :super
342
+
343
+ def push_eval(scope)
344
+ @eval = scope
345
+ end
346
+
347
+ alias_method :eval?, :eval
348
+
349
+ def push_loop
350
+ @loop += 1
351
+ end
352
+
353
+ def pop_loop
354
+ @loop -= 1 if loop?
355
+ end
356
+
357
+ def loop?
358
+ @loop > 0
359
+ end
360
+ end
361
+ end
362
+ end
@@ -0,0 +1,106 @@
1
+ # -*- encoding: us-ascii -*-
2
+
3
+ module Rubinius
4
+ module AST
5
+ class And < Node
6
+ attr_accessor :left, :right
7
+
8
+ def initialize(line, left, right)
9
+ @line = line
10
+ @left = left
11
+ @right = right
12
+ end
13
+
14
+ def sexp_name
15
+ :and
16
+ end
17
+
18
+ def to_sexp
19
+ [sexp_name, @left.to_sexp, @right.to_sexp]
20
+ end
21
+ end
22
+
23
+ class Or < And
24
+ def sexp_name
25
+ :or
26
+ end
27
+ end
28
+
29
+ class Not < Node
30
+ attr_accessor :value
31
+
32
+ def initialize(line, value)
33
+ @line = line
34
+ @value = value
35
+ end
36
+
37
+ def to_sexp
38
+ [:not, @value.to_sexp]
39
+ end
40
+ end
41
+
42
+ class OpAssign1 < Node
43
+ attr_accessor :receiver, :op, :arguments, :value
44
+
45
+ def initialize(line, receiver, arguments, op, value)
46
+ @line = line
47
+ @receiver = receiver
48
+ @op = op
49
+ arguments = nil if arguments.is_a?(EmptyArray)
50
+ @arguments = ActualArguments.new line, arguments
51
+ @value = value
52
+ end
53
+
54
+ def to_sexp
55
+ arguments = [:arglist] + @arguments.to_sexp
56
+ op = @op == :or ? :"||" : :"&&"
57
+ [:op_asgn1, @receiver.to_sexp, arguments, op, @value.to_sexp]
58
+ end
59
+ end
60
+
61
+ class OpAssign2 < Node
62
+ attr_accessor :receiver, :name, :assign, :op, :value
63
+
64
+ def initialize(line, receiver, name, op, value)
65
+ @line = line
66
+ @receiver = receiver
67
+ @name = name
68
+ @op = op
69
+ @value = value
70
+ @assign = name.to_s[-1] == ?= ? name : :"#{name}="
71
+ end
72
+
73
+ def to_sexp
74
+ op = @op == :or ? :"||" : :"&&"
75
+ [:op_asgn2, @receiver.to_sexp, :"#{@name}=", op, @value.to_sexp]
76
+ end
77
+ end
78
+
79
+ class OpAssignAnd < Node
80
+ attr_accessor :left, :right
81
+
82
+ def initialize(line, left, right)
83
+ @line = line
84
+ @left = left
85
+ @right = right
86
+ end
87
+
88
+ def sexp_name
89
+ :op_asgn_and
90
+ end
91
+
92
+ def to_sexp
93
+ [sexp_name, @left.to_sexp, @right.to_sexp]
94
+ end
95
+ end
96
+
97
+ class OpAssignOr < OpAssignAnd
98
+ def sexp_name
99
+ :op_asgn_or
100
+ end
101
+ end
102
+
103
+ class OpAssignOr19 < OpAssignOr
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,15 @@
1
+ # -*- encoding: us-ascii -*-
2
+
3
+ module Rubinius
4
+ module AST
5
+ class Self < Node
6
+ def value_defined(g, f)
7
+ g.push :self
8
+ end
9
+
10
+ def to_sexp
11
+ [:self]
12
+ end
13
+ end
14
+ end
15
+ end