linked list of methods instead of list of methods
api changes slightly, especially for each, but mostly sama sama
This commit is contained in:
parent
ad497b34f1
commit
fb29fb6431
@ -24,7 +24,7 @@ module Elf
|
|||||||
|
|
||||||
# for debug add labels for labels
|
# for debug add labels for labels
|
||||||
Parfait.object_space.each_type do |type|
|
Parfait.object_space.each_type do |type|
|
||||||
type.methods.each do |f|
|
type.each_method do |f|
|
||||||
f.cpu_instructions.each do |label|
|
f.cpu_instructions.each do |label|
|
||||||
next unless label.is_a?(Risc::Label)
|
next unless label.is_a?(Risc::Label)
|
||||||
add_symbol "#{type.name}::#{f.name}:#{label.name}" , Positioned.position(label)
|
add_symbol "#{type.name}::#{f.name}:#{label.name}" , Positioned.position(label)
|
||||||
|
@ -75,7 +75,7 @@ module Parfait
|
|||||||
def collect_methods
|
def collect_methods
|
||||||
methods = []
|
methods = []
|
||||||
each_type do | type |
|
each_type do | type |
|
||||||
type.methods.each do |meth|
|
type.each_method do |meth|
|
||||||
methods << meth
|
methods << meth
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -52,7 +52,7 @@ module Parfait
|
|||||||
# this part of the init is seperate because at boot time we can not use normal new
|
# this part of the init is seperate because at boot time we can not use normal new
|
||||||
# new is overloaded to grab the type from space, and before boot, that is not set up
|
# new is overloaded to grab the type from space, and before boot, that is not set up
|
||||||
def init_lists(hash)
|
def init_lists(hash)
|
||||||
@methods = List.new
|
@methods = nil
|
||||||
@names = List.new
|
@names = List.new
|
||||||
@types = List.new
|
@types = List.new
|
||||||
raise "No type Type in #{hash}" unless hash[:type]
|
raise "No type Type in #{hash}" unless hash[:type]
|
||||||
@ -68,7 +68,8 @@ module Parfait
|
|||||||
|
|
||||||
def method_names
|
def method_names
|
||||||
names = List.new
|
names = List.new
|
||||||
@methods.each do |method|
|
return names unless @methods
|
||||||
|
@methods.each_method do |method|
|
||||||
names.push method.name
|
names.push method.name
|
||||||
end
|
end
|
||||||
names
|
names
|
||||||
@ -95,25 +96,39 @@ module Parfait
|
|||||||
if self.is_a?(Class) and (method.for_type != self)
|
if self.is_a?(Class) and (method.for_type != self)
|
||||||
raise "Adding to wrong class, should be #{method.for_class}"
|
raise "Adding to wrong class, should be #{method.for_class}"
|
||||||
end
|
end
|
||||||
found = get_method( method.name )
|
if get_method( method.name )
|
||||||
if found
|
remove_method(method.name)
|
||||||
@methods.delete(found)
|
|
||||||
end
|
end
|
||||||
@methods.push method
|
method.set_next( @methods )
|
||||||
|
@methods = method
|
||||||
#puts "#{self.name} add #{method.name}"
|
#puts "#{self.name} add #{method.name}"
|
||||||
method
|
method
|
||||||
end
|
end
|
||||||
|
|
||||||
def remove_method( method_name )
|
def remove_method( method_name )
|
||||||
found = get_method( method_name )
|
raise "May not remove method_missing" if method_name == :method_missing
|
||||||
raise "No such method #{method_name} in #{self.name}" unless found
|
raise "No such method #{method_name} in #{self.name}" unless @methods
|
||||||
@methods.delete(found)
|
if( @methods.name == method_name)
|
||||||
|
@methods = @methods.next_method
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
method = @methods
|
||||||
|
while(method && method.next_method)
|
||||||
|
if( method.next_method.name == method_name)
|
||||||
|
method.set_next( method.next_method.next_method )
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
method = method.next_method
|
||||||
|
end
|
||||||
|
end
|
||||||
|
raise "No such method #{method_name} in #{self.name}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_method( fname )
|
def get_method( fname )
|
||||||
raise "get_method #{fname}.#{fname.class}" unless fname.is_a?(Symbol)
|
raise "get_method #{fname}.#{fname.class}" unless fname.is_a?(Symbol)
|
||||||
#if we had a hash this would be easier. Detect or find would help too
|
#if we had a hash this would be easier. Detect or find would help too
|
||||||
@methods.each do |m|
|
return nil unless @methods
|
||||||
|
@methods.each_method do |m|
|
||||||
return m if(m.name == fname )
|
return m if(m.name == fname )
|
||||||
end
|
end
|
||||||
nil
|
nil
|
||||||
@ -133,6 +148,13 @@ module Parfait
|
|||||||
sup.instance_type.resolve_method(fname)
|
sup.instance_type.resolve_method(fname)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def methods_length
|
||||||
|
return 0 unless @methods
|
||||||
|
len = 0
|
||||||
|
@methods.each_method { len += 1}
|
||||||
|
return len
|
||||||
|
end
|
||||||
|
|
||||||
def == other
|
def == other
|
||||||
self.object_id == other.object_id
|
self.object_id == other.object_id
|
||||||
end
|
end
|
||||||
@ -195,6 +217,10 @@ module Parfait
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def each_method(&block)
|
||||||
|
return unless @methods
|
||||||
|
@methods.each_method(&block)
|
||||||
|
end
|
||||||
def to_hash
|
def to_hash
|
||||||
hash = {}
|
hash = {}
|
||||||
each do |name , type|
|
each do |name , type|
|
||||||
|
@ -22,7 +22,7 @@ module Parfait
|
|||||||
class TypedMethod < Object
|
class TypedMethod < Object
|
||||||
|
|
||||||
attr_reader :name , :risc_instructions , :for_type , :cpu_instructions
|
attr_reader :name , :risc_instructions , :for_type , :cpu_instructions
|
||||||
attr_reader :arguments , :frame , :binary
|
attr_reader :arguments , :frame , :binary , :next_method
|
||||||
|
|
||||||
# not part of the parfait model, hence ruby accessor
|
# not part of the parfait model, hence ruby accessor
|
||||||
attr_accessor :source
|
attr_accessor :source
|
||||||
@ -118,5 +118,12 @@ module Parfait
|
|||||||
"#{@for_type.object_class.name}:#{name}(#{arguments.inspect})"
|
"#{@for_type.object_class.name}:#{name}(#{arguments.inspect})"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def each_method( &block )
|
||||||
|
block.call( self )
|
||||||
|
next_method.each_method( &block ) if next_method
|
||||||
|
end
|
||||||
|
def set_next( method )
|
||||||
|
@next_method = method
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -145,14 +145,15 @@ module Risc
|
|||||||
false_object: :FalseClass , nil_object: :NilClass},
|
false_object: :FalseClass , nil_object: :NilClass},
|
||||||
NamedList: {},
|
NamedList: {},
|
||||||
Type: {names: :List , types: :List ,
|
Type: {names: :List , types: :List ,
|
||||||
object_class: :Class, methods: :List } ,
|
object_class: :Class, methods: :TypedMethod } ,
|
||||||
Class: {instance_methods: :List, instance_type: :Type, name: :Word,
|
Class: {instance_methods: :List, instance_type: :Type, name: :Word,
|
||||||
super_class_name: :Word , instance_names: :List },
|
super_class_name: :Word , instance_names: :List },
|
||||||
Dictionary: {keys: :List , values: :List } ,
|
Dictionary: {keys: :List , values: :List } ,
|
||||||
CacheEntry: {cached_type: :Type , cached_method: :TypedMethod } ,
|
CacheEntry: {cached_type: :Type , cached_method: :TypedMethod } ,
|
||||||
TypedMethod: {name: :Word, source: :Object, risc_instructions: :Object,
|
TypedMethod: {name: :Word, source: :Object, risc_instructions: :Object,
|
||||||
cpu_instructions: :Object, binary: :BinaryCode,
|
cpu_instructions: :Object, binary: :BinaryCode,
|
||||||
arguments: :Type , for_type: :Type, frame: :Type } ,
|
arguments: :Type , for_type: :Type, frame: :Type ,
|
||||||
|
next_method: :TypedMethod} ,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -55,10 +55,8 @@ module Risc
|
|||||||
# This method is just a placeholder until boot is over and the real method is
|
# This method is just a placeholder until boot is over and the real method is
|
||||||
# parsed.
|
# parsed.
|
||||||
def resolve_method( context)
|
def resolve_method( context)
|
||||||
compiler = compiler_for(:Word, :resolve_method , {:value => :Object} )
|
compiler = compiler_for(:Word, :resolve_method , {:value => :Type} )
|
||||||
args = compiler.method.arguments
|
|
||||||
len = args.instance_length
|
|
||||||
raise "Compiler arg number mismatch, method=#{args} " if len != 2
|
|
||||||
compiler.add_mom( Mom::ReturnSequence.new)
|
compiler.add_mom( Mom::ReturnSequence.new)
|
||||||
return compiler.method
|
return compiler.method
|
||||||
end
|
end
|
||||||
|
@ -99,6 +99,11 @@ module Risc
|
|||||||
true
|
true
|
||||||
end
|
end
|
||||||
# Instruction interpretation starts here
|
# Instruction interpretation starts here
|
||||||
|
def execute_DynamicJump
|
||||||
|
label = get_register(@instruction.register)
|
||||||
|
puts "Jump to :#{label}:"
|
||||||
|
set_instruction label
|
||||||
|
end
|
||||||
def execute_Branch
|
def execute_Branch
|
||||||
label = @instruction.label
|
label = @instruction.label
|
||||||
set_instruction label
|
set_instruction label
|
||||||
|
@ -149,13 +149,13 @@ class TestSpace < MiniTest::Test
|
|||||||
def test_no_methods_in_types
|
def test_no_methods_in_types
|
||||||
test_remove_methods
|
test_remove_methods
|
||||||
@space.each_type do |type|
|
@space.each_type do |type|
|
||||||
assert_equal 0 , type.methods.get_length , "name #{type.name}"
|
assert_equal 0 , type.methods_length , "name #{type.name}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
def test_no_methods_in_classes
|
def test_no_methods_in_classes
|
||||||
test_remove_methods
|
test_remove_methods
|
||||||
@space.classes.each do |name , cl|
|
@space.classes.each do |name , cl|
|
||||||
assert_equal 0 , cl.instance_type.methods.get_length , "name #{cl.name}"
|
assert_equal 0 , cl.instance_type.methods_length , "name #{cl.name}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -25,24 +25,30 @@ class TestMethodApi < MiniTest::Test
|
|||||||
@space.get_class_by_name(:Object).instance_type
|
@space.get_class_by_name(:Object).instance_type
|
||||||
end
|
end
|
||||||
def test_new_methods
|
def test_new_methods
|
||||||
assert_equal @try_type.method_names.class, @try_type.methods.class
|
assert_equal Parfait::List , @try_type.method_names.class
|
||||||
assert_equal @try_type.method_names.get_length , @try_type.methods.get_length
|
assert_equal @try_type.method_names.get_length , @try_type.methods_length
|
||||||
end
|
end
|
||||||
def test_add_method
|
def test_add_method
|
||||||
before = @try_type.methods.get_length
|
before = @try_type.methods_length
|
||||||
add_foo_to
|
add_foo_to
|
||||||
assert_equal 1 , @try_type.methods.get_length - before
|
assert_equal 1 , @try_type.methods_length - before
|
||||||
assert @try_type.method_names.inspect.include?(":foo")
|
assert @try_type.method_names.inspect.include?(":foo")
|
||||||
end
|
end
|
||||||
def test_remove_method
|
def test_remove_method
|
||||||
add_foo_to
|
add_foo_to
|
||||||
assert_equal true , @try_type.remove_method(:foo)
|
assert @try_type.remove_method(:foo)
|
||||||
end
|
end
|
||||||
def test_remove_not_there
|
def test_remove_not_there
|
||||||
assert_raises RuntimeError do
|
assert_raises RuntimeError do
|
||||||
@try_type.remove_method(:foo)
|
@try_type.remove_method(:foo)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
def test_remove_method_missing
|
||||||
|
# assert @try_type.get_method( :method_missing)
|
||||||
|
assert_raises RuntimeError do
|
||||||
|
@try_type.remove_method(:method_missing)
|
||||||
|
end
|
||||||
|
end
|
||||||
def test_create_method
|
def test_create_method
|
||||||
args = Parfait::Type.for_hash( @try_class , { bar: :Integer})
|
args = Parfait::Type.for_hash( @try_class , { bar: :Integer})
|
||||||
@try_type.create_method :bar, args , empty_frame
|
@try_type.create_method :bar, args , empty_frame
|
||||||
|
@ -50,6 +50,10 @@ module Risc
|
|||||||
assert_equal Label , call_ins.class
|
assert_equal Label , call_ins.class
|
||||||
assert_equal "Word_Type.resolve_method" , call_ins.name
|
assert_equal "Word_Type.resolve_method" , call_ins.name
|
||||||
end
|
end
|
||||||
|
def est_dyn
|
||||||
|
cal = ticks(102)
|
||||||
|
assert_equal DynamicJump , cal.class
|
||||||
|
end
|
||||||
#should end in exit, but doesn't, becasue resolve never returns
|
#should end in exit, but doesn't, becasue resolve never returns
|
||||||
def ttest_sys
|
def ttest_sys
|
||||||
sys = ticks(20)
|
sys = ticks(20)
|
||||||
|
Loading…
Reference in New Issue
Block a user