rubinius-ast 2.1.3 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: us-ascii -*-
2
2
 
3
- module Rubinius::ToolSets.current::ToolSet
3
+ module CodeTools
4
4
  module AST
5
5
  module Transforms
6
6
  def self.register(category, name, klass)
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: us-ascii -*-
2
2
 
3
- module Rubinius::ToolSets.current::ToolSet
3
+ module CodeTools
4
4
  module AST
5
5
  class SplatValue < Node
6
6
  attr_accessor :value
@@ -11,8 +11,63 @@ module Rubinius::ToolSets.current::ToolSet
11
11
  end
12
12
 
13
13
  def bytecode(g)
14
+ done = g.new_label
15
+ coerce = g.new_label
16
+ make_array = g.new_label
17
+
14
18
  @value.bytecode(g)
15
- g.cast_array unless @value.kind_of? ArrayLiteral
19
+ kind_of_array(g, done)
20
+
21
+ g.dup
22
+ g.push_literal :to_a
23
+ g.push :true
24
+ g.send :respond_to?, 2, true
25
+ g.git coerce
26
+
27
+ make_array.set!
28
+ g.make_array 1
29
+ g.goto done
30
+
31
+ coerce.set!
32
+ g.dup
33
+ g.send :to_a, 0, true
34
+
35
+ discard = g.new_label
36
+ check_array = g.new_label
37
+
38
+ g.dup
39
+ g.push :nil
40
+ g.send :equal?, 1, true
41
+ g.gif check_array
42
+
43
+ g.pop
44
+ g.goto make_array
45
+
46
+ check_array.set!
47
+ kind_of_array(g, discard)
48
+
49
+ g.push_type
50
+ g.move_down 2
51
+ g.push_literal :to_a
52
+ g.push_cpath_top
53
+ g.find_const :Array
54
+ g.send :coerce_to_type_error, 4, true
55
+ g.goto done
56
+
57
+ discard.set!
58
+ g.swap
59
+ g.pop
60
+
61
+ done.set!
62
+ end
63
+
64
+ def kind_of_array(g, label)
65
+ g.dup
66
+ g.push_cpath_top
67
+ g.find_const :Array
68
+ g.swap
69
+ g.kind_of
70
+ g.git label
16
71
  end
17
72
 
18
73
  def to_sexp
@@ -34,15 +89,72 @@ module Rubinius::ToolSets.current::ToolSet
34
89
  end
35
90
 
36
91
  def bytecode(g)
37
- if @array
38
- @array.bytecode(g)
39
- @rest.bytecode(g)
40
- g.cast_array
41
- g.send :+, 1
42
- else
43
- @rest.bytecode(g)
44
- g.cast_array
45
- end
92
+ @array.bytecode(g) if @array
93
+
94
+ @rest.bytecode(g)
95
+ convert_to_a(g)
96
+
97
+ g.send :+, 1, true if @array
98
+ end
99
+
100
+ # TODO: de-dup
101
+ def convert_to_a(g)
102
+ done = g.new_label
103
+ coerce = g.new_label
104
+ make_array = g.new_label
105
+
106
+ kind_of_array(g, done)
107
+
108
+ g.dup
109
+ g.push_literal :to_a
110
+ g.push :true
111
+ g.send :respond_to?, 2, true
112
+ g.git coerce
113
+
114
+ make_array.set!
115
+ g.make_array 1
116
+ g.goto done
117
+
118
+ coerce.set!
119
+ g.dup
120
+ g.send :to_a, 0, true
121
+
122
+ discard = g.new_label
123
+ check_array = g.new_label
124
+
125
+ g.dup
126
+ g.push :nil
127
+ g.send :equal?, 1, true
128
+ g.gif check_array
129
+
130
+ g.pop
131
+ g.goto make_array
132
+
133
+ check_array.set!
134
+ kind_of_array(g, discard)
135
+
136
+ g.push_type
137
+ g.move_down 2
138
+ g.push_literal :to_a
139
+ g.push_cpath_top
140
+ g.find_const :Array
141
+ g.send :coerce_to_type_error, 4, true
142
+ g.goto done
143
+
144
+ discard.set!
145
+ g.swap
146
+ g.pop
147
+
148
+ done.set!
149
+ end
150
+
151
+ def kind_of_array(g, label)
152
+ g.dup
153
+ g.push_cpath_top
154
+ g.find_const :Array
155
+ g.swap
156
+ g.kind_of
157
+ g.git label
46
158
  end
47
159
 
48
160
  # Dive down and try to find an array of regular values
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: us-ascii -*-
2
2
 
3
- module Rubinius::ToolSets.current::ToolSet
3
+ module CodeTools
4
4
  module AST
5
5
  class BackRef < Node
6
6
  attr_accessor :kind
@@ -502,7 +502,7 @@ module Rubinius::ToolSets.current::ToolSet
502
502
  class LocalVariableAssignment < VariableAssignment
503
503
  include LocalVariable
504
504
 
505
- def initialize(line, name, value)
505
+ def initialize(line, name, value=nil)
506
506
  @line = line
507
507
  @name = name
508
508
  @value = value
@@ -582,44 +582,6 @@ module Rubinius::ToolSets.current::ToolSet
582
582
  end
583
583
  end
584
584
 
585
- def pad_short(g)
586
- short = @left.body.size - @right.body.size
587
- if short > 0
588
- short.times { g.push :nil }
589
- g.make_array 0 if @splat
590
- end
591
- end
592
-
593
- def pop_excess(g)
594
- excess = @right.body.size - @left.body.size
595
- excess.times { g.pop } if excess > 0
596
- end
597
-
598
- def make_array(g)
599
- size = @right.body.size - @left.body.size
600
- g.make_array size if size >= 0
601
- end
602
-
603
- def make_retval(g)
604
- size = @right.body.size
605
- if @left and !@splat
606
- lhs = @left.body.size
607
- size = lhs if lhs > size
608
- end
609
- g.dup_many @right.body.size
610
- g.make_array @right.body.size
611
- g.move_down size
612
- end
613
-
614
- def rotate(g)
615
- if @splat
616
- size = @left.body.size + 1
617
- else
618
- size = @right.body.size
619
- end
620
- g.rotate size
621
- end
622
-
623
585
  def iter_arguments
624
586
  @iter_arguments = true
625
587
  end
@@ -648,208 +610,205 @@ module Rubinius::ToolSets.current::ToolSet
648
610
  end
649
611
 
650
612
  def bytecode(g, array_on_stack=false)
651
- unless array_on_stack
652
- g.cast_array unless @right or (@splat and not @left)
613
+ declare_local_scope(g.state.scope)
614
+
615
+ case @right
616
+ when ArrayLiteral, SplatValue
617
+ @right.bytecode(g)
618
+ g.dup
619
+ when ToArray
620
+ @right.value.bytecode(g)
621
+ g.dup
622
+ convert_to_ary(g)
623
+ when nil
624
+ convert_to_ary(g)
625
+ else
626
+ @right.bytecode(g)
627
+ g.dup
628
+ convert_to_ary(g)
653
629
  end
654
630
 
655
- declare_local_scope(g.state.scope)
631
+ size = g.new_stack_local
632
+ g.dup
633
+ g.send :size, 0, true
634
+ g.set_stack_local size
635
+ g.pop
656
636
 
657
- if @fixed
658
- pad_short(g) if @left and !@splat
659
- @right.body.each { |x| x.bytecode(g) }
637
+ index = g.new_stack_local
638
+ g.push 0
639
+ g.set_stack_local index
640
+ g.pop
660
641
 
661
- if @left
662
- make_retval(g)
642
+ g.state.push_masgn
663
643
 
664
- if @splat
665
- pad_short(g)
666
- make_array(g)
667
- end
644
+ assign_values g, @left, index if @left
668
645
 
669
- rotate(g)
646
+ if @splat
647
+ g.dup
648
+ g.push_stack_local index
670
649
 
671
- g.state.push_masgn
672
- @left.body.each do |x|
673
- x.bytecode(g)
674
- g.pop
675
- end
676
- g.state.pop_masgn
650
+ check_count = g.new_label
677
651
 
678
- pop_excess(g) unless @splat
679
- end
680
- else
681
- if @right
682
- if @right.kind_of? ArrayLiteral and @right.body.size == 1
683
- @right.body.first.bytecode(g)
684
- g.cast_multi_value
685
- else
686
- @right.bytecode(g)
687
- end
652
+ if @post
653
+ g.push_stack_local size
654
+ g.push @post.body.size
655
+ g.send :-, 1, true
688
656
 
689
- g.cast_array unless @right.kind_of? ToArray
690
- g.dup # Use the array as the return value
691
- end
657
+ g.push_stack_local index
658
+ g.send :-, 1, true
692
659
 
693
- if @left
694
- g.state.push_masgn
695
- @left.body.each do |x|
696
- g.shift_array
697
- g.cast_array if x.kind_of? MultipleAssignment and x.left
698
- x.bytecode(g)
699
- g.pop
700
- end
701
- g.state.pop_masgn
702
- end
660
+ g.goto check_count
661
+ else
662
+ g.push_stack_local size
663
+ g.push_stack_local index
664
+ g.send :-, 1, true
703
665
 
704
- if @post
705
- g.state.push_masgn
706
- @post.body.reverse_each do |x|
707
- g.dup
708
- g.send :pop, 0
709
- g.cast_array if x.kind_of? MultipleAssignment and x.left
710
- x.bytecode(g)
711
- g.pop
712
- end
713
- g.state.pop_masgn
666
+ g.goto check_count
714
667
  end
715
- end
716
668
 
717
- if @splat
718
- g.state.push_masgn
719
- @splat.bytecode(g)
669
+ underflow = g.new_label
670
+ assign_splat = g.new_label
720
671
 
721
- # Use the array as the return value
722
- g.dup if @fixed and !@left
672
+ underflow.set!
673
+ g.pop_many 3
674
+ g.make_array 0
723
675
 
724
- g.state.pop_masgn
725
- end
676
+ g.goto assign_splat
726
677
 
727
- g.pop if @right and (!@fixed or @splat)
728
- end
678
+ check_count.set!
679
+ g.dup
680
+ g.push 0
681
+ g.send :<, 1, true
682
+ g.git underflow
729
683
 
730
- def defined(g)
731
- g.push_literal "assignment"
732
- end
684
+ g.dup
685
+ g.push_stack_local index
686
+ g.send :+, 1, true
687
+ g.set_stack_local index
688
+ g.pop
733
689
 
734
- def to_sexp
735
- left = @left ? @left.to_sexp : [:array]
736
- case @splat
737
- when EmptySplat
738
- left << [:splat]
739
- when nil
740
- else
741
- left << [:splat, @splat.to_sexp]
690
+ g.send :[], 2, true
691
+
692
+ assign_splat.set!
693
+
694
+ # TODO: Fix nodes to work correctly.
695
+ case @splat
696
+ when EmptySplat
697
+ # nothing
698
+ when SplatArray, SplatWrapped
699
+ @splat.value.bytecode(g)
700
+ else
701
+ @splat.bytecode(g)
702
+ end
703
+ g.pop
742
704
  end
743
- left << @block.to_sexp if @block
744
705
 
745
- sexp = [:masgn, left]
746
- sexp << @right.to_sexp if @right
747
- sexp
706
+ assign_values g, @post, index if @post
707
+
708
+ g.state.pop_masgn
709
+ g.pop
748
710
  end
749
- end
750
711
 
751
- class LeftPatternVariable < Node
752
- include LocalVariable
712
+ def convert_to_ary(g)
713
+ done = g.new_label
714
+ coerce = g.new_label
715
+ make_array = g.new_label
753
716
 
754
- attr_accessor :name, :value
717
+ kind_of_array(g, done)
755
718
 
756
- def initialize(line, name)
757
- @line = line
758
- @name = name
759
- @variable = nil
760
- end
719
+ g.dup
720
+ g.push_literal :to_ary
721
+ g.push :true
722
+ g.send :respond_to?, 2, true
723
+ g.git coerce
761
724
 
762
- def position_bytecode(g)
763
- @variable.get_bytecode(g)
764
- g.cast_array
765
- end
725
+ make_array.set!
726
+ g.make_array 1
727
+ g.goto done
766
728
 
767
- def bytecode(g)
768
- pos(g)
729
+ coerce.set!
730
+ g.dup
731
+ g.send :to_ary, 0, true
769
732
 
770
- unless @variable
771
- g.state.scope.assign_local_reference self
772
- end
733
+ discard = g.new_label
734
+ check_array = g.new_label
735
+
736
+ g.dup
737
+ g.push :nil
738
+ g.send :equal?, 1, true
739
+ g.gif check_array
773
740
 
774
- g.shift_array
775
- @variable.set_bytecode(g)
776
741
  g.pop
777
- end
778
- end
742
+ g.goto make_array
779
743
 
780
- class SplatPatternVariable < Node
781
- include LocalVariable
744
+ check_array.set!
745
+ kind_of_array(g, discard)
782
746
 
783
- attr_accessor :name, :value
747
+ g.push_type
748
+ g.move_down 2
749
+ g.push_literal :to_ary
750
+ g.push_cpath_top
751
+ g.find_const :Array
752
+ g.send :coerce_to_type_error, 4, true
753
+ g.goto done
784
754
 
785
- def initialize(line, name)
786
- @line = line
787
- @name = name
788
- @variable = nil
789
- end
755
+ discard.set!
756
+ g.swap
757
+ g.pop
790
758
 
791
- def position_bytecode(g)
792
- @variable.get_bytecode(g)
793
- g.cast_array
759
+ done.set!
794
760
  end
795
761
 
796
- def bytecode(g)
797
- pos(g)
798
-
799
- unless @variable
800
- g.state.scope.assign_local_reference self
801
- end
802
-
762
+ def kind_of_array(g, label)
803
763
  g.dup
804
- @variable.set_bytecode(g)
805
- g.pop
764
+ g.push_cpath_top
765
+ g.find_const :Array
766
+ g.swap
767
+ g.kind_of
768
+ g.git label
806
769
  end
807
- end
808
770
 
809
- class PostPatternVariable < Node
810
- include LocalVariable
771
+ def get_element(g, index)
772
+ g.dup
773
+ g.push_stack_local index
811
774
 
812
- attr_accessor :name, :value
775
+ g.dup
776
+ g.push 1
777
+ g.send :+, 1, true
778
+ g.set_stack_local index
779
+ g.pop
813
780
 
814
- def initialize(line, name, idx)
815
- @line = line
816
- @name = name
817
- @pos = idx
818
- @variable = nil
781
+ g.send :[], 1, true
819
782
  end
820
783
 
821
- def position_bytecode(g)
822
- @variable.get_bytecode(g)
823
- g.cast_array
784
+ def assign_values(g, array, index)
785
+ array.body.each do |x|
786
+ get_element(g, index)
787
+ g.dup if x.kind_of? MultipleAssignment
788
+ x.bytecode(g)
789
+ g.pop
790
+ end
824
791
  end
825
792
 
826
- def bytecode(g)
827
- pos(g)
793
+ def defined(g)
794
+ g.push_literal "assignment"
795
+ end
828
796
 
829
- unless @variable
830
- g.state.scope.assign_local_reference self
797
+ def to_sexp
798
+ left = @left ? @left.to_sexp : [:array]
799
+ case @splat
800
+ when EmptySplat
801
+ left << [:splat]
802
+ when nil
803
+ else
804
+ left << [:splat, @splat.to_sexp]
831
805
  end
806
+ left << @block.to_sexp if @block
832
807
 
833
- too_big = g.new_label
834
- done = g.new_label
835
-
836
- g.dup
837
- g.send :size, 0
838
- g.push_int @pos
839
- g.send :>, 1
840
- g.gif too_big
841
- g.dup
842
- g.send :pop, 0
843
-
844
- g.goto done
845
- too_big.set!
846
- g.push_nil
847
- @variable.set_bytecode(g)
848
- g.goto done
849
-
850
- done.set!
851
- @variable.set_bytecode(g)
852
- g.pop
808
+ sexp = [:masgn, left]
809
+ sexp += @post.body.map { |x| x.to_sexp } if @post
810
+ sexp << @right.to_sexp if @right
811
+ sexp
853
812
  end
854
813
  end
855
814
  end