2015-04-08 19:24:50 +02:00
|
|
|
# An Object is really a hash like structure. It is dynamic and
|
2015-05-14 18:54:38 +02:00
|
|
|
# you want to store values by name (instance variable names).
|
|
|
|
#
|
2015-04-08 19:24:50 +02:00
|
|
|
# One could (like mri), store the names in each object, but that is wasteful
|
|
|
|
# Instead we store only the values, and access them by index.
|
|
|
|
# The Layout allows the mapping of names to index.
|
|
|
|
|
|
|
|
# The Layout of an object describes the memory layout of the object
|
|
|
|
# The Layout is a simple list of the names of instance variables.
|
2015-05-11 17:55:49 +02:00
|
|
|
#
|
|
|
|
# As every object has a Layout to describe it, the name "layout" is the
|
2015-04-08 19:24:50 +02:00
|
|
|
# first name in the list for every Layout.
|
2015-05-17 13:40:02 +02:00
|
|
|
|
|
|
|
# But as we want every Object to have a class, the Layout carries that class.
|
|
|
|
# So the layout of layout has an entry "object_class"
|
2015-04-08 19:24:50 +02:00
|
|
|
|
2015-10-26 13:33:36 +01:00
|
|
|
# But Objects must also be able to carry methods themselves (ruby calls singleton_methods)
|
|
|
|
# and those too are stored in the Layout (both layout and class include behaviour)
|
|
|
|
|
2015-04-08 19:24:50 +02:00
|
|
|
# In other words, the Layout is a list of names that describe
|
|
|
|
# the values stored in an actual object.
|
2015-05-12 18:10:45 +02:00
|
|
|
# The object is an List of values of length n and
|
2015-10-26 13:33:36 +01:00
|
|
|
# the Layout is an List of names of length n , plus class reference and methods reference
|
2015-05-11 17:55:49 +02:00
|
|
|
# Together they turn the object into a hash like structure
|
2015-04-08 19:24:50 +02:00
|
|
|
|
2015-05-11 17:55:49 +02:00
|
|
|
module Parfait
|
2015-10-25 18:16:12 +01:00
|
|
|
class Layout < Object
|
2015-07-21 14:40:25 +02:00
|
|
|
attribute :object_class
|
2015-10-26 13:33:36 +01:00
|
|
|
include Behaviour
|
2015-04-08 19:24:50 +02:00
|
|
|
|
2015-10-26 11:22:32 +01:00
|
|
|
include Indexed
|
2015-10-26 13:33:36 +01:00
|
|
|
self.offset(3)
|
2015-10-26 11:22:32 +01:00
|
|
|
|
2015-05-19 19:29:33 +02:00
|
|
|
def initialize( object_class )
|
2015-05-20 16:17:11 +02:00
|
|
|
super()
|
2015-10-29 11:45:29 +01:00
|
|
|
add_instance_variable :layout ,:Layout
|
2015-10-26 14:14:38 +01:00
|
|
|
self.object_class = object_class
|
2015-05-19 19:29:33 +02:00
|
|
|
end
|
|
|
|
|
2015-06-03 09:01:59 +02:00
|
|
|
def == other
|
|
|
|
self.object_id == other.object_id
|
|
|
|
end
|
|
|
|
|
2015-05-19 19:29:33 +02:00
|
|
|
# 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
|
2015-10-29 11:45:29 +01:00
|
|
|
def add_instance_variable name , type
|
|
|
|
raise "Name shouldn't be nil" unless name
|
|
|
|
raise "Type shouldn't be nil" unless type
|
2015-05-19 19:29:33 +02:00
|
|
|
self.push(name)
|
2015-10-29 11:45:29 +01:00
|
|
|
self.push(type)
|
2015-05-19 19:29:33 +02:00
|
|
|
self.get_length
|
2015-05-16 13:01:48 +02:00
|
|
|
end
|
|
|
|
|
2015-10-26 11:57:54 +01:00
|
|
|
def instance_names
|
2015-07-20 12:20:43 +02:00
|
|
|
names = List.new
|
2015-10-29 11:45:29 +01:00
|
|
|
name = true
|
2015-10-26 11:22:32 +01:00
|
|
|
each do |item|
|
2015-10-29 11:45:29 +01:00
|
|
|
names.push(item) if name
|
|
|
|
name = ! name
|
2015-07-20 12:20:43 +02:00
|
|
|
end
|
|
|
|
names
|
|
|
|
end
|
2015-07-21 14:40:25 +02:00
|
|
|
|
2015-10-26 11:57:54 +01:00
|
|
|
def instance_length
|
2015-11-04 15:11:25 +01:00
|
|
|
(self.get_length / 2).to_i # to_i for opal
|
2015-10-29 11:45:29 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
alias :super_index :index_of
|
|
|
|
def index_of(name)
|
|
|
|
raise "Use variable_index instead"
|
2015-10-22 10:02:46 +02:00
|
|
|
end
|
|
|
|
|
2015-10-17 09:03:39 +02:00
|
|
|
# index of the variable when using internal_object_get
|
|
|
|
# (internal_object_get is 1 based and 1 is always the layout)
|
2015-07-21 14:40:25 +02:00
|
|
|
def variable_index name
|
2015-10-29 11:45:29 +01:00
|
|
|
has = super_index(name)
|
2015-10-17 09:03:39 +02:00
|
|
|
return nil unless has
|
2015-10-26 11:22:32 +01:00
|
|
|
raise "internal error #{name}:#{has}" if has < 1
|
2015-11-04 15:11:25 +01:00
|
|
|
(1 + has / 2).to_i # to_i for opal
|
2015-07-21 14:40:25 +02:00
|
|
|
end
|
|
|
|
|
2015-10-13 13:46:07 +02:00
|
|
|
def inspect
|
2015-10-26 14:07:59 +01:00
|
|
|
"Layout[#{super}]"
|
2015-10-13 13:46:07 +02:00
|
|
|
end
|
|
|
|
|
2015-06-19 18:50:53 +02:00
|
|
|
def sof_reference_name
|
2015-07-21 14:40:25 +02:00
|
|
|
"#{self.object_class.name}_Layout"
|
2015-06-19 18:50:53 +02:00
|
|
|
end
|
2015-10-26 16:24:28 +01:00
|
|
|
alias :name :sof_reference_name
|
|
|
|
|
|
|
|
def super_class_name
|
|
|
|
nil # stop resolve recursing up metaclasses
|
|
|
|
end
|
|
|
|
|
|
|
|
def create_instance_method method_name , arguments
|
|
|
|
raise "create_instance_method #{method_name}.#{method_name.class}" unless method_name.is_a?(Symbol)
|
|
|
|
#puts "Self: #{self.class} clazz: #{clazz.name}"
|
|
|
|
add_instance_method Method.new( self , method_name , arguments )
|
|
|
|
end
|
2015-06-19 18:50:53 +02:00
|
|
|
|
2015-05-11 17:55:49 +02:00
|
|
|
end
|
2015-04-08 19:24:50 +02:00
|
|
|
end
|