From c22aff4c4f09f9cbf24176137f4ab79a81139bbf Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Wed, 6 Jun 2018 10:00:07 +0300 Subject: [PATCH] start on insertion events and handling --- lib/arm/instructions/instruction.rb | 7 ++-- lib/risc/position/instruction_listener.rb | 30 +++++++++++++++++ lib/risc/position/position.rb | 9 ++++++ test/risc/position/helper.rb | 5 +++ .../position/test_instruction_listener.rb | 20 ------------ .../position/test_instruction_listener1.rb | 32 +++++++++++++++++++ test/risc/position/test_position.rb | 16 ++++++++-- 7 files changed, 93 insertions(+), 26 deletions(-) create mode 100644 test/risc/position/test_instruction_listener1.rb diff --git a/lib/arm/instructions/instruction.rb b/lib/arm/instructions/instruction.rb index cecb4517..b49dcec1 100644 --- a/lib/arm/instructions/instruction.rb +++ b/lib/arm/instructions/instruction.rb @@ -22,10 +22,9 @@ module Arm end def insert(instruction) - super - my_pos = Risc::Position.get(self) - listener = Risc::InstructionListener.new( instruction , my_pos.get_code ) - my_pos.position_listener(listener) + ret = super + Risc::Position.get(self).trigger_inserted if Risc::Position.set?(self) + ret end end end diff --git a/lib/risc/position/instruction_listener.rb b/lib/risc/position/instruction_listener.rb index 02ac01c0..318905cb 100644 --- a/lib/risc/position/instruction_listener.rb +++ b/lib/risc/position/instruction_listener.rb @@ -19,6 +19,10 @@ module Risc @binary = binary end + # if the position of the instruction before us changes, we need to + # adjust the position of this instruction accordingly + # Taking into account that BinaryCodes only take 13 instructions, + # meaning that chain may have to be extended def position_changed(position) fix_binary my_pos = Position.get(@instruction) @@ -34,6 +38,32 @@ module Risc my_pos.set(next_pos) end + # When this is called, only the actual insert has happened (keeping the + # position logic out of the instruction assembly). + # + # This event happens at the listener that was dependent on the position + # before the insert, ie: + # position : the arg is the first instruction in the chain where insert happened + # position.object.next : is the newly inserted instruction we need to setup + # @instruction : previously dependent on position, now on .next's position + # + # So we need to : + # - move the listener of @instruction to listen to the inserted instruction + # - add a listener for the new instruction (to listen to the arg) + # - set the new position (moving the chain along) + def position_inserted(position) + inserted = position.object.next + raise "uups" unless inserted ## TODO: remove + position.remove_position_listener(InstructionListener) + new_pos = Position.get(inserted) + new_pos.position_listener(old_listener) + + my_pos = Position.get(@instruction) + listen = InstructionListener.new(position.object , @binary) + my_pos.position_listener(listen) + + end + # check that the binary we use is the one where the current position falls # if not move up and register/unregister (soon) def fix_binary diff --git a/lib/risc/position/position.rb b/lib/risc/position/position.rb index 3bbd2223..40381f2e 100644 --- a/lib/risc/position/position.rb +++ b/lib/risc/position/position.rb @@ -43,6 +43,11 @@ module Risc register_event(:position_changed , listener) end + # When instruction get inserted, we have to move listeners around, remove given + def remove_position_listener(list) + unregister_event(:position_changed, list) + end + # utility to get all registered listeners to the :position_changed event # returns an array def position_listeners @@ -68,6 +73,10 @@ module Risc int end + def trigger_inserted + event_table[:position_changed].each { |handler| handler.position_inserted( self) } + end + def +(offset) offset = offset.at if offset.is_a?(Position) @at + offset diff --git a/test/risc/position/helper.rb b/test/risc/position/helper.rb index 2e009502..4978ff98 100644 --- a/test/risc/position/helper.rb +++ b/test/risc/position/helper.rb @@ -14,5 +14,10 @@ module Risc def initialize(nekst = nil) @next = nekst end + def insert(instruction) + ret = super + Position.get(self).trigger_inserted if Position.set?(self) + ret + end end end diff --git a/test/risc/position/test_instruction_listener.rb b/test/risc/position/test_instruction_listener.rb index 691742b7..4e1d1c68 100644 --- a/test/risc/position/test_instruction_listener.rb +++ b/test/risc/position/test_instruction_listener.rb @@ -53,24 +53,4 @@ module Risc assert_equal Branch , at_8.object.class end end - class TestInstructionListenerBig < MiniTest::Test - def setup - Risc.machine.boot - @binary = Parfait::BinaryCode.new(1) - @bin_pos = Position.new(@binary,0) - @instruction = DummyInstruction.new - 13.times {@instruction.last.insert(DummyInstruction.new) } - @position = InstructionListener.init(@instruction , @binary) - @position.set(8) - end - def test_padding - assert_equal 64 , @binary.padded_length - end - def test_last - assert_equal 72 , Position.get(@instruction.last).at - end - def test_next - assert @binary.next - end - end end diff --git a/test/risc/position/test_instruction_listener1.rb b/test/risc/position/test_instruction_listener1.rb new file mode 100644 index 00000000..c19aa226 --- /dev/null +++ b/test/risc/position/test_instruction_listener1.rb @@ -0,0 +1,32 @@ +require_relative "helper" + +module Risc + class TestInstructionListenerBig < MiniTest::Test + def setup + Risc.machine.boot + @binary = Parfait::BinaryCode.new(1) + @bin_pos = Position.new(@binary,0) + @instruction = DummyInstruction.new + 13.times {@instruction.last.insert(DummyInstruction.new) } + @position = InstructionListener.init(@instruction , @binary) + @position.set(8) + end + def test_padding + assert_equal 64 , @binary.padded_length + end + def test_last + assert_equal 72 , Position.get(@instruction.last).at + end + def test_next + assert @binary.next + end + def test_insert_initializes + @instruction.insert DummyInstruction.new + assert Position.get(@instruction.next) + end + def pest_insert_pushes + @instruction.insert DummyInstruction.new + assert_equal 76 , Position.get(@instruction.last).at + end + end +end diff --git a/test/risc/position/test_position.rb b/test/risc/position/test_position.rb index a17e00a2..b110303a 100644 --- a/test/risc/position/test_position.rb +++ b/test/risc/position/test_position.rb @@ -24,6 +24,9 @@ module Risc def test_has_listeners_helper assert_equal Array , @pos.position_listeners.class end + def test_has_trigger_inserted + assert_equal [] , @pos.trigger_inserted + end def test_listeners_empty assert @pos.position_listeners.empty? end @@ -80,7 +83,7 @@ module Risc def test_can_unregister listener = PositionListener.new(self) assert @position.position_listener(listener) - assert @position.unregister_event(:position_changed ,listener) + assert @position.remove_position_listener(listener) end def test_fires @object = @instruction @@ -92,13 +95,22 @@ module Risc @object = @instruction Position.new(self, 10) assert @position.register_event(:position_changed , self) - assert @position.unregister_event(:position_changed ,self) + assert @position.remove_position_listener(self) @position.trigger(:position_changed , @position) assert_nil @trigger end + def test_can_trigger_inserted + @object = @instruction + @position.register_event(:position_changed , self) + @position.trigger_inserted + assert_equal @position , @trigger + end def position_changed(pos) @trigger = pos end + def position_inserted(pos) + @trigger = pos + end end end