basic immutability for type
add_instance_variable now uses global type list to check adds hash and to_has functions use backdoor (send) for booting
This commit is contained in:
parent
137d3c9231
commit
a31f75fe93
@ -93,8 +93,8 @@ module Register
|
|||||||
# helper to create a Type, name is the parfait name, ie :Type
|
# helper to create a Type, name is the parfait name, ie :Type
|
||||||
def type_for( name , ivars )
|
def type_for( name , ivars )
|
||||||
l = Parfait::Type.allocate.compile_time_init
|
l = Parfait::Type.allocate.compile_time_init
|
||||||
l.add_instance_variable :type , name
|
l.send(:private_add_instance_variable , :type , name)
|
||||||
ivars.each {|n,t| l.add_instance_variable( n , t) }
|
ivars.each {|n,t| l.send(:private_add_instance_variable, n , t) }
|
||||||
l
|
l
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ module Soml
|
|||||||
index = for_class.instance_type.variable_index(statement.name)
|
index = for_class.instance_type.variable_index(statement.name)
|
||||||
#raise "class field already defined:#{name} for class #{for_class.name}" if index
|
#raise "class field already defined:#{name} for class #{for_class.name}" if index
|
||||||
#puts "Define field #{name} on class #{for_class.name}"
|
#puts "Define field #{name} on class #{for_class.name}"
|
||||||
index = for_class.instance_type.add_instance_variable( statement.name , statement.type )
|
for_class.instance_type.add_instance_variable( statement.name , statement.type )
|
||||||
|
|
||||||
return nil # statements don't reurn values, only expressions
|
return nil # statements don't reurn values, only expressions
|
||||||
end
|
end
|
||||||
|
@ -40,10 +40,31 @@ module Parfait
|
|||||||
include Indexed
|
include Indexed
|
||||||
self.offset(3)
|
self.offset(3)
|
||||||
|
|
||||||
def initialize( object_class )
|
def self.new_for_hash( object_class , hash)
|
||||||
|
new_type = Type.new( object_class , hash)
|
||||||
|
code = new_type.hash
|
||||||
|
Space.object_space.types[code] = new_type
|
||||||
|
new_type
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.hash_code_for( dict )
|
||||||
|
index = 1
|
||||||
|
hash = 0
|
||||||
|
dict.each do |name , type|
|
||||||
|
item_hash = name.hash + type.hash
|
||||||
|
hash += item_hash + (item_hash / 256 ) * index
|
||||||
|
index += 1
|
||||||
|
end
|
||||||
|
hash
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize( object_class , hash = nil)
|
||||||
super()
|
super()
|
||||||
add_instance_variable :type ,:Type
|
private_add_instance_variable :type ,:Type
|
||||||
self.object_class = object_class
|
self.object_class = object_class
|
||||||
|
hash.each do |name , type|
|
||||||
|
private_add_instance_variable name , type
|
||||||
|
end if hash
|
||||||
end
|
end
|
||||||
|
|
||||||
def == other
|
def == other
|
||||||
@ -51,17 +72,18 @@ module Parfait
|
|||||||
end
|
end
|
||||||
|
|
||||||
# add the name of an instance variable
|
# add the name of an instance variable
|
||||||
# The index will be returned and can subsequently be searched with index_of
|
# Type objects are immutable, so a new object is returned
|
||||||
# The index of the name is the index of the data in the object
|
# As types are also unique, two same adds will result in identical results
|
||||||
#
|
def add_instance_variable( name , type )
|
||||||
# TODO , later we would need to COPY the type to keep the old constant
|
hash = to_hash
|
||||||
# but now we are concerned with booting, ie getting a working structure
|
hash[name] = type
|
||||||
def add_instance_variable name , type
|
code = Type.hash_code_for( hash )
|
||||||
raise "Name shouldn't be nil" unless name
|
existing = Space.object_space.types[code]
|
||||||
raise "Value Type shouldn't be nil" unless type
|
if existing
|
||||||
self.push(name)
|
return existing
|
||||||
self.push(type)
|
else
|
||||||
self.get_length
|
return Type.new_for_hash( object_class , hash)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def instance_names
|
def instance_names
|
||||||
@ -108,8 +130,26 @@ module Parfait
|
|||||||
nil # stop resolve recursing up metaclasses
|
nil # stop resolve recursing up metaclasses
|
||||||
end
|
end
|
||||||
|
|
||||||
def hash
|
def to_hash
|
||||||
h = name.hash
|
hash = Dictionary.new
|
||||||
|
each_pair do |name, type |
|
||||||
|
hash[name] = type
|
||||||
end
|
end
|
||||||
|
hash
|
||||||
|
end
|
||||||
|
|
||||||
|
def hash
|
||||||
|
Type.hash_code_for( to_hash )
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def private_add_instance_variable( name , type)
|
||||||
|
raise "Name shouldn't be nil" unless name
|
||||||
|
raise "Value Type shouldn't be nil" unless type
|
||||||
|
self.push(name)
|
||||||
|
self.push(type)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -70,7 +70,7 @@ class BasicType < MiniTest::Test
|
|||||||
|
|
||||||
def test_add_name
|
def test_add_name
|
||||||
type = Parfait::Type.new Register.machine.space.get_class_by_name(:Type)
|
type = Parfait::Type.new Register.machine.space.get_class_by_name(:Type)
|
||||||
type.add_instance_variable :boo , :Object
|
type.send(:private_add_instance_variable, :boo , :Object)
|
||||||
assert_equal 2 , type.variable_index(:boo)
|
assert_equal 2 , type.variable_index(:boo)
|
||||||
assert_equal 4 , type.get_length
|
assert_equal 4 , type.get_length
|
||||||
assert_equal :type , type.get(1)
|
assert_equal :type , type.get(1)
|
||||||
|
49
test/typed/type/test_hash.rb
Normal file
49
test/typed/type/test_hash.rb
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
require_relative "../helper"
|
||||||
|
|
||||||
|
class TypeHash < MiniTest::Test
|
||||||
|
|
||||||
|
def setup
|
||||||
|
@types = Register.machine.boot.space.types
|
||||||
|
@first = @types.values.first
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_hash
|
||||||
|
assert_equal Parfait::Dictionary , @types.class
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_length
|
||||||
|
assert_equal 16 , @types.length
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_two_hashs_not_equal
|
||||||
|
assert @types.keys.last != @types.keys.first
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_name
|
||||||
|
assert_equal "Word_Type" , @types.values.first.name
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_to_hash
|
||||||
|
hash = @first.to_hash
|
||||||
|
assert_equal hash[:type] , :Word
|
||||||
|
assert_equal hash[:char_length] , :Integer
|
||||||
|
assert_equal 2 , @first.instance_length
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_hashcode_with_hash
|
||||||
|
assert_equal @first.hash , Parfait::Type.hash_code_for( @first.to_hash)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_second_hash_different
|
||||||
|
hash2 = @first.to_hash
|
||||||
|
hash2[:random] = :Type
|
||||||
|
assert @first.hash != Parfait::Type.hash_code_for( hash2 )
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_add_is_different
|
||||||
|
type = @first.add_instance_variable :random , :Integer
|
||||||
|
assert type != @first , "new: #{type.inspect} , old: #{@first.inspect}"
|
||||||
|
assert @first.hash != type.hash
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Loading…
Reference in New Issue
Block a user