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,842 @@
1
+ # -*- encoding: us-ascii -*-
2
+
3
+ module Rubinius::ToolSet.current::TS
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 bytecode(g)
30
+ pos(g)
31
+ g.last_match mode, 0
32
+ end
33
+
34
+ def defined(g)
35
+ if @kind == :~
36
+ g.push_literal "global-variable"
37
+ g.string_dup
38
+ return
39
+ end
40
+
41
+ f = g.new_label
42
+ done = g.new_label
43
+
44
+ g.last_match mode, 0
45
+ g.is_nil
46
+ g.git f
47
+
48
+ g.push_literal "$#{@kind}"
49
+ g.string_dup
50
+
51
+ g.goto done
52
+
53
+ f.set!
54
+ g.push :nil
55
+
56
+ done.set!
57
+ end
58
+
59
+ def to_sexp
60
+ [:back_ref, @kind]
61
+ end
62
+ end
63
+
64
+ class NthRef < Node
65
+ attr_accessor :which
66
+
67
+ def initialize(line, ref)
68
+ @line = line
69
+ @which = ref
70
+ end
71
+
72
+ Mode = 5
73
+
74
+ def bytecode(g)
75
+ pos(g)
76
+
77
+ # These are for $1, $2, etc. We subtract 1 because
78
+ # we start numbering the captures from 0.
79
+ g.last_match Mode, @which - 1
80
+ end
81
+
82
+ def defined(g)
83
+ f = g.new_label
84
+ done = g.new_label
85
+
86
+ g.last_match Mode, @which - 1
87
+ g.is_nil
88
+ g.git f
89
+
90
+ g.push_literal "$#{@which}"
91
+ g.string_dup
92
+
93
+ g.goto done
94
+
95
+ f.set!
96
+ g.push :nil
97
+
98
+ done.set!
99
+ end
100
+
101
+ def to_sexp
102
+ [:nth_ref, @which]
103
+ end
104
+ end
105
+
106
+ class VariableAccess < Node
107
+ attr_accessor :name
108
+
109
+ def initialize(line, name)
110
+ @line = line
111
+ @name = name
112
+ end
113
+
114
+ def value_defined(g, f)
115
+ variable_defined(g, f)
116
+ bytecode(g)
117
+ end
118
+ end
119
+
120
+ class VariableAssignment < Node
121
+ attr_accessor :name, :value
122
+
123
+ def initialize(line, name, value)
124
+ @line = line
125
+ @name = name
126
+ @value = value
127
+ end
128
+
129
+ def defined(g)
130
+ g.push_literal "assignment"
131
+ end
132
+
133
+ def to_sexp
134
+ sexp = [sexp_name, @name]
135
+ sexp << @value.to_sexp if @value
136
+ sexp
137
+ end
138
+ end
139
+
140
+ class ClassVariableAccess < VariableAccess
141
+ def or_bytecode(g)
142
+ pos(g)
143
+
144
+ done = g.new_label
145
+ notfound = g.new_label
146
+
147
+ variable_defined(g, notfound)
148
+
149
+ # Ok, we know the value exists, get it.
150
+ bytecode(g)
151
+ g.dup
152
+ g.git done
153
+ g.pop
154
+
155
+ # yield to generate the code for when it's not found
156
+ notfound.set!
157
+ yield
158
+
159
+ done.set!
160
+ end
161
+
162
+ def bytecode(g)
163
+ pos(g)
164
+
165
+ push_scope(g)
166
+ g.send :class_variable_get, 1
167
+ end
168
+
169
+ def push_scope(g)
170
+ if g.state.scope.module?
171
+ g.push :self
172
+ else
173
+ g.push_scope
174
+ end
175
+ g.push_literal @name
176
+ end
177
+
178
+ def variable_defined(g, f)
179
+ push_scope(g)
180
+ g.send :class_variable_defined?, 1
181
+ g.gif f
182
+ end
183
+
184
+ def defined(g)
185
+ f = g.new_label
186
+ done = g.new_label
187
+
188
+ variable_defined(g, f)
189
+ g.push_literal "class variable"
190
+ g.goto done
191
+
192
+ f.set!
193
+ g.push :nil
194
+
195
+ done.set!
196
+ end
197
+
198
+ def to_sexp
199
+ [:cvar, @name]
200
+ end
201
+ end
202
+
203
+ class ClassVariableAssignment < VariableAssignment
204
+ def bytecode(g)
205
+ pos(g)
206
+
207
+ if g.state.scope.module?
208
+ g.push :self
209
+ else
210
+ g.push_scope
211
+ end
212
+
213
+ if @value
214
+ g.push_literal @name
215
+ @value.bytecode(g)
216
+ else
217
+ g.swap
218
+ g.push_literal @name
219
+ g.swap
220
+ end
221
+
222
+ pos(g)
223
+ g.send :class_variable_set, 2
224
+ end
225
+
226
+ def sexp_name
227
+ :cvasgn
228
+ end
229
+ end
230
+
231
+ class ClassVariableDeclaration < ClassVariableAssignment
232
+ def sexp_name
233
+ :cvdecl
234
+ end
235
+ end
236
+
237
+ class CurrentException < Node
238
+ def bytecode(g)
239
+ pos(g)
240
+ g.push_current_exception
241
+ end
242
+
243
+ def defined(g)
244
+ g.push_literal "global-variable"
245
+ end
246
+
247
+ def to_sexp
248
+ [:gvar, :$!]
249
+ end
250
+ end
251
+
252
+ class GlobalVariableAccess < VariableAccess
253
+ EnglishBackrefs = {
254
+ :$LAST_MATCH_INFO => :~,
255
+ :$MATCH => :&,
256
+ :$PREMATCH => :'`',
257
+ :$POSTMATCH => :"'",
258
+ :$LAST_PAREN_MATCH => :+,
259
+ }
260
+
261
+ def self.for_name(line, name)
262
+ case name
263
+ when :$!
264
+ CurrentException.new(line)
265
+ when :$~
266
+ BackRef.new(line, :~)
267
+ else
268
+ if backref = EnglishBackrefs[name]
269
+ BackRef.new(line, backref)
270
+ else
271
+ new(line, name)
272
+ end
273
+ end
274
+ end
275
+
276
+ def bytecode(g)
277
+ pos(g)
278
+
279
+ g.push_rubinius
280
+ g.find_const :Globals
281
+ g.push_literal @name
282
+ g.send :[], 1
283
+ end
284
+
285
+ def variable_defined(g, f)
286
+ g.push_rubinius
287
+ g.find_const :Globals
288
+ g.push_literal @name
289
+ g.send :key?, 1
290
+ g.gif f
291
+ end
292
+
293
+ def defined(g)
294
+ f = g.new_label
295
+ done = g.new_label
296
+
297
+ variable_defined(g, f)
298
+ g.push_literal "global-variable"
299
+ g.goto done
300
+
301
+ f.set!
302
+ g.push :nil
303
+
304
+ done.set!
305
+ end
306
+
307
+ def to_sexp
308
+ [:gvar, @name]
309
+ end
310
+ end
311
+
312
+ class GlobalVariableAssignment < VariableAssignment
313
+ def bytecode(g)
314
+ # @value can be nil if this is coming via an masgn, which means
315
+ # the value is already on the stack.
316
+ if @name == :$!
317
+ g.push_self
318
+ @value.bytecode(g) if @value
319
+ pos(g)
320
+ g.send :raise, 1, true
321
+ else
322
+ pos(g)
323
+ g.push_rubinius
324
+ g.find_const :Globals
325
+ if @value
326
+ g.push_literal @name
327
+ @value.bytecode(g)
328
+ else
329
+ g.swap
330
+ g.push_literal @name
331
+ g.swap
332
+ end
333
+ pos(g)
334
+ g.send :[]=, 2
335
+ end
336
+ end
337
+
338
+ def sexp_name
339
+ :gasgn
340
+ end
341
+ end
342
+
343
+ class SplatAssignment < Node
344
+ attr_accessor :value
345
+
346
+ def initialize(line, value)
347
+ @line = line
348
+ @value = value
349
+ end
350
+
351
+ def bytecode(g)
352
+ pos(g)
353
+
354
+ g.cast_array
355
+ @value.bytecode(g)
356
+ end
357
+
358
+ def to_sexp
359
+ [:splat_assign, @value.to_sexp]
360
+ end
361
+ end
362
+
363
+ class SplatArray < SplatAssignment
364
+ def initialize(line, value, size)
365
+ @line = line
366
+ @value = value
367
+ @size = size
368
+ end
369
+
370
+ def bytecode(g)
371
+ pos(g)
372
+
373
+ g.make_array @size
374
+
375
+ @value.bytecode(g)
376
+ end
377
+
378
+ def to_sexp
379
+ [:splat, @value.to_sexp]
380
+ end
381
+ end
382
+
383
+ class SplatWrapped < SplatAssignment
384
+ def bytecode(g)
385
+ pos(g)
386
+
387
+ assign = g.new_label
388
+
389
+ g.dup
390
+ g.push_cpath_top
391
+ g.find_const :Array
392
+ g.swap
393
+ g.kind_of
394
+ g.git assign
395
+ g.make_array 1
396
+
397
+ assign.set!
398
+ @value.bytecode(g)
399
+ end
400
+
401
+ def to_sexp
402
+ [:splat, @value.to_sexp]
403
+ end
404
+ end
405
+
406
+ class EmptySplat < Node
407
+ def initialize(line, size)
408
+ @line = line
409
+ @size = size
410
+ end
411
+
412
+ def bytecode(g)
413
+ return if @size == 0
414
+
415
+ pos(g)
416
+
417
+ g.make_array @size
418
+ end
419
+
420
+ def to_sexp
421
+ [:splat]
422
+ end
423
+ end
424
+
425
+ class InstanceVariableAccess < VariableAccess
426
+ def bytecode(g)
427
+ pos(g)
428
+
429
+ g.push_ivar @name
430
+ end
431
+
432
+ def variable_defined(g, f)
433
+ g.push :self
434
+ g.push_literal @name
435
+ g.send :__instance_variable_defined_p__, 1
436
+ g.gif f
437
+ end
438
+
439
+ def defined(g)
440
+ f = g.new_label
441
+ done = g.new_label
442
+
443
+ variable_defined(g, f)
444
+ g.push_literal "instance-variable"
445
+ g.goto done
446
+
447
+ f.set!
448
+ g.push :nil
449
+
450
+ done.set!
451
+ end
452
+
453
+ def to_sexp
454
+ [:ivar, @name]
455
+ end
456
+ end
457
+
458
+ class InstanceVariableAssignment < VariableAssignment
459
+ def bytecode(g)
460
+ @value.bytecode(g) if @value
461
+
462
+ pos(g)
463
+ g.set_ivar @name
464
+ end
465
+
466
+ def sexp_name
467
+ :iasgn
468
+ end
469
+ end
470
+
471
+ class LocalVariableAccess < VariableAccess
472
+ include LocalVariable
473
+
474
+ def initialize(line, name)
475
+ @line = line
476
+ @name = name
477
+ @variable = nil
478
+ end
479
+
480
+ def bytecode(g)
481
+ pos(g)
482
+
483
+ unless @variable
484
+ g.state.scope.assign_local_reference self
485
+ end
486
+ @variable.get_bytecode(g)
487
+ end
488
+
489
+ def defined(g)
490
+ g.push_literal "local-variable"
491
+ end
492
+
493
+ def value_defined(g, f)
494
+ bytecode(g)
495
+ end
496
+
497
+ def to_sexp
498
+ [:lvar, @name]
499
+ end
500
+ end
501
+
502
+ class LocalVariableAssignment < VariableAssignment
503
+ include LocalVariable
504
+
505
+ def initialize(line, name, value)
506
+ @line = line
507
+ @name = name
508
+ @value = value
509
+ @variable = nil
510
+ end
511
+
512
+ def bytecode(g)
513
+ unless @variable
514
+ g.state.scope.assign_local_reference self
515
+ end
516
+
517
+ if @value
518
+ @value.bytecode(g)
519
+ end
520
+
521
+ # Set the position after the value, so the position
522
+ # reflects where the assignment itself is done
523
+ pos(g)
524
+
525
+ @variable.set_bytecode(g)
526
+ end
527
+
528
+ def sexp_name
529
+ :lasgn
530
+ end
531
+ end
532
+
533
+ class PostArg < Node
534
+ attr_accessor :into, :rest
535
+
536
+ def initialize(line, into, rest)
537
+ @line = line
538
+ @into = into
539
+ @rest = rest
540
+ end
541
+ end
542
+
543
+ class MultipleAssignment < Node
544
+ attr_accessor :left, :right, :splat, :block, :post
545
+
546
+ def initialize(line, left, right, splat)
547
+ @line = line
548
+ @left = left
549
+ @right = right
550
+ @splat = nil
551
+ @block = nil # support for |&b|
552
+ @post = nil # in `a,*b,c`, c is in post.
553
+
554
+ @fixed = right.kind_of?(ArrayLiteral) ? true : false
555
+
556
+ if splat.kind_of? Node
557
+ if @left
558
+ if right
559
+ @splat = SplatAssignment.new line, splat
560
+ else
561
+ @splat = SplatWrapped.new line, splat
562
+ end
563
+ elsif @fixed
564
+ @splat = SplatArray.new line, splat, right.body.size
565
+ elsif right.kind_of? SplatValue
566
+ @splat = splat
567
+ else
568
+ @splat = SplatWrapped.new line, splat
569
+ end
570
+ elsif splat
571
+ # We need a node for eg { |*| } and { |a, *| }
572
+ size = @fixed ? right.body.size : 0
573
+ @splat = EmptySplat.new line, size
574
+ end
575
+ end
576
+
577
+ def pad_short(g)
578
+ short = @left.body.size - @right.body.size
579
+ if short > 0
580
+ short.times { g.push :nil }
581
+ g.make_array 0 if @splat
582
+ end
583
+ end
584
+
585
+ def pop_excess(g)
586
+ excess = @right.body.size - @left.body.size
587
+ excess.times { g.pop } if excess > 0
588
+ end
589
+
590
+ def make_array(g)
591
+ size = @right.body.size - @left.body.size
592
+ g.make_array size if size >= 0
593
+ end
594
+
595
+ def make_retval(g)
596
+ size = @right.body.size
597
+ if @left and !@splat
598
+ lhs = @left.body.size
599
+ size = lhs if lhs > size
600
+ end
601
+ g.dup_many @right.body.size
602
+ g.make_array @right.body.size
603
+ g.move_down size
604
+ end
605
+
606
+ def rotate(g)
607
+ if @splat
608
+ size = @left.body.size + 1
609
+ else
610
+ size = @right.body.size
611
+ end
612
+ g.rotate size
613
+ end
614
+
615
+ def iter_arguments
616
+ @iter_arguments = true
617
+ end
618
+
619
+ def declare_local_scope(scope)
620
+ # Fix the scope for locals introduced by the left. We
621
+ # do this before running the code for the right so that
622
+ # right side sees the proper scoping of the locals on the left.
623
+
624
+ if @left
625
+ @left.body.each do |var|
626
+ case var
627
+ when LocalVariable
628
+ scope.assign_local_reference var
629
+ when MultipleAssignment
630
+ var.declare_local_scope(scope)
631
+ end
632
+ end
633
+ end
634
+
635
+ if @splat and @splat.kind_of?(SplatAssignment)
636
+ if @splat.value.kind_of?(LocalVariable)
637
+ scope.assign_local_reference @splat.value
638
+ end
639
+ end
640
+ end
641
+
642
+ def bytecode(g, array_on_stack=false)
643
+ unless array_on_stack
644
+ g.cast_array unless @right or (@splat and not @left)
645
+ end
646
+
647
+ declare_local_scope(g.state.scope)
648
+
649
+ if @fixed
650
+ pad_short(g) if @left and !@splat
651
+ @right.body.each { |x| x.bytecode(g) }
652
+
653
+ if @left
654
+ make_retval(g)
655
+
656
+ if @splat
657
+ pad_short(g)
658
+ make_array(g)
659
+ end
660
+
661
+ rotate(g)
662
+
663
+ g.state.push_masgn
664
+ @left.body.each do |x|
665
+ x.bytecode(g)
666
+ g.pop
667
+ end
668
+ g.state.pop_masgn
669
+
670
+ pop_excess(g) unless @splat
671
+ end
672
+ else
673
+ if @right
674
+ if @right.kind_of? ArrayLiteral and @right.body.size == 1
675
+ @right.body.first.bytecode(g)
676
+ g.cast_multi_value
677
+ else
678
+ @right.bytecode(g)
679
+ end
680
+
681
+ g.cast_array unless @right.kind_of? ToArray
682
+ g.dup # Use the array as the return value
683
+ end
684
+
685
+ if @left
686
+ g.state.push_masgn
687
+ @left.body.each do |x|
688
+ g.shift_array
689
+ g.cast_array if x.kind_of? MultipleAssignment and x.left
690
+ x.bytecode(g)
691
+ g.pop
692
+ end
693
+ g.state.pop_masgn
694
+ end
695
+
696
+ if @post
697
+ g.state.push_masgn
698
+ @post.body.each do |x|
699
+ g.dup
700
+ g.send :pop, 0
701
+ g.cast_array if x.kind_of? MultipleAssignment and x.left
702
+ x.bytecode(g)
703
+ g.pop
704
+ end
705
+ g.state.pop_masgn
706
+ end
707
+ end
708
+
709
+ if @splat
710
+ g.state.push_masgn
711
+ @splat.bytecode(g)
712
+
713
+ # Use the array as the return value
714
+ g.dup if @fixed and !@left
715
+
716
+ g.state.pop_masgn
717
+ end
718
+
719
+ g.pop if @right and (!@fixed or @splat)
720
+ end
721
+
722
+ def defined(g)
723
+ g.push_literal "assignment"
724
+ end
725
+
726
+ def to_sexp
727
+ left = @left ? @left.to_sexp : [:array]
728
+ left << [:splat, @splat.to_sexp] if @splat
729
+ left << @block.to_sexp if @block
730
+
731
+ sexp = [:masgn, left]
732
+ sexp << @right.to_sexp if @right
733
+ sexp
734
+ end
735
+ end
736
+
737
+ class LeftPatternVariable < Node
738
+ include LocalVariable
739
+
740
+ attr_accessor :name, :value
741
+
742
+ def initialize(line, name)
743
+ @line = line
744
+ @name = name
745
+ @variable = nil
746
+ end
747
+
748
+ def position_bytecode(g)
749
+ @variable.get_bytecode(g)
750
+ g.cast_array
751
+ end
752
+
753
+ def bytecode(g)
754
+ pos(g)
755
+
756
+ unless @variable
757
+ g.state.scope.assign_local_reference self
758
+ end
759
+
760
+ g.shift_array
761
+ @variable.set_bytecode(g)
762
+ g.pop
763
+ end
764
+ end
765
+
766
+ class SplatPatternVariable < Node
767
+ include LocalVariable
768
+
769
+ attr_accessor :name, :value
770
+
771
+ def initialize(line, name)
772
+ @line = line
773
+ @name = name
774
+ @variable = nil
775
+ end
776
+
777
+ def position_bytecode(g)
778
+ @variable.get_bytecode(g)
779
+ g.cast_array
780
+ end
781
+
782
+ def bytecode(g)
783
+ pos(g)
784
+
785
+ unless @variable
786
+ g.state.scope.assign_local_reference self
787
+ end
788
+
789
+ g.dup
790
+ @variable.set_bytecode(g)
791
+ g.pop
792
+ end
793
+ end
794
+
795
+ class PostPatternVariable < Node
796
+ include LocalVariable
797
+
798
+ attr_accessor :name, :value
799
+
800
+ def initialize(line, name, idx)
801
+ @line = line
802
+ @name = name
803
+ @pos = idx
804
+ @variable = nil
805
+ end
806
+
807
+ def position_bytecode(g)
808
+ @variable.get_bytecode(g)
809
+ g.cast_array
810
+ end
811
+
812
+ def bytecode(g)
813
+ pos(g)
814
+
815
+ unless @variable
816
+ g.state.scope.assign_local_reference self
817
+ end
818
+
819
+ too_big = g.new_label
820
+ done = g.new_label
821
+
822
+ g.dup
823
+ g.send :size, 0
824
+ g.push_int @pos
825
+ g.send :>, 1
826
+ g.gif too_big
827
+ g.dup
828
+ g.send :pop, 0
829
+
830
+ g.goto done
831
+ too_big.set!
832
+ g.push_nil
833
+ @variable.set_bytecode(g)
834
+ g.goto done
835
+
836
+ done.set!
837
+ @variable.set_bytecode(g)
838
+ g.pop
839
+ end
840
+ end
841
+ end
842
+ end