rubinius-ast 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ # -*- encoding: us-ascii -*-
2
+
3
+ module Rubinius::ToolSet.current::TS
4
+ module AST
5
+ class File < Node
6
+ def bytecode(g)
7
+ pos(g)
8
+
9
+ g.push_scope
10
+ g.send :active_path, 0
11
+ end
12
+
13
+ def to_sexp
14
+ [:file]
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,89 @@
1
+ # -*- encoding: us-ascii -*-
2
+
3
+ module Rubinius::ToolSet.current::TS
4
+ module AST
5
+ class AsciiGrapher
6
+ def initialize(ast, node_kind=Node)
7
+ @ast = ast
8
+ @node_kind = node_kind
9
+ end
10
+
11
+ def print
12
+ graph_node @ast
13
+ end
14
+
15
+ def indented_print(level, value)
16
+ puts "#{" " * level}#{value}"
17
+ end
18
+
19
+ def print_node(node, level, idx=nil)
20
+ name = node.class.to_s.split("::").last
21
+
22
+ name = "#{name} [#{idx}]" if idx
23
+
24
+ indented_print level, name
25
+ end
26
+
27
+ def graph_node(node, level=0, idx=nil)
28
+ print_node node, level, idx
29
+ level += 2
30
+
31
+ nodes = []
32
+ node.instance_variables.each do |v|
33
+ next if v == "@compiler"
34
+
35
+ value = node.instance_variable_get v
36
+
37
+ # lame, yes. remove when Node doesn't have @body by default
38
+ next if v == "@body" and value.nil? and not v.respond_to? :body=
39
+
40
+ if value.kind_of? @node_kind
41
+ nodes << [v, value]
42
+ else
43
+ graph_value v, value, level
44
+ end
45
+ end
46
+
47
+ nodes.each do |name, n|
48
+ puts "#{" " * level}#{name}: \\"
49
+ graph_node n, level + 2
50
+ end
51
+ end
52
+
53
+ def graph_simple(name, value, level)
54
+ puts "#{" " * level}#{name}: #{value}"
55
+ end
56
+
57
+ def graph_value(name, value, level)
58
+ case value
59
+ when NilClass, String
60
+ graph_simple name, value.inspect, level
61
+ when Symbol
62
+ puts "#{" " * level}#{name}: :#{value}"
63
+ when TrueClass, FalseClass, Fixnum
64
+ graph_simple name, value, level
65
+ when Array
66
+ if value.empty?
67
+ puts "#{" " * level}#{name}: []"
68
+ else
69
+ puts "#{" " * level}#{name}: ["
70
+ nodes = []
71
+ value.each_with_index do |v,i|
72
+ if v.kind_of? @node_kind
73
+ nodes << [v, i]
74
+ else
75
+ graph_value "[#{i}] ", v, level + 2
76
+ end
77
+ end
78
+
79
+ nodes.each { |n| graph_node n[0], level + 2, n[1] }
80
+
81
+ puts "#{' ' * level}]"
82
+ end
83
+ else
84
+ graph_simple name, value.class, level
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,555 @@
1
+ # -*- encoding: us-ascii -*-
2
+
3
+ module Rubinius::ToolSet.current::TS
4
+ module AST
5
+ class ArrayLiteral < Node
6
+ attr_accessor :body
7
+
8
+ def initialize(line, array)
9
+ @line = line
10
+ @body = array
11
+ end
12
+
13
+ def bytecode(g)
14
+ pos(g)
15
+
16
+ @body.each do |x|
17
+ x.bytecode(g)
18
+ end
19
+
20
+ g.make_array @body.size
21
+ end
22
+
23
+ def defined(g)
24
+ not_found = g.new_label
25
+ done = g.new_label
26
+ @body.each do |x|
27
+ x.defined(g)
28
+ g.gif not_found
29
+ end
30
+ g.push_literal "expression"
31
+ g.goto done
32
+ not_found.set!
33
+ g.push_nil
34
+ g.goto done
35
+
36
+ done.set!
37
+ end
38
+
39
+ def to_sexp
40
+ @body.inject([:array]) { |s, x| s << x.to_sexp }
41
+ end
42
+ end
43
+
44
+ class EmptyArray < Node
45
+ def bytecode(g)
46
+ pos(g)
47
+
48
+ g.make_array 0
49
+ end
50
+
51
+ def defined(g)
52
+ g.push_literal "expression"
53
+ end
54
+
55
+ def to_sexp
56
+ [:array]
57
+ end
58
+ end
59
+
60
+ class FalseLiteral < Node
61
+ def bytecode(g)
62
+ pos(g)
63
+
64
+ g.push :false
65
+ end
66
+
67
+ def defined(g)
68
+ g.push_literal "false"
69
+ end
70
+
71
+ def to_sexp
72
+ [:false]
73
+ end
74
+ end
75
+
76
+ class TrueLiteral < Node
77
+ def bytecode(g)
78
+ pos(g)
79
+
80
+ g.push :true
81
+ end
82
+
83
+ def defined(g)
84
+ g.push_literal "true"
85
+ end
86
+
87
+ def to_sexp
88
+ [:true]
89
+ end
90
+ end
91
+
92
+ class FloatLiteral < Node
93
+ attr_accessor :value
94
+
95
+ def initialize(line, str)
96
+ @line = line
97
+ @value = str.to_f
98
+ end
99
+
100
+ def bytecode(g)
101
+ pos(g)
102
+
103
+ g.push_unique_literal @value
104
+ end
105
+
106
+ def defined(g)
107
+ g.push_literal "expression"
108
+ end
109
+
110
+ def to_sexp
111
+ [:lit, @value]
112
+ end
113
+ end
114
+
115
+ class HashLiteral < Node
116
+ attr_accessor :array
117
+
118
+ def initialize(line, array)
119
+ @line = line
120
+ @array = array
121
+ end
122
+
123
+ def bytecode(g)
124
+ pos(g)
125
+
126
+ count = @array.size
127
+ i = 0
128
+
129
+ g.push_cpath_top
130
+ g.find_const :Hash
131
+ g.push count / 2
132
+ g.send :new_from_literal, 1
133
+
134
+ while i < count
135
+ k = @array[i]
136
+ v = @array[i + 1]
137
+
138
+ g.dup
139
+ k.bytecode(g)
140
+ v.bytecode(g)
141
+ g.send :[]=, 2
142
+ g.pop
143
+
144
+ i += 2
145
+ end
146
+ end
147
+
148
+ def defined(g)
149
+ g.push_literal "expression"
150
+ end
151
+
152
+ def to_sexp
153
+ @array.inject([:hash]) { |s, x| s << x.to_sexp }
154
+ end
155
+ end
156
+
157
+ class SymbolLiteral < Node
158
+ attr_accessor :value
159
+
160
+ def initialize(line, sym)
161
+ @line = line
162
+ @value = sym
163
+ end
164
+
165
+ def bytecode(g)
166
+ pos(g)
167
+
168
+ g.push_literal @value
169
+ end
170
+
171
+ def defined(g)
172
+ g.push_literal "expression"
173
+ end
174
+
175
+ def to_sexp
176
+ [:lit, @value]
177
+ end
178
+ end
179
+
180
+ class NilLiteral < Node
181
+ def bytecode(g)
182
+ pos(g)
183
+
184
+ g.push :nil
185
+ end
186
+
187
+ def defined(g)
188
+ g.push_literal "nil"
189
+ end
190
+
191
+ def to_sexp
192
+ [:nil]
193
+ end
194
+ end
195
+
196
+ class NumberLiteral < Node
197
+ attr_accessor :value
198
+
199
+ def initialize(line, value)
200
+ @line = line
201
+ @value = value
202
+ end
203
+
204
+ def bytecode(g)
205
+ pos(g)
206
+
207
+ g.push_unique_literal @value
208
+ end
209
+
210
+ def defined(g)
211
+ g.push_literal "expression"
212
+ end
213
+
214
+ def to_sexp
215
+ [:lit, @value]
216
+ end
217
+ end
218
+
219
+ class FixnumLiteral < NumberLiteral
220
+ def initialize(line, value)
221
+ @line = line
222
+ @value = value
223
+ end
224
+
225
+ def bytecode(g)
226
+ pos(g)
227
+
228
+ g.push @value
229
+ end
230
+
231
+ def defined(g)
232
+ g.push_literal "expression"
233
+ end
234
+ end
235
+
236
+ class Range < Node
237
+ attr_accessor :start, :finish
238
+
239
+ def initialize(line, start, finish)
240
+ @line = line
241
+ @start = start
242
+ @finish = finish
243
+ end
244
+
245
+ def bytecode(g)
246
+ pos(g)
247
+
248
+ g.push_cpath_top
249
+ g.find_const :Range
250
+ g.send :allocate, 0, true
251
+ g.dup
252
+ @start.bytecode(g)
253
+ @finish.bytecode(g)
254
+ g.send :initialize, 2, true
255
+ g.pop
256
+ end
257
+
258
+ def defined(g)
259
+ g.push_literal "expression"
260
+ end
261
+
262
+ def to_sexp
263
+ [:dot2, @start.to_sexp, @finish.to_sexp]
264
+ end
265
+ end
266
+
267
+ class RangeExclude < Range
268
+ def initialize(line, start, finish)
269
+ @line = line
270
+ @start = start
271
+ @finish = finish
272
+ end
273
+
274
+ def bytecode(g)
275
+ pos(g)
276
+
277
+ g.push_cpath_top
278
+ g.find_const :Range
279
+ g.send :allocate, 0, true
280
+ g.dup
281
+ @start.bytecode(g)
282
+ @finish.bytecode(g)
283
+ g.push :true
284
+ g.send :initialize, 3, true
285
+ g.pop
286
+ end
287
+
288
+ def to_sexp
289
+ [:dot3, @start.to_sexp, @finish.to_sexp]
290
+ end
291
+ end
292
+
293
+ class RegexLiteral < Node
294
+ attr_accessor :source, :options
295
+
296
+ def initialize(line, str, flags)
297
+ @line = line
298
+ @source = str
299
+ @options = flags
300
+ end
301
+
302
+ def bytecode(g)
303
+ pos(g)
304
+
305
+ # A regex literal should only be converted to a Regexp the first time it
306
+ # is encountered. We push a literal nil here, and then overwrite the
307
+ # literal value with the created Regexp if it is nil, i.e. the first time
308
+ # only. Subsequent encounters will use the previously created Regexp
309
+ idx = g.add_literal(nil)
310
+ g.push_literal_at idx
311
+ g.dup
312
+ g.is_nil
313
+
314
+ lbl = g.new_label
315
+ g.gif lbl
316
+ g.pop
317
+ g.push_cpath_top
318
+ g.find_const :Regexp
319
+ g.push_literal @source
320
+ g.push @options
321
+ g.send :new, 2
322
+ g.set_literal idx
323
+ lbl.set!
324
+ end
325
+
326
+ def defined(g)
327
+ g.push_literal "expression"
328
+ end
329
+
330
+ def to_sexp
331
+ [:regex, @source, @options]
332
+ end
333
+ end
334
+
335
+ class StringLiteral < Node
336
+ attr_accessor :string
337
+
338
+ def initialize(line, str)
339
+ @line = line
340
+ @string = str
341
+ end
342
+
343
+ def bytecode(g)
344
+ pos(g)
345
+
346
+ # TODO: change to push_unique_literal
347
+ g.push_literal @string
348
+ g.string_dup
349
+ end
350
+
351
+ def defined(g)
352
+ g.push_literal "expression"
353
+ end
354
+
355
+ def to_sexp
356
+ [:str, @string]
357
+ end
358
+ end
359
+
360
+ class DynamicString < StringLiteral
361
+ attr_accessor :array, :options
362
+
363
+ def initialize(line, str, array)
364
+ @line = line
365
+ @string = str
366
+ @array = array
367
+ end
368
+
369
+ # This extensive logic is 100% for optimizing rather ridiculous edge
370
+ # cases for string interpolation and I (brixen) do not think it is
371
+ # worthwhile.
372
+ #
373
+ # Some examples:
374
+ #
375
+ # "#{}"
376
+ # "#{} foo"
377
+ # "foo #{}"
378
+ # "#{}#{}"
379
+ # "#{bar}"
380
+ #
381
+ # Also, as Zocx pointed out in IRC, the following code is not compatible
382
+ # in Rubinius because we convert an empty evstr into "" directly in
383
+ # Melbourne parse tree to AST processor rather than calling #to_s on
384
+ # 'nil'.
385
+ #
386
+ # def nil.to_s; "hello"; end
387
+ # a = "#{}" # => "hello" in MRI
388
+ #
389
+ # We also do not handle any case where #to_s does not actually return a
390
+ # String instance.
391
+ #
392
+ def bytecode(g)
393
+ pos(g)
394
+
395
+ if @string.empty?
396
+ if @array.size == 1
397
+ case x = @array.first
398
+ when StringLiteral
399
+ x.bytecode(g)
400
+ else
401
+ x.bytecode(g)
402
+ # string_build has some auto-conversion logic, use it.
403
+ g.string_build 1
404
+ end
405
+ return
406
+ end
407
+
408
+ prefix = false
409
+ else
410
+ prefix = true
411
+ g.push_literal @string
412
+ end
413
+
414
+ total = 0
415
+ @array.each do |e|
416
+ case e
417
+ when StringLiteral
418
+ unless e.string.empty?
419
+ g.push_literal e.string
420
+ total += 1
421
+ end
422
+ else
423
+ e.bytecode(g)
424
+ total += 1
425
+ end
426
+ end
427
+
428
+ if prefix
429
+ if total == 0
430
+ g.string_dup
431
+ return
432
+ end
433
+ total += 1
434
+ else
435
+ if total == 0
436
+ g.push_literal ""
437
+ g.string_dup
438
+ return
439
+ elsif total == 1
440
+ g.string_build 1
441
+ return
442
+ end
443
+ end
444
+
445
+ g.string_build total
446
+ end
447
+
448
+ def defined(g)
449
+ f = g.new_label
450
+ done = g.new_label
451
+
452
+ @array.each do |x|
453
+ x.value_defined(g, f)
454
+ g.pop
455
+ end
456
+
457
+ g.push_literal "expression"
458
+ g.goto done
459
+
460
+ f.set!
461
+ g.push :nil
462
+
463
+ done.set!
464
+ end
465
+
466
+ def sexp_name
467
+ :dstr
468
+ end
469
+
470
+ def to_sexp
471
+ @array.inject([sexp_name, @string]) { |s, x| s << x.to_sexp }
472
+ end
473
+ end
474
+
475
+ class DynamicSymbol < DynamicString
476
+ def bytecode(g)
477
+ super(g)
478
+ g.send :to_sym, 0, true
479
+ end
480
+
481
+ def sexp_name
482
+ :dsym
483
+ end
484
+ end
485
+
486
+ class DynamicExecuteString < DynamicString
487
+ def bytecode(g)
488
+ g.push :self
489
+ super(g)
490
+ g.send :`, 1, true #`
491
+ end
492
+
493
+ def sexp_name
494
+ :dxstr
495
+ end
496
+ end
497
+
498
+ class DynamicRegex < DynamicString
499
+ def initialize(line, str, array, flags)
500
+ super line, str, array
501
+ @options = flags || 0
502
+ end
503
+
504
+ def bytecode(g)
505
+ g.push_cpath_top
506
+ g.find_const :Regexp
507
+ super(g)
508
+ g.push @options
509
+ g.send :new, 2
510
+ end
511
+
512
+ def sexp_name
513
+ :dregx
514
+ end
515
+ end
516
+
517
+ class DynamicOnceRegex < DynamicRegex
518
+ def bytecode(g)
519
+ pos(g)
520
+
521
+ idx = g.add_literal(nil)
522
+ g.push_literal_at idx
523
+ g.dup
524
+ g.is_nil
525
+
526
+ lbl = g.new_label
527
+ g.gif lbl
528
+ g.pop
529
+
530
+ super(g)
531
+
532
+ g.set_literal idx
533
+ lbl.set!
534
+ end
535
+
536
+ def sexp_name
537
+ :dregx_once
538
+ end
539
+ end
540
+
541
+ class ExecuteString < StringLiteral
542
+ def bytecode(g)
543
+ pos(g)
544
+
545
+ g.push :self
546
+ super(g)
547
+ g.send :`, 1, true # ` (silly vim/emacs)
548
+ end
549
+
550
+ def to_sexp
551
+ [:xstr, @string]
552
+ end
553
+ end
554
+ end
555
+ end