Torsten Rüger
2dcb2a9a72
Just for future, as this gives us a way to know immediately in the type, which represent normal, and which singleton classes Also instantiate singleton class lazily (with singleton type) This makes the type of class single, ie unique, immediately when it is used, ie methods or variables defined. Fixes a design mistake, where all singletonn classes shared the same type, and thus unique methods per class were impossible (Also some misc in commit)
150 lines
6.3 KiB
Ruby
150 lines
6.3 KiB
Ruby
module Parfait
|
|
|
|
# The general idea is that compiling is creating an object graph. Functionally
|
|
# one tends to think of methods, and that is complicated enough, sure.
|
|
# But for an object system the graph includes classes and all instance variables
|
|
#
|
|
# And so we have a chicken and egg problem. At the end of the boot function we want
|
|
# to have a working Space object
|
|
# But that has instance variables (List and Dictionary) and off course a class.
|
|
# Or more precisely in rubyx, a Type, that points to a class.
|
|
# So we need a Type, but that has Type and Class too. hmmm
|
|
#
|
|
# The way out is to build empty shell objects and stuff the neccessary data into them
|
|
# (not use the normal initialize way)
|
|
# (PPS: The "real" solution is to read a rx-file graph and not do this by hand
|
|
# That graph can be programatically built and written (with this to boot that process :-))
|
|
|
|
|
|
# temporary shorthand getter for the space
|
|
# See implementation, space is now moved to inside the Object class
|
|
# (not module anymore), but there is a lot of code (about 100, 50/50 li/test)
|
|
# still calling this old version and since it is shorter . . .
|
|
def self.object_space
|
|
Object.object_space
|
|
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
|
|
instance_type = Type.new(name , ivars , 0)
|
|
space.add_type instance_type
|
|
space.classes[name] = Class.new(name , nil , instance_type)
|
|
end
|
|
# cant set it before or new will try to take types from it
|
|
Parfait::Object.set_object_space( space )
|
|
fix_types
|
|
space.init_mem(options)
|
|
end
|
|
|
|
# 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
|
|
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)
|
|
raise "nil type" unless object_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 ,
|
|
Data8: :DataObject ,
|
|
Data16: :DataObject ,
|
|
Data32: :DataObject ,
|
|
BinaryCode: :Data32 ,
|
|
TrueClass: :Data4 ,
|
|
FalseClass: :Data4 ,
|
|
NilClass: :Data4 ,
|
|
Integer: :Data4 ,
|
|
Word: :Data8 ,
|
|
List: :Data16 ,
|
|
CallableMethod: :Callable,
|
|
Block: :Callable,
|
|
Class: :Behaviour,
|
|
SingletonClass: :Behaviour ,
|
|
ReturnAddress: :Integer}
|
|
end
|
|
|
|
# the function really just returns a constant (just avoiding the constant)
|
|
# 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
|
|
{Behaviour: {instance_type: :Type , instance_methods: :List } ,
|
|
BinaryCode: {next_code: :BinaryCode} ,
|
|
Block: {binary: :BinaryCode, next_callable: :Block,
|
|
arguments_type: :Type , self_type: :Type, frame_type: :Type,
|
|
name: :Word , blocks: :Block } ,
|
|
CacheEntry: {cached_type: :Type , cached_method: :CallableMethod } ,
|
|
Callable: {binary: :BinaryCode,next_callable: :Callable ,
|
|
arguments_type: :Type , self_type: :Type, frame_type: :Type,
|
|
name: :Word , blocks: :Block } ,
|
|
CallableMethod: {binary: :BinaryCode, next_callable: :CallableMethod ,
|
|
arguments_type: :Type , self_type: :Type, frame_type: :Type ,
|
|
name: :Word , blocks: :Block} ,
|
|
Class: {instance_methods: :List, instance_type: :Type,
|
|
name: :Word, super_class_name: :Word , single_class: :SingletonClass},
|
|
DataObject: {},
|
|
Data4: {},
|
|
Data8: {},
|
|
Data16: {},
|
|
Data32: {},
|
|
Dictionary: {i_keys: :List , i_values: :List } ,
|
|
FalseClass: {},
|
|
Factory: { for_type: :Type , next_object: :Object , reserve: :Object ,
|
|
attribute_name: :Word , page_size: :Integer },
|
|
Integer: {next_integer: :Integer},
|
|
List: {indexed_length: :Integer , next_list: :List} ,
|
|
Message: { next_message: :Message, receiver: :Object, frame: :Object ,
|
|
return_address: :Integer, return_value: :Object,
|
|
caller: :Message , method: :TypedMethod ,
|
|
arguments_given: :Integer ,
|
|
arg1: :Object , arg2: :Object, arg3: :Object,
|
|
arg4: :Object, arg5: :Object, arg6: :Object,
|
|
locals_used: :Integer,
|
|
local1: :Object , local2: :Object, local3: :Object, local4: :Object,
|
|
local5: :Object, local6: :Object ,local7: :Object, local8: :Object ,
|
|
local9: :Object ,local10: :Object, local11: :Object , local12: :Object,
|
|
local13: :Object, local14: :Object, local15: :Object},
|
|
SingletonClass: {instance_methods: :List, instance_type: :Type, clazz: :Class },
|
|
NilClass: {},
|
|
Object: {},
|
|
ReturnAddress: {next_integer: :ReturnAddress},
|
|
Space: {classes: :Dictionary , types: :Dictionary , factories: :Dictionary,
|
|
true_object: :TrueClass, false_object: :FalseClass , nil_object: :NilClass},
|
|
TrueClass: {},
|
|
Type: {names: :List , types: :List ,
|
|
object_class: :Class, methods: :CallableMethod ,
|
|
is_single: :Object} ,
|
|
VoolMethod: { name: :Word , args_type: :Type , frame_type: :Type } ,
|
|
Word: {char_length: :Integer , next_word: :Word} ,
|
|
}
|
|
end
|
|
|
|
end
|