Get a basic MetaClass going
Does get created in new, but not in boot. Also not yet used in compiling
This commit is contained in:
parent
2fbea82039
commit
3db7707614
@ -30,6 +30,7 @@ require_relative "parfait/data_object"
|
|||||||
require_relative "parfait/integer"
|
require_relative "parfait/integer"
|
||||||
require_relative "parfait/behaviour"
|
require_relative "parfait/behaviour"
|
||||||
require_relative "parfait/class"
|
require_relative "parfait/class"
|
||||||
|
require_relative "parfait/meta_class"
|
||||||
require_relative "parfait/list"
|
require_relative "parfait/list"
|
||||||
require_relative "parfait/word"
|
require_relative "parfait/word"
|
||||||
require_relative "parfait/binary_code"
|
require_relative "parfait/binary_code"
|
||||||
|
@ -45,7 +45,7 @@ module Parfait
|
|||||||
raise "resolve_method #{m_name}.#{m_name.class}" unless m_name.is_a?(Symbol)
|
raise "resolve_method #{m_name}.#{m_name.class}" unless m_name.is_a?(Symbol)
|
||||||
method = get_instance_method(m_name)
|
method = get_instance_method(m_name)
|
||||||
return method if method
|
return method if method
|
||||||
if( super_class_name != :Object )
|
if( super_class_name && super_class_name != :Object )
|
||||||
method = self.super_class.resolve_method(m_name)
|
method = self.super_class.resolve_method(m_name)
|
||||||
end
|
end
|
||||||
method
|
method
|
||||||
|
@ -18,10 +18,11 @@ module Parfait
|
|||||||
class Class < Object
|
class Class < Object
|
||||||
include Behaviour
|
include Behaviour
|
||||||
|
|
||||||
attr :type, :instance_type , :name , :instance_methods , :super_class_name
|
attr :type, :instance_type , :name , :instance_methods
|
||||||
|
attr :super_class_name , :meta_class
|
||||||
|
|
||||||
def self.type_length
|
def self.type_length
|
||||||
5
|
6
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize( name , superclass , instance_type)
|
def initialize( name , superclass , instance_type)
|
||||||
@ -30,6 +31,7 @@ module Parfait
|
|||||||
self.super_class_name = superclass
|
self.super_class_name = superclass
|
||||||
self.instance_methods = List.new
|
self.instance_methods = List.new
|
||||||
set_instance_type( instance_type )
|
set_instance_type( instance_type )
|
||||||
|
self.meta_class = MetaClass.new( self )
|
||||||
end
|
end
|
||||||
|
|
||||||
def rxf_reference_name
|
def rxf_reference_name
|
||||||
|
107
lib/parfait/meta_class.rb
Normal file
107
lib/parfait/meta_class.rb
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
#
|
||||||
|
# In many respects a MetaClass is like a Class. We haven't gone to the full ruby/oo level
|
||||||
|
# yet, where the metaclass is actually a class instance, but someday.
|
||||||
|
|
||||||
|
# A Class in general can be viewed as a way to generate methods for a group of objects.
|
||||||
|
|
||||||
|
# A MetaClass serves the same function, but just for one object, the class object that
|
||||||
|
# is the meta_class of.
|
||||||
|
# This is slightnly different in the way that the type of the class must actually
|
||||||
|
# change, whereas for a class the instance type changes and only objects generated
|
||||||
|
# henceafter have a different type.
|
||||||
|
|
||||||
|
# This is still a first version, this change is not implemeted, also classes at boot don't
|
||||||
|
# have metaclasses yet, so still a bit TODO
|
||||||
|
|
||||||
|
# Another current difference is that a metaclass has no superclass. Also no name.
|
||||||
|
# There is a one to one relationship between a class instance and it's meta_class instance.
|
||||||
|
|
||||||
|
module Parfait
|
||||||
|
class MetaClass < Object
|
||||||
|
include Behaviour
|
||||||
|
|
||||||
|
attr :type, :instance_type , :instance_methods , :clazz
|
||||||
|
|
||||||
|
def self.type_length
|
||||||
|
4
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize( clazz )
|
||||||
|
super()
|
||||||
|
self.clazz = clazz
|
||||||
|
self.instance_methods = List.new
|
||||||
|
set_instance_type( clazz.get_type() )
|
||||||
|
end
|
||||||
|
|
||||||
|
def rxf_reference_name
|
||||||
|
clazz.name
|
||||||
|
end
|
||||||
|
|
||||||
|
def inspect
|
||||||
|
"MetaClass(#{clazz.name})"
|
||||||
|
end
|
||||||
|
|
||||||
|
# no superclass, return nil to signal
|
||||||
|
def super_class_name
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_method_for(name , type , frame , body )
|
||||||
|
method = Parfait::VoolMethod.new(name , type , frame , body )
|
||||||
|
add_method( method )
|
||||||
|
method
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_method(method)
|
||||||
|
raise "Must be untyped method #{method}" unless method.is_a? Parfait::VoolMethod
|
||||||
|
instance_methods.push(method)
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_method(name)
|
||||||
|
instance_methods.find{|m| m.name == name }
|
||||||
|
end
|
||||||
|
|
||||||
|
# adding an instance changes the instance_type to include that variable
|
||||||
|
def add_instance_variable( name , type)
|
||||||
|
self.instance_type = instance_type.add_instance_variable( name , type )
|
||||||
|
end
|
||||||
|
|
||||||
|
# setting the type generates all methods for this type
|
||||||
|
# (or will do, once we store the methods code to do that)
|
||||||
|
def set_instance_type( type )
|
||||||
|
raise "type must be type #{type}" unless type.is_a?(Type)
|
||||||
|
self.instance_type = type
|
||||||
|
end
|
||||||
|
|
||||||
|
# return the super class, but raise exception if either the super class name
|
||||||
|
# or the super classs is nil.
|
||||||
|
# Use only for non Object base class
|
||||||
|
def super_class!
|
||||||
|
raise "No super_class for class #{name}" unless super_class_name
|
||||||
|
s = super_class
|
||||||
|
raise "superclass not found for class #{name} (#{super_class_name})" unless s
|
||||||
|
s
|
||||||
|
end
|
||||||
|
|
||||||
|
# return the super class
|
||||||
|
# we only store the name, and so have to resolve.
|
||||||
|
# Nil name means no superclass, and so nil is a valid return value
|
||||||
|
def super_class
|
||||||
|
return nil unless super_class_name
|
||||||
|
Parfait.object_space.get_class_by_name(super_class_name)
|
||||||
|
end
|
||||||
|
|
||||||
|
# ruby 2.1 list (just for reference, keep at bottom)
|
||||||
|
#:allocate, :new, :superclass
|
||||||
|
|
||||||
|
# + modules
|
||||||
|
# :<, :<=, :>, :>=, :included_modules, :include?, :name, :ancestors, :instance_methods, :public_instance_methods,
|
||||||
|
# :protected_instance_methods, :private_instance_methods, :constants, :const_get, :const_set, :const_defined?,
|
||||||
|
# :const_missing, :class_variables, :remove_class_variable, :class_variable_get, :class_variable_set,
|
||||||
|
# :class_variable_defined?, :public_constant, :private_constant, :singleton_class?, :include, :prepend,
|
||||||
|
# :module_exec, :class_exec, :module_eval, :class_eval, :method_defined?, :public_method_defined?,
|
||||||
|
# :private_method_defined?, :protected_method_defined?, :public_class_method, :private_class_method, :autoload,
|
||||||
|
# :autoload?, :instance_method, :public_instance_method
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
@ -146,7 +146,7 @@ module Parfait
|
|||||||
arguments_type: :Type , self_type: :Type, frame_type: :Type ,
|
arguments_type: :Type , self_type: :Type, frame_type: :Type ,
|
||||||
name: :Word , blocks: :Block} ,
|
name: :Word , blocks: :Block} ,
|
||||||
Class: {instance_methods: :List, instance_type: :Type,
|
Class: {instance_methods: :List, instance_type: :Type,
|
||||||
name: :Word, super_class_name: :Word },
|
name: :Word, super_class_name: :Word , meta_class: :MetaClass},
|
||||||
DataObject: {},
|
DataObject: {},
|
||||||
Data4: {},
|
Data4: {},
|
||||||
Data8: {},
|
Data8: {},
|
||||||
@ -158,6 +158,7 @@ module Parfait
|
|||||||
Message: { next_message: :Message, receiver: :Object, frame: :NamedList ,
|
Message: { next_message: :Message, receiver: :Object, frame: :NamedList ,
|
||||||
return_address: :Integer, return_value: :Object,
|
return_address: :Integer, return_value: :Object,
|
||||||
caller: :Message , method: :TypedMethod , arguments: :NamedList },
|
caller: :Message , method: :TypedMethod , arguments: :NamedList },
|
||||||
|
MetaClass: {instance_methods: :List, instance_type: :Type, clazz: :Class },
|
||||||
NamedList: {},
|
NamedList: {},
|
||||||
NilClass: {},
|
NilClass: {},
|
||||||
Object: {},
|
Object: {},
|
||||||
|
50
test/parfait/test_meta_class.rb
Normal file
50
test/parfait/test_meta_class.rb
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
require_relative "helper"
|
||||||
|
|
||||||
|
module Parfait
|
||||||
|
class TestMetaClass < ParfaitTest
|
||||||
|
|
||||||
|
def setup
|
||||||
|
super
|
||||||
|
@try = @space.create_class( :Try , :Object).meta_class
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_type_forclass
|
||||||
|
assert_equal "Class(Space)" , @space.get_type.object_class.inspect
|
||||||
|
assert_equal :Space , @space.get_type.object_class.name
|
||||||
|
end
|
||||||
|
def test_new_superclass_name
|
||||||
|
assert_equal :Object , @try.clazz.super_class_name
|
||||||
|
end
|
||||||
|
def test_new_superclass
|
||||||
|
assert_equal "Class(Try)" , @try.clazz.inspect
|
||||||
|
assert_equal "MetaClass(Try)" , @try.inspect
|
||||||
|
end
|
||||||
|
def test_new_methods
|
||||||
|
assert_equal @try.method_names.class, @try.instance_methods.class
|
||||||
|
assert_equal @try.method_names.get_length , @try.instance_methods.get_length
|
||||||
|
end
|
||||||
|
def test_remove_nothere
|
||||||
|
assert !@try.remove_instance_method(:foo)
|
||||||
|
end
|
||||||
|
def test_resolve
|
||||||
|
assert_nil @try.resolve_method :foo
|
||||||
|
end
|
||||||
|
def test_remove_method
|
||||||
|
assert_equal false , @try.remove_instance_method( :foo)
|
||||||
|
end
|
||||||
|
def test_add_nil_method_raises
|
||||||
|
assert_raises{ @try.add_instance_method(nil)}
|
||||||
|
end
|
||||||
|
def test_add_instance_variable_changes_type
|
||||||
|
before = @space.get_class.instance_type
|
||||||
|
@space.get_class.add_instance_variable(:counter , :Integer)
|
||||||
|
assert before != @space.get_class.instance_type
|
||||||
|
end
|
||||||
|
def test_add_instance_variable_changes_type_hash
|
||||||
|
before = @space.get_class.instance_type.hash
|
||||||
|
@space.get_class.add_instance_variable(:counter , :Integer)
|
||||||
|
assert before != @space.get_class.instance_type.hash
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
@ -6,7 +6,7 @@ module Parfait
|
|||||||
def classes
|
def classes
|
||||||
[:BinaryCode,:Block,:CacheEntry,:Callable,:CallableMethod,:Class,
|
[:BinaryCode,:Block,:CacheEntry,:Callable,:CallableMethod,:Class,
|
||||||
:DataObject,:Data4,:Data8,:Data16,:Dictionary,:Factory, :Integer,:FalseClass,
|
:DataObject,:Data4,:Data8,:Data16,:Dictionary,:Factory, :Integer,:FalseClass,
|
||||||
:List,:Message,:NamedList,:NilClass,:Object,:ReturnAddress,
|
:List,:Message, :MetaClass, :NamedList,:NilClass,:Object,:ReturnAddress,
|
||||||
:Space,:TrueClass,:Type,:VoolMethod,:Word]
|
:Space,:TrueClass,:Type,:VoolMethod,:Word]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ module Risc
|
|||||||
ret = main_ticks(68)
|
ret = main_ticks(68)
|
||||||
assert_equal FunctionReturn , ret.class
|
assert_equal FunctionReturn , ret.class
|
||||||
assert_equal :r1 , ret.register.symbol
|
assert_equal :r1 , ret.register.symbol
|
||||||
assert_equal 22284 , @interpreter.get_register(ret.register)
|
assert_equal 24204 , @interpreter.get_register(ret.register)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -54,7 +54,7 @@ module Risc
|
|||||||
end
|
end
|
||||||
def test_pc1
|
def test_pc1
|
||||||
@interpreter.tick
|
@interpreter.tick
|
||||||
assert_equal 21688 , @interpreter.pc
|
assert_equal 23672 , @interpreter.pc
|
||||||
end
|
end
|
||||||
def test_tick2
|
def test_tick2
|
||||||
@interpreter.tick
|
@interpreter.tick
|
||||||
@ -68,7 +68,7 @@ module Risc
|
|||||||
def test_pc2
|
def test_pc2
|
||||||
@interpreter.tick
|
@interpreter.tick
|
||||||
@interpreter.tick
|
@interpreter.tick
|
||||||
assert_equal 21692 , @interpreter.pc
|
assert_equal 23676 , @interpreter.pc
|
||||||
end
|
end
|
||||||
def test_tick_14_jump
|
def test_tick_14_jump
|
||||||
14.times {@interpreter.tick}
|
14.times {@interpreter.tick}
|
||||||
|
@ -25,7 +25,7 @@ module Risc
|
|||||||
assert_equal 0 , Position.get(@linker.cpu_init).at
|
assert_equal 0 , Position.get(@linker.cpu_init).at
|
||||||
end
|
end
|
||||||
def test_cpu_at
|
def test_cpu_at
|
||||||
assert_equal "0x4f1c" , Position.get(@linker.cpu_init.first).to_s
|
assert_equal "0x569c" , Position.get(@linker.cpu_init.first).to_s
|
||||||
end
|
end
|
||||||
def test_cpu_label
|
def test_cpu_label
|
||||||
assert_equal Position , Position.get(@linker.cpu_init.first).class
|
assert_equal Position , Position.get(@linker.cpu_init.first).class
|
||||||
|
@ -16,8 +16,12 @@ module VoolBlocks
|
|||||||
begin
|
begin
|
||||||
vool.to_mom(nil)
|
vool.to_mom(nil)
|
||||||
rescue => err
|
rescue => err
|
||||||
assert err.message.include?("Blocks")
|
assert err.message.include?("Blocks") , err.message
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
def test_assign_compiles
|
||||||
|
vool = Ruby::RubyCompiler.compile( as_class_method("val = 0") ).to_vool
|
||||||
|
assert_equal Mom::MomCompiler , vool.to_mom(nil).class
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user