diff --git a/lib/parfait/list.rb b/lib/parfait/list.rb index 8fe28fce..9288a09a 100644 --- a/lib/parfait/list.rb +++ b/lib/parfait/list.rb @@ -1,25 +1,25 @@ # A List, or rather an ordered list, is just that, a list of items. -# For a programmer this may be a little strange as this new start goes with trying to break old -# bad habits. A List would be an array in some languages, but list is a better name, closer to -# common language. -# Another bad habit is to start a list from 0. This is "just" programmers lazyness, as it goes -# with the standard c implementation. But it bends the mind, and in oo we aim not to. -# If you have a list of three items, they will be first, second and third, ie 1,2,3 # # For the implementation we use Objects memory which is index addressable -# But, objects are also lists where indexes start with 1, except 1 is taken for the Type -# so all incoming/outgoing indexes have to be shifted one up/down +# But, objects are also lists where indexes start with 0, except 0 is taken for the Type +# so all incoming/outgoing indexes have to be shifted two up/down (one more for length) module Parfait - class List < Data32 - attr_reader :indexed_length + class List < Data16 + attr_reader :indexed_length , :next def self.type_length - 2 # 0 type , 1 length + 3 # 0 type , 1 length , 2 - next_list end def self.get_length_index - type_length - 1 + 1 + end + def self.data_length + self.memory_size - self.type_length - 1 #one for the jump + end + def data_length + self.class.data_length end def get_length @@ -27,6 +27,11 @@ module Parfait r.nil? ? 0 : r end + def ensure_next + @next = List.new unless @next + @next + end + # set the value at index. # Lists start from index 0 def set( index , value) @@ -34,20 +39,28 @@ module Parfait if index >= get_length grow_to(index + 1) end - # start one higher than offset, which is where the length is - set_internal_word( index + self.class.type_length, value) + if index >= data_length + ensure_next + @next.set( index - data_length , value) + else + set_internal_word( index + self.class.type_length, value) + end end # set the value at index. # Lists start from index 0 def get( index ) raise "Only positive indexes, #{index}" if index < 0 - ret = nil - if(index < get_length) - # start one higher than offset, which is where the length is - ret = get_internal_word(index + self.class.type_length ) + if index >= data_length + return nil unless @next + return @next.get( index - data_length) + else + ret = nil + if(index < get_length) + ret = get_internal_word(index + self.class.type_length ) + end + return ret end - ret end alias :[] :get diff --git a/lib/risc/parfait_boot.rb b/lib/risc/parfait_boot.rb index d3dce960..9aba0eca 100644 --- a/lib/risc/parfait_boot.rb +++ b/lib/risc/parfait_boot.rb @@ -115,7 +115,7 @@ module Parfait # superclasses other than default object def self.super_class_names - { Data4: :DataObject , Data8: :DataObject ,Data16: :DataObject , + { Data4: :DataObject , Data8: :DataObject ,Data16: :DataObject ,Data32: :DataObject , BinaryCode: :Data16 , Integer: :Data4 , Word: :Data8 , Object: :BasicObject , List: :Data16 , ReturnAddress: :Integer} end @@ -124,8 +124,8 @@ module Parfait # unfortuantely that constant condenses every detail about the system, class names # and all instance variable names. Really have to find a better way def self.type_names - { Word: {char_length: :Integer} , - List: {indexed_length: :Integer} , + { Word: {char_length: :Integer , next_word: :Word} , + List: {indexed_length: :Integer , next_list: :List} , Message: { next_message: :Message, receiver: :Object, frame: :NamedList , return_address: :Integer, return_value: :Object, caller: :Message , name: :Word , arguments: :NamedList }, @@ -146,14 +146,15 @@ module Parfait NamedList: {}, Type: {names: :List , types: :List , object_class: :Class, methods: :TypedMethod } , - Class: {instance_methods: :List, instance_type: :Type, name: :Word, - super_class_name: :Word , instance_names: :List }, + Class: {instance_methods: :List, instance_type: :Type, + name: :Word, super_class_name: :Word }, Dictionary: {keys: :List , values: :List } , CacheEntry: {cached_type: :Type , cached_method: :TypedMethod } , TypedMethod: {name: :Word, risc_instructions: :Object, cpu_instructions: :Object, binary: :BinaryCode, arguments_type: :Type , for_type: :Type, frame_type: :Type , next_method: :TypedMethod} , + VoolMethod: { name: :Word , args_type: :Type , frame_type: :Type } , } end end diff --git a/test/parfait/test_list.rb b/test/parfait/test_list.rb index 98694f12..3e4d7814 100644 --- a/test/parfait/test_list.rb +++ b/test/parfait/test_list.rb @@ -10,6 +10,12 @@ module Parfait def test_isa assert @list.is_a? Parfait::List end + def test_data_length + assert_equal 12 , @list.data_length + end + def test_class_data_length + assert_equal 12 , List.data_length + end def test_old_type assert_equal Parfait::Type , Parfait.object_space.classes.keys.get_type.class end @@ -29,7 +35,7 @@ module Parfait assert_equal 0, @list.indexed_length end def test_offset - assert_equal 2 , @list.class.type_length + assert_equal 3 , @list.class.type_length end def test_indexed_index # 0 type , 1 indexed_length @@ -39,7 +45,7 @@ module Parfait @list.push :one assert_equal 1 , @list.get_length assert_equal 1 , @list.indexed_length - assert_equal :one , @list.get_internal_word(Parfait::TYPE_INDEX + 2) + assert_equal :one , @list.get_internal_word(List.type_length ) end def test_list_inspect @list.set(0,1) @@ -62,8 +68,8 @@ module Parfait end def test_one_set1 assert_equal 2 , @list.set(0,2) - assert_equal 1 , @list.get_internal_word(1) - assert_equal 2 , @list.get_internal_word(2) + assert_equal 1 , @list.get_internal_word(List.get_length_index) + assert_equal 2 , @list.get_internal_word(List.type_length) end def test_set1_len @list.set(0,1) @@ -111,79 +117,4 @@ module Parfait assert_nil @list.last end end - class TestListMany < ParfaitTest - def setup - super - @list = ::Parfait::List.new - @shouldda = { 0 => :one , 1 => :two , 2 => :three} - @shouldda.each{|k,v| @list.set(k,v)} - end - def test_next_value_ok - assert_equal :two , @list.next_value(:one) - end - def test_next_value_end - assert_nil @list.next_value(:three) - end - def test_delete_at - assert @list.delete_at 1 - assert_equal 2 , @list.get_length - assert_equal 1 , @list.index_of( :three ) - end - def test_last - assert_equal :three , @list.last - end - def test_many_get - assert @list.delete :two - assert_equal 2 , @list.get_length - assert_equal 1 , @list.index_of( :three ) - end - def test_index_of - assert_equal 1 , @list.index_of( :two ) - assert_equal 2 , @list.index_of( :three ) - assert_nil @list.index_of( :four ) - end - def test_inspect - assert @list.inspect.include?("one") , @list.inspect - assert @list.inspect.include?("three") , @list.inspect - end - def test_inlcude - assert_equal true , @list.include?( :two ) - assert_equal false , @list.include?( :four ) - end - def test_next_value_not_int - assert_nil @list.next_value(:three) - end - def test_each - shouldda_values = @shouldda.values - @list.each do |val| - shouldda_values.delete val - end - assert_equal 0 , shouldda_values.length - end - def test_each_index - @list.each_with_index do |val , index| - assert_equal @list[index] , val - end - end - def test_each_pair_length - shouldda_values = @shouldda.values - @list.each_pair do |key,val| - shouldda_values.delete key - shouldda_values.delete val - end - assert_equal 0 , shouldda_values.length - end - def test_each_pair_count - counter = 0 - @list.each_pair do |key,val| - counter += 1 - end - assert_equal 2 , counter - end - def test_to_a - arr = @list.to_a - assert_equal Array , arr.class - assert_equal 3 , arr.length - end - end end diff --git a/test/parfait/test_list1.rb b/test/parfait/test_list1.rb new file mode 100644 index 00000000..09fa3d4f --- /dev/null +++ b/test/parfait/test_list1.rb @@ -0,0 +1,79 @@ +require_relative "helper" + +module Parfait + class TestListMany < ParfaitTest + def setup + super + @list = ::Parfait::List.new + @shouldda = { 0 => :one , 1 => :two , 2 => :three} + @shouldda.each{|k,v| @list.set(k,v)} + end + def test_next_value_ok + assert_equal :two , @list.next_value(:one) + end + def test_next_value_end + assert_nil @list.next_value(:three) + end + def test_delete_at + assert @list.delete_at 1 + assert_equal 2 , @list.get_length + assert_equal 1 , @list.index_of( :three ) + end + def test_last + assert_equal :three , @list.last + end + def test_many_get + assert @list.delete :two + assert_equal 2 , @list.get_length + assert_equal 1 , @list.index_of( :three ) + end + def test_index_of + assert_equal 1 , @list.index_of( :two ) + assert_equal 2 , @list.index_of( :three ) + assert_nil @list.index_of( :four ) + end + def test_inspect + assert @list.inspect.include?("one") , @list.inspect + assert @list.inspect.include?("three") , @list.inspect + end + def test_inlcude + assert_equal true , @list.include?( :two ) + assert_equal false , @list.include?( :four ) + end + def test_next_value_not_int + assert_nil @list.next_value(:three) + end + def test_each + shouldda_values = @shouldda.values + @list.each do |val| + shouldda_values.delete val + end + assert_equal 0 , shouldda_values.length + end + def test_each_index + @list.each_with_index do |val , index| + assert_equal @list[index] , val + end + end + def test_each_pair_length + shouldda_values = @shouldda.values + @list.each_pair do |key,val| + shouldda_values.delete key + shouldda_values.delete val + end + assert_equal 0 , shouldda_values.length + end + def test_each_pair_count + counter = 0 + @list.each_pair do |key,val| + counter += 1 + end + assert_equal 2 , counter + end + def test_to_a + arr = @list.to_a + assert_equal Array , arr.class + assert_equal 3 , arr.length + end + end +end diff --git a/test/parfait/test_list2.rb b/test/parfait/test_list2.rb new file mode 100644 index 00000000..bcab0bd2 --- /dev/null +++ b/test/parfait/test_list2.rb @@ -0,0 +1,36 @@ +require_relative "helper" + +module Parfait + class TestListTooMany < ParfaitTest + def setup + super + @list = ::Parfait::List.new + @list.data_length.times { |i| @list.push i.to_s } + end + def add_two + @list.push(@list.data_length.to_s) + @list.push((@list.data_length + 1).to_s) + end + def test_next + assert_nil @list.next + end + def test_setup_len + assert_equal List.data_length , @list.get_length + end + def test_setup_last + assert_equal (List.data_length - 1).to_s , @list.last + end + def test_length_two + add_two + assert_equal List.data_length + 2 , @list.get_length + end + def test_get_last + add_two + assert_equal (List.data_length + 1).to_s , @list.last + end + def test_get_but_last + add_two + assert_equal List.data_length.to_s , @list[List.data_length] + end + end +end