@@ -802,6 +802,65 @@ def serialize(insn)
802
802
# This class is responsible for taking a compiled instruction sequence and
803
803
# walking through it to generate equivalent Ruby code.
804
804
class Disassembler
805
+ module DSL
806
+ def Args ( parts )
807
+ Args . new ( parts : parts , location : Location . default )
808
+ end
809
+
810
+ def ArgParen ( arguments )
811
+ ArgParen . new ( arguments : arguments , location : Location . default )
812
+ end
813
+
814
+ def Assign ( target , value )
815
+ Assign . new ( target : target , value : value , location : Location . default )
816
+ end
817
+
818
+ def Binary ( left , operator , right )
819
+ Binary . new ( left : left , operator : operator , right : right , location : Location . default )
820
+ end
821
+
822
+ def CallNode ( receiver , operator , message , arguments )
823
+ CallNode . new ( receiver : receiver , operator : operator , message : message , arguments : arguments , location : Location . default )
824
+ end
825
+
826
+ def FloatLiteral ( value )
827
+ FloatLiteral . new ( value : value , location : Location . default )
828
+ end
829
+
830
+ def Ident ( value )
831
+ Ident . new ( value : value , location : Location . default )
832
+ end
833
+
834
+ def Int ( value )
835
+ Int . new ( value : value , location : Location . default )
836
+ end
837
+
838
+ def Period ( value )
839
+ Period . new ( value : value , location : Location . default )
840
+ end
841
+
842
+ def Program ( statements )
843
+ Program . new ( statements : statements , location : Location . default )
844
+ end
845
+
846
+ def ReturnNode ( arguments )
847
+ ReturnNode . new ( arguments : arguments , location : Location . default )
848
+ end
849
+
850
+ def Statements ( body )
851
+ Statements . new ( nil , body : body , location : Location . default )
852
+ end
853
+
854
+ def VarField ( value )
855
+ VarField . new ( value : value , location : Location . default )
856
+ end
857
+
858
+ def VarRef ( value )
859
+ VarRef . new ( value : value , location : Location . default )
860
+ end
861
+ end
862
+
863
+ include DSL
805
864
attr_reader :iseq
806
865
807
866
def initialize ( iseq )
@@ -812,78 +871,88 @@ def to_ruby
812
871
stack = [ ]
813
872
814
873
iseq . insns . each do |insn |
874
+ # skip line numbers and events
875
+ next unless insn . is_a? ( Array )
876
+
815
877
case insn [ 0 ]
816
878
when :getlocal_WC_0
817
- value = iseq . local_table . locals [ insn [ 1 ] ] . name . to_s
818
- stack << VarRef . new (
819
- value : Ident . new ( value : value , location : Location . default ) ,
820
- location : Location . default
821
- )
879
+ stack << VarRef ( Ident ( local_name ( insn [ 1 ] , 0 ) ) )
822
880
when :leave
823
- stack << ReturnNode . new (
824
- arguments :
825
- Args . new ( parts : [ stack . pop ] , location : Location . default ) ,
826
- location : Location . default
827
- )
881
+ stack << ReturnNode ( Args ( [ stack . pop ] ) )
882
+ when :opt_and
883
+ left , right = stack . pop ( 2 )
884
+ stack << Binary ( left , :& , right )
885
+ when :opt_div
886
+ left , right = stack . pop ( 2 )
887
+ stack << Binary ( left , :/ , right )
888
+ when :opt_eq
889
+ left , right = stack . pop ( 2 )
890
+ stack << Binary ( left , :== , right )
891
+ when :opt_ge
892
+ left , right = stack . pop ( 2 )
893
+ stack << Binary ( left , :>= , right )
894
+ when :opt_gt
895
+ left , right = stack . pop ( 2 )
896
+ stack << Binary ( left , :> , right )
897
+ when :opt_le
898
+ left , right = stack . pop ( 2 )
899
+ stack << Binary ( left , :<= , right )
900
+ when :opt_lt
901
+ left , right = stack . pop ( 2 )
902
+ stack << Binary ( left , :< , right )
903
+ when :opt_ltlt
904
+ left , right = stack . pop ( 2 )
905
+ stack << Binary ( left , :<< , right )
906
+ when :opt_minus
907
+ left , right = stack . pop ( 2 )
908
+ stack << Binary ( left , :- , right )
909
+ when :opt_mod
910
+ left , right = stack . pop ( 2 )
911
+ stack << Binary ( left , :% , right )
828
912
when :opt_mult
829
913
left , right = stack . pop ( 2 )
830
- stack << Binary . new (
831
- left : left ,
832
- operator : :* ,
833
- right : right ,
834
- location : Location . default
835
- )
914
+ stack << Binary ( left , :* , right )
915
+ when :opt_neq
916
+ left , right = stack . pop ( 2 )
917
+ stack << Binary ( left , :"!=" , right )
918
+ when :opt_or
919
+ left , right = stack . pop ( 2 )
920
+ stack << Binary ( left , :| , right )
836
921
when :opt_plus
837
922
left , right = stack . pop ( 2 )
838
- stack << Binary . new (
839
- left : left ,
840
- operator : :+ ,
841
- right : right ,
842
- location : Location . default
843
- )
923
+ stack << Binary ( left , :+ , right )
924
+ when :opt_send_without_block
925
+ receiver , *arguments = stack . pop ( insn [ 1 ] [ :orig_argc ] + 1 )
926
+ stack << CallNode ( receiver , Period ( "." ) , Ident ( insn [ 1 ] [ :mid ] ) , ArgParen ( Args ( arguments ) ) )
844
927
when :putobject
845
928
case insn [ 1 ]
846
929
when Float
847
- stack << FloatLiteral . new (
848
- value : insn [ 1 ] . inspect ,
849
- location : Location . default
850
- )
930
+ stack << FloatLiteral ( insn [ 1 ] . inspect )
851
931
when Integer
852
- stack << Int . new (
853
- value : insn [ 1 ] . inspect ,
854
- location : Location . default
855
- )
856
- when Rational
857
- stack << RationalLiteral . new (
858
- value : insn [ 1 ] . inspect ,
859
- location : Location . default
860
- )
932
+ stack << Int ( insn [ 1 ] . inspect )
861
933
else
862
934
raise "Unknown object type: #{ insn [ 1 ] . class . name } "
863
935
end
936
+ when :putobject_INT2FIX_0_
937
+ stack << Int ( "0" )
864
938
when :putobject_INT2FIX_1_
865
- stack << Int . new ( value : "1" , location : Location . default )
939
+ stack << Int ( "1" )
866
940
when :setlocal_WC_0
867
- target =
868
- VarField . new (
869
- value :
870
- Ident . new (
871
- value : iseq . local_table . locals [ insn [ 1 ] ] . name . to_s ,
872
- location : Location . default
873
- ) ,
874
- location : Location . default
875
- )
876
- stack << Assign . new (
877
- target : target ,
878
- value : stack . pop ,
879
- location : Location . default
880
- )
941
+ stack << Assign ( VarField ( Ident ( local_name ( insn [ 1 ] , 0 ) ) ) , stack . pop )
881
942
else
882
943
raise "Unknown instruction #{ insn [ 0 ] } "
883
944
end
884
945
end
885
946
886
- Statements . new ( nil , body : stack , location : Location . default )
947
+ Program ( Statements ( stack ) )
948
+ end
949
+
950
+ private
951
+
952
+ def local_name ( index , level )
953
+ current = iseq
954
+ level . times { current = current . parent_iseq }
955
+ current . local_table . locals [ index ] . name . to_s
887
956
end
888
957
end
889
958
0 commit comments