create behavior module
behavior handles instance methods (add/remove/find) and shall be included in layout later too
This commit is contained in:
parent
b76c140d32
commit
9f4952b5ac
@ -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
68
lib/parfait/behaviour.rb
Normal 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
|
@ -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
|
||||||
|
@ -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
|
|
@ -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 ]
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user