diff --git a/lib/arm/instructions/instruction.rb b/lib/arm/instructions/instruction.rb index 29c2ecb6..b814dbc8 100644 --- a/lib/arm/instructions/instruction.rb +++ b/lib/arm/instructions/instruction.rb @@ -25,7 +25,7 @@ module Arm super my_pos = Risc::Position.get(self) # set my position to set next according to rules - Risc::Position::InstructionListener.init(instruction , my_pos.get_code) + Risc::InstructionListener.init(instruction , my_pos.get_code) end end end diff --git a/lib/parfait/binary_code.rb b/lib/parfait/binary_code.rb index 5a55bda5..7eed8440 100644 --- a/lib/parfait/binary_code.rb +++ b/lib/parfait/binary_code.rb @@ -42,7 +42,7 @@ module Parfait if Risc::Position.set?(self) Risc::Position.log.debug "extending one in #{self}" my_pos = Risc::Position.get(self) - Risc::Position.reset(my_pos , my_pos.at , my_pos.method) + Risc::CodeListener.init( @next , my_pos + self.padded_length) end end diff --git a/lib/risc/interpreter.rb b/lib/risc/interpreter.rb index 13fad8d4..e60f4977 100644 --- a/lib/risc/interpreter.rb +++ b/lib/risc/interpreter.rb @@ -49,12 +49,12 @@ module Risc raise "Not int #{pos}" unless pos.is_a? Numeric position = Position.at(pos) raise "No position #{pos.to_s(16)}" unless position - if position.is_a?(Position::CodePosition) + if position.is_a?(CodePosition) raise "Setting Code #{clock}-#{position}, #{position.method}" #return set_pc(position.at + Parfait::BinaryCode.byte_offset) end log.debug "Setting Position #{clock}-#{position}, #{position.binary}" - raise "not instruction position #{position}-#{position.class}-#{position.object.class}" unless position.is_a?(Position::InstructionPosition) + raise "not instruction position #{position}-#{position.class}-#{position.object.class}" unless position.is_a?(InstructionPosition) set_instruction( position.instruction ) @clock += 1 @pc = position.at diff --git a/lib/risc/machine.rb b/lib/risc/machine.rb index 3f72b8bd..a1b04bb9 100644 --- a/lib/risc/machine.rb +++ b/lib/risc/machine.rb @@ -85,7 +85,7 @@ module Risc def position_all raise "Not translated " unless @translated #need the initial jump at 0 and then functions - Position::ObjectPosition.init(cpu_init , -1) + Position.init(cpu_init , -1) code_start = position_objects( @platform.padding ) # and then everything code position_code(code_start) @@ -101,8 +101,8 @@ module Risc sorted.each do | objekt| next if objekt.is_a?( Parfait::BinaryCode) or objekt.is_a?( Risc::Label ) before = at - position = Position::ObjectPosition.init(objekt,at) - previous.register_event(:position_changed , Position::ObjectListener.new(objekt)) if previous + position = Position.init(objekt,at) + previous.register_event(:position_changed , PositionListener.new(objekt)) if previous previous = position at += objekt.padded_length log.debug "Object #{objekt.class}:#{before.to_s(16)} len: #{(at - before).to_s(16)}" @@ -121,8 +121,8 @@ module Risc Parfait.object_space.types.values.each do |type| next unless type.methods type.methods.each_method do |method| - last_code = Position::CodeListener.init(method.binary , code_start) - Position::InstructionListener.init(method.cpu_instructions, method.binary) + last_code = CodeListener.init(method.binary , code_start) + InstructionListener.init(method.cpu_instructions, method.binary) last_code.register_event(:position_changed , prev_code.object) if prev_code prev_code = last_code code_start = last_code.next_slot diff --git a/lib/risc/position/code_listener.rb b/lib/risc/position/code_listener.rb index a965bc68..69154218 100644 --- a/lib/risc/position/code_listener.rb +++ b/lib/risc/position/code_listener.rb @@ -1,79 +1,59 @@ module Risc - module Position - # BinaryCodes form a linked list - # - # We want to keep all code for a method continous, so we propagate Positions - # - # At the end of the list the propagation spills into the next methods - # binary and so on - # - class CodeListener + # BinaryCodes form a linked list + # + # We want to keep all code for a method continous, so we propagate Positions + # + # At the end of the list the propagation spills into the next methods + # binary and so on + # + class CodeListener - attr_reader :code , :method + attr_reader :code , :method - def initialize(code , method) - super(code,pos) - @code = code - @method = method - raise "Method nil" unless method + def initialize(code , method) + super(code,pos) + @code = code + @method = method + raise "Method nil" unless method + end + def set(at ) + next_pos = at + code.padded_length + if code.next + Position.set(code.next , next_pos, method) + set_jump(at) + else + next_meth = next_method + return unless next_meth + Position.set( next_meth.binary , next_pos , next_meth) + next_cpu_pos = next_pos + Parfait::BinaryCode.byte_offset + Position.set( next_meth.cpu_instructions, next_cpu_pos , next_meth.binary) end - def set(at ) - next_pos = at + code.padded_length + end + + # insert a jump to the next instruction, at the last instruction + # thus hopping over the object header + def set_jump(at) + jump = Branch.new("BinaryCode #{at.to_s(16)}" , code.next) + translator = Risc.machine.platform.translator + cpu_jump = translator.translate(jump) + pos = at + code.padded_length - cpu_jump.byte_length + Position.set( cpu_jump , pos , code) + cpu_jump.assemble(JumpWriter.new(code)) + end + + def self.init( code , at = -1) + while code + position = Position.new(code , at) + Position.set_to(position , at) if code.next - Position.set(code.next , next_pos, method) - set_jump(at) - else - next_meth = next_method - return unless next_meth - Position.set( next_meth.binary , next_pos , next_meth) - next_cpu_pos = next_pos + Parfait::BinaryCode.byte_offset - Position.set( next_meth.cpu_instructions, next_cpu_pos , next_meth.binary) + listener = PositionListener.new(code.next) + position.register_event(:position_changed , listener) end + at += code.padded_length unless at < 0 + code = code.next end - - # insert a jump to the next instruction, at the last instruction - # thus hopping over the object header - def set_jump(at) - jump = Branch.new("BinaryCode #{at.to_s(16)}" , code.next) - translator = Risc.machine.platform.translator - cpu_jump = translator.translate(jump) - pos = at + code.padded_length - cpu_jump.byte_length - Position.set( cpu_jump , pos , code) - cpu_jump.assemble(JumpWriter.new(code)) - end - - def next_method - next_m = @method.next_method - return next_m if next_m - Position.log.debug "Type now #{@method.for_type.name}" - type = next_type(@method.for_type) - if type - Position.log.debug "Position for #{type.name}" - return type.methods - else - return nil - end - end - def next_type(type) - nekst = Parfait.object_space.types.next_value(type) - return nil unless nekst - return nekst if nekst.methods - return next_type(nekst) - end - def self.init( code , at = -1) - while code - position = ObjectPosition.new(code , at) - Position.set_to(position , at) - if code.next - listener = ObjectListener.new(code.next) - position.register_event(:position_changed , listener) - end - at += code.padded_length unless at < 0 - code = code.next - end - position - end + position end end end diff --git a/lib/risc/position/instruction_listener.rb b/lib/risc/position/instruction_listener.rb index d7d418dd..17bd9d5c 100644 --- a/lib/risc/position/instruction_listener.rb +++ b/lib/risc/position/instruction_listener.rb @@ -1,75 +1,72 @@ module Risc - module Position - - # Instructions are also a linked list, but their position is not really - # the position of the object. - # Rather it is the position of the assembled code in the binary. - # (Luckily arm is sane, so this is realtively simple) - # - # Really we only need to calculate Positions at a jump, so between the - # Jump and the label it jumps too. The other instructions are "just" fill. - # But off course we need to propagate positions to get it right. - # - # Assembled instructions are kept in BinaryCode objects. - # When propagating positions we have to see that the next position assembles into - # the same BinaryCode, or else move it and the code along - # - class InstructionListener - attr_reader :instruction , :binary - def initialize(instruction , binary) - pos = 0 - @instruction = instruction - @binary = binary + # Instructions are also a linked list, but their position is not really + # the position of the object. + # Rather it is the position of the assembled code in the binary. + # (Luckily arm is sane, so this is realtively simple) + # + # Really we only need to calculate Positions at a jump, so between the + # Jump and the label it jumps too. The other instructions are "just" fill. + # But off course we need to propagate positions to get it right. + # + # Assembled instructions are kept in BinaryCode objects. + # When propagating positions we have to see that the next position assembles into + # the same BinaryCode, or else move it and the code along + # + class InstructionListener + attr_reader :instruction , :binary + def initialize(instruction , binary) + pos = 0 + @instruction = instruction + @binary = binary + end + def init(at, binary) + @binary = binary + instruction.address.set_value(at) if instruction.is_a?(Label) + return if at == 0 and binary.nil? + raise "faux pas" if at < Position.get(binary).at + return unless @instruction.next + nekst = at + @instruction.byte_length + diff = nekst - Position.get(@binary).at + Position.log.debug "Diff: #{diff.to_s(16)} , next #{nekst.to_s(16)} , binary #{Position.get(@binary)}" + raise "Invalid position #{diff.to_s(16)} , next #{nekst.to_s(16)} #{self}" if diff < 8 + if( (diff % (binary.padded_length - @instruction.byte_length)) == 0 ) + binary.extend_one unless binary.next + binary = binary.next + raise "end of line " unless binary + nekst = Position.get(binary).at + Parfait::BinaryCode.byte_offset + Position.log.debug "Jump to: #{nekst.to_s(16)}" end - def init(at, binary) - @binary = binary - instruction.address.set_value(at) if instruction.is_a?(Label) - return if at == 0 and binary.nil? - raise "faux pas" if at < Position.get(binary).at - return unless @instruction.next - nekst = at + @instruction.byte_length - diff = nekst - Position.get(@binary).at - Position.log.debug "Diff: #{diff.to_s(16)} , next #{nekst.to_s(16)} , binary #{Position.get(@binary)}" - raise "Invalid position #{diff.to_s(16)} , next #{nekst.to_s(16)} #{self}" if diff < 8 - if( (diff % (binary.padded_length - @instruction.byte_length)) == 0 ) - binary.extend_one unless binary.next - binary = binary.next - raise "end of line " unless binary - nekst = Position.get(binary).at + Parfait::BinaryCode.byte_offset - Position.log.debug "Jump to: #{nekst.to_s(16)}" + Position.set(@instruction.next, nekst , binary) + end + + def reset_to(pos , binary) + super(pos , binary) + init(pos , binary) + Position.log.debug "ResetInstruction (#{pos.to_s(16)}) #{instruction}" + end + + # initialize the dependency graph for instructions + # + # starting from the given instruction, create Positions + # for it and the whole chain. Then attach InstructionListeners + # for dependency tracking. All positions are initialized with -1 + # and so setting the first will trigger a chain reaction + # + # return the position for the first instruction which may be used to + # set all positions in the chain + def self.init( instruction , code ) + first = nil + while(instruction) + position = Position.new(instruction , -1) + first = position unless first + nekst = instruction.next + if nekst + listener = InstructionListener.new( nekst , code ) + position.register_event(:position_changed , listener) end - Position.set(@instruction.next, nekst , binary) - end - - def reset_to(pos , binary) - super(pos , binary) - init(pos , binary) - Position.log.debug "ResetInstruction (#{pos.to_s(16)}) #{instruction}" - end - - # initialize the dependency graph for instructions - # - # starting from the given instruction, create ObjectPositions - # for it and the whole chain. Then attach InstructionListeners - # for dependency tracking. All positions are initialized with -1 - # and so setting the first will trigger a chain reaction - # - # return the position for the first instruction which may be used to - # set all positions in the chain - def self.init( instruction , code ) - first = nil - while(instruction) - position = ObjectPosition.new(instruction , -1) - first = position unless first - nekst = instruction.next - if nekst - listener = InstructionListener.new( nekst , code ) - position.register_event(:position_changed , listener) - end - instruction = nekst - end - first + instruction = nekst end + first end end end diff --git a/lib/risc/position/object_listener.rb b/lib/risc/position/object_listener.rb index 24d60d49..a428c6e4 100644 --- a/lib/risc/position/object_listener.rb +++ b/lib/risc/position/object_listener.rb @@ -1,31 +1,29 @@ module Risc - module Position - # Listeners localise the changes that need to happen. + # Listeners localise the changes that need to happen. + # + # An object listener assmes it is set up to the previous object. + # so when position changes, it places itself just behind the previous object + # + # This is handy, since the "normal" chaining of object is forward + # But the dependencies are backwards. This way we don't clutter the + # actual object (or even the position), but keep the logic seperate. + class PositionListener + + # initialize with the object that needs to react to change + def initialize(object) + @object = object + end + + # when the argument changes position, we update the objects + # position to reflect that change # - # An object listener assmes it is set up to the previous object. - # so when position changes, it places itself just behind the previous object - # - # This is handy, since the "normal" chaining of object is forward - # But the dependencies are backwards. This way we don't clutter the - # actual object (or even the position), but keep the logic seperate. - class ObjectListener - - # initialize with the object that needs to react to change - def initialize(object) - @object = object - end - - # when the argument changes position, we update the objects - # position to reflect that change - # - def position_changed(previous) - me = previous.at + previous.object.padded_length - object_pos = Position.get(@object) - return if me == object_pos.at - Position.set(@object , me) - end + def position_changed(previous) + me = previous.at + previous.object.padded_length + object_pos = Position.get(@object) + return if me == object_pos.at + Position.set(@object , me) end end end diff --git a/lib/risc/position/object_position.rb b/lib/risc/position/object_position.rb deleted file mode 100644 index 878b2fc6..00000000 --- a/lib/risc/position/object_position.rb +++ /dev/null @@ -1,60 +0,0 @@ -require "util/eventable" - -module Risc - module Position - class ObjectPosition - include Util::Eventable - - attr_reader :at , :object - - # initialize with a given object, first parameter - # The object ill be the key in global position map - # Give an integer as the actual position, where -1 - # which means no legal position known - def initialize(object , pos ) - @at = pos - @object = object - Position.set_to(self , pos) - end - - #look for InstructionListener and return its code if found - def get_code - listener = event_table.find{|one| one.class == InstructionListener} - return nil unless listener - listener.code - end - def +(offset) - offset = offset.at if offset.is_a?(ObjectPosition) - @at + offset - end - - def -(offset) - offset = offset.at if offset.is_a?(ObjectPosition) - @at - offset - end - def to_s - "0x#{@at.to_s(16)}" - end - # just a callback after creation AND insertion - def init(pos , is_nil) - end - def reset_to(pos , guaranteed_nil ) - return false if pos == at - if((at - pos).abs > 1000) - raise "position set too far off #{pos}!=#{at} for #{object}:#{object.class}" - end - @at = pos - trigger(:position_changed , self) - true - end - def next_slot - return -1 if at < 0 - at + object.byte_length - end - def self.init(object , at = -1) - position = ObjectPosition.new(object , at) - Position.set_to( position , at) - end - end - end -end diff --git a/lib/risc/position/position.rb b/lib/risc/position/position.rb index ad23477b..e2cfee10 100644 --- a/lib/risc/position/position.rb +++ b/lib/risc/position/position.rb @@ -1,3 +1,5 @@ +require "util/eventable" + module Risc # Positions are very different during compilation and run-time. # At run-time they are inherrent to the object, and fixed. @@ -14,10 +16,50 @@ module Risc # While the (different)Position objects transmit the change that (re) positioning # entails to affected objects. - module Position + class Position include Util::Logging log_level :info + include Util::Eventable + + attr_reader :at , :object + + # initialize with a given object, first parameter + # The object ill be the key in global position map + # Give an integer as the actual position, where -1 + # which means no legal position known + def initialize(object , pos ) + @at = pos + @object = object + Position.set_to(self , pos) + end + + #look for InstructionListener and return its code if found + def get_code + listener = event_table.find{|one| one.class == InstructionListener} + return nil unless listener + listener.code + end + + def +(offset) + offset = offset.at if offset.is_a?(Position) + @at + offset + end + + def -(offset) + offset = offset.at if offset.is_a?(Position) + @at - offset + end + def to_s + "0x#{@at.to_s(16)}" + end + + def next_slot + return -1 if at < 0 + at + object.byte_length + end + + ## class level forward and reverse cache @positions = {} @reverse_cache = {} @@ -41,7 +83,7 @@ module Risc def self.get(object) pos = self.positions[object] if pos == nil - str = "position accessed but not set, " + str = "position accessed but not initialized, " str += "0x#{object.object_id.to_s(16)}\n" str += "for #{object.class} " str += "byte_length #{object.byte_length}" if object.respond_to?(:byte_length) @@ -51,16 +93,11 @@ module Risc pos end - def self.reset(obj) - old = self.get(obj) - old.reset_to( old.at ) - end - def self.set_to( position , to) - postest = Position.positions[position.object] unless to < 0 + postest = Position.positions[position.object] unless to < 0 raise "Mismatch #{position}" if postest and postest != position @reverse_cache.delete(position.at) unless position.object.is_a? Label - testing = self.at( position.at ) if position.at >= 0 + testing = self.at( position.at ) unless position.at < 0 if testing and testing.class != position.class raise "Mismatch (at #{pos.to_s(16)}) was:#{position} #{position.class} #{position.object} , should #{testing}#{testing.class}" end @@ -71,7 +108,6 @@ module Risc end end end -require_relative "object_position" require_relative "object_listener" require_relative "instruction_listener" require_relative "code_listener" diff --git a/test/risc/position/helper.rb b/test/risc/position/helper.rb index 026cc2ca..754a03e4 100644 --- a/test/risc/position/helper.rb +++ b/test/risc/position/helper.rb @@ -1,11 +1,9 @@ require_relative "../helper" module Risc - module Position - class Dummy - def padded_length - 4 - end + class Dummy + def padded_length + 4 end end end diff --git a/test/risc/position/test_code_listener.rb b/test/risc/position/test_code_listener.rb index 780e2c45..79a6ea2d 100644 --- a/test/risc/position/test_code_listener.rb +++ b/test/risc/position/test_code_listener.rb @@ -1,35 +1,33 @@ require_relative "helper" module Risc - module Position - # tests that require a boot and test propagation - class TestcodeListener < MiniTest::Test - def setup - Risc.machine.boot - @binary = Parfait::BinaryCode.new(1) - @method = Parfait.object_space.types.values.first.methods - @label = Risc.label("hi","ho") - end + # tests that require a boot and test propagation + class TestcodeListener < MiniTest::Test + def setup + Risc.machine.boot + @binary = Parfait::BinaryCode.new(1) + @method = Parfait.object_space.types.values.first.methods + @label = Risc.label("hi","ho") + end - def test_has_init - pos = CodeListener.init(@binary) - assert_equal pos, Position.get(@binary) - end - def test_init_returns_position + def test_has_init + pos = CodeListener.init(@binary) + assert_equal pos, Position.get(@binary) + end + def test_init_returns_position - assert_equal Position::ObjectPosition , CodeListener.init(@binary).class - end - def test_init_listner - @binary.extend_one - CodeListener.init(@binary) - pos = Position.get(@binary) - assert !pos.event_table[:position_changed].empty? - end - def test_not_init_listner - CodeListener.init(@binary) - pos = Position.get(@binary) - assert pos.event_table[:position_changed].empty? - end + assert_equal Position , CodeListener.init(@binary).class + end + def test_init_listner + @binary.extend_one + CodeListener.init(@binary) + pos = Position.get(@binary) + assert !pos.event_table[:position_changed].empty? + end + def test_not_init_listner + CodeListener.init(@binary) + pos = Position.get(@binary) + assert pos.event_table[:position_changed].empty? end end end diff --git a/test/risc/position/test_code_position.rb b/test/risc/position/test_code_position.rb index 377d8175..20cb6456 100644 --- a/test/risc/position/test_code_position.rb +++ b/test/risc/position/test_code_position.rb @@ -11,7 +11,7 @@ module Risc end def test_set_bin pos = Position.set( @binary , 0 , @method) - assert_equal Position::CodePosition , pos.class + assert_equal CodePosition , pos.class end def test_type pos = Position.set( @binary , 0 , @method) diff --git a/test/risc/position/test_instruction_listener.rb b/test/risc/position/test_instruction_listener.rb index b7542ac4..f499c39b 100644 --- a/test/risc/position/test_instruction_listener.rb +++ b/test/risc/position/test_instruction_listener.rb @@ -1,63 +1,61 @@ require_relative "helper" module Risc - module Position - # tests that require a boot and test propagation - class TestInstructionListener < MiniTest::Test - def setup - Risc.machine.boot - @binary = Parfait::BinaryCode.new(1) - #Position.set(@binary , 0 , Parfait.object_space.get_main) - @label = Risc.label("hi","ho") - end - def test_init - assert InstructionListener.init(@label , @binary) - end - def pest_set_instr - pos = Position.set( @label , 8 , @binary) - assert_equal InstructionPosition , pos.class - end - def pest_label_set_int - Position.set( @label , 8 , @binary) - assert_equal 8 , @label.address.value - end - def pest_label_reset_int - Position.set( @label , 8 , @binary) - Position.set( @label , 18 , @binary) - assert_equal 18 , @label.address.value - end - def pest_ins_propagates - @label.set_next Arm::ArmMachine.b( @label) - Position.set( @label , 8 , @binary) - assert_equal 8 , Position.get(@label.next).at - end - def pest_ins_propagates_again - second = Arm::ArmMachine.b( @label) - @label.set_next(second) - Position.set( @label , 8 , @binary) - Position.set(second , 12 , @binary) - Position.set( @label , 8 , @binary) - assert_equal 8 , Position.get(@label.next).at - end - def pest_label_at - branch = Branch.new("b" , @label) - Position.set(@label , 8 , @binary) - Position.set(branch , 8 , @binary) - at_4 = Position.at(8) - assert_equal InstructionPosition , at_4.class - assert_equal Branch , at_4.instruction.class - end - def pest_label_at_reverse - branch = Branch.new("b" , @label) - Position.set(branch , 8 , @binary) - Position.set(@label , 8 , @binary) - at_4 = Position.at(8) - assert_equal InstructionPosition , at_4.class - assert_equal Branch , at_4.instruction.class - end - def pest_reset_false_type - assert_raises {Position.set(@label , 0 , @binary)} - end + # tests that require a boot and test propagation + class TestInstructionListener < MiniTest::Test + def setup + Risc.machine.boot + @binary = Parfait::BinaryCode.new(1) + #Position.set(@binary , 0 , Parfait.object_space.get_main) + @label = Risc.label("hi","ho") + end + def test_init + assert InstructionListener.init(@label , @binary) + end + def pest_set_instr + pos = Position.set( @label , 8 , @binary) + assert_equal InstructionPosition , pos.class + end + def pest_label_set_int + Position.set( @label , 8 , @binary) + assert_equal 8 , @label.address.value + end + def pest_label_reset_int + Position.set( @label , 8 , @binary) + Position.set( @label , 18 , @binary) + assert_equal 18 , @label.address.value + end + def pest_ins_propagates + @label.set_next Arm::ArmMachine.b( @label) + Position.set( @label , 8 , @binary) + assert_equal 8 , Position.get(@label.next).at + end + def pest_ins_propagates_again + second = Arm::ArmMachine.b( @label) + @label.set_next(second) + Position.set( @label , 8 , @binary) + Position.set(second , 12 , @binary) + Position.set( @label , 8 , @binary) + assert_equal 8 , Position.get(@label.next).at + end + def pest_label_at + branch = Branch.new("b" , @label) + Position.set(@label , 8 , @binary) + Position.set(branch , 8 , @binary) + at_4 = Position.at(8) + assert_equal InstructionPosition , at_4.class + assert_equal Branch , at_4.instruction.class + end + def pest_label_at_reverse + branch = Branch.new("b" , @label) + Position.set(branch , 8 , @binary) + Position.set(@label , 8 , @binary) + at_4 = Position.at(8) + assert_equal InstructionPosition , at_4.class + assert_equal Branch , at_4.instruction.class + end + def pest_reset_false_type + assert_raises {Position.set(@label , 0 , @binary)} end end end diff --git a/test/risc/position/test_object_listener.rb b/test/risc/position/test_object_listener.rb index fc2312ef..d21aabc0 100644 --- a/test/risc/position/test_object_listener.rb +++ b/test/risc/position/test_object_listener.rb @@ -1,29 +1,27 @@ require_relative "helper" module Risc - module Position - class TestObjectListener < MiniTest::Test + class TestPositionListener < MiniTest::Test - def setup - @object = Dummy.new - @dependent = Dummy.new - @pos = ObjectPosition.new(@object,0) - ObjectPosition.new(@dependent,0) - @listener = ObjectListener.new(@dependent) - end - def test_register - assert @pos.register_event(:position_changed , @listener) - end - def test_no_fire - @pos.register_event(:position_changed , self) - Position.set_to(@pos,0) - assert_equal 0 , Position.get(@object).at - end - def test_reset - @pos.register_event(:position_changed , @listener) - Position.set_to(@pos,4) - assert_equal 0 , Position.at(4).at - end + def setup + @object = Dummy.new + @dependent = Dummy.new + @pos = Position.new(@object,0) + Position.new(@dependent,0) + @listener = PositionListener.new(@dependent) + end + def test_register + assert @pos.register_event(:position_changed , @listener) + end + def test_no_fire + @pos.register_event(:position_changed , self) + Position.set_to(@pos,0) + assert_equal 0 , Position.get(@object).at + end + def test_reset + @pos.register_event(:position_changed , @listener) + Position.set_to(@pos,4) + assert_equal 0 , Position.at(4).at end end end diff --git a/test/risc/position/test_object_position.rb b/test/risc/position/test_object_position.rb deleted file mode 100644 index 9c792f38..00000000 --- a/test/risc/position/test_object_position.rb +++ /dev/null @@ -1,89 +0,0 @@ -require_relative "helper" - -module Risc - module Position - # tests that do no require a boot and only test basic positioning - class TestObjectPosition < MiniTest::Test - - def test_init - assert ObjectPosition.init(self , -1) - end - def test_next_slot - mov = Arm::ArmMachine.mov(:r1 , :r1) - position = ObjectPosition.new(mov , 0) - assert_equal 4, position.next_slot - end - def test_has_get_code - assert_nil ObjectPosition.init(self , -1).get_code - end - def pest_creation_ok - assert ObjectPosition.new(self,0) - end - def pest_creation_fail - assert_raises {Position.new("0")} - end - def pest_add - res = ObjectPosition.new(self,0) + 5 - assert_equal 5 , res - end - def pest_sub - res = ObjectPosition.new(self,0) - 1 - assert_equal -1 , res - end - def pest_sub_pos - res = ObjectPosition.new(self,0) - ObjectPosition.new(self,0) - assert_equal 0 , res - end - def pest_set - pos = Position.set(self , 5) - assert_equal 5 , pos.at - end - def tet_tos - assert_equal "0x10" , Position.set(self).to_s - end - def pest_reset_ok - pos = Position.set(self , 5) - pos = Position.set(self , 10) - assert_equal 10 , pos.at - end - def pest_reset_fail - Position.set(self , 5) - assert_raises{Position.set(self , 10000)} - end - def pest_raises_set_nil - assert_raises { Position.set(self,nil)} - end - def pest_at - pos = Position.set(self , 5) - pos = Position.at(5) - assert_equal 5 , pos.at - end - end - class TestPositionEvents < MiniTest::Test - def setup - @position = ObjectPosition.new(self) - end - def pest_has_register - assert @position.register_event(:position_changed , self) - end - def pest_can_unregister - assert @position.register_event(:position_changed ,self) - assert @position.unregister_event(:position_changed ,self) - end - def pest_fires - @position.register_event(:position_changed ,self) - @position.trigger(:position_changed , @position) - assert_equal @position , @trigger - end - def pest_no_fire_after_unregister - assert @position.register_event(:position_changed ,self) - assert @position.unregister_event(:position_changed ,self) - @position.trigger(:position_changed , @position) - assert_nil @trigger - end - def position_changed(pos) - @trigger = pos - end - end - end -end diff --git a/test/risc/position/test_position.rb b/test/risc/position/test_position.rb index cd5c5ecf..3641e6bc 100644 --- a/test/risc/position/test_position.rb +++ b/test/risc/position/test_position.rb @@ -1,5 +1,91 @@ require_relative "helper" +module Risc + # tests that do no require a boot and only test basic positioning + class TestPosition < MiniTest::Test + + def test_new + assert Position.new(self , -1) + end + def test_next_slot + mov = Arm::ArmMachine.mov(:r1 , :r1) + position = Position.new(mov , 0) + assert_equal 4, position.next_slot + end + def test_has_get_code + assert_nil Position.new(self , -1).get_code + end + def pest_creation_ok + assert Position.new(self,0) + end + def pest_creation_fail + assert_raises {Position.new("0")} + end + def pest_add + res = Position.new(self,0) + 5 + assert_equal 5 , res + end + def pest_sub + res = Position.new(self,0) - 1 + assert_equal -1 , res + end + def pest_sub_pos + res = Position.new(self,0) - Position.new(self,0) + assert_equal 0 , res + end + def pest_set + pos = Position.set(self , 5) + assert_equal 5 , pos.at + end + def tet_tos + assert_equal "0x10" , Position.set(self).to_s + end + def pest_reset_ok + pos = Position.set(self , 5) + pos = Position.set(self , 10) + assert_equal 10 , pos.at + end + def pest_reset_fail + Position.set(self , 5) + assert_raises{Position.set(self , 10000)} + end + def pest_raises_set_nil + assert_raises { Position.set(self,nil)} + end + def pest_at + pos = Position.set(self , 5) + pos = Position.at(5) + assert_equal 5 , pos.at + end + end + class TestPositionEvents < MiniTest::Test + def setup + @position = Position.new(self) + end + def pest_has_register + assert @position.register_event(:position_changed , self) + end + def pest_can_unregister + assert @position.register_event(:position_changed ,self) + assert @position.unregister_event(:position_changed ,self) + end + def pest_fires + @position.register_event(:position_changed ,self) + @position.trigger(:position_changed , @position) + assert_equal @position , @trigger + end + def pest_no_fire_after_unregister + assert @position.register_event(:position_changed ,self) + assert @position.unregister_event(:position_changed ,self) + @position.trigger(:position_changed , @position) + assert_nil @trigger + end + def position_changed(pos) + @trigger = pos + end + end +end + module Risc class TestMachinePositions < MiniTest::Test def setup diff --git a/test/risc/test_machine.rb b/test/risc/test_machine.rb index 7f7e1d44..57e37732 100644 --- a/test/risc/test_machine.rb +++ b/test/risc/test_machine.rb @@ -51,7 +51,7 @@ module Risc assert_equal "0x5ecc" , Position.get(Position.get(@machine.cpu_init.first).binary).to_s end def test_cpu_label - assert_equal Position::InstructionPosition , Position.get(@machine.cpu_init.first).class + assert_equal InstructionPosition , Position.get(@machine.cpu_init.first).class end def test_first_binary_jump bin = Parfait.object_space.get_init.binary