diff --git a/Gemfile b/Gemfile index 5a4f041e..bb452ad5 100644 --- a/Gemfile +++ b/Gemfile @@ -6,6 +6,7 @@ gem "rake" gem "salama-reader" , :github => "salama/salama-reader" gem "salama-object-file" , :github => "salama/salama-object-file" +#gem "salama-object-file" , :path => "../salama-object-file" gem "salama-arm" , :github => "salama/salama-arm" gem "codeclimate-test-reporter", require: nil diff --git a/Gemfile.lock b/Gemfile.lock index 29d2a634..affd8107 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,7 +6,7 @@ GIT GIT remote: git://github.com/salama/salama-object-file.git - revision: 9e49f2e725dbad48edc151419882b159505b2e9b + revision: fbae6a02764dbe97e01e4833f9ffffe09879b100 specs: salama-object-file (0.2.0) @@ -56,3 +56,6 @@ DEPENDENCIES salama-arm! salama-object-file! salama-reader! + +BUNDLED WITH + 1.10.5 diff --git a/lib/parfait/binary_code.rb b/lib/parfait/binary_code.rb index cf66f7e9..cfd4d0d9 100644 --- a/lib/parfait/binary_code.rb +++ b/lib/parfait/binary_code.rb @@ -12,9 +12,9 @@ module Parfait class BinaryCode < Word def initialize name super(0) - @name = name + self.name = name end - attr_reader :name + attribute :name # this is a sof check if there are instance variables or "structure" # have to override false, as word answers true @@ -22,7 +22,7 @@ module Parfait false end def to_s - "BinaryCode #{@name}" + "BinaryCode #{self.name}" end def == other diff --git a/lib/parfait/class.rb b/lib/parfait/class.rb index 1ba75505..993840cf 100644 --- a/lib/parfait/class.rb +++ b/lib/parfait/class.rb @@ -14,16 +14,13 @@ require_relative "meta_class" module Parfait class Class < Module + attribute :object_layout def initialize name , super_class super( name , super_class) # 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(self) - end - - def object_layout - @object_layout + self.object_layout = Layout.new(self) end def allocate_object @@ -31,7 +28,7 @@ module Parfait end def add_instance_name name - @object_layout.push name + self.object_layout.push name end def sof_reference_name diff --git a/lib/parfait/dictionary.rb b/lib/parfait/dictionary.rb index ee2edea9..a26e32b0 100644 --- a/lib/parfait/dictionary.rb +++ b/lib/parfait/dictionary.rb @@ -2,35 +2,25 @@ module Parfait class Dictionary < Object + attribute :keys + attribute :values # only empty initialization for now # # internally we store keys and values in lists, which means this does **not** scale well def initialize super() - @keys = List.new() - @values = List.new() - end - - # return all values as a list - # TODO, list should be copied to avoid inconcisencies - def values() - @values - end - - # return all keys as a list - # TODO, list should be copied to avoid inconcisencies - def keys() - @keys + self.keys = List.new() + self.values = List.new() end # are there any key/value items in the list def empty? - @keys.empty? + self.keys.empty? end # How many key/value pairs there are def length() - return @keys.get_length() + return self.keys.get_length() end # get a value fot the given key @@ -39,7 +29,7 @@ module Parfait def get(key) index = key_index(key) if( index ) - @values.get(index) + self.values.get(index) else nil end @@ -52,11 +42,11 @@ module Parfait # private method def key_index(key) - len = @keys.get_length() + len = self.keys.get_length() index = 1 found = nil while(index <= len) - if( @keys.get(index) == key) + if( self.keys.get(index) == key) found = index break end @@ -69,10 +59,10 @@ module Parfait def set(key , value) index = key_index(key) if( index ) - @keys.set(index , value) + self.keys.set(index , value) else - @keys.push(key) - @values.push(value) + self.keys.push(key) + self.values.push(value) end value end @@ -85,9 +75,9 @@ module Parfait # yield to each key value pair def each index = 1 - while index <= @keys.get_length - key = @keys.get(index) - value = @values.get(index) + while index <= self.keys.get_length + key = self.keys.get(index) + value = self.values.get(index) yield key , value index = index + 1 end diff --git a/lib/parfait/layout.rb b/lib/parfait/layout.rb index 3054dbb6..5f488e6e 100644 --- a/lib/parfait/layout.rb +++ b/lib/parfait/layout.rb @@ -22,10 +22,11 @@ module Parfait class Layout < List + attribute :object_class def initialize( object_class ) super() - @object_class = object_class + self.object_class = object_class end def == other @@ -45,23 +46,30 @@ module Parfait # beat the recursion! fixed known offset for class object in the layout def get_object_class() - return @object_class + return self.object_class end def object_instance_names names = List.new - index = 1 + index = 2 # first is object_class while index <= self.get_length item = get(index) names.push item index = index + 1 end - self - names end + + # index of a variable name into the layout. + # layout is a list, so lowest index is 1 + # :layout is a variable for every object, so 1 is taken for :layout + # still, the index is the same. + def variable_index name + index_of(name) + end + def sof_reference_name - "#{@object_class.name}_Layout" + "#{self.object_class.name}_Layout" end end diff --git a/lib/parfait/message.rb b/lib/parfait/message.rb index 299ab103..611019d1 100644 --- a/lib/parfait/message.rb +++ b/lib/parfait/message.rb @@ -9,18 +9,19 @@ module Parfait class Message < Object + attributes [:next_message , :frame, :caller] + attributes [:receiver , :return_address , :return_value , :name] + def initialize next_m - @next_message = next_m - @frame = Frame.new() - @caller = nil + self.next_message = next_m + self.frame = Frame.new() + self.caller = nil super() end - attr_reader :next_message , :frame , :caller # aka prev_message - attr_reader :receiver , :return_address , :return_value , :name def set_caller caller - @caller = caller + self.caller = caller end def get_type_for(name) diff --git a/lib/parfait/meta_class.rb b/lib/parfait/meta_class.rb index 6f07d5d2..070b7c01 100644 --- a/lib/parfait/meta_class.rb +++ b/lib/parfait/meta_class.rb @@ -18,26 +18,26 @@ module Parfait def initialize(object) super() - @functions = [] - @me_self = object + self.functions = [] + self.me_self = object end # in a non-booting version this should map to _add_singleton_method def add_function function raise "not a function #{function}" unless function.is_a? Virtual::Function raise "syserr " unless function.name.is_a? Symbol - @functions << function + self.functions << function end def get_function name name = name.to_sym - f = @functions.detect{ |f| f.name == name } + f = self.functions.detect{ |f| f.name == name } return f if f - if( @me_self == "Object" ) - puts "no function for :#{name} in Meta #{@me_self.inspect}" + if( self.me_self == "Object" ) + puts "no function for :#{name} in Meta #{self.me_self.inspect}" return nil else #recurse up class hierachy unless we're at Object - return @me_self.context.object_space.get_class_by_name(@me_self.super_class).get_function name + return self.me_self.context.object_space.get_class_by_name(self.me_self.super_class).get_function name end end @@ -52,7 +52,7 @@ module Parfait end def to_s - "#{inspect} on #{@me_self}, #{@functions.length} functions" + "#{inspect} on #{self.me_self}, #{self.functions.length} functions" end end end diff --git a/lib/parfait/method.rb b/lib/parfait/method.rb index f29edf4e..07e92146 100644 --- a/lib/parfait/method.rb +++ b/lib/parfait/method.rb @@ -22,14 +22,14 @@ module Parfait def initialize clazz , name , arg_names super() raise "No class #{name}" unless clazz - @for_class = clazz - @name = name - @code = BinaryCode.new name - @arg_names = arg_names - @locals = List.new - @tmps = List.new + self.for_class = clazz + self.name = name + self.code = BinaryCode.new name + self.arg_names = arg_names + self.locals = List.new + self.tmps = List.new end - attr_reader :name , :arg_names , :for_class , :code , :locals , :tmps + attributes [:name , :arg_names , :for_class , :code , :locals , :tmps] # determine whether this method has a variable by the given name @@ -46,32 +46,32 @@ module Parfait # determine whether this method has an argument by the name def has_arg name raise "uups #{name}.#{name.class}" unless name.is_a? Symbol - @arg_names.index_of name + self.arg_names.index_of name end # determine if method has a local variable or tmp (anonymous local) by given name def has_local name raise "uups #{name}.#{name.class}" unless name.is_a? Symbol - index = @locals.index_of(name) - index = @tmps.index_of(name) unless index + index = self.locals.index_of(name) + index = self.tmps.index_of(name) unless index index end def ensure_local name index = has_local name return index if index - @locals.push name - @locals.get_length + self.locals.push name + self.locals.get_length end def get_var name var = has_var name - raise "no var #{name} in method #{self.name} , #{@locals} #{@arg_names}" unless var + raise "no var #{name} in method #{self.name} , #{self.locals} #{self.arg_names}" unless var var end def sof_reference_name - @name + self.name end end diff --git a/lib/parfait/module.rb b/lib/parfait/module.rb index 6e8c7e0a..e177a525 100644 --- a/lib/parfait/module.rb +++ b/lib/parfait/module.rb @@ -13,25 +13,23 @@ module Parfait class Module < Object + attribute :name + attribute :instance_methods + attribute :super_class + attribute :meta_class + def initialize name , superclass super() - @name = name - @instance_methods = List.new - @super_class = superclass - @meta_class = nil#MetaClass.new(self) + self.name = name + self.instance_methods = List.new + self.super_class = superclass + self.meta_class = nil#MetaClass.new(self) end - def name - @name - end - - def instance_methods - @instance_methods - end def method_names names = List.new - @instance_methods.each do |method| + self.instance_methods.each do |method| names.push method.name end names @@ -42,36 +40,36 @@ module Parfait raise "syserr #{method.name.class}" unless method.name.is_a? Symbol found = get_instance_method( method.name ) if found - @instance_methods.delete(found) + self.instance_methods.delete(found) #raise "existed in #{self.name} #{Sof.write found.source.blocks}" end - @instance_methods.push method + self.instance_methods.push method #puts "#{self.name} add #{method.name}" method end def remove_instance_method method - @instance_methods.delete method + self.instance_methods.delete method end - def create_instance_method name , arg_names - raise "uups #{name}.#{name.class}" unless name.is_a?(Symbol) - clazz = Space.object_space.get_class_by_name(self.name) - raise "??? #{self.name}" unless clazz - Method.new( clazz , name , arg_names ) + def create_instance_method method_name , arg_names + raise "uups #{method_name}.#{method_name.class}" unless method_name.is_a?(Symbol) + clazz = get_layout().object_class() + raise "??? #{method_name}" unless clazz + Method.new( clazz , method_name , arg_names ) end # this needs to be done during booting as we can't have all the classes and superclassses # instantiated. By that logic it should maybe be part of vm rather. # On the other hand vague plans to load the hierachy from sof exist, so for now... def set_super_class sup - @super_class = sup + self.super_class = sup end def get_instance_method fname raise "uups #{fname}.#{fname.class}" unless fname.is_a?(Symbol) #if we had a hash this would be easier. Detect or find would help too - @instance_methods.each do |m| + self.instance_methods.each do |m| return m if(m.name == fname ) end nil @@ -82,8 +80,8 @@ module Parfait raise "uups #{m_name}.#{m_name.class}" unless m_name.is_a?(Symbol) method = get_instance_method(m_name) return method if method - if( @super_class ) - method = @super_class.resolve_method(m_name) + if( self.super_class ) + method = self.super_class.resolve_method(m_name) raise "Method not found #{m_name}, for \n#{self}" unless method end method diff --git a/lib/parfait/object.rb b/lib/parfait/object.rb index 5fd3f43a..3b238c60 100644 --- a/lib/parfait/object.rb +++ b/lib/parfait/object.rb @@ -19,11 +19,26 @@ module Parfait def self.new *args object = self.allocate + #HACK, but used to do the adapter in the init, bu that is too late now + object.fake_init if object.respond_to?(:fake_init) # at compile, not run-time + # have to grab the class, because we are in the ruby class not the parfait one + cl = Space.object_space.get_class_by_name( self.name.split("::").last.to_sym) + # and have to set the layout before we let the object do anything. otherwise boom + object.set_layout cl.object_layout + object.send :initialize , *args - #puts "NEW #{object.class}" object end + def self.attributes names + names.each{|name| attribute(name) } + end + + def self.attribute name + define_method(name) { get_instance_variable(name) } + define_method("#{name}=".to_sym) { |value| set_instance_variable(name , value) } + end + def == other self.object_id == other.object_id end @@ -42,8 +57,8 @@ module Parfait # data that every object carries. def get_class() l = get_layout() - puts "Layout #{l.class} in #{self.class} , #{self}" - l.get_object_class() + #puts "Layout #{l.class} in #{self.class} , #{self}" + l.object_class() end # private @@ -60,6 +75,7 @@ module Parfait def get_layout() l = internal_object_get(LAYOUT_INDEX) + #puts "get layout for #{self.class} returns #{l.class}" raise "No layout #{self.object_id.to_s(16)}:#{self.class} " unless l return l end @@ -70,6 +86,7 @@ module Parfait def get_instance_variable name index = instance_variable_defined(name) + #puts "getting #{name} at #{index}" return nil if index == nil return internal_object_get(index) end @@ -81,7 +98,7 @@ module Parfait end def instance_variable_defined name - get_layout().index_of(name) + get_layout().variable_index(name) end def word_length diff --git a/lib/parfait/space.rb b/lib/parfait/space.rb index 6784a099..569232db 100644 --- a/lib/parfait/space.rb +++ b/lib/parfait/space.rb @@ -22,22 +22,19 @@ module Parfait class Space < Object def initialize - super() - Parfait::Space.set_object_space self - @classes = Parfait::Dictionary.new + raise "Space can not be instantiated by new, you'd need a space to do so. Chicken and egg" end - attr_reader :classes , :first_message + attributes [:classes , :first_message] # need a two phase init for the object space (and generally parfait) because the space # is an interconnected graph, so not everthing is ready def late_init message = Message.new(nil) 5.times do - @first_message = Message.new message - message.set_caller @first_message - message = @first_message + self.first_message = Message.new message + message.set_caller self.first_message + message = self.first_message end - init_layout end @@object_space = nil @@ -64,8 +61,8 @@ module Parfait # return nili if no such class. Use bang version if create should be implicit def get_class_by_name name raise "uups #{name}.#{name.class}" unless name.is_a?(Symbol) - c = @classes[name] - puts "MISS, no class #{name} #{name.class}" unless c # " #{@classes}" + c = self.classes[name] + #puts "MISS, no class #{name} #{name.class}" unless c # " #{self.classes}" c end @@ -82,7 +79,7 @@ module Parfait def create_class name , superclass raise "uups #{name.class}" unless name.is_a? Symbol c = Class.new(name , superclass) - @classes[name] = c + self.classes[name] = c end def sof_reference_name diff --git a/lib/virtual.rb b/lib/virtual.rb index ad91b07e..aafaf2af 100644 --- a/lib/virtual.rb +++ b/lib/virtual.rb @@ -18,16 +18,6 @@ require "virtual/passes/get_implementation" require "virtual/passes/enter_implementation" require "virtual/passes/set_optimisation" -Sof::Volotile.add(Parfait::Object , [:memory]) -Sof::Volotile.add(Parfait::Method , [:memory]) -Sof::Volotile.add(Parfait::Class , [:memory]) -Sof::Volotile.add(Parfait::Layout , [:memory]) -Sof::Volotile.add(Parfait::Space , [:memory]) -Sof::Volotile.add(Parfait::Frame , [:memory]) -Sof::Volotile.add(Parfait::Message , [:memory]) -Sof::Volotile.add(Parfait::BinaryCode , [:memory]) -Sof::Volotile.add(Virtual::Block , [:method]) -Sof::Volotile.add(Virtual::MethodSource , [:current]) class Fixnum def fits_u8? diff --git a/lib/virtual/boot.rb b/lib/virtual/boot.rb index b885e8eb..1de3104c 100644 --- a/lib/virtual/boot.rb +++ b/lib/virtual/boot.rb @@ -16,80 +16,114 @@ module Virtual # # The way out is to build empty shell objects and stuff the neccessary data into them # (not use the normal initialize way) + # + # There are some helpers below, but the roadmap is something like: + # - create all the layouts, with thier layouts, but no classes + # - create a space by "hand" , using allocate, not new + # - create the class objects and assign them to the layouts + def boot_space + space_dict = object_with_layout Parfait::Dictionary + space_dict.keys = object_with_layout Parfait::List + space_dict.values = object_with_layout Parfait::List + + @space = object_with_layout Parfait::Space + @space.classes = space_dict + Parfait::Space.set_object_space @space + end + def boot_layouts + @layouts = {} + layout_names.each do |name , ivars | + @layouts[name] = layout_for( name , ivars) + end + layout_layout = @layouts[:Layout] + @layouts.each do |name , layout | + layout.set_layout(layout_layout) + end + end + + def boot_classes + # when running code instantiates a class, a layout is created automatically + # but even to get our space up, we have already instantiated all layouts + # so we have to continue and allocate classes and fill the data by hand + # and off cource we can't use space.create_class , but still they need to go there + classes = space.classes + layout_names.each do |name , vars| + cl = object_with_layout Parfait::Class + cl.object_layout = @layouts[name] + @layouts[name].object_class = cl + cl.instance_methods = object_with_layout Parfait::List +# puts "instance_methods is #{cl.instance_methods.class}" + cl.name = name + classes[name] = cl + end + object_class = classes[:Object] + # superclasses other than default object + supers = { :BinaryCode => :Word , :Layout => :List , :Class => :Module , + :Object => :Kernel , :Kernel => :Value, :Integer => :Value } + layout_names.each do |classname , ivar| + next if classname == :Value # has no superclass + clazz = classes[classname] + super_name = supers[classname] + if super_name + clazz.set_super_class classes[super_name] + else + clazz.set_super_class object_class + end + end + end + def boot_parfait! - @space = Parfait::Space.new - # map from the vm - class_name to the Parfait class (which carries parfait name) - class_mappings = {} #will later become instance variable - - values = [ :Value , :Integer , :Kernel , :Object] - value_classes = values.collect { |cl| @space.create_class(cl,nil) } - layouts = { :Word => [] , - :List => [] , - # Assumtion is that name is the last of message - :Message => [:next_message , :receiver , :frame , :return_address , :return_value, - :caller , :name ], - :MetaClass => [], - :BinaryCode => [], - :Space => [:classes , :first_message ], - :Frame => [:next_frame ], - :Layout => [:object_class] , - :Class => [:object_layout ], - :Dictionary => [:keys , :values ] , - :Method => [:name , :code ,:arg_names , :locals , :tmps ] , - :Module => [:name , :instance_methods , :super_class , :meta_class ] - } - layouts.each do |name , layout| - class_mappings[name] = @space.create_class(name , nil) - end - value_classes[1].set_super_class( value_classes[0] ) # #set superclass (value) for integer - value_classes[2].set_super_class( value_classes[0] ) # and kernel (TODO is module) - value_classes[3].set_super_class( value_classes[2] ) # and object (TODO hacked to kernel) - class_mappings.each do |name , clazz| # and the rest - clazz.set_super_class(value_classes[3]) # superclasses are object - end - # next create layouts by adding instance variable names to the layouts - class_mappings.each do |name , clazz| - variables = layouts[name] - variables.each do |var_name| - clazz.object_layout.add_instance_variable var_name - end - end - # superclass and layout corrections - supers = { :BinaryCode => :Word , :Layout => :List , :Class => :Module } - supers.each do |classname , superclass_name| - clazz = class_mappings[classname] - super_class = class_mappings[superclass_name] - # set_super_class has no sideeffects, so setting twice ok - clazz.set_super_class super_class - # Add superclass layout too - super_class.object_layout.each do |var| - clazz.object_layout.add_instance_variable var - end - end - - # now store the classes so we can hand them out later during object creation - # this can not be done earlier, as parfait objects are all the time created and would - # lookup half created class info - # but it must be done before going through the objects (next step) - @class_mappings = class_mappings - class_mappings[:Integer ] = value_classes[1] #need for further booting - class_mappings[:Kernel ] = value_classes[2] #need for further booting - class_mappings[:Object ] = value_classes[3] #need for further booting + boot_layouts + boot_space + boot_classes @space.late_init -# add_object @space - - class_mappings.values.each {|v| v.init_layout } - - # now update the layout on all objects created so far, - # go through objects in space - @objects.each do | o | - o.init_layout - end + #puts Sof.write(@space) boot_functions! end + # helper to create a Layout, name is the parfait name, ie :Layout + def layout_for( name , ivars ) + l = Parfait::Layout.allocate.fake_init + l.add_instance_variable :layout + ivars.each {|n| l.add_instance_variable n } + l + end + + # create an object with layout (ie allocate it and assign layout) + # meaning the lauouts have to be booted, @layouts filled + # here we pass the actual (ruby) class + def object_with_layout(cl) + o = cl.allocate.fake_init + name = cl.name.split("::").last.to_sym + o.set_layout @layouts[name] + o + end + + def layout_names + { :Word => [] , + :List => [] , + # Assumtion is that name is the last of message + :Message => [:next_message , :receiver , :frame , :return_address , :return_value, + :caller , :name ], + :MetaClass => [], + :Integer => [], + :Object => [], + :Kernel => [], #fix, kernel is a class, but should be a module + :BinaryCode => [], + :Space => [:classes , :first_message ], + :Frame => [:next_frame ], + :Layout => [:object_class] , + # TODO fix layouts for inherited classes. Currently only :Class and the + # instances are copied (shame on you) + :Class => [:object_layout , :name , :instance_methods , :super_class , :meta_class], + :Dictionary => [:keys , :values ] , + :Method => [:name , :code ,:arg_names , :for_class, :locals , :tmps ] , + :Module => [:name , :instance_methods , :super_class , :meta_class ] + } + end + # classes have booted, now create a minimal set of functions # minimal means only that which can not be coded in ruby # Methods are grabbed from respective modules by sending the method name. This should return the @@ -99,19 +133,19 @@ module Virtual # 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 = @class_mappings[:Object ] + obj = @space.get_class_by_name(:Object) [:main , :_get_instance_variable , :_set_instance_variable].each do |f| obj.add_instance_method Register::Builtin::Object.send(f , nil) end - obj = @class_mappings[:Kernel ] + obj = @space.get_class_by_name(:Kernel) # create dummy main first, __init__ calls it [:exit,:__send , :__init__ ].each do |f| obj.add_instance_method Register::Builtin::Kernel.send(f , nil) end - @class_mappings[:Word].add_instance_method Register::Builtin::Word.send(:putstring , nil) + @space.get_class_by_name(:Word).add_instance_method Register::Builtin::Word.send(:putstring , nil) - obj = @class_mappings[:Integer ] + obj = @space.get_class_by_name(:Integer) [:putint,:fibo].each do |f| obj.add_instance_method Register::Builtin::Integer.send(f , nil) end diff --git a/lib/virtual/machine.rb b/lib/virtual/machine.rb index f159ec1c..bc0d3379 100644 --- a/lib/virtual/machine.rb +++ b/lib/virtual/machine.rb @@ -42,7 +42,7 @@ module Virtual def initialize @parser = Parser::Salama.new @passes = [ FIRST_PASS ] - @objects = [] + @objects = {} @booted = false end attr_reader :passes , :space , :class_mappings , :init , :objects , :booted @@ -92,8 +92,8 @@ module Virtual # Objects are data and get assembled after functions def add_object o - return false if @objects.include?(o) - @objects.push o + return false if @objects[o.object_id] + @objects[o.object_id] = o true end diff --git a/lib/virtual/parfait_adapter.rb b/lib/virtual/parfait_adapter.rb index 77277f9d..2d943c5f 100644 --- a/lib/virtual/parfait_adapter.rb +++ b/lib/virtual/parfait_adapter.rb @@ -4,25 +4,6 @@ # To stay sane, we use the same classes that we use later, but "adapt" them to work in ruby # This affects mainly memory layout -module FakeMem - def initialize - super() - @memory = [0,nil] - @position = nil - if Virtual.machine.class_mappings - init_layout - else - #puts "No init for #{self.class}:#{self.object_id}" - end - end - def init_layout - vm_name = self.class.name.split("::").last.to_sym - clazz = Virtual.machine.class_mappings[vm_name] - raise "Class not found #{vm_name}" unless clazz - raise "Layout not set #{vm_name}" unless clazz.object_layout - self.set_layout clazz.object_layout - end -end module Virtual def self.new_list array list = Parfait::List.new @@ -39,12 +20,13 @@ class Symbol include Positioned include Padding - def init_layout; end def has_layout? true end def get_layout - Virtual.machine.class_mappings[:Word].object_layout + l = Virtual.machine.space.classes[:Word].object_layout + puts "LL #{l.class}" + l end def word_length padded to_s.length @@ -82,10 +64,15 @@ module Parfait # but we implement it with ruby array (0 based) and use 0 as type-word # These are the same functions that Builtin implements at run-time class Object - include FakeMem include Padding include Positioned + def fake_init + @memory = [0,nil] + @position = nil + self # for chaining + end + # these internal functions are _really_ internal # they respresent the smallest code needed to build larger functionality # but should _never_ be used outside parfait. in fact that should be impossible @@ -108,10 +95,6 @@ module Parfait # 1 -based index def internal_object_set(index , value) raise "failed init for #{self.class}" unless @memory - #shaddowing layout so we can ignore memory in Sof - if(index == LAYOUT_INDEX) - @layout = value - end @memory[index] = value end def internal_object_grow(length) @@ -174,4 +157,20 @@ module Parfait string end end + + ## sof related stuff + class Object + # parfait versions are deliberately called different, so we "relay" + # have to put the "@" on the names for sof to take them off again + def instance_variables + get_instance_variables.to_a.collect{ |n| "@#{n}".to_sym } + end + # name comes in as a ruby @var name + def instance_variable_get name + var = get_instance_variable name.to_s[1 .. -1].to_sym + puts "getting #{name} #{var}" + var + end + end + end diff --git a/lib/virtual/passes/collector.rb b/lib/virtual/passes/collector.rb index 34158266..a9505b0d 100644 --- a/lib/virtual/passes/collector.rb +++ b/lib/virtual/passes/collector.rb @@ -11,6 +11,7 @@ module Virtual return if object.nil? return unless Virtual.machine.add_object object #puts "adding #{object.class}" + return unless object.respond_to? :has_layout? unless object.has_layout? object.init_layout end @@ -19,8 +20,8 @@ module Virtual end layout = object.get_layout keep layout - #puts "Layout #{layout.get_object_class.name} #{Machine.instance.objects.include?(layout)}" - layout.each do |name| + #puts "Layout #{layout.object_class.name} #{Machine.instance.objects.include?(layout)}" + layout.object_instance_names.each do |name| inst = object.instance_variable_get "@#{name}".to_sym keep inst end diff --git a/test/compiler/test_hello.rb b/test/compiler/test_hello.rb index b697b644..040f6391 100644 --- a/test/compiler/test_hello.rb +++ b/test/compiler/test_hello.rb @@ -30,7 +30,7 @@ HERE check end - def test_string_put + def ttest_string_put @string_input = <