Fix meta_class, sis lass instance variables and class methods
after some serious recursive thinking it now actually makes sense The key was to change the actual type of the class that the meta_class manages For objects it's (still) ok just to change the instance_type, but since the class object exists and has type, when adding instance variables, that actual type has to change
This commit is contained in:
parent
7b40bb9106
commit
6993e337bf
@ -1,8 +1,17 @@
|
|||||||
# Behaviour is something that has methods, basically class and modules superclass
|
|
||||||
|
|
||||||
# instance_methods is the attribute in the including class that has the methods
|
|
||||||
|
|
||||||
module Parfait
|
module Parfait
|
||||||
|
# Behaviour is the old smalltalk name for the duperclass of class and meta_class
|
||||||
|
#
|
||||||
|
# Classes and meta_classes are in fact very similar, in that they manage
|
||||||
|
# - the type of instances
|
||||||
|
# - the methods for instances
|
||||||
|
#
|
||||||
|
# The main way they differ is that Classes manage type for a class of objects (ie many)
|
||||||
|
# whereas meta_class, or singleton_class manages the type of only one object (here a class)
|
||||||
|
#
|
||||||
|
# Singleton classes can manage the type/methods of any single object, and in the
|
||||||
|
# future off course they will, just not yet. Most single objects don't need that,
|
||||||
|
# only Classes and Modules _always _ do, so that's where we start.
|
||||||
|
#
|
||||||
class Behaviour < Object
|
class Behaviour < Object
|
||||||
|
|
||||||
attr_reader :instance_type , :instance_methods
|
attr_reader :instance_type , :instance_methods
|
||||||
|
@ -43,6 +43,12 @@ module Parfait
|
|||||||
inspect
|
inspect
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# adding an instance changes the instance_type to include that variable
|
||||||
|
def add_instance_variable( name , type)
|
||||||
|
super(name,type)
|
||||||
|
@clazz.set_type(@instance_type)
|
||||||
|
end
|
||||||
|
|
||||||
# Nil name means no superclass, and so nil returned
|
# Nil name means no superclass, and so nil returned
|
||||||
def super_class
|
def super_class
|
||||||
return nil
|
return nil
|
||||||
|
@ -85,14 +85,14 @@ module Parfait
|
|||||||
# 0 -based index
|
# 0 -based index
|
||||||
def get_internal_word(index)
|
def get_internal_word(index)
|
||||||
return @type if index == Parfait::TYPE_INDEX
|
return @type if index == Parfait::TYPE_INDEX
|
||||||
name = Parfait.name_for_index(self , index)
|
name = self.type.names[index]
|
||||||
return nil unless name
|
return nil unless name
|
||||||
instance_eval("@#{name}")
|
instance_eval("@#{name}")
|
||||||
end
|
end
|
||||||
|
|
||||||
# 0 -based index
|
# 0 -based index
|
||||||
def set_internal_word(index , value)
|
def set_internal_word(index , value)
|
||||||
name = Parfait.name_for_index(self , index)
|
name = self.type.names[index] #unless name.is_a?(Symbol)
|
||||||
raise "not sym for #{index} in #{self}:#{self.type}:#{name.class}" unless name.is_a?(Symbol)
|
raise "not sym for #{index} in #{self}:#{self.type}:#{name.class}" unless name.is_a?(Symbol)
|
||||||
instance_eval("@#{name}=value" )
|
instance_eval("@#{name}=value" )
|
||||||
value
|
value
|
||||||
@ -100,16 +100,6 @@ module Parfait
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.name_for_index(object , index)
|
|
||||||
return :type if index == 0
|
|
||||||
clazz = object.class.name.split("::").last.to_sym
|
|
||||||
cl = self.type_names[clazz]
|
|
||||||
keys = cl.keys
|
|
||||||
keys[index - 1] # -1 because type is excluded in the lists (FIX)
|
|
||||||
# FIXME Now that we use instance variables in parfait, they should be parsed
|
|
||||||
# and the type_names generated automatically
|
|
||||||
end
|
|
||||||
|
|
||||||
# new list from ruby array to be precise
|
# new list from ruby array to be precise
|
||||||
def self.new_list array
|
def self.new_list array
|
||||||
list = Parfait::List.new
|
list = Parfait::List.new
|
||||||
|
@ -36,15 +36,18 @@ module Parfait
|
|||||||
assert_raises{ @try.add_instance_method(nil)}
|
assert_raises{ @try.add_instance_method(nil)}
|
||||||
end
|
end
|
||||||
def test_add_instance_variable_changes_type
|
def test_add_instance_variable_changes_type
|
||||||
before = @space.get_class.instance_type
|
before = @try.instance_type
|
||||||
@space.get_class.add_instance_variable(:counter , :Integer)
|
@try.add_instance_variable(:counter , :Integer)
|
||||||
assert before != @space.get_class.instance_type
|
assert before != @try.instance_type
|
||||||
end
|
end
|
||||||
def test_add_instance_variable_changes_type_hash
|
def test_add_instance_variable_changes_type_hash
|
||||||
before = @space.get_class.instance_type.hash
|
before = @try.instance_type.hash
|
||||||
@space.get_class.add_instance_variable(:counter , :Integer)
|
@try.add_instance_variable(:counter , :Integer)
|
||||||
assert before != @space.get_class.instance_type.hash
|
assert before != @try.instance_type.hash
|
||||||
|
end
|
||||||
|
def test_add_instance_variable_changes_class_type
|
||||||
|
@try.add_instance_variable(:counter , :Integer)
|
||||||
|
assert_equal @try.clazz.type , @try.instance_type
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
require_relative "../helper"
|
require_relative "../helper"
|
||||||
|
|
||||||
module Risc
|
module Risc
|
||||||
class InterpreterSetters < MiniTest::Test
|
class InterpreterGetters < MiniTest::Test
|
||||||
include Ticker
|
include Ticker
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
@ -19,7 +19,7 @@ module Risc
|
|||||||
MAIN
|
MAIN
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
#Space type is wrong, shold be same as meta_class.instance_type
|
||||||
def test_chain
|
def test_chain
|
||||||
#show_main_ticks # get output of what is
|
#show_main_ticks # get output of what is
|
||||||
run_input @string_input
|
run_input @string_input
|
||||||
|
@ -23,7 +23,7 @@ MAIN
|
|||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
|
||||||
def est_chain
|
def test_chain
|
||||||
#show_main_ticks # get output of what is
|
#show_main_ticks # get output of what is
|
||||||
run_input @string_input
|
run_input @string_input
|
||||||
assert_equal 5 , get_return
|
assert_equal 5 , get_return
|
||||||
|
@ -12,7 +12,7 @@ module Vool
|
|||||||
return @inst
|
return @inst
|
||||||
end
|
end
|
||||||
def main(arg)
|
def main(arg)
|
||||||
return Space.one_plus
|
return Space.some_inst
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
eos
|
eos
|
||||||
@ -20,7 +20,9 @@ module Vool
|
|||||||
|
|
||||||
def setup
|
def setup
|
||||||
ret = RubyX::RubyXCompiler.new(RubyX.default_test_options).ruby_to_mom(class_main)
|
ret = RubyX::RubyXCompiler.new(RubyX.default_test_options).ruby_to_mom(class_main)
|
||||||
@ins = ret.compilers.find{|c|c.callable.name==:some_inst}.mom_instructions.next
|
@compiler = ret.compilers.find{|c|c.callable.name==:some_inst}
|
||||||
|
@main = ret.compilers.find{|c|c.callable.name==:main}
|
||||||
|
@ins = @compiler.mom_instructions.next
|
||||||
end
|
end
|
||||||
def test_class_inst
|
def test_class_inst
|
||||||
space_class = Parfait.object_space.get_class
|
space_class = Parfait.object_space.get_class
|
||||||
@ -28,9 +30,25 @@ module Vool
|
|||||||
names = space_class.meta_class.instance_type.names
|
names = space_class.meta_class.instance_type.names
|
||||||
assert names.index_of(:inst) , names
|
assert names.index_of(:inst) , names
|
||||||
end
|
end
|
||||||
|
def test_compiler
|
||||||
|
assert_equal Mom::MethodCompiler, @compiler.class
|
||||||
|
assert_equal Parfait::Type, @compiler.callable.self_type.class
|
||||||
|
assert_equal 6, @compiler.callable.self_type.names.index_of(:inst) , @compiler.callable.self_type.names
|
||||||
|
end
|
||||||
def test_array
|
def test_array
|
||||||
check_array [SlotLoad, ReturnJump, Label, ReturnSequence, Label] , @ins
|
check_array [SlotLoad, ReturnJump, Label, ReturnSequence, Label] , @ins
|
||||||
end
|
end
|
||||||
|
def test_main_array
|
||||||
|
check_array [MessageSetup, ArgumentTransfer, SimpleCall, SlotLoad, ReturnJump ,
|
||||||
|
Label, ReturnSequence, Label] , @main.mom_instructions.next
|
||||||
|
end
|
||||||
|
def test_main_args
|
||||||
|
args = @main.mom_instructions.next(2)
|
||||||
|
assert_equal Parfait::Class , args.receiver.known_object.class
|
||||||
|
assert_equal :Space , args.receiver.known_object.name
|
||||||
|
assert_equal :some_inst , args.receiver.known_object.type.method_names.first
|
||||||
|
assert_equal :inst , args.receiver.known_object.type.names.last
|
||||||
|
end
|
||||||
def test_load_inst
|
def test_load_inst
|
||||||
assert_equal SlotLoad, @ins.class
|
assert_equal SlotLoad, @ins.class
|
||||||
end
|
end
|
||||||
|
@ -40,7 +40,7 @@ module Vool
|
|||||||
assert_equal SimpleCall, @ins.next(2).class
|
assert_equal SimpleCall, @ins.next(2).class
|
||||||
assert_equal :one_plus, @ins.next(2).method.name
|
assert_equal :one_plus, @ins.next(2).method.name
|
||||||
assert_equal Parfait::Type, @ins.next(2).method.self_type.class
|
assert_equal Parfait::Type, @ins.next(2).method.self_type.class
|
||||||
assert_equal :Object, @ins.next(2).method.self_type.object_class.name
|
assert_equal :Class, @ins.next(2).method.self_type.object_class.name
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user