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
|
syscall( function.insertion_point , 4 ) # 4 == write
|
||||||
end
|
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
|
# the number (a Vm::integer) is (itself) divided by 10, ie overwritten by the result
|
||||||
# and the remainder is overwritten (ie an out argument)
|
# and the remainder is overwritten (ie an out argument)
|
||||||
|
@ -26,9 +26,8 @@ module Ast
|
|||||||
raise "uups #{clazz}.#{name}" unless clazz
|
raise "uups #{clazz}.#{name}" unless clazz
|
||||||
#class qualifier, means call from metaclass
|
#class qualifier, means call from metaclass
|
||||||
clazz = clazz.meta_class
|
clazz = clazz.meta_class
|
||||||
value = clazz
|
puts "CLAZZ #{clazz}"
|
||||||
puts "CLAZZ #{value}"
|
clazz
|
||||||
function = clazz.get_or_create_function(name)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -7,20 +7,33 @@ module Ast
|
|||||||
def compile context
|
def compile context
|
||||||
into = context.function
|
into = context.function
|
||||||
params = args.collect{ |a| a.compile(context) }
|
params = args.collect{ |a| a.compile(context) }
|
||||||
|
puts "compiling receiver #{receiver} (call #{name})"
|
||||||
if receiver.is_a?(NameExpression) and (receiver.name == :self)
|
if receiver.is_a? ModuleName
|
||||||
function = context.current_class.get_or_create_function(name)
|
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)
|
||||||
|
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)
|
value_receiver = Vm::Integer.new(Vm::RegisterMachine.instance.receiver_register)
|
||||||
else
|
else
|
||||||
value_receiver = receiver.compile(context)
|
value_receiver = receiver.compile(context)
|
||||||
function = context.current_class.get_or_create_function(name)
|
# TODO HACK warning: should determine class dynamically
|
||||||
|
function = context.current_class.resolve_function(name)
|
||||||
end
|
end
|
||||||
# this lot below should go, since the compile should handle all
|
elsif receiver.is_a? VariableExpression
|
||||||
if receiver.is_a? VariableExpression
|
|
||||||
raise "not implemented instance var:#{receiver}"
|
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
|
end
|
||||||
raise "No such method error #{3.to_s}:#{name}" if (function.nil?)
|
raise "No such method error #{inspect}" if (function.nil?)
|
||||||
raise "No receiver error #{inspect}:#{value_receiver}:#{name}" if (value_receiver.nil?)
|
raise "No receiver error #{inspect}:#{receiver}" if (value_receiver.nil?)
|
||||||
call = Vm::CallSite.new( name , value_receiver , params , function)
|
call = Vm::CallSite.new( name , value_receiver , params , function)
|
||||||
current_function = context.function
|
current_function = context.function
|
||||||
into.push([]) unless current_function.nil?
|
into.push([]) unless current_function.nil?
|
||||||
@ -30,7 +43,6 @@ module Ast
|
|||||||
after = into.new_block("#{name}#{@@counter+=1}")
|
after = into.new_block("#{name}#{@@counter+=1}")
|
||||||
into.insert_at after
|
into.insert_at after
|
||||||
into.pop([]) unless current_function.nil?
|
into.pop([]) unless current_function.nil?
|
||||||
puts "compile call #{function.return_type}"
|
|
||||||
function.return_type
|
function.return_type
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -22,7 +22,7 @@ module Boot
|
|||||||
me = get_function.receiver
|
me = get_function.receiver
|
||||||
var_name = get_function.args.first
|
var_name = get_function.args.first
|
||||||
return_to = get_function.return_type
|
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.push( [me] )
|
||||||
get_function.call( index_function )
|
get_function.call( index_function )
|
||||||
after_body = get_function.new_block("after_index")
|
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).
|
# We use this module syntax to avoid the (ugly) self (also eases searching).
|
||||||
module ClassMethods
|
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
|
def putstring context
|
||||||
function = Vm::Function.new(:putstring , Vm::Integer , [] )
|
function = Vm::Function.new(:putstring , Vm::Integer , [] )
|
||||||
ret = Vm::RegisterMachine.instance.write_stdout(function)
|
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)
|
context.object_space.add_object buffer # and save it (function local variable: a no no)
|
||||||
int = putint_function.receiver
|
int = putint_function.receiver
|
||||||
moved_int = putint_function.new_local
|
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
|
putint_function.instance_eval do
|
||||||
mov( moved_int , int ) # move arg up
|
mov( moved_int , int ) # move arg up
|
||||||
add( int , buffer ,nil ) # string to write to (add string address to pc)
|
add( int , buffer ,nil ) # string to write to (add string address to pc)
|
||||||
|
@ -28,23 +28,20 @@ module Vm
|
|||||||
f
|
f
|
||||||
end
|
end
|
||||||
|
|
||||||
# way of creating new functions that have not been parsed.
|
# get the function and if not found, try superclasses. raise error if not found
|
||||||
def get_or_create_function name
|
def resolve_function name
|
||||||
fun = get_function name
|
fun = get_function name
|
||||||
unless fun or name == :Object
|
unless fun or name == :Object
|
||||||
supr = @context.object_space.get_or_create_class(@super_class)
|
supr = @context.object_space.get_or_create_class(@super_class)
|
||||||
fun = supr.get_function name
|
fun = supr.get_function name
|
||||||
puts "#{supr.functions.collect(&:name)} for #{name} GOT #{fun.class}" if name == :index_of
|
puts "#{supr.functions.collect(&:name)} for #{name} GOT #{fun.class}" if name == :index_of
|
||||||
end
|
end
|
||||||
unless fun
|
raise "Method not found :#{name}, for #{inspect}" unless fun
|
||||||
fun = Core::Kernel.send(name , @context)
|
|
||||||
@functions << fun
|
|
||||||
end
|
|
||||||
fun
|
fun
|
||||||
end
|
end
|
||||||
|
|
||||||
def inspect
|
def inspect
|
||||||
"BootClass #{@name} , super #{@super_class} #{@functions.length} functions"
|
"BootClass #{@name} < #{@super_class}:#{@functions.collect(&:name)}"
|
||||||
end
|
end
|
||||||
def to_s
|
def to_s
|
||||||
inspect
|
inspect
|
||||||
|
@ -64,12 +64,16 @@ module Vm
|
|||||||
# dummies, just for the other to compile
|
# dummies, just for the other to compile
|
||||||
obj = get_or_create_class :Object
|
obj = get_or_create_class :Object
|
||||||
[:index_of , :_get_instance_variable].each do |f|
|
[:index_of , :_get_instance_variable].each do |f|
|
||||||
puts "adding #{f}"
|
puts "Boot Object::#{f}"
|
||||||
obj.add_function Boot::Object.send(f , @context)
|
obj.add_function Boot::Object.send(f , @context)
|
||||||
end
|
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
|
obj = get_or_create_class :String
|
||||||
[:get , :set].each do |f|
|
[:get , :set].each do |f|
|
||||||
puts "adding #{f}"
|
puts "Boot String::#{f}"
|
||||||
obj.add_function Boot::String.send(f , @context)
|
obj.add_function Boot::String.send(f , @context)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -30,14 +30,13 @@ module Vm
|
|||||||
puts "no function for :#{name} in Meta #{@me_self.inspect}" unless f
|
puts "no function for :#{name} in Meta #{@me_self.inspect}" unless f
|
||||||
f
|
f
|
||||||
end
|
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
|
fun = get_function name
|
||||||
unless fun or name == :Object
|
# TODO THE BOOK says is class A derives from B , then the metaclass of A derives from the metaclass of B
|
||||||
supr = @me_self.context.object_space.get_or_create_class(@super_class)
|
# just get to it ! (and stop whimpering)
|
||||||
fun = supr.get_function name
|
raise "Method not found #{name} , for #{inspect}" unless fun
|
||||||
puts "#{supr.functions.collect(&:name)} for #{name} GOT #{fun.class}"
|
|
||||||
end
|
|
||||||
fun
|
fun
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -6,6 +6,27 @@ class TestClass < MiniTest::Test
|
|||||||
def test_class
|
def test_class
|
||||||
@string_input = <<HERE
|
@string_input = <<HERE
|
||||||
class Object
|
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 )
|
def index_of( name )
|
||||||
l = @layout
|
l = @layout
|
||||||
return l.index_of(name)
|
return l.index_of(name)
|
||||||
@ -13,10 +34,6 @@ class Object
|
|||||||
def layout()
|
def layout()
|
||||||
return @layout
|
return @layout
|
||||||
end
|
end
|
||||||
def class()
|
|
||||||
l = @layout
|
|
||||||
return l.class()
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
class Class
|
class Class
|
||||||
def Class.new_object( length )
|
def Class.new_object( length )
|
||||||
|
@ -31,12 +31,12 @@ HERE
|
|||||||
# not my hand off course, found in the net from a basic introduction
|
# not my hand off course, found in the net from a basic introduction
|
||||||
def test_kernel_fibo
|
def test_kernel_fibo
|
||||||
int = Vm::Integer.new(Vm::RegisterMachine.instance.receiver_register)
|
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 = @object_space.main
|
||||||
main.mov int , 10
|
main.mov int , 10
|
||||||
main.call( fibo )
|
main.call( fibo )
|
||||||
main.mov( Vm::RegisterMachine.instance.receiver_register , Vm::RegisterMachine.instance.return_register )
|
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 )
|
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]
|
@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]
|
@target = [:Object , :fibo]
|
||||||
|
Loading…
Reference in New Issue
Block a user