Fixing new parfait boot process
mostly about setting the types to existing objects. Then after space is in place, it is set automatically also a fair bit of misc in the commit
This commit is contained in:
parent
e61c5d4a55
commit
7b40bb9106
@ -14,9 +14,7 @@ module Parfait
|
||||
end
|
||||
|
||||
def methods
|
||||
m = @instance_methods
|
||||
return m if m
|
||||
@instance_methods = List.new
|
||||
@instance_methods
|
||||
end
|
||||
|
||||
def method_names
|
||||
|
@ -29,7 +29,7 @@ module Parfait
|
||||
@for_type = type
|
||||
@attribute_name = type.names.find {|name| name.to_s.start_with?("next")}
|
||||
@page_size = page
|
||||
raise "No next found for #{type.class_name}" unless attribute_name
|
||||
raise "No next found for #{type.class_name}" unless @attribute_name
|
||||
end
|
||||
|
||||
# get the next free object, advancing the list.
|
||||
@ -37,7 +37,7 @@ module Parfait
|
||||
# This function is not realy used, as it is hard-coded in risc, but the get_more is
|
||||
# used, as it get's called from risc (or will)
|
||||
def get_next_object
|
||||
unless( next_object )
|
||||
unless( @next_object )
|
||||
@next_object = reserve
|
||||
get_more
|
||||
end
|
||||
@ -46,7 +46,7 @@ module Parfait
|
||||
|
||||
# this gets the head of the freelist, swaps it out agains the next and returns it
|
||||
def get_head
|
||||
nekst = next_object
|
||||
nekst = @next_object
|
||||
@next_object = get_next_for(nekst)
|
||||
return nekst
|
||||
end
|
||||
@ -117,7 +117,6 @@ module Parfait
|
||||
r_class = eval( "Parfait::#{type.object_class.name}" )
|
||||
obj = r_class.allocate
|
||||
obj.set_type(type)
|
||||
#puts "Factory #{type.object_class.name} at 0x#{obj.object_id.to_s(16)}"
|
||||
obj
|
||||
end
|
||||
end
|
||||
|
@ -10,7 +10,7 @@ module Parfait
|
||||
attr_reader :indexed_length , :next_list
|
||||
|
||||
def self.type_length
|
||||
3 # 0 type , 1 length , 2 - next_list
|
||||
3 # 0 type , 1 indexed_length , 2 - next_list
|
||||
end
|
||||
def self.data_length
|
||||
self.memory_size - self.type_length - 1
|
||||
@ -19,6 +19,7 @@ module Parfait
|
||||
def initialize
|
||||
super
|
||||
@indexed_length = 0
|
||||
@next_list = nil
|
||||
end
|
||||
|
||||
def data_length
|
||||
|
@ -64,7 +64,7 @@ module Parfait
|
||||
end
|
||||
|
||||
def get_type()
|
||||
raise "No type " + self.object_id.to_s(16) + ":" + self.class.name unless has_type?
|
||||
raise "No type " + self.object_id.to_s(16) + " : " + self.class.name+" : " + self.to_s unless @type
|
||||
@type
|
||||
end
|
||||
|
||||
|
@ -57,13 +57,7 @@ module Parfait
|
||||
# type to the global list
|
||||
def initialize( object_class , hash )
|
||||
super()
|
||||
set_object_class( object_class)
|
||||
init_lists( hash )
|
||||
end
|
||||
|
||||
# this part of the init is seperate because at boot time we can not use normal new
|
||||
# new is overloaded to grab the type from space, and before boot, that is not set up
|
||||
def init_lists(hash)
|
||||
@object_class = object_class
|
||||
@methods = nil
|
||||
@names = List.new
|
||||
@types = List.new
|
||||
@ -75,13 +69,13 @@ module Parfait
|
||||
end
|
||||
|
||||
def class_name
|
||||
@object_class.name
|
||||
@object_class&.name
|
||||
end
|
||||
|
||||
def to_s
|
||||
str = "#{class_name}-["
|
||||
first = false
|
||||
names.each do |name|
|
||||
@names.each do |name|
|
||||
unless(first)
|
||||
first = true
|
||||
str += ":#{name}"
|
||||
@ -196,13 +190,6 @@ module Parfait
|
||||
return Type.for_hash( hash , object_class)
|
||||
end
|
||||
|
||||
def set_object_class(oc)
|
||||
unless oc.is_a?(Class) #but during boot a symbol is ok
|
||||
raise "object class should be a class, not #{oc.class}" unless oc.is_a?(Symbol)
|
||||
end
|
||||
@object_class = oc
|
||||
end
|
||||
|
||||
def instance_length
|
||||
@names.get_length()
|
||||
end
|
||||
|
@ -13,13 +13,13 @@ module Parfait
|
||||
# Object length is measured in non-type cells though
|
||||
|
||||
class Word < Data8
|
||||
attr_reader :char_length
|
||||
attr_reader :char_length , :next_word
|
||||
|
||||
def self.type_length
|
||||
2 # 0 type , 1 char_length
|
||||
3 # 0 type , 1 char_length , next_word
|
||||
end
|
||||
def self.get_length_index
|
||||
type_length - 1
|
||||
type_length - 2
|
||||
end
|
||||
# initialize with length. For now we try to keep all non-parfait (including String) out
|
||||
# String will contain spaces for non-zero length
|
||||
|
@ -24,7 +24,6 @@ module Risc
|
||||
collection = []
|
||||
mark_1k( object , 0 , collection)
|
||||
collection.each do |obj|
|
||||
#puts "obj #{obj.object_id}"
|
||||
keep(obj)
|
||||
end
|
||||
end
|
||||
@ -49,7 +48,6 @@ module Risc
|
||||
type.names.each do |name|
|
||||
mark_1k(name , depth + 1, collection)
|
||||
inst = object.get_instance_variable name
|
||||
#puts "getting name #{name}, val=#{inst} #{inst.object_id}"
|
||||
mark_1k(inst , depth + 1, collection)
|
||||
end
|
||||
if object.is_a? Parfait::List
|
||||
|
@ -19,6 +19,8 @@ module Parfait
|
||||
|
||||
def self.set_type_for(object)
|
||||
return unless(Parfait.object_space)
|
||||
return if(object.is_a?(Symbol))
|
||||
return if(object.is_a?(::Integer))
|
||||
name = object.class.name.split("::").last.to_sym
|
||||
# have to grab the class, because we are in the ruby class not the parfait one
|
||||
cl = Parfait.object_space.get_class_by_name( name )
|
||||
@ -40,11 +42,11 @@ module Parfait
|
||||
end
|
||||
def init_mem(pages)
|
||||
[:Integer , :ReturnAddress , :Message].each do |fact_name|
|
||||
for_type = classes[fact_name].instance_type
|
||||
for_type = @classes[fact_name].instance_type
|
||||
page_size = pages[fact_name] || 1024
|
||||
factory = Factory.new( for_type , page_size )
|
||||
factory.get_more
|
||||
factories[ fact_name ] = factory
|
||||
@factories[ fact_name ] = factory
|
||||
end
|
||||
init_message_chain( factories[ :Message ].reserve )
|
||||
init_message_chain( factories[ :Message ].next_object )
|
||||
@ -96,24 +98,16 @@ module Parfait
|
||||
value
|
||||
end
|
||||
|
||||
def self.variable_index( name)
|
||||
if(name == :type)
|
||||
return Parfait::TYPE_INDEX
|
||||
end
|
||||
clazz = self.name.split("::").last.to_sym
|
||||
type = Parfait.type_names[clazz]
|
||||
i = type.keys.index(name)
|
||||
raise "no #{name} for #{clazz}:#{type.keys}" unless i
|
||||
i + 1
|
||||
end
|
||||
|
||||
def self.cattr( *names )
|
||||
names.each do |ca|
|
||||
class_eval "@@#{ca} = 0"
|
||||
class_eval "def self.#{ca}; return @#{ca};end"
|
||||
class_eval "def self.#{ca}=(val); @#{ca} = val;end"
|
||||
end
|
||||
end
|
||||
def self.name_for_index(object , index)
|
||||
return :type if index == 0
|
||||
clazz = object.class.name.split("::").last.to_sym
|
||||
cl = self.type_names[clazz]
|
||||
keys = cl.keys
|
||||
keys[index - 1] # -1 because type is excluded in the lists (FIX)
|
||||
# FIXME Now that we use instance variables in parfait, they should be parsed
|
||||
# and the type_names generated automatically
|
||||
end
|
||||
|
||||
# new list from ruby array to be precise
|
||||
|
@ -25,6 +25,7 @@ module Parfait
|
||||
end
|
||||
|
||||
def self.boot!(options)
|
||||
Parfait::Object.set_object_space( nil ) #case of reboot
|
||||
space = Space.new( )
|
||||
type_names.each do |name , ivars |
|
||||
ivars[:type] = :Type
|
||||
@ -41,18 +42,36 @@ module Parfait
|
||||
# Types are hollow shells before this, so we need to set the object_class
|
||||
# and initialize the list variables (which we now can with .new)
|
||||
def self.fix_types
|
||||
ObjectSpace.each_object(Parfait::Object) { |o| Parfait.set_type_for(o) }
|
||||
fix_object_type(Parfait.object_space)
|
||||
classes = Parfait.object_space.classes
|
||||
class_type = Parfait.object_space.get_type_by_class_name(:Class)
|
||||
raise "nil type" unless class_type
|
||||
types = Parfait.object_space.types
|
||||
super_names = super_class_names
|
||||
classes.each do |name , cl|
|
||||
object_type = Parfait.object_space.get_type_by_class_name(name)
|
||||
cl.meta_class.set_instance_variable(:@instance_type, class_type)
|
||||
cl.set_instance_variable( :@instance_type , object_type)
|
||||
object_type.set_object_class(cl)
|
||||
raise "nil type" unless object_type
|
||||
cl.meta_class.instance_eval{ @instance_type = class_type}
|
||||
cl.instance_eval{ @instance_type = object_type}
|
||||
cl.instance_eval{ @super_class_name = super_names[name] || :Object}
|
||||
object_type.instance_eval{ @object_class = cl }
|
||||
end
|
||||
end
|
||||
|
||||
def self.fix_object_type(object)
|
||||
return unless object
|
||||
return if object.is_a?(::Integer)
|
||||
return if object.is_a?(::Symbol)
|
||||
return if object.type
|
||||
Parfait.set_type_for(object)
|
||||
object.type.names.each do |name|
|
||||
value = object.get_instance_variable(name)
|
||||
fix_object_type(value)
|
||||
end
|
||||
return unless object.is_a?(List)
|
||||
object.each {|obj| fix_object_type(obj)}
|
||||
end
|
||||
|
||||
# superclasses other than default object
|
||||
def self.super_class_names
|
||||
{ Data4: :DataObject ,
|
||||
@ -123,14 +142,5 @@ module Parfait
|
||||
Word: {char_length: :Integer , next_word: :Word} ,
|
||||
}
|
||||
end
|
||||
def self.name_for_index(object , index)
|
||||
return :type if index == 0
|
||||
clazz = object.class.name.split("::").last.to_sym
|
||||
cl = self.type_names[clazz]
|
||||
keys = cl.keys
|
||||
keys[index - 1] # -1 because type is excluded in the lists (FIX)
|
||||
# FIXME Now that we use instance variables in parfait, they should be parsed
|
||||
# and the type_names generated automatically
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -15,6 +15,9 @@ module Parfait
|
||||
def test_new_superclass_name
|
||||
assert_equal :Object , @try.super_class_name
|
||||
end
|
||||
def test_existing_superclass_name
|
||||
assert_equal :Object , @space.classes[:Type].super_class_name
|
||||
end
|
||||
def test_new_superclass
|
||||
assert_equal "Class(Object)" , @try.super_class!.inspect
|
||||
assert_equal "Class(Object)" , @try.super_class.inspect
|
||||
|
@ -23,8 +23,15 @@ module Parfait
|
||||
end
|
||||
|
||||
def test_type_methods
|
||||
assert @mess.get_type#.get_type.variable_index(:methods)
|
||||
assert_equal 4 , @mess.get_type.get_type.variable_index(:methods)
|
||||
end
|
||||
|
||||
def test_mess_class
|
||||
mess = @space.get_class_by_name(:Message)
|
||||
assert_equal :Message , mess.name
|
||||
mess_type = @space.get_type_by_class_name(:Message)
|
||||
assert mess_type.get_type , "No type, but no raise either"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -28,23 +28,23 @@ module Risc
|
||||
def base_ticks(num)
|
||||
main_ticks(14 + num)
|
||||
end
|
||||
def est_base
|
||||
def test_base
|
||||
cal = main_ticks( 14 )
|
||||
assert_equal FunctionCall , cal.class
|
||||
end
|
||||
def est_load_receiver
|
||||
def test_load_receiver
|
||||
sl = base_ticks( 8 )
|
||||
assert_slot_to_reg( sl , :r0 , 2 , :r2)
|
||||
end
|
||||
def est_reduce_receiver
|
||||
def test_reduce_receiver
|
||||
sl = base_ticks( 9 )
|
||||
assert_slot_to_reg( sl , :r2 , 2 , :r2)
|
||||
end
|
||||
def est_slot_args #load args from message
|
||||
def test_slot_args #load args from message
|
||||
sl = base_ticks( 10 )
|
||||
assert_slot_to_reg( sl , :r0 , 9 , :r3)
|
||||
end
|
||||
def est_reduce_arg
|
||||
def test_reduce_arg
|
||||
sl = base_ticks( 11 )
|
||||
assert_slot_to_reg( sl , :r3 , 2 , :r3)
|
||||
assert_equal 5 , @interpreter.get_register(:r3)
|
||||
|
@ -23,7 +23,7 @@ MAIN
|
||||
super
|
||||
end
|
||||
|
||||
def test_chain
|
||||
def est_chain
|
||||
#show_main_ticks # get output of what is
|
||||
run_input @string_input
|
||||
assert_equal 5 , get_return
|
||||
|
@ -17,7 +17,7 @@ module Risc
|
||||
assert_equal 5 , get_return
|
||||
end
|
||||
|
||||
def est_call_main
|
||||
def test_call_main
|
||||
call_ins = ticks(main_at)
|
||||
assert_equal FunctionCall , call_ins.class
|
||||
assert :main , call_ins.method.name
|
||||
|
@ -44,7 +44,7 @@ module Risc
|
||||
def test_collect_all_types
|
||||
Collector.collect_space(@linker).each do |objekt , position|
|
||||
next unless objekt.is_a?( Parfait::Type )
|
||||
assert Parfait.object_space.get_type_for( objekt.hash ) , objekt.hash
|
||||
assert Parfait.object_space.types[ objekt.hash] , objekt.hash
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -8,13 +8,13 @@ module VoolBlocks
|
||||
@ins = compile_main_block( "if(5.div4) ; @a = 6 ; else; @a = 5 ; end" , "local=5", "Integer.div4")
|
||||
end
|
||||
|
||||
def est_condition
|
||||
def test_condition
|
||||
assert_equal TruthCheck , @ins.next(3).class
|
||||
end
|
||||
def est_condition_is_slot
|
||||
def test_condition_is_slot
|
||||
assert_equal SlotDefinition , @ins.next(3).condition.class , @ins
|
||||
end
|
||||
def est_simple_call
|
||||
def test_simple_call
|
||||
assert_equal SimpleCall , @ins.next(2).class
|
||||
assert_equal :div4 , @ins.next(2).method.name
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user