2015-10-26 12:27:56 +01:00
|
|
|
module Parfait
|
2019-09-29 21:37:28 +02:00
|
|
|
# Behaviour is the old smalltalk name for the superclass of class and singleton_class
|
2019-09-23 19:42:46 +02:00
|
|
|
#
|
2019-09-23 19:57:33 +02:00
|
|
|
# Classes and singleton_classes are in fact very similar, in that they manage
|
2019-09-23 19:42:46 +02:00
|
|
|
# - the type of instances
|
|
|
|
# - the methods for instances
|
|
|
|
#
|
2019-09-29 21:37:28 +02:00
|
|
|
# - the instance methods are source level methods defined on the class
|
|
|
|
# - the type refers to the instance variables and callable methods of objects
|
|
|
|
# (in other words the type is a concrete representation, while instance_methods
|
|
|
|
# is more abstract, ie source level)
|
|
|
|
#
|
2019-09-23 19:42:46 +02:00
|
|
|
# The main way they differ is that Classes manage type for a class of objects (ie many)
|
2019-09-29 21:37:28 +02:00
|
|
|
# whereas singleton_class, or singleton_class manages the type of only one object
|
|
|
|
# (here a class)
|
2019-09-23 19:42:46 +02:00
|
|
|
#
|
|
|
|
# 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.
|
|
|
|
#
|
2019-09-21 17:50:33 +02:00
|
|
|
class Behaviour < Object
|
2015-10-26 12:27:56 +01:00
|
|
|
|
2019-09-21 17:50:33 +02:00
|
|
|
attr_reader :instance_type , :instance_methods
|
|
|
|
|
|
|
|
def initialize(type)
|
2015-10-26 13:33:36 +01:00
|
|
|
super()
|
2019-09-10 11:33:57 +02:00
|
|
|
@instance_methods = List.new
|
2019-09-21 17:50:33 +02:00
|
|
|
@instance_type = type
|
2015-10-26 13:33:36 +01:00
|
|
|
end
|
|
|
|
|
2015-10-26 16:23:02 +01:00
|
|
|
def methods
|
2019-09-22 23:07:30 +02:00
|
|
|
@instance_methods
|
2015-10-26 16:23:02 +01:00
|
|
|
end
|
2016-12-06 10:38:09 +01:00
|
|
|
|
2015-10-26 12:27:56 +01:00
|
|
|
def method_names
|
|
|
|
names = List.new
|
2019-09-29 21:37:28 +02:00
|
|
|
@instance_methods.each do |method|
|
2015-10-26 12:27:56 +01:00
|
|
|
names.push method.name
|
|
|
|
end
|
|
|
|
names
|
|
|
|
end
|
|
|
|
|
2019-09-29 21:37:28 +02:00
|
|
|
def create_instance_method_for(name , type , frame , body )
|
|
|
|
raise "Method exists #{name}" if get_instance_method(name)
|
2019-10-03 23:36:49 +02:00
|
|
|
method = Parfait::SolMethod.new(name , type , frame , body )
|
2019-09-21 17:50:33 +02:00
|
|
|
add_instance_method( method )
|
|
|
|
end
|
|
|
|
|
2016-12-15 13:00:34 +01:00
|
|
|
def add_instance_method( method )
|
2019-09-29 21:37:28 +02:00
|
|
|
raise "Method exists #{method.name}" if get_instance_method(method.name)
|
2019-09-21 17:50:33 +02:00
|
|
|
@instance_methods.push(method)
|
2015-10-26 12:27:56 +01:00
|
|
|
method
|
|
|
|
end
|
|
|
|
|
2016-12-15 13:00:34 +01:00
|
|
|
def remove_instance_method( method_name )
|
2015-10-26 12:27:56 +01:00
|
|
|
found = get_instance_method( method_name )
|
2019-09-10 11:33:57 +02:00
|
|
|
found ? methods.delete(found) : false
|
2015-10-26 12:27:56 +01:00
|
|
|
end
|
|
|
|
|
2016-12-15 13:00:34 +01:00
|
|
|
def get_instance_method( fname )
|
2015-10-26 12:27:56 +01:00
|
|
|
raise "get_instance_method #{fname}.#{fname.class}" unless fname.is_a?(Symbol)
|
2019-09-09 19:26:54 +02:00
|
|
|
@instance_methods.find {|m| m.name == fname }
|
2015-10-26 12:27:56 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
# get the method and if not found, try superclasses. raise error if not found
|
2018-04-02 16:06:31 +02:00
|
|
|
def resolve_method( m_name )
|
2015-10-26 12:27:56 +01:00
|
|
|
raise "resolve_method #{m_name}.#{m_name.class}" unless m_name.is_a?(Symbol)
|
|
|
|
method = get_instance_method(m_name)
|
|
|
|
return method if method
|
2019-09-29 11:06:37 +02:00
|
|
|
if( s_class = super_class )
|
|
|
|
method = s_class.resolve_method(m_name)
|
2015-10-26 12:27:56 +01:00
|
|
|
end
|
|
|
|
method
|
|
|
|
end
|
|
|
|
|
2019-09-29 11:06:37 +02:00
|
|
|
# assume resolving is needed, ie getting has failed, raise if it hasnt
|
|
|
|
def resolve_method!( m_name )
|
|
|
|
method = get_instance_method(m_name)
|
|
|
|
if method
|
|
|
|
tm = @instance_type.method_names
|
2019-09-29 21:37:28 +02:00
|
|
|
raise "resolve_method #{name}.#{m_name} has #{tm}:#{method_names}"
|
2019-09-29 11:06:37 +02:00
|
|
|
end
|
2019-10-01 19:55:05 +02:00
|
|
|
#puts "resolve #{m_name}:#{super_class}:"
|
2019-09-29 11:06:37 +02:00
|
|
|
return nil unless( s_class = super_class )
|
|
|
|
s_class.resolve_method(m_name)
|
|
|
|
end
|
|
|
|
|
2019-09-21 17:50:33 +02:00
|
|
|
# adding an instance changes the instance_type to include that variable
|
|
|
|
def add_instance_variable( name , type)
|
|
|
|
@instance_type = @instance_type.add_instance_variable( name , type )
|
|
|
|
end
|
|
|
|
|
2015-10-26 12:27:56 +01:00
|
|
|
end
|
|
|
|
end
|