From d6c503ecf40194778c5a3950c567db1533462ea8 Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Fri, 30 Dec 2016 21:00:18 +0200 Subject: [PATCH] inlined indexed into list which was the only one using it. A whole lot simpler, considering it will have to be bootstrapped someday --- lib/register/collector.rb | 2 +- lib/typed/parfait/indexed.rb | 249 -------------------------------- lib/typed/parfait/list.rb | 220 +++++++++++++++++++++++++++- test/elf/test_zero.rb | 9 +- test/typed/parfait/test_list.rb | 1 - 5 files changed, 226 insertions(+), 255 deletions(-) delete mode 100644 lib/typed/parfait/indexed.rb diff --git a/lib/register/collector.rb b/lib/register/collector.rb index a0d103d6..1334f348 100644 --- a/lib/register/collector.rb +++ b/lib/register/collector.rb @@ -26,7 +26,7 @@ module Register inst = object.get_instance_variable name keep(inst , depth + 1) end - if object.is_a? Parfait::Indexed + if object.is_a? Parfait::List object.each do |item| #puts "Keep item " keep(item , depth + 1) diff --git a/lib/typed/parfait/indexed.rb b/lib/typed/parfait/indexed.rb deleted file mode 100644 index 4f7a5246..00000000 --- a/lib/typed/parfait/indexed.rb +++ /dev/null @@ -1,249 +0,0 @@ -module Parfait - # Various classes would derive from array in ruby, ie have indexed variables - # - # But for our memory type we need the variable part of an object to be after - # the fixed, ie the instance variables - # - # Just using ruby derivation will not allow us to offset the index, so instead the - # function will be generated and included to the classes that need them. - # - # Basic functionality depends on the offset, and those methods are generated by - # the offset method that has to be called seperately when including this Module - - module Indexed # marker module - def self.included(base) - base.extend(OffsetMethods) - end - - def initialize( ) - super() - @memory = [] - end - - # include? means non nil index - def include? item - return index_of(item) != nil - end - - # index of item, remeber first item has index 1 - # return nil if no such item - def index_of item - max = self.get_length - #puts "length #{max} #{max.class}" - counter = 1 - while( counter <= max ) - if( get(counter) == item) - return counter - end - counter = counter + 1 - end - return nil - end - - # push means add to the end - # this automatically grows the List - def push value - to = self.get_length + 1 - set( to , value) - to - end - - def delete value - index = index_of value - return false unless index - delete_at index - end - - def delete_at index - # TODO bounds check - while(index < self.get_length) - set( index , get(index + 1)) - index = index + 1 - end - set_length( self.get_length - 1) - true - end - - def first - return nil if empty? - get(1) - end - - def last - return nil if empty? - get(get_length()) - end - - def empty? - self.get_length == 0 - end - - def equal? other - # this should call parfait get_class, alas that is not implemented yet - return false if other.class != self.class - return false if other.get_length != self.get_length - index = self.get_length - while(index > 0) - return false if other.get(index) != self.get(index) - index = index - 1 - end - return true - end - - # above, correct, implementation causes problems in the machine object space - # because when a second empty (newly created) list is added, it is not actually - # added as it exists already. TODO, but hack with below identity function - def == other - self.object_id == other.object_id - end - - # word length (padded) is the amount of space taken by the object - # For your basic object this means the number of instance variables as determined by type - # This is off course 0 for a list, unless someone squeezed an instance variable in - # but additionally, the amount of data comes on top. - # unfortuntely we can't just use super because of the Padding - def padded_length - padded_words( get_type().instance_length + get_length() ) - end - - def each - index = 1 - while index <= self.get_length - item = get(index) - yield item - index = index + 1 - end - self - end - - def each_with_index - index = 1 - while index <= self.get_length - item = get(index) - yield item , index - index = index + 1 - end - self - end - - def each_pair - index = 1 - while index <= self.get_length - key = get( index ) - value = get(index + 1) - yield key , value - index = index + 2 - end - self - end - - def find - index = 1 - while index <= self.get_length - item = get(index) - return item if yield item - index = index + 1 - end - return nil - end - - def set_length len - was = self.get_length - return if was == len - if(was < len) - grow_to len - else - shrink_to len - end - end - - def inspect - index = 1 - ret = "" - while index <= self.get_length - item = get(index) - ret += item.inspect - ret += "," unless index == self.get_length - index = index + 1 - end - ret - end - - # 1 -based index - def get_internal_word(index) - @memory[index] - end - - # 1 -based index - def set_internal_word(index , value) - raise "Word[#{index}] = " if((self.class == Parfait::Word) and value.nil? ) - @memory[index] = value - value - end - - module OffsetMethods - # generate all methods that depend on the (memory) offset - # These are get/set shrink_to/grow_to - def offset( offset ) - offset += 1 # for the attribute we add (indexed_length) - - # define methods on the class that includes. - # weird syntax, but at least it's possible - (class << self;self;end).send :define_method , :get_length_index do - offset - end - (class << self;self;end).send :define_method , :get_indexed do |index| - offset + index - end - define_method :get_offset do - offset - end - - define_method :get_length do - r = get_internal_word( offset ) #one for type - r.nil? ? 0 : r - end - - # set the value at index. - # Lists start from index 1 - define_method :set do | index , value| - raise "Only positive indexes #{index}" if index <= 0 - if index > self.get_length - grow_to(index) - end - # start one higher than offset, which is where the length is - set_internal_word( index + offset, value) - end - - # set the value at index. - # Lists start from index 1 - define_method :get do | index| - raise "Only positive indexes, #{index}" if index <= 0 - ret = nil - if(index <= self.get_length) - # start one higher than offset, which is where the length is - ret = get_internal_word(index + offset ) - end - ret - end - - define_method :grow_to do | len| - raise "Only positive lenths, #{len}" if len < 0 - old_length = self.get_length - return if old_length >= len -# raise "bounds error at #{len}" if( len + offset > 16 ) - # be nice to use the indexed_length , but that relies on booted space - set_internal_word( offset , len) #one for type - end - - define_method :shrink_to do | len| - raise "Only positive lenths, #{len}" if len < 0 - old_length = self.get_length - return if old_length <= len - set_internal_word( offset , len) - end - - end - end - end -end diff --git a/lib/typed/parfait/list.rb b/lib/typed/parfait/list.rb index 01e199cc..0a089db5 100644 --- a/lib/typed/parfait/list.rb +++ b/lib/typed/parfait/list.rb @@ -1,4 +1,3 @@ -require_relative "indexed" # 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 @@ -14,18 +13,233 @@ require_relative "indexed" module Parfait class List < Object - include Indexed - self.offset(1) + def self.get_length_index + 2 + end + def self.get_indexed(index) + index + 2 + end + + def get_offset + 2 + end + + def get_length + r = get_internal_word( 2 ) #one for type + r.nil? ? 0 : r + end + + # set the value at index. + # Lists start from index 1 + def set( index , value) + raise "Only positive indexes #{index}" if index <= 0 + if index > get_length + grow_to(index) + end + # start one higher than offset, which is where the length is + set_internal_word( index + 2, value) + end + + # set the value at index. + # Lists start from index 1 + 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 + 2 ) + end + ret + end + + def grow_to( len) + raise "Only positive lenths, #{len}" if len < 0 + old_length = get_length + return if old_length >= len + # raise "bounds error at #{len}" if( len + offset > 16 ) + # be nice to use the indexed_length , but that relies on booted space + set_internal_word( 2 , len) #one for type + end + + def shrink_to( len ) + raise "Only positive lenths, #{len}" if len < 0 + old_length = get_length + return if old_length <= len + set_internal_word( 2 , len) + end def self.attributes [:indexed_length] end + def indexed_length get_length() end def initialize( ) super() + @memory = [] + end + + # include? means non nil index + def include? item + return index_of(item) != nil + end + + # index of item, remeber first item has index 1 + # return nil if no such item + def index_of( item ) + max = self.get_length + #puts "length #{max} #{max.class}" + counter = 1 + while( counter <= max ) + if( get(counter) == item) + return counter + end + counter = counter + 1 + end + return nil + end + + # push means add to the end + # this automatically grows the List + def push( value ) + to = self.get_length + 1 + set( to , value) + to + end + + def delete( value ) + index = index_of value + return false unless index + delete_at index + end + + def delete_at( index ) + # TODO bounds check + while(index < self.get_length) + set( index , get(index + 1)) + index = index + 1 + end + set_length( self.get_length - 1) + true + end + + def first + return nil if empty? + get(1) + end + + def last + return nil if empty? + get(get_length()) + end + + def empty? + self.get_length == 0 + end + + def equal? other + # this should call parfait get_class, alas that is not implemented yet + return false if other.class != self.class + return false if other.get_length != self.get_length + index = self.get_length + while(index > 0) + return false if other.get(index) != self.get(index) + index = index - 1 + end + return true + end + + # above, correct, implementation causes problems in the machine object space + # because when a second empty (newly created) list is added, it is not actually + # added as it exists already. TODO, but hack with below identity function + def == other + self.object_id == other.object_id + end + + # word length (padded) is the amount of space taken by the object + # For your basic object this means the number of instance variables as determined by type + # This is off course 0 for a list, unless someone squeezed an instance variable in + # but additionally, the amount of data comes on top. + # unfortuntely we can't just use super because of the Padding + def padded_length + padded_words( get_type().instance_length + get_length() ) + end + + def each + index = 1 + while index <= self.get_length + item = get(index) + yield item + index = index + 1 + end + self + end + + def each_with_index + index = 1 + while index <= self.get_length + item = get(index) + yield item , index + index = index + 1 + end + self + end + + def each_pair + index = 1 + while index <= self.get_length + key = get( index ) + value = get(index + 1) + yield key , value + index = index + 2 + end + self + end + + def find + index = 1 + while index <= self.get_length + item = get(index) + return item if yield item + index = index + 1 + end + return nil + end + + def set_length len + was = self.get_length + return if was == len + if(was < len) + grow_to len + else + shrink_to len + end + end + + def inspect + index = 1 + ret = "" + while index <= self.get_length + item = get(index) + ret += item.inspect + ret += "," unless index == self.get_length + index = index + 1 + end + ret + end + + # 1 -based index + def get_internal_word(index) + @memory[index] + end + + # 1 -based index + def set_internal_word(index , value) + raise "Word[#{index}] = " if((self.class == Parfait::Word) and value.nil? ) + @memory[index] = value + value end alias :[] :get diff --git a/test/elf/test_zero.rb b/test/elf/test_zero.rb index 6d9d22fe..a2769974 100644 --- a/test/elf/test_zero.rb +++ b/test/elf/test_zero.rb @@ -4,7 +4,14 @@ class TestZeroCode < MiniTest::Test def test_string_put machine = Register.machine.boot - machine.collect + space = Parfait.object_space + space.each_type do | type | + type.method_names.each do |method| + type.remove_method(method) + end + end + assert_equal 0 , space.collect_methods.length + machine.collect_space machine.translate_arm # writer = Elf::ObjectWriter.new # writer.save "test/zero.o" diff --git a/test/typed/parfait/test_list.rb b/test/typed/parfait/test_list.rb index 36fa0180..06a9e2be 100644 --- a/test/typed/parfait/test_list.rb +++ b/test/typed/parfait/test_list.rb @@ -7,7 +7,6 @@ class TestList < MiniTest::Test end def test_isa assert @list.is_a? Parfait::List - assert @list.is_a? Parfait::Indexed end def test_old_type assert_equal Parfait::Type , Parfait.object_space.classes.keys.get_type.class