still working on the method dispatch
This commit is contained in:
parent
ebf117a63a
commit
a7551ea8b6
@ -102,6 +102,11 @@ module Arm
|
||||
syscall( function.insertion_point , 4 ) # 4 == write
|
||||
end
|
||||
|
||||
# stop, do not return
|
||||
def exit function #, string
|
||||
syscall( function.insertion_point , 1 ) # 1 == exit
|
||||
end
|
||||
|
||||
|
||||
# the number (a Vm::integer) is (itself) divided by 10, ie overwritten by the result
|
||||
# and the remainder is overwritten (ie an out argument)
|
||||
|
@ -26,9 +26,8 @@ module Ast
|
||||
raise "uups #{clazz}.#{name}" unless clazz
|
||||
#class qualifier, means call from metaclass
|
||||
clazz = clazz.meta_class
|
||||
value = clazz
|
||||
puts "CLAZZ #{value}"
|
||||
function = clazz.get_or_create_function(name)
|
||||
puts "CLAZZ #{clazz}"
|
||||
clazz
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -7,20 +7,33 @@ module Ast
|
||||
def compile context
|
||||
into = context.function
|
||||
params = args.collect{ |a| a.compile(context) }
|
||||
|
||||
if receiver.is_a?(NameExpression) and (receiver.name == :self)
|
||||
function = context.current_class.get_or_create_function(name)
|
||||
value_receiver = Vm::Integer.new(Vm::RegisterMachine.instance.receiver_register)
|
||||
else
|
||||
puts "compiling receiver #{receiver} (call #{name})"
|
||||
if receiver.is_a? ModuleName
|
||||
clazz = context.object_space.get_or_create_class receiver.name
|
||||
function = clazz.resolve_function name
|
||||
elsif receiver.is_a?(StringExpression) or receiver.is_a?(IntegerExpression)
|
||||
#TODO obviously the class is wrong, but you gotta start somewhere
|
||||
clazz = context.object_space.get_or_create_class :Object
|
||||
function = clazz.resolve_function name
|
||||
value_receiver = receiver.compile(context)
|
||||
function = context.current_class.get_or_create_function(name)
|
||||
end
|
||||
# this lot below should go, since the compile should handle all
|
||||
if receiver.is_a? VariableExpression
|
||||
elsif receiver.is_a?(NameExpression)
|
||||
if(receiver.name == :self)
|
||||
function = context.current_class.resolve_function(name)
|
||||
value_receiver = Vm::Integer.new(Vm::RegisterMachine.instance.receiver_register)
|
||||
else
|
||||
value_receiver = receiver.compile(context)
|
||||
# TODO HACK warning: should determine class dynamically
|
||||
function = context.current_class.resolve_function(name)
|
||||
end
|
||||
elsif receiver.is_a? VariableExpression
|
||||
raise "not implemented instance var:#{receiver}"
|
||||
else
|
||||
#This , how does one say nowadays, smells. Smells of unused polymorphism actually
|
||||
raise "Not sure this is possible, but never good to leave elses open #{receiver} #{receiver.class}"
|
||||
# this lot below should go, since the compile should handle all
|
||||
end
|
||||
raise "No such method error #{3.to_s}:#{name}" if (function.nil?)
|
||||
raise "No receiver error #{inspect}:#{value_receiver}:#{name}" if (value_receiver.nil?)
|
||||
raise "No such method error #{inspect}" if (function.nil?)
|
||||
raise "No receiver error #{inspect}:#{receiver}" if (value_receiver.nil?)
|
||||
call = Vm::CallSite.new( name , value_receiver , params , function)
|
||||
current_function = context.function
|
||||
into.push([]) unless current_function.nil?
|
||||
@ -30,7 +43,6 @@ module Ast
|
||||
after = into.new_block("#{name}#{@@counter+=1}")
|
||||
into.insert_at after
|
||||
into.pop([]) unless current_function.nil?
|
||||
puts "compile call #{function.return_type}"
|
||||
function.return_type
|
||||
end
|
||||
end
|
||||
|
@ -22,7 +22,7 @@ module Boot
|
||||
me = get_function.receiver
|
||||
var_name = get_function.args.first
|
||||
return_to = get_function.return_type
|
||||
index_function = context.object_space.get_or_create_class(:Object).get_or_create_function(:index_of)
|
||||
index_function = context.object_space.get_or_create_class(:Object).resolve_function(:index_of)
|
||||
get_function.push( [me] )
|
||||
get_function.call( index_function )
|
||||
after_body = get_function.new_block("after_index")
|
||||
|
@ -5,6 +5,13 @@ module Core
|
||||
# We use this module syntax to avoid the (ugly) self (also eases searching).
|
||||
module ClassMethods
|
||||
|
||||
def exit context
|
||||
function = Vm::Function.new(:exit , Vm::Integer , [] )
|
||||
ret = Vm::RegisterMachine.instance.exit(function)
|
||||
function.set_return ret
|
||||
function
|
||||
end
|
||||
|
||||
def putstring context
|
||||
function = Vm::Function.new(:putstring , Vm::Integer , [] )
|
||||
ret = Vm::RegisterMachine.instance.write_stdout(function)
|
||||
@ -18,7 +25,7 @@ module Core
|
||||
context.object_space.add_object buffer # and save it (function local variable: a no no)
|
||||
int = putint_function.receiver
|
||||
moved_int = putint_function.new_local
|
||||
utoa = context.object_space.get_or_create_class(:Object).get_or_create_function(:utoa)
|
||||
utoa = context.object_space.get_or_create_class(:Object).resolve_function(:utoa)
|
||||
putint_function.instance_eval do
|
||||
mov( moved_int , int ) # move arg up
|
||||
add( int , buffer ,nil ) # string to write to (add string address to pc)
|
||||
|
@ -28,23 +28,20 @@ module Vm
|
||||
f
|
||||
end
|
||||
|
||||
# way of creating new functions that have not been parsed.
|
||||
def get_or_create_function name
|
||||
# get the function and if not found, try superclasses. raise error if not found
|
||||
def resolve_function name
|
||||
fun = get_function name
|
||||
unless fun or name == :Object
|
||||
supr = @context.object_space.get_or_create_class(@super_class)
|
||||
fun = supr.get_function name
|
||||
puts "#{supr.functions.collect(&:name)} for #{name} GOT #{fun.class}" if name == :index_of
|
||||
end
|
||||
unless fun
|
||||
fun = Core::Kernel.send(name , @context)
|
||||
@functions << fun
|
||||
end
|
||||
raise "Method not found :#{name}, for #{inspect}" unless fun
|
||||
fun
|
||||
end
|
||||
|
||||
def inspect
|
||||
"BootClass #{@name} , super #{@super_class} #{@functions.length} functions"
|
||||
"BootClass #{@name} < #{@super_class}:#{@functions.collect(&:name)}"
|
||||
end
|
||||
def to_s
|
||||
inspect
|
||||
|
@ -64,12 +64,16 @@ module Vm
|
||||
# dummies, just for the other to compile
|
||||
obj = get_or_create_class :Object
|
||||
[:index_of , :_get_instance_variable].each do |f|
|
||||
puts "adding #{f}"
|
||||
puts "Boot Object::#{f}"
|
||||
obj.add_function Boot::Object.send(f , @context)
|
||||
end
|
||||
[:utoa, :putstring,:putint,:fibo,:exit].each do |f|
|
||||
puts "Boot Kernel::#{f}"
|
||||
obj.add_function Core::Kernel.send(f , @context)
|
||||
end
|
||||
obj = get_or_create_class :String
|
||||
[:get , :set].each do |f|
|
||||
puts "adding #{f}"
|
||||
puts "Boot String::#{f}"
|
||||
obj.add_function Boot::String.send(f , @context)
|
||||
end
|
||||
end
|
||||
|
@ -30,14 +30,13 @@ module Vm
|
||||
puts "no function for :#{name} in Meta #{@me_self.inspect}" unless f
|
||||
f
|
||||
end
|
||||
# way of creating new functions that have not been parsed.
|
||||
def get_or_create_function name
|
||||
|
||||
# get the function and if not found, try superclasses. raise error if not found
|
||||
def resolve_function name
|
||||
fun = get_function name
|
||||
unless fun or name == :Object
|
||||
supr = @me_self.context.object_space.get_or_create_class(@super_class)
|
||||
fun = supr.get_function name
|
||||
puts "#{supr.functions.collect(&:name)} for #{name} GOT #{fun.class}"
|
||||
end
|
||||
# TODO THE BOOK says is class A derives from B , then the metaclass of A derives from the metaclass of B
|
||||
# just get to it ! (and stop whimpering)
|
||||
raise "Method not found #{name} , for #{inspect}" unless fun
|
||||
fun
|
||||
end
|
||||
|
||||
|
@ -6,6 +6,27 @@ class TestClass < MiniTest::Test
|
||||
def test_class
|
||||
@string_input = <<HERE
|
||||
class Object
|
||||
def raise()
|
||||
putstring()
|
||||
exit()
|
||||
end
|
||||
def method_missing(name,args)
|
||||
name.raise()
|
||||
end
|
||||
def class()
|
||||
l = @layout
|
||||
return l.class()
|
||||
end
|
||||
def resolve_method(name)
|
||||
clazz = class()
|
||||
function = clazz._get_instance_variable(name)
|
||||
index = clazz.index_of(name)
|
||||
if( function == 0 )
|
||||
name.raise()
|
||||
else
|
||||
return function
|
||||
end
|
||||
end
|
||||
def index_of( name )
|
||||
l = @layout
|
||||
return l.index_of(name)
|
||||
@ -13,10 +34,6 @@ class Object
|
||||
def layout()
|
||||
return @layout
|
||||
end
|
||||
def class()
|
||||
l = @layout
|
||||
return l.class()
|
||||
end
|
||||
end
|
||||
class Class
|
||||
def Class.new_object( length )
|
||||
|
@ -31,12 +31,12 @@ HERE
|
||||
# not my hand off course, found in the net from a basic introduction
|
||||
def test_kernel_fibo
|
||||
int = Vm::Integer.new(Vm::RegisterMachine.instance.receiver_register)
|
||||
fibo = @object_space.get_or_create_class(:Object).get_or_create_function(:fibo)
|
||||
fibo = @object_space.get_or_create_class(:Object).resolve_function(:fibo)
|
||||
main = @object_space.main
|
||||
main.mov int , 10
|
||||
main.call( fibo )
|
||||
main.mov( Vm::RegisterMachine.instance.receiver_register , Vm::RegisterMachine.instance.return_register )
|
||||
putint = @object_space.get_or_create_class(:Object).get_or_create_function(:putint)
|
||||
putint = @object_space.get_or_create_class(:Object).resolve_function(:putint)
|
||||
main.call( putint )
|
||||
@should = [0x0,0x40,0x2d,0xe9,0x1,0x0,0x52,0xe3,0x2,0x0,0xa0,0xd1,0x7,0x0,0x0,0xda,0x1,0x30,0xa0,0xe3,0x0,0x40,0xa0,0xe3,0x4,0x30,0x83,0xe0,0x4,0x40,0x43,0xe0,0x1,0x20,0x42,0xe2,0x1,0x0,0x52,0xe3,0xfa,0xff,0xff,0x1a,0x3,0x0,0xa0,0xe1,0x0,0x80,0xbd,0xe8]
|
||||
@target = [:Object , :fibo]
|
||||
|
Loading…
Reference in New Issue
Block a user