rubyx/lib/virtual/object.rb
2014-10-07 12:01:33 +03:00

146 lines
4.0 KiB
Ruby

require_relative "type"
require "parfait/message"
module Positioned
def position
raise "position accessed but not set at #{length} for #{self.inspect[0...500]}" if @position == nil
@position
end
def set_position pos
# resetting of position used to be error, but since relink and dynamic instruction size it is ok. in measures
if @position != nil and ((@position - pos).abs > 32)
raise "position set again #{pos}!=#{@position} for #{self}"
end
@position = pos
end
end
module Virtual
# our machine is made up of objects, some of which are code, some data
#
# during compilation objects are module Virtual objects, but during execution they are not scoped
#
# So compiling/linking/assembly turns ::virtual objects into binary that represents ruby objects at runtime
# The equivalence is listed below (i'll try and work on clearer correspondence later)
# ::Virtual Runtime / parfait
# Object Object
# BootClass Class
# MetaClass self/Object
# BootSpace ObjectSpace
# CompiledMethod Function
# (ruby)Array Array
# String String
class Object
include Positioned
def initialize
@position = nil
@length = -1
end
attr_accessor :length , :layout
def inspect
Sof::Writer.write(self)
end
def to_s
inspect
end
def mem_length
raise "abstract #{self.class}"
end
@@EMPTY = { :names => [] , :types => []}
def layout
raise "Find me #{self}"
self.class.layout
end
def self.layout
@@EMPTY
end
# class variables to have _identical_ objects passed back (stops recursion)
@@ARRAY = { :names => [] , :types => []}
# @@HASH = { :names => [:keys,:values] , :types => [Virtual::Reference,Virtual::Reference]}
# @@CLAZZ = { :names => [:name , :super_class_name , :instance_methods] , :types => [Virtual::Reference,Virtual::Reference,Virtual::Reference]}
# @@SPACE = { :names => [:classes,:objects] , :types => [Virtual::Reference,Virtual::Reference]}
def layout_for(object)
case object
when Array , Symbol , String , Virtual::CompiledMethod , Virtual::Block , Virtual::StringConstant
@@ARRAY
when Hash
@@HASH.merge :keys => object.keys , :values => object.values
when Virtual::BootClass
@@CLAZZ
when Virtual::BootSpace
@@SPACE
else
raise "linker encounters unknown class #{object.class}"
end
end
# objects only come in lengths of multiple of 8 words
# but there is a constant overhead of 2 words, one for type, one for layout
# and as we would have to subtract 1 to make it work without overhead, we now have to add 7
def padded len
a = 32 * (1 + (len + 7)/32 )
#puts "#{a} for #{len}"
a
end
def padded_words words
padded(words*4) # 4 == word length, a constant waiting for a home
end
end
end
::Message.class_eval do
include Positioned
def layout
Virtual::Object.layout
end
def mem_length
Virtual::Object.new.padded_words(2)
end
end
::Frame.class_eval do
include Positioned
def layout
Virtual::Object.layout
end
def mem_length
Virtual::Object.new.padded_words(2)
end
end
Parfait::Hash.class_eval do
include Positioned
HASH = { :names => [:keys,:values] , :types => [Virtual::Reference,Virtual::Reference]}
def layout
HASH
end
def mem_length
Virtual::Object.new.padded_words(2)
end
end
Array.class_eval do
include Positioned
def layout
Virtual::Object.layout
end
def mem_length
Virtual::Object.new.padded_words(length())
end
end
Symbol.class_eval do
include Positioned
def layout
Virtual::Object.layout
end
def mem_length
Virtual::Object.new.padded(1 + to_s.length())
end
end
String.class_eval do
include Positioned
def layout
Virtual::Object.layout
end
def mem_length
Virtual::Object.new.padded(1 + length())
end
end