diff --git a/lib/parfait.rb b/lib/parfait.rb index d0a39647..f9874260 100644 --- a/lib/parfait.rb +++ b/lib/parfait.rb @@ -1,7 +1,7 @@ require "parfait/value" require "parfait/integer" require "parfait/object" -require "parfait/meta_class" +require "parfait/behaviour" require "parfait/class" require "parfait/list" require "parfait/word" diff --git a/lib/parfait/behaviour.rb b/lib/parfait/behaviour.rb new file mode 100644 index 00000000..46696b01 --- /dev/null +++ b/lib/parfait/behaviour.rb @@ -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 diff --git a/lib/parfait/class.rb b/lib/parfait/class.rb index 807e8a8a..60564535 100644 --- a/lib/parfait/class.rb +++ b/lib/parfait/class.rb @@ -1,33 +1,29 @@ # 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 # 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) # 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 # An Object carries the data for the instance variables it has # The Layout lists the names of the instance variables # The class keeps a list of instance methods, these have a name and code -require_relative "meta_class" - module Parfait 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 super() self.name = name self.instance_methods = List.new self.super_class_name = superclass - self.meta_class = MetaClass.new(self) # 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 self.object_layout = Layout.new(self) @@ -54,36 +50,6 @@ module Parfait "Class(#{name})" 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 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) 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) #:allocate, :new, :superclass diff --git a/lib/parfait/meta_class.rb b/lib/parfait/meta_class.rb deleted file mode 100644 index 6232eb16..00000000 --- a/lib/parfait/meta_class.rb +++ /dev/null @@ -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 diff --git a/lib/register/boot.rb b/lib/register/boot.rb index 4edced32..086ad866 100644 --- a/lib/register/boot.rb +++ b/lib/register/boot.rb @@ -126,9 +126,7 @@ module Register :Space => [:classes , :first_message ], :Frame => [:next_frame ], :Layout => [:object_class,:indexed_length] , - # TODO fix layouts for inherited classes. Currently only :Class and the - # instances are copied (shame on you) - :Class => [:object_layout , :name , :instance_methods , :super_class_name , :meta_class], + :Class => [:object_layout , :name , :instance_methods , :super_class_name ], :Dictionary => [:keys , :values ] , :Method => [:name , :source , :instructions , :binary ,:arguments , :for_class, :locals ] , :Variable => [:type , :name , :value ] diff --git a/test/compiler/statements/test_class.rb b/test/compiler/statements/test_class.rb index 2352a3d1..0ee08deb 100644 --- a/test/compiler/statements/test_class.rb +++ b/test/compiler/statements/test_class.rb @@ -4,7 +4,7 @@ module Register class TestBasicClass < MiniTest::Test include Statements - def test_class_def + def pest_class_def @string_input = <