2018-06-29 13:36:11 +02:00
|
|
|
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
|
|
|
|
#
|
2019-09-22 18:10:47 +02:00
|
|
|
# And so we have a chicken and egg problem. At the end of the boot function we want
|
|
|
|
# to have a working Space object
|
2018-06-29 13:36:11 +02:00
|
|
|
# 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 :-))
|
|
|
|
|
|
|
|
|
2019-09-22 18:10:47 +02:00
|
|
|
# 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
|
2018-06-29 13:36:11 +02:00
|
|
|
end
|
|
|
|
|
2019-09-22 18:10:47 +02:00
|
|
|
def self.boot!(options)
|
2019-09-22 23:07:30 +02:00
|
|
|
Parfait::Object.set_object_space( nil ) #case of reboot
|
2019-09-22 18:10:47 +02:00
|
|
|
space = Space.new( )
|
|
|
|
type_names.each do |name , ivars |
|
|
|
|
ivars[:type] = :Type
|
|
|
|
instance_type = Type.new(name , ivars)
|
|
|
|
space.add_type instance_type
|
|
|
|
space.classes[name] = Class.new(name , nil , instance_type)
|
2018-06-29 13:36:11 +02:00
|
|
|
end
|
2019-09-22 18:10:47 +02:00
|
|
|
# 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)
|
2018-06-29 13:36:11 +02:00
|
|
|
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)
|
2019-09-22 18:10:47 +02:00
|
|
|
def self.fix_types
|
2019-09-22 23:07:30 +02:00
|
|
|
fix_object_type(Parfait.object_space)
|
2019-09-22 18:10:47 +02:00
|
|
|
classes = Parfait.object_space.classes
|
|
|
|
class_type = Parfait.object_space.get_type_by_class_name(:Class)
|
2019-09-22 23:07:30 +02:00
|
|
|
raise "nil type" unless class_type
|
2019-09-22 18:10:47 +02:00
|
|
|
types = Parfait.object_space.types
|
2019-09-22 23:07:30 +02:00
|
|
|
super_names = super_class_names
|
2019-09-22 18:10:47 +02:00
|
|
|
classes.each do |name , cl|
|
|
|
|
object_type = Parfait.object_space.get_type_by_class_name(name)
|
2019-09-22 23:07:30 +02:00
|
|
|
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 }
|
2018-06-29 13:36:11 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-09-22 23:07:30 +02:00
|
|
|
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
|
|
|
|
|
2018-06-29 13:36:11 +02:00
|
|
|
# superclasses other than default object
|
|
|
|
def self.super_class_names
|
2018-07-07 08:11:09 +02:00
|
|
|
{ Data4: :DataObject ,
|
|
|
|
Data8: :DataObject ,
|
|
|
|
Data16: :DataObject ,
|
2018-07-01 12:43:53 +02:00
|
|
|
Data32: :DataObject ,
|
2019-08-22 11:26:40 +02:00
|
|
|
BinaryCode: :Data32 ,
|
2018-07-07 08:11:09 +02:00
|
|
|
Integer: :Data4 ,
|
|
|
|
Word: :Data8 ,
|
|
|
|
List: :Data16 ,
|
|
|
|
CallableMethod: :Callable,
|
2018-07-07 14:50:43 +02:00
|
|
|
Block: :Callable,
|
2019-09-21 17:50:33 +02:00
|
|
|
Class: :Behaviour,
|
|
|
|
MetaClass: :Behaviour ,
|
2018-07-07 08:11:09 +02:00
|
|
|
ReturnAddress: :Integer}
|
2018-06-29 13:36:11 +02:00
|
|
|
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
|
2019-09-21 17:50:33 +02:00
|
|
|
{Behaviour: {instance_type: :Type , instance_methods: :List } ,
|
|
|
|
BinaryCode: {next_code: :BinaryCode} ,
|
2018-08-11 18:17:20 +02:00
|
|
|
Block: {binary: :BinaryCode, next_callable: :Block,
|
2018-07-30 09:21:43 +02:00
|
|
|
arguments_type: :Type , self_type: :Type, frame_type: :Type,
|
2018-08-12 12:10:44 +02:00
|
|
|
name: :Word , blocks: :Block } ,
|
2018-07-07 08:11:09 +02:00
|
|
|
CacheEntry: {cached_type: :Type , cached_method: :CallableMethod } ,
|
2018-08-11 18:17:20 +02:00
|
|
|
Callable: {binary: :BinaryCode,next_callable: :Callable ,
|
2018-07-30 09:21:43 +02:00
|
|
|
arguments_type: :Type , self_type: :Type, frame_type: :Type,
|
2018-08-12 12:10:44 +02:00
|
|
|
name: :Word , blocks: :Block } ,
|
2018-08-11 18:17:20 +02:00
|
|
|
CallableMethod: {binary: :BinaryCode, next_callable: :CallableMethod ,
|
2018-07-07 08:11:09 +02:00
|
|
|
arguments_type: :Type , self_type: :Type, frame_type: :Type ,
|
2018-07-27 09:48:45 +02:00
|
|
|
name: :Word , blocks: :Block} ,
|
2018-07-07 08:11:09 +02:00
|
|
|
Class: {instance_methods: :List, instance_type: :Type,
|
2019-02-16 22:24:16 +01:00
|
|
|
name: :Word, super_class_name: :Word , meta_class: :MetaClass},
|
2018-07-07 08:11:09 +02:00
|
|
|
DataObject: {},
|
|
|
|
Data4: {},
|
|
|
|
Data8: {},
|
|
|
|
Data16: {},
|
2019-08-22 16:54:17 +02:00
|
|
|
Data32: {},
|
2018-08-11 18:17:20 +02:00
|
|
|
Dictionary: {i_keys: :List , i_values: :List } ,
|
2018-07-07 08:11:09 +02:00
|
|
|
FalseClass: {},
|
2019-08-24 08:46:33 +02:00
|
|
|
Factory: { for_type: :Type , next_object: :Object , reserve: :Object ,
|
|
|
|
attribute_name: :Word , page_size: :Integer },
|
2019-07-28 15:42:40 +02:00
|
|
|
Integer: {next_integer: :Integer},
|
2018-07-07 08:11:09 +02:00
|
|
|
List: {indexed_length: :Integer , next_list: :List} ,
|
2019-09-18 21:07:05 +02:00
|
|
|
Message: { next_message: :Message, receiver: :Object, frame: :Object ,
|
2018-07-07 08:11:09 +02:00
|
|
|
return_address: :Integer, return_value: :Object,
|
2019-08-22 16:54:17 +02:00
|
|
|
caller: :Message , method: :TypedMethod ,
|
|
|
|
arguments_given: :Integer ,
|
2019-08-23 09:20:39 +02:00
|
|
|
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},
|
2019-02-16 22:24:16 +01:00
|
|
|
MetaClass: {instance_methods: :List, instance_type: :Type, clazz: :Class },
|
2018-07-07 08:11:09 +02:00
|
|
|
NilClass: {},
|
|
|
|
Object: {},
|
|
|
|
ReturnAddress: {next_integer: :ReturnAddress},
|
2018-08-24 17:49:21 +02:00
|
|
|
Space: {classes: :Dictionary , types: :Dictionary , factories: :Dictionary,
|
2018-07-07 08:11:09 +02:00
|
|
|
true_object: :TrueClass, false_object: :FalseClass , nil_object: :NilClass},
|
|
|
|
TrueClass: {},
|
|
|
|
Type: {names: :List , types: :List ,
|
|
|
|
object_class: :Class, methods: :CallableMethod } ,
|
|
|
|
VoolMethod: { name: :Word , args_type: :Type , frame_type: :Type } ,
|
|
|
|
Word: {char_length: :Integer , next_word: :Word} ,
|
2018-06-29 13:36:11 +02:00
|
|
|
}
|
|
|
|
end
|
2019-09-22 18:10:47 +02:00
|
|
|
|
2018-06-29 13:36:11 +02:00
|
|
|
end
|