diff --git a/lib/parfait/indexed.rb b/lib/parfait/indexed.rb index cf6ecb4f..310e4131 100644 --- a/lib/parfait/indexed.rb +++ b/lib/parfait/indexed.rb @@ -8,159 +8,167 @@ # # Using ruby include does not work for similar reasons, so Indexed.at is the main # function that generates the methods + # ( do have to use a marker module so we can test with is_a?) -module Indexed - - def self.at( offset , clazz ) - - clazz.send :define_method , :get_length do - internal_object_length - 1 +module Parfait + module Indexed # marker module + def self.included(base) + base.extend(Methods) end - # index of item, remeber first item has index 1 - # return nil if no such item - clazz.send :define_method , :index_of do |item| - max = self.get_length - counter = 1 - while( counter <= max ) - if( get(counter) == item) - return counter + module Methods + def offset( offset ) + + define_method :get_length do + internal_object_length - 1 end - counter = counter + 1 - end - return nil - end - # include? means non nil index - clazz.send :define_method , :include? do |item| - return index_of(item) != nil - end + # index of item, remeber first item has index 1 + # return nil if no such item + define_method :index_of do |item| + max = self.get_length + 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 - clazz.send :define_method , :push do |value| - set( self.get_length + 1 , value) - end + # include? means non nil index + define_method :include? do |item| + return index_of(item) != nil + end - clazz.send :define_method , :delete do |value| - index = index_of value - return false unless index - delete_at index - end + # push means add to the end + # this automatically grows the List + define_method :push do |value| + set( self.get_length + 1 , value) + end - clazz.send :define_method , :delete_at do |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 + define_method :delete do |value| + index = index_of value + return false unless index + delete_at index + end + + define_method :delete_at do |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 - clazz.send :define_method , :first do - return nil if empty? - get(1) - end + define_method :first do + return nil if empty? + get(1) + end - clazz.send :define_method , :last do - return nil if empty? - get(get_length()) - end + define_method :last do + return nil if empty? + get(get_length()) + end - # set the value at index. - # Lists start from index 1 - clazz.send :define_method , :set do | index , value| - raise "Only positive indexes #{index}" if index <= 0 - if index > self.get_length - grow_to(index) - end - # internally 1 is reserved for the layout - internal_object_set( index + 1, value) - 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 + # internally 1 is reserved for the layout + internal_object_set( index + 1, 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 + if index > self.get_length + return nil + else + return internal_object_get(index + 1) + end + end + + define_method :empty? do + self.get_length == 0 + end + + define_method :set_length do | len| + was = self.get_length + return if was == len + if(was < len) + grow_to len + else + shrink_to len + end + 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 + internal_object_grow(len + 1) + 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 + internal_object_shrink(len + 1) + end + + define_method :equal? do | 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 + define_method :== do | 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 layout + # 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 + define_method :word_length do + padded_words( get_layout().get_length() + get_length() ) + end + + define_method :inspect do + inspect_from 1 + end + + define_method :inspect_from do |index| + ret = "" + while index <= self.get_length + item = get(index) + ret += item.inspect + ret += "," unless index == self.get_length + index = index + 1 + end + ret + end - # set the value at index. - # Lists start from index 1 - clazz.send :define_method , :get do | index| - raise "Only positive indexes, #{index}" if index <= 0 - if index > self.get_length - return nil - else - return internal_object_get(index + 1) end end - - clazz.send :define_method , :empty? do - self.get_length == 0 - end - - clazz.send :define_method , :set_length do | len| - was = self.get_length - return if was == len - if(was < len) - grow_to len - else - shrink_to len - end - end - - clazz.send :define_method , :grow_to do | len| - raise "Only positive lenths, #{len}" if len < 0 - old_length = self.get_length - return if old_length >= len - internal_object_grow(len + 1) - end - - clazz.send :define_method , :shrink_to do | len| - raise "Only positive lenths, #{len}" if len < 0 - old_length = self.get_length - return if old_length <= len - internal_object_shrink(len + 1) - end - - clazz.send :define_method , :equal? do | 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 - clazz.send :define_method , :== do | 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 layout - # 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 - clazz.send :define_method , :word_length do - padded_words( get_layout().get_length() + get_length() ) - end - - clazz.send :define_method , :inspect do - inspect_from 1 - end - - clazz.send :define_method , :inspect_from do |index| - ret = "" - while index <= self.get_length - item = get(index) - ret += item.inspect - ret += "," unless index == self.get_length - index = index + 1 - end - ret - end - end end diff --git a/lib/parfait/layout.rb b/lib/parfait/layout.rb index 91977eec..188658fc 100644 --- a/lib/parfait/layout.rb +++ b/lib/parfait/layout.rb @@ -21,7 +21,22 @@ # Together they turn the object into a hash like structure module Parfait - class Layout < List + class Layout < Object + include Indexed + self.offset(0) + + def each + # not sure how to do this with define_method, because of the double block issue. + # probably some clever way around that, but not important + index = 1 + while index <= self.get_length + item = get(index) + yield item + index = index + 1 + end + self + end + attribute :object_class def initialize( object_class ) diff --git a/lib/parfait/list.rb b/lib/parfait/list.rb index c7854d60..c93c78ec 100644 --- a/lib/parfait/list.rb +++ b/lib/parfait/list.rb @@ -14,7 +14,8 @@ require_relative "indexed" module Parfait class List < Object - Indexed.at(0 , self) + include Indexed + self.offset(0) def initialize( ) super() diff --git a/lib/register/assembler.rb b/lib/register/assembler.rb index 73a3a159..5552d094 100644 --- a/lib/register/assembler.rb +++ b/lib/register/assembler.rb @@ -168,7 +168,7 @@ module Register end #puts "layout length=#{layout.get_length.to_s(16)} mem_len=#{layout.word_length.to_s(16)}" l = layout.get_length - if( object.is_a? Parfait::List) + if( object.is_a? Parfait::Indexed) object.each do |inst| write_ref_for(inst) end diff --git a/lib/register/collector.rb b/lib/register/collector.rb index 1d13e689..7ce49329 100644 --- a/lib/register/collector.rb +++ b/lib/register/collector.rb @@ -27,7 +27,7 @@ module Register inst = object.get_instance_variable name keep(inst , depth + 1) end - if object.is_a? Parfait::List + if object.is_a? Parfait::Indexed object.each do |item| #puts "Keep item " keep(item , depth + 1) diff --git a/test/parfait/test_list.rb b/test/parfait/test_list.rb index e020f36f..adc3d51d 100644 --- a/test/parfait/test_list.rb +++ b/test/parfait/test_list.rb @@ -6,6 +6,10 @@ class TestList < MiniTest::Test Register.machine.boot unless Register.machine.booted @list = ::Parfait::List.new end + def test_isa + assert @list.is_a? Parfait::List + assert @list.is_a? Parfait::Indexed + end def test_old_layout assert_equal Parfait::Layout , Register.machine.space.classes.keys.get_layout.class end