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
|
||||
def type_for( name , ivars )
|
||||
l = Parfait::Type.allocate.compile_time_init
|
||||
l.add_instance_variable :type , name
|
||||
ivars.each {|n,t| l.add_instance_variable( n , t) }
|
||||
l.send(:private_add_instance_variable , :type , name)
|
||||
ivars.each {|n,t| l.send(:private_add_instance_variable, n , t) }
|
||||
l
|
||||
end
|
||||
|
||||
|
@ -10,7 +10,7 @@ module Soml
|
||||
index = for_class.instance_type.variable_index(statement.name)
|
||||
#raise "class field already defined:#{name} for class #{for_class.name}" if index
|
||||
#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
|
||||
end
|
||||
|
@ -40,10 +40,31 @@ module Parfait
|
||||
include Indexed
|
||||
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()
|
||||
add_instance_variable :type ,:Type
|
||||
private_add_instance_variable :type ,:Type
|
||||
self.object_class = object_class
|
||||
hash.each do |name , type|
|
||||
private_add_instance_variable name , type
|
||||
end if hash
|
||||
end
|
||||
|
||||
def == other
|
||||
@ -51,17 +72,18 @@ module Parfait
|
||||
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 type to keep the old constant
|
||||
# but now we are concerned with booting, ie getting a working structure
|
||||
def 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)
|
||||
self.get_length
|
||||
# Type objects are immutable, so a new object is returned
|
||||
# As types are also unique, two same adds will result in identical results
|
||||
def add_instance_variable( name , type )
|
||||
hash = to_hash
|
||||
hash[name] = type
|
||||
code = Type.hash_code_for( hash )
|
||||
existing = Space.object_space.types[code]
|
||||
if existing
|
||||
return existing
|
||||
else
|
||||
return Type.new_for_hash( object_class , hash)
|
||||
end
|
||||
end
|
||||
|
||||
def instance_names
|
||||
@ -108,8 +130,26 @@ module Parfait
|
||||
nil # stop resolve recursing up metaclasses
|
||||
end
|
||||
|
||||
def to_hash
|
||||
hash = Dictionary.new
|
||||
each_pair do |name, type |
|
||||
hash[name] = type
|
||||
end
|
||||
hash
|
||||
end
|
||||
|
||||
def hash
|
||||
h = name.hash
|
||||
end
|
||||
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
|
||||
|
@ -70,7 +70,7 @@ class BasicType < MiniTest::Test
|
||||
|
||||
def test_add_name
|
||||
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 4 , type.get_length
|
||||
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