From 9c5d17a3bb28b9ca2b15cbad29e7134b8d1aa32e Mon Sep 17 00:00:00 2001 From: Torsten Date: Wed, 4 Mar 2020 12:39:52 +0200 Subject: [PATCH] Fix div10 without method_missing but reanimate infer_type to auto create the needed regsiters also some helpers --- lib/risc/builder.rb | 18 ++++++++++++++++-- lib/risc/callable_compiler.rb | 5 +++-- lib/risc/instructions/load_constant.rb | 23 +++++++++++++---------- lib/slot_machine/macro/div10.rb | 13 ++++++++----- test/risc/test_builder2.rb | 6 ++++++ test/slot_machine/macro/test_div10.rb | 2 +- 6 files changed, 47 insertions(+), 20 deletions(-) diff --git a/lib/risc/builder.rb b/lib/risc/builder.rb index 2e210da9..49e989ff 100644 --- a/lib/risc/builder.rb +++ b/lib/risc/builder.rb @@ -24,6 +24,20 @@ module Risc @source_used = false end + # especially for the macros (where register allocation is often manual) + # register need to be created. And since the code is "ported" we create + # them with the old names, which used the infer_type to infer the type + # + # Return the RegisterValue with given name and inferred type, compiler set + def register( name ) + RegisterValue.new(name , infer_type(name) ).set_compiler(compiler) + end + + # create an add a RegisterTransfer instruction with to and from + def transfer(to , from) + add_code Risc.transfer(@source, to , from) + end + # Infer the type from a symbol. In the simplest case the symbol is the class name. # But in building, sometimes variations are needed, so next_message or caller work # too (and both return "Message") @@ -90,8 +104,8 @@ module Risc return ins end - def load_object(object) - @compiler.load_object(object) + def load_object(object , into = nil) + @compiler.load_object(object , into) end # for some methods that return an integer it is beneficial to pre allocate the diff --git a/lib/risc/callable_compiler.rb b/lib/risc/callable_compiler.rb index 095dd4f9..d64d9245 100644 --- a/lib/risc/callable_compiler.rb +++ b/lib/risc/callable_compiler.rb @@ -93,8 +93,9 @@ module Risc # Load a constant, meaning create a LoadConstant instruction for the constant # add the instruction to the code and return the register_value that was created # for further use - def load_object( object ) - ins = Risc.load_constant("load to #{object}" , object) + # register may be passed in (epecially in mcro building) as second arg + def load_object( object , into = nil) + ins = Risc.load_constant("load to #{object}" , object , into) ins.register.set_compiler(self) add_code ins # todo for constants (not objects) diff --git a/lib/risc/instructions/load_constant.rb b/lib/risc/instructions/load_constant.rb index da725637..afbb72fe 100644 --- a/lib/risc/instructions/load_constant.rb +++ b/lib/risc/instructions/load_constant.rb @@ -32,18 +32,21 @@ module Risc end end end - def self.load_constant( source , constant ) + + def self.load_constant( source , constant , register = nil) value = constant - case constant - when Parfait::Object - type = constant.get_type - when Label - type = constant.address.get_type - else - type = constant.ct_type - value = constant.value + unless register + case constant + when Parfait::Object + type = constant.get_type + when Label + type = constant.address.get_type + else + type = constant.ct_type + value = constant.value + end + register = RegisterValue.new( "id_#{value.object_id}".to_sym , type ) end - register = RegisterValue.new( "id_#{value.object_id}".to_sym , type ) LoadConstant.new( source , constant , register ) end end diff --git a/lib/slot_machine/macro/div10.rb b/lib/slot_machine/macro/div10.rb index 320047bc..d967191d 100644 --- a/lib/slot_machine/macro/div10.rb +++ b/lib/slot_machine/macro/div10.rb @@ -4,13 +4,16 @@ module SlotMachine s = "div_10 " builder = compiler.builder(compiler.source) integer_tmp = builder.allocate_int + integer_1 = builder.register( :integer_1 ) + integer_reg = builder.register( :integer_reg ) + integer_const = builder.register( :integer_const ) builder.build do - integer_self! << message[:receiver] - integer_self.reduce_int - integer_1! << integer_self - integer_reg! << integer_self + integer_self = message[:receiver].to_reg.reduce_int + transfer( integer_self , integer_1) + transfer( integer_self , integer_reg) + + load_object( Parfait::Integer.new(1) , integer_const) - integer_const! << 1 integer_1.op :>> , integer_const integer_const << 2 diff --git a/test/risc/test_builder2.rb b/test/risc/test_builder2.rb index 1b56fc79..11ab64d7 100644 --- a/test/risc/test_builder2.rb +++ b/test/risc/test_builder2.rb @@ -10,6 +10,12 @@ module Risc @compiler = Risc::MethodCompiler.new( method, SlotMachine::Label.new( "source_name", "return_label") ) @builder = @compiler.builder(method) end + def test_register_creation + assert_equal RegisterValue , @builder.register(:name).class + end + def test_register_creation_compiler + assert @builder.register(:name).compiler + end def test_list assert_equal :List , @builder.infer_type(:list).class_name end diff --git a/test/slot_machine/macro/test_div10.rb b/test/slot_machine/macro/test_div10.rb index ed2785d6..88891b3b 100644 --- a/test/slot_machine/macro/test_div10.rb +++ b/test/slot_machine/macro/test_div10.rb @@ -14,7 +14,7 @@ module SlotMachine assert_equal Risc::MethodCompiler , @method.to_risc.class end def test_risc_length - assert_equal 70 , @method.to_risc.risc_instructions.length + assert_equal 69 , @method.to_risc.risc_instructions.length end end end