externalize boot process

Booting is complicated, make an own file for it
This commit is contained in:
Torsten Ruger 2015-05-19 20:29:33 +03:00
parent 4e3640e432
commit 8ec8a519ba
5 changed files with 122 additions and 82 deletions

View File

@ -17,8 +17,13 @@ module Parfait
def initialize name , super_class = nil
super( name , super_class)
# class methods
@object_layout = Layout.new_object
# the layout for this class (class = object of type Class) carries the class
# as an instance. The relation is from an object through the Layout to it's class
@object_layout = Layout.new_object(self)
end
def allocate_object
#space, and ruby allocate
end
def add_instance_name name

View File

@ -23,19 +23,24 @@
module Parfait
class Layout < List
# set the names of the instance variables in one go
# used while booting the classes. At runtime the list would grow dynamically
def set_names list
self.set_length list.get_length
index = 0
while index < list.get_length do
list.set(index , array.get(index))
end
def initialize( object_class )
@object_class = object_class
end
# add the name of an instance variable
# The index will be returned and can subsequently be searched with index_of
# The index of the name is the index of the data in the object
#
# TODO , later we would need to COPY the layout to keep the old constant
# but now we are concerned with booting, ie getting a working structure
def add_instance_name name
self.push(name)
self.get_length
end
# beat the recursion! fixed known offset for class object in the layout
def get_object_class()
return internal_object_get(CLASS_INDEX)
return @object_class
end
end
end

View File

@ -32,6 +32,7 @@ module Parfait
@messages = 100.times.collect{ ::Parfait::Message.new }
@next_message = @messages.first
@next_frame = @frames.first
Parfait::Space.set_object_space self
end
attr_reader :classes , :objects , :symbols,:messages, :next_message , :next_frame
@ -41,6 +42,16 @@ module Parfait
@@SPACE
end
@@object_space = nil
# Make the object space globally available
def self.object_space
@@object_space
end
# TODO Must get rid of the setter
def self.set_object_space space
@@space = space
end
# Objects are data and get assembled after functions
def add_object o
return if @objects.include?(o)

86
lib/virtual/boot.rb Normal file
View File

@ -0,0 +1,86 @@
module Virtual
class Machine
# 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 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 salama, a Layout, that points to a class.
# So we need a Layout, but that has Layout 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)
def boot_parfait!
@space = Parfait::Space.new_object
object_class = Parfait::Class.new_object "Parfait::Object"
space_class = Parfait::Class.new_object "Parfait::Space" , object_class
space_layout = Parfait::Layout.new_object space_class
puts "Space #{space.get_layout}"
end
def boot_classes!
puts "BOOT"
values = [ "Integer" , "Object" , "Value" , "Kernel"]
rest = ["Word" , "Class" , "Dictionary" , "Space" , "List", "Layout"]
(values + rest).each { |cl| @space.create_class(cl) }
value_class = @space.get_class_by_name "Value"
@space.get_class_by_name("Integer").set_super_class( value_class )
object_class = @space.get_class_by_name("Object")
object_class.set_super_class( value_class )
rest.each do |name|
cl = @space.get_class_by_name( name )
cl.set_super_class(object_class)
end
boot_layouts!
end
def boot_layouts!
end
# boot the classes, ie create a minimal set of classes with a minimal set of functions
# minimal means only that which can not be coded in ruby
# CompiledMethods are grabbed from respective modules by sending the method name. This should return the
# implementation of the method (ie a method object), not actually try to implement it (as that's impossible in ruby)
def boot_functions!
@space = Parfait::Space.new
boot_classes!
# very fiddly chicken 'n egg problem. Functions need to be in the right order, and in fact we
# have to define some dummies, just for the other to compile
# TODO: go through the virtual parfait layer and adjust function names to what they really are
obj = @space.get_class_by_name "Object"
[:index_of , :_get_instance_variable , :_set_instance_variable].each do |f|
obj.add_instance_method Builtin::Object.send(f , nil)
end
obj = @space.get_class_by_name "Kernel"
# create main first, __init__ calls it
@main = Builtin::Kernel.send(:main , @context)
obj.add_instance_method @main
underscore_init = Builtin::Kernel.send(:__init__ ,nil) #store , so we don't have to resolve it below
obj.add_instance_method underscore_init
[:putstring,:exit,:__send].each do |f|
obj.add_instance_method Builtin::Kernel.send(f , nil)
end
# and the @init block in turn _jumps_ to __init__
# the point of which is that by the time main executes, all is "normal"
@init = Block.new(:_init_ , nil )
@init.add_code(Register::RegisterMain.new(underscore_init))
obj = @space.get_class_by_name "Integer"
[:putint,:fibo].each do |f|
obj.add_instance_method Builtin::Integer.send(f , nil)
end
obj = @space.get_class_by_name "Word"
[:get , :set , :puts].each do |f|
obj.add_instance_method Builtin::Word.send(f , nil)
end
obj = space.get_class_by_name "List"
[:get , :set , :push].each do |f|
obj.add_instance_method Builtin::Array.send(f , nil)
end
end
end
end

View File

@ -36,7 +36,6 @@ module Virtual
@parser = Parser::Salama.new
#the_end = Halt.new
@passes = [ "Virtual::SendImplementation" ]
@space = Parfait::Space.new
# @message = Message.new(the_end , the_end , "Object" )
end
attr_reader :message , :passes , :space , :init , :main
@ -77,8 +76,8 @@ module Virtual
def self.boot
instance = self.instance
instance.boot_parfait! # boot is a verb here
instance.boot
# boot is a verb here. this is a somewhat tricky process which is in it's own file, boot.rb
instance.boot_parfait!
instance
end
def self.instance
@ -91,73 +90,6 @@ module Virtual
@instance = nil
self.boot
end
# boot the classes, ie create a minimal set of classes with a minimal set of functions
# minimal means only that which can not be coded in ruby
# CompiledMethods are grabbed from respective modules by sending the method name. This should return the
# implementation of the method (ie a method object), not actually try to implement it (as that's impossible in ruby)
def boot_parfait!
boot_classes!
# very fiddly chicken 'n egg problem. Functions need to be in the right order, and in fact we
# have to define some dummies, just for the other to compile
# TODO: go through the virtual parfait layer and adjust function names to what they really are
obj = @space.get_class_by_name "Object"
[:index_of , :_get_instance_variable , :_set_instance_variable].each do |f|
obj.add_instance_method Builtin::Object.send(f , nil)
end
obj = @space.get_class_by_name "Kernel"
# create main first, __init__ calls it
@main = Builtin::Kernel.send(:main , @context)
obj.add_instance_method @main
underscore_init = Builtin::Kernel.send(:__init__ ,nil) #store , so we don't have to resolve it below
obj.add_instance_method underscore_init
[:putstring,:exit,:__send].each do |f|
obj.add_instance_method Builtin::Kernel.send(f , nil)
end
# and the @init block in turn _jumps_ to __init__
# the point of which is that by the time main executes, all is "normal"
@init = Block.new(:_init_ , nil )
@init.add_code(Register::RegisterMain.new(underscore_init))
obj = @space.get_class_by_name "Integer"
[:putint,:fibo].each do |f|
obj.add_instance_method Builtin::Integer.send(f , nil)
end
obj = @space.get_class_by_name "Word"
[:get , :set , :puts].each do |f|
obj.add_instance_method Builtin::Word.send(f , nil)
end
obj = space.get_class_by_name "List"
[:get , :set , :push].each do |f|
obj.add_instance_method Builtin::Array.send(f , nil)
end
end
def boot_classes!
values = [ "Integer" , "Object" , "Value" , "Kernel"]
rest = ["Word" , "Class" , "Dictionary" , "Space" , "List", "Layout"]
(values + rest).each { |cl| @space.create_class(cl) }
value_class = @space.get_class_by_name "Value"
@space.get_class_by_name("Integer").set_super_class( value_class )
object_class = @space.get_class_by_name("Object")
object_class.set_super_class( value_class )
rest.each do |name|
cl = @space.get_class_by_name( name )
cl.set_super_class(object_class)
end
boot_layouts!
end
def boot_layouts!
end
def boot
# read all the files needed for a minimal system at compile
classes = ["object"]
classes.each do |clazz|
bytes = File.read(File.join( File.dirname( __FILE__ ) , ".." , "parfait" , "#{clazz}.rb") )
bytes = 0 #shuts up my atom linter
# expression = compile_main(bytes)
end
end
def compile_main bytes
syntax = @parser.parse_with_debug(bytes)
parts = Parser::Transform.new.apply(syntax)
@ -165,5 +97,6 @@ module Virtual
Compiler.compile( parts , main )
end
end
end
require_relative "boot"