From 91ddae2251736407245eb02aeb06e7459a77549c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Torsten=20R=C3=BCger?= <torsten@rubydesign.fi>
Date: Mon, 12 Aug 2019 11:08:09 +0300
Subject: [PATCH] Start to convert integer operations

All apart from operators, which are its own thing
---
 lib/risc/builtin.rb               |   4 +-
 lib/risc/builtin/integer.rb       | 200 ++++++++++++++++--------------
 test/risc/builtin/test_integer.rb |  78 ++++++++++++
 test/risc/test_builtin.rb         |   2 +-
 4 files changed, 187 insertions(+), 97 deletions(-)
 create mode 100644 test/risc/builtin/test_integer.rb

diff --git a/lib/risc/builtin.rb b/lib/risc/builtin.rb
index 988ec2a0..11553f10 100644
--- a/lib/risc/builtin.rb
+++ b/lib/risc/builtin.rb
@@ -51,8 +51,8 @@ module Risc
       Risc.operators.each do |op|
         #compilers << operator_compiler( int_type , op)
       end
-      [:putint, :div4, :div10 , :<,:<= , :>=, :>].each do |f|   #div4 is just a forward declaration
-        #compilers << compiler_for( int_type , Integer , f)
+      [ :div4, :<,:<= , :>=, :> , :div10 ].each do |f|   #div4 is just a forward declaration
+        compilers << compiler_for( int_type , Integer , f)
       end
       compilers
     end
diff --git a/lib/risc/builtin/integer.rb b/lib/risc/builtin/integer.rb
index eba3fc37..94c699d8 100644
--- a/lib/risc/builtin/integer.rb
+++ b/lib/risc/builtin/integer.rb
@@ -14,19 +14,25 @@ module Risc
         # return new int with result
         def div4(context)
           compiler = compiler_for(:Integer,:div4 ,{})
-          builder = compiler.builder(compiler.source)
-          integer_tmp = builder.allocate_int
-          builder.build do
-            integer_self! << message[:receiver]
-            integer_self.reduce_int
-            integer_1! << 2
-            integer_self.op :>> , integer_1
-            integer_tmp[Parfait::Integer.integer_index] << integer_self
-            message[:return_value] << integer_tmp
-          end
-          compiler.add_mom( Mom::ReturnSequence.new)
+          compiler.add_code Div4.new("div4")
           return compiler
         end
+        class Div4 < ::Mom::Instruction
+          def to_risc(compiler)
+            builder = compiler.builder(compiler.source)
+            integer_tmp = builder.allocate_int
+            builder.build do
+              integer_self! << message[:receiver]
+              integer_self.reduce_int
+              integer_1! << 2
+              integer_self.op :>> , integer_1
+              integer_tmp[Parfait::Integer.integer_index] << integer_self
+              message[:return_value] << integer_tmp
+            end
+            return compiler
+          end
+        end
+
         # implemented by the comparison
         def >( context )
           comparison( :> )
@@ -53,33 +59,35 @@ module Risc
         # - return
         def comparison( operator  )
           compiler = compiler_for(:Integer, operator ,{other: :Integer })
-          builder = compiler.builder(compiler.source)
-          builder.build do
-            integer! << message[:receiver]
-            integer.reduce_int
-            integer_reg! << message[:arguments]
-            integer_reg << integer_reg[Parfait::NamedList.type_length + 0] #"other" is at index 0
-            integer_reg.reduce_int
-            swap_names(:integer , :integer_reg) if(operator.to_s.start_with?('<') )
-            integer.op :- , integer_reg
-            if_minus false_label
-            if_zero( false_label ) if operator.to_s.length == 1
-            object! << Parfait.object_space.true_object
-            branch merge_label
-            add_code false_label
-            object << Parfait.object_space.false_object
-            add_code merge_label
-            message[:return_value] << object
-          end
-          compiler.add_mom( Mom::ReturnSequence.new)
+          compiler.add_code Comparison.new("comparison" , operator)
           return compiler
         end
-
-        # not implemented, would need a itos and that needs "new" (wip)
-        def putint(context)
-          compiler = compiler_for(:Integer,:putint ,{})
-          compiler.add_mom( Mom::ReturnSequence.new)
-          return compiler
+        class Comparison < ::Mom::Instruction
+          attr_reader :operator
+          def initialize(name , operator)
+            @operator = operator
+          end
+          def to_risc(compiler)
+            builder = compiler.builder(compiler.source)
+            builder.build do
+              integer! << message[:receiver]
+              integer.reduce_int
+              integer_reg! << message[:arguments]
+              integer_reg << integer_reg[Parfait::NamedList.type_length + 0] #"other" is at index 0
+              integer_reg.reduce_int
+              swap_names(:integer , :integer_reg) if(@operator.to_s.start_with?('<') )
+              integer.op :- , integer_reg
+              if_minus false_label
+              if_zero( false_label ) if @operator.to_s.length == 1
+              object! << Parfait.object_space.true_object
+              branch merge_label
+              add_code false_label
+              object << Parfait.object_space.false_object
+              add_code merge_label
+              message[:return_value] << object
+            end
+            return compiler
+          end
         end
 
         # implemented all known binary operators that map straight to machine codes
@@ -115,67 +123,71 @@ module Risc
         # In fact it is possible to generate specific div function for any given
         # integer and some are even more faster (as eg div4).
         def div10( context )
-          s = "div_10 "
           compiler = compiler_for(:Integer,:div10 ,{})
-          builder = compiler.builder(compiler.source)
-          integer_tmp = builder.allocate_int
-          builder.build do
-            integer_self! << message[:receiver]
-            integer_self.reduce_int
-            integer_1! << integer_self
-            integer_reg! << integer_self
-
-            integer_const! << 1
-            integer_1.op :>> , integer_const
-
-            integer_const << 2
-            integer_reg.op :>> , integer_const
-            integer_reg.op :+ , integer_1
-
-            integer_const << 4
-            integer_1 << integer_reg
-            integer_reg.op :>> , integer_1
-
-            integer_reg.op :+ , integer_1
-
-            integer_const << 8
-            integer_1 << integer_reg
-            integer_1.op :>> , integer_const
-
-            integer_reg.op :+ , integer_1
-
-            integer_const << 16
-            integer_1 << integer_reg
-            integer_1.op :>> , integer_const
-
-            integer_reg.op :+ , integer_1
-
-            integer_const << 3
-            integer_reg.op :>> , integer_const
-
-            integer_const << 10
-            integer_1 << integer_reg
-            integer_1.op :* , integer_const
-
-            integer_self.op :- , integer_1
-            integer_1 << integer_self
-
-            integer_const << 6
-            integer_1.op :+ , integer_const
-
-            integer_const << 4
-            integer_1.op :>> , integer_const
-
-            integer_reg.op :+ , integer_1
-
-            integer_tmp[Parfait::Integer.integer_index] << integer_reg
-            message[:return_value] << integer_tmp
-
-          end
-
-          compiler.add_mom( Mom::ReturnSequence.new)
+          compiler.add_code Div10.new("div10")
           return compiler
         end
+        class Div10 < ::Mom::Instruction
+          def to_risc(compiler)
+            s = "div_10 "
+            builder = compiler.builder(compiler.source)
+            integer_tmp = builder.allocate_int
+            builder.build do
+              integer_self! << message[:receiver]
+              integer_self.reduce_int
+              integer_1! << integer_self
+              integer_reg! << integer_self
+
+              integer_const! << 1
+              integer_1.op :>> , integer_const
+
+              integer_const << 2
+              integer_reg.op :>> , integer_const
+              integer_reg.op :+ , integer_1
+
+              integer_const << 4
+              integer_1 << integer_reg
+              integer_reg.op :>> , integer_1
+
+              integer_reg.op :+ , integer_1
+
+              integer_const << 8
+              integer_1 << integer_reg
+              integer_1.op :>> , integer_const
+
+              integer_reg.op :+ , integer_1
+
+              integer_const << 16
+              integer_1 << integer_reg
+              integer_1.op :>> , integer_const
+
+              integer_reg.op :+ , integer_1
+
+              integer_const << 3
+              integer_reg.op :>> , integer_const
+
+              integer_const << 10
+              integer_1 << integer_reg
+              integer_1.op :* , integer_const
+
+              integer_self.op :- , integer_1
+              integer_1 << integer_self
+
+              integer_const << 6
+              integer_1.op :+ , integer_const
+
+              integer_const << 4
+              integer_1.op :>> , integer_const
+
+              integer_reg.op :+ , integer_1
+
+              integer_tmp[Parfait::Integer.integer_index] << integer_reg
+              message[:return_value] << integer_tmp
+
+            end
+            return compiler
+          end
+        end
       end
       extend ClassMethods
     end
diff --git a/test/risc/builtin/test_integer.rb b/test/risc/builtin/test_integer.rb
new file mode 100644
index 00000000..a48ea153
--- /dev/null
+++ b/test/risc/builtin/test_integer.rb
@@ -0,0 +1,78 @@
+require_relative "helper"
+
+module Risc
+  module Builtin
+    class TestIntDiv4 < BootTest
+      def setup
+        super
+        @method = get_compiler(:div4)
+      end
+      def test_has_get_internal
+        assert_equal Mom::MethodCompiler , @method.class
+      end
+      def test_mom_length
+        assert_equal 5 , @method.mom_instructions.length
+      end
+      def test_compile
+        assert_equal Risc::MethodCompiler , @method.to_risc.class
+      end
+      def test_risc_length
+        assert_equal 47 , @method.to_risc.risc_instructions.length
+      end
+    end
+    class TestIntDiv10 < BootTest
+      def setup
+        super
+        @method = get_compiler(:div10)
+      end
+      def test_has_get_internal
+        assert_equal Mom::MethodCompiler , @method.class
+      end
+      def test_mom_length
+        assert_equal 5 , @method.mom_instructions.length
+      end
+      def test_compile
+        assert_equal Risc::MethodCompiler , @method.to_risc.class
+      end
+      def test_risc_length
+        assert_equal 76 , @method.to_risc.risc_instructions.length
+      end
+    end
+    class TestIntComp1 < BootTest
+      def setup
+        super
+        @method = get_compiler(:<)
+      end
+      def test_has_get_internal
+        assert_equal Mom::MethodCompiler , @method.class
+      end
+      def test_mom_length
+        assert_equal 5 , @method.mom_instructions.length
+      end
+      def test_compile
+        assert_equal Risc::MethodCompiler , @method.to_risc.class
+      end
+      def test_risc_length
+        assert_equal 27 , @method.to_risc.risc_instructions.length
+      end
+    end
+    class TestIntComp2 < BootTest
+      def setup
+        super
+        @method = get_compiler(:>=)
+      end
+      def test_has_get_internal
+        assert_equal Mom::MethodCompiler , @method.class
+      end
+      def test_mom_length
+        assert_equal 5 , @method.mom_instructions.length
+      end
+      def test_compile
+        assert_equal Risc::MethodCompiler , @method.to_risc.class
+      end
+      def test_risc_length
+        assert_equal 27 , @method.to_risc.risc_instructions.length
+      end
+    end
+  end
+end
diff --git a/test/risc/test_builtin.rb b/test/risc/test_builtin.rb
index eb26f545..0829039d 100644
--- a/test/risc/test_builtin.rb
+++ b/test/risc/test_builtin.rb
@@ -14,7 +14,7 @@ module Risc
       assert_equal Array, @functions.class
     end
     def test_boot_function_length
-      assert_equal 9, @functions.length
+      assert_equal 15, @functions.length
     end
     def test_boot_function_first
       assert_equal Mom::MethodCompiler, @functions.first.class