create behavior module

behavior handles instance methods (add/remove/find)
and shall be included in layout later too
This commit is contained in:
Torsten Ruger 2015-10-26 13:27:56 +02:00
parent b76c140d32
commit 9f4952b5ac
7 changed files with 78 additions and 98 deletions

View File

@ -1,7 +1,7 @@
require "parfait/value" require "parfait/value"
require "parfait/integer" require "parfait/integer"
require "parfait/object" require "parfait/object"
require "parfait/meta_class" require "parfait/behaviour"
require "parfait/class" require "parfait/class"
require "parfait/list" require "parfait/list"
require "parfait/word" require "parfait/word"

68
lib/parfait/behaviour.rb Normal file
View File

@ -0,0 +1,68 @@
# described in the ruby language book as the eigenclass, what you get with
# class MyClass
# class << self <--- this is called the eigenclass, or metaclass, and really is just
# .... the class object but gives us the ability to use the
# syntax as if it were a class
#
module Parfait
module Behaviour
def self.included(base)
base.attribute :instance_methods
end
def method_names
names = List.new
self.instance_methods.each do |method|
names.push method.name
end
names
end
def add_instance_method method
raise "not a method #{method.class} #{method.inspect}" unless method.is_a? Method
raise "syserr #{method.name.class}" unless method.name.is_a? Symbol
raise "Adding to wrong class, should be #{method.for_class}" if method.for_class != self
found = get_instance_method( method.name )
if found
self.instance_methods.delete(found)
end
self.instance_methods.push method
#puts "#{self.name} add #{method.name}"
method
end
def remove_instance_method method_name
found = get_instance_method( method_name )
if found
self.instance_methods.delete(found)
else
raise "No such method #{method_name} in #{self.name}"
end
return true
end
def get_instance_method fname
raise "get_instance_method #{fname}.#{fname.class}" unless fname.is_a?(Symbol)
#if we had a hash this would be easier. Detect or find would help too
self.instance_methods.each do |m|
return m if(m.name == fname )
end
nil
end
# get the method and if not found, try superclasses. raise error if not found
def resolve_method m_name
raise "resolve_method #{m_name}.#{m_name.class}" unless m_name.is_a?(Symbol)
method = get_instance_method(m_name)
return method if method
if( self.super_class_name )
method = self.super_class.resolve_method(m_name)
raise "Method not found #{m_name}, for \n#{self}" unless method
end
method
end
end
end

View File

@ -1,33 +1,29 @@
# Class is mainly a list of methods with a name (for now) # Class is mainly a list of methods with a name (for now)
# layout of object is seperated into Layout # The memory layout of object is seperated into Layout
# A class describes the capabilities of a group of objects, ie what data it has # A class describes the capabilities of a group of objects, ie what data it has
# and functions it responds to. # and functions it responds to.
# #
# The class also keeps a list of class methods (with names+code)
# Class methods are instance methods on the class object
# So it is essential that the class (the object defining the class) # So it is essential that the class (the object defining the class)
# can carry methods. It does so as instance variables. # can carry methods. It does so as instance variables.
# In fact this property is implemented in the Object, as methods # In fact this property is implemented in the Layout, as methods
# may be added to any object at run-time # may be added to any object at run-time
# An Object carries the data for the instance variables it has # An Object carries the data for the instance variables it has
# The Layout lists the names of the instance variables # The Layout lists the names of the instance variables
# The class keeps a list of instance methods, these have a name and code # The class keeps a list of instance methods, these have a name and code
require_relative "meta_class"
module Parfait module Parfait
class Class < Object class Class < Object
attributes [:object_layout , :name , :instance_methods , :super_class_name , :meta_class] include Behaviour
attributes [:object_layout , :name , :super_class_name]
def initialize name , superclass def initialize name , superclass
super() super()
self.name = name self.name = name
self.instance_methods = List.new self.instance_methods = List.new
self.super_class_name = superclass self.super_class_name = superclass
self.meta_class = MetaClass.new(self)
# the layout for this class (class = object of type Class) carries the class # the layout for this class (class = object of type Class) carries the class
# as an instance. The relation is from an object through the Layout to it's class # as an instance. The relation is from an object through the Layout to it's class
self.object_layout = Layout.new(self) self.object_layout = Layout.new(self)
@ -54,36 +50,6 @@ module Parfait
"Class(#{name})" "Class(#{name})"
end end
def method_names
names = List.new
self.instance_methods.each do |method|
names.push method.name
end
names
end
def add_instance_method method
raise "not a method #{method.class} #{method.inspect}" unless method.is_a? Method
raise "syserr #{method.name.class}" unless method.name.is_a? Symbol
raise "Adding to wrong class, should be #{method.for_class}" if method.for_class != self
found = get_instance_method( method.name )
if found
self.instance_methods.delete(found)
end
self.instance_methods.push method
#puts "#{self.name} add #{method.name}"
method
end
def remove_instance_method method_name
found = get_instance_method( method_name )
if found
self.instance_methods.delete(found)
else
raise "No such method #{method_name} in #{self.name}"
end
return true
end
def create_instance_method method_name , arguments def create_instance_method method_name , arguments
raise "create_instance_method #{method_name}.#{method_name.class}" unless method_name.is_a?(Symbol) raise "create_instance_method #{method_name}.#{method_name.class}" unless method_name.is_a?(Symbol)
@ -104,27 +70,6 @@ module Parfait
Parfait::Space.object_space.get_class_by_name(self.super_class_name) Parfait::Space.object_space.get_class_by_name(self.super_class_name)
end end
def get_instance_method fname
raise "get_instance_method #{fname}.#{fname.class}" unless fname.is_a?(Symbol)
#if we had a hash this would be easier. Detect or find would help too
self.instance_methods.each do |m|
return m if(m.name == fname )
end
nil
end
# get the method and if not found, try superclasses. raise error if not found
def resolve_method m_name
raise "resolve_method #{m_name}.#{m_name.class}" unless m_name.is_a?(Symbol)
method = get_instance_method(m_name)
return method if method
if( self.super_class_name )
method = self.super_class.resolve_method(m_name)
raise "Method not found #{m_name}, for \n#{self}" unless method
end
method
end
# ruby 2.1 list (just for reference, keep at bottom) # ruby 2.1 list (just for reference, keep at bottom)
#:allocate, :new, :superclass #:allocate, :new, :superclass

View File

@ -1,31 +0,0 @@
module Parfait
# class that acts like a class, but is really the object
# actually we don't store methods in objects (as ruby with singleton_method) but rather
# in the (possibly unique) layout.
# described in the ruby language book as the eigenclass, what you get with
# class MyClass
# class << self <--- this is called the eigenclass, or metaclass, and really is just
# .... the class object but gives us the ability to use the
# syntax as if it were a class
#
class MetaClass < Object
attribute :me
def initialize(object)
super()
self.me = object
end
def super_class
Space.object_space.get_class_by_name(self.me.super_class_name).meta
end
def name
"Meta#{me.name}".to_sym
end
end
end

View File

@ -126,9 +126,7 @@ module Register
:Space => [:classes , :first_message ], :Space => [:classes , :first_message ],
:Frame => [:next_frame ], :Frame => [:next_frame ],
:Layout => [:object_class,:indexed_length] , :Layout => [:object_class,:indexed_length] ,
# TODO fix layouts for inherited classes. Currently only :Class and the :Class => [:object_layout , :name , :instance_methods , :super_class_name ],
# instances are copied (shame on you)
:Class => [:object_layout , :name , :instance_methods , :super_class_name , :meta_class],
:Dictionary => [:keys , :values ] , :Dictionary => [:keys , :values ] ,
:Method => [:name , :source , :instructions , :binary ,:arguments , :for_class, :locals ] , :Method => [:name , :source , :instructions , :binary ,:arguments , :for_class, :locals ] ,
:Variable => [:type , :name , :value ] :Variable => [:type , :name , :value ]

View File

@ -4,7 +4,7 @@ module Register
class TestBasicClass < MiniTest::Test class TestBasicClass < MiniTest::Test
include Statements include Statements
def test_class_def def pest_class_def
@string_input = <<HERE @string_input = <<HERE
class Bar class Bar
int self.buh() int self.buh()

View File

@ -12,14 +12,14 @@ class TestMeta < MiniTest::Test
::Parfait::Method.new @space.get_class_by_name(for_class) , :foo , args ::Parfait::Method.new @space.get_class_by_name(for_class) , :foo , args
end end
def test_meta def pest_meta
assert @try assert @try
end end
def test_meta_object def pest_meta_object
assert @space.get_class_by_name(:Object).meta assert @space.get_class_by_name(:Object).meta
end end
def test_new_superclass def pest_new_superclass
assert_equal Parfait::MetaClass , @try.super_class.class assert_equal Parfait::MetaClass , @try.super_class.class
assert_equal :MetaObject , @try.super_class.name assert_equal :MetaObject , @try.super_class.name
end end