rubinius-ast 2.1.3 → 2.2.0

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.
@@ -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