still recoving from previous block - function change. no more exceptions at least

This commit is contained in:
Torsten Ruger 2014-06-11 00:38:46 +03:00
parent e9519d4f05
commit 7cca50cd3a
9 changed files with 72 additions and 74 deletions

View File

@ -73,18 +73,24 @@ module Arm
call.function.return_type call.function.return_type
end end
def main_start entry def main_start context
entry = Vm::Block.new("main_entry",nil,nil)
entry.do_add mov( :fp , 0 ) entry.do_add mov( :fp , 0 )
entry.do_add call( context.function.entry )
entry
end end
def main_exit exit def main_exit context
exit = Vm::Block.new("main_exit",nil,nil)
syscall(exit , 1) syscall(exit , 1)
exit exit
end end
def function_entry block, f_name def function_entry block, f_name
block.do_add push( [:lr] ) block.do_add push( [:lr] )
block
end end
def function_exit entry , f_name def function_exit entry , f_name
entry.do_add pop( [:pc] ) entry.do_add pop( [:pc] )
entry
end end
# assumes string in r0 and r1 and moves them along for the syscall # assumes string in r0 and r1 and moves them along for the syscall
@ -98,11 +104,11 @@ module Arm
# 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)
# not really a function, more a macro, # not really a function, more a macro,
def div10 block, number , remainder def div10 function, number , remainder
# Note about division: devision is MUCH more expensive than one would have thought # Note about division: devision is MUCH more expensive than one would have thought
# And coding it is a bit of a mind leap: it's all about finding a a result that gets the # And coding it is a bit of a mind leap: it's all about finding a a result that gets the
# remainder smaller than an int. i'll post some links sometime. This is from the arm manual # remainder smaller than an int. i'll post some links sometime. This is from the arm manual
block.instance_eval do function.instance_eval do
sub( remainder , number , 10 ) sub( remainder , number , 10 )
sub( number , number , number , shift_lsr: 2) sub( number , number , number , shift_lsr: 2)
add( number , number , number , shift_lsr: 4) add( number , number , number , shift_lsr: 4)

View File

@ -28,7 +28,6 @@ module Ast
context.locals = locals context.locals = locals
context.function = function context.function = function
into = function.body
last_compiled = nil last_compiled = nil
body.each do |b| body.each do |b|
puts "compiling in function #{b}" puts "compiling in function #{b}"
@ -38,9 +37,9 @@ module Ast
return_reg = Vm::Integer.new(Vm::RegisterMachine.instance.return_register) return_reg = Vm::Integer.new(Vm::RegisterMachine.instance.return_register)
if last_compiled.is_a?(Vm::IntegerConstant) or last_compiled.is_a?(Vm::ObjectConstant) if last_compiled.is_a?(Vm::IntegerConstant) or last_compiled.is_a?(Vm::ObjectConstant)
return_reg.load into , last_compiled if last_compiled.register_symbol != return_reg.register_symbol return_reg.load function , last_compiled if last_compiled.register_symbol != return_reg.register_symbol
else else
return_reg.move( into, last_compiled ) if last_compiled.register_symbol != return_reg.register_symbol return_reg.move( function, last_compiled ) if last_compiled.register_symbol != return_reg.register_symbol
end end
function.set_return return_reg function.set_return return_reg

View File

@ -2,6 +2,7 @@ module Ast
class ReturnExpression < Expression class ReturnExpression < Expression
# attr_reader :expression # attr_reader :expression
def compile context def compile context
into = context.function
puts "compiling return expression #{expression}, now return in return_regsiter" puts "compiling return expression #{expression}, now return in return_regsiter"
expression_value = expression.compile(context) expression_value = expression.compile(context)
# copied from function expression: TODO make function # copied from function expression: TODO make function

View File

@ -4,12 +4,13 @@ module Ast
def compile context def compile context
into = context.function into = context.function
while_block = into.new_block "while" while_block = into.new_block "while"
ret = while_block.new_block "return" ret = into.new_block "return"
into.insert_at while_block into.insert_at while_block
puts "compiling while condition #{condition}" puts "compiling while condition #{condition}"
cond_val = condition.compile(context) cond_val = condition.compile(context)
while_block.b ret , condition_code: cond_val.not_operator into.b ret , condition_code: cond_val.not_operator
while_block.branch = ret into.insertion_point.branch = ret
last = nil last = nil
@ -17,7 +18,9 @@ module Ast
puts "compiling in while #{part}" puts "compiling in while #{part}"
last = part.compile(context) last = part.compile(context)
end end
while_block.b while_block into.b while_block
into.insertion_point.branch = while_block
puts "compile while end" puts "compile while end"
into.insert_at ret into.insert_at ret
return last return last

View File

@ -4,22 +4,6 @@ module Core
#there are no Kernel instances, only class methods. #there are no Kernel instances, only class methods.
# 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 main_start block
#TODO extract args into array of strings
Vm::RegisterMachine.instance.main_start block
block
end
def main_exit block
# Machine.exit mov r7 , 0 + swi 0
Vm::RegisterMachine.instance.main_exit block
block
end
def function_entry block , f_name
Vm::RegisterMachine.instance.function_entry block , f_name
end
def function_exit block , f_name
Vm::RegisterMachine.instance.function_exit block , f_name
end
#TODO this is in the wrong place. It is a function that returns a function object #TODO this is in the wrong place. It is a function that returns a function object
# while all other methods add their code into some block. --> kernel # while all other methods add their code into some block. --> kernel
@ -39,19 +23,20 @@ module Core
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).get_or_create_function(:utoa)
body = putint_function.body putint_function.instance_eval do
body.mov( moved_int , int ) #move arg up mov( moved_int , int ) #move arg up
#body.a buffer => int # string to write to #body.a buffer => int # string to write to
body.add( int , buffer ,nil ) # string to write to add( int , buffer ,nil ) # string to write to
body.add(int , int , buffer.length - 3) add(int , int , buffer.length - 3)
body.call( utoa ) call( utoa )
after = body.new_block("#{body.name}_a") after = new_block("#{body.name}_a")
body.insert_at after insert_at after
# And now we "just" have to print it, using the write_stdout # And now we "just" have to print it, using the write_stdout
after.add( int , buffer , nil ) # string to write to add( int , buffer , nil ) # string to write to
after.mov( moved_int , buffer.length ) mov( moved_int , buffer.length )
Vm::RegisterMachine.instance.write_stdout(after) Vm::RegisterMachine.instance.write_stdout(after)
end
putint_function putint_function
end end
@ -65,14 +50,15 @@ module Core
str_addr = utoa_function.receiver str_addr = utoa_function.receiver
number = utoa_function.args.first number = utoa_function.args.first
remainder = utoa_function.new_local remainder = utoa_function.new_local
Vm::RegisterMachine.instance.div10( utoa_function.body , number , remainder ) Vm::RegisterMachine.instance.div10( utoa_function , number , remainder )
# make char out of digit (by using ascii encoding) 48 == "0" # make char out of digit (by using ascii encoding) 48 == "0"
body = utoa_function.body utoa_function.instance_eval do
body.add(remainder , remainder , 48) add( remainder , remainder , 48)
body.strb( remainder, str_addr ) strb( remainder, str_addr )
body.sub( str_addr, str_addr , 1 ) sub( str_addr, str_addr , 1 )
body.cmp( number , 0 ) cmp( number , 0 )
body.callne( utoa_function ) callne( utoa_function )
end
return utoa_function return utoa_function
end end
@ -87,25 +73,29 @@ module Core
count = fibo_function.new_local count = fibo_function.new_local
f1 = fibo_function.new_local f1 = fibo_function.new_local
f2 = fibo_function.new_local f2 = fibo_function.new_local
body = fibo_function.body fibo_function.instance_eval do
body.cmp int , 1 cmp int , 1
body.mov( result, int , condition_code: :le) mov( result, int , condition_code: :le)
body.mov( :pc , :lr , condition_code: :le) mov( :pc , :lr , condition_code: :le)
body.push [ count , f1 , f2 , :lr] push [ count , f1 , f2 , :lr]
body.mov f1 , 1 mov f1 , 1
body.mov f2 , 0 mov f2 , 0
body.sub count , int , 2 sub count , int , 2
end
l = fibo_function.body.new_block("loop") l = fibo_function.new_block("loop")
fibo_function.insert_at l
l.add f1 , f1 , f2 fibo_function.instance_eval do
l.sub f2 , f1 , f2 add f1 , f1 , f2
l.sub count , count , 1 , set_update_status: 1 sub f2 , f1 , f2
l.bpl( l ) sub count , count , 1 , set_update_status: 1
l.mov( result , f1 ) bpl( l )
mov( result , f1 )
pop [ count , f1 , f2 , :pc]
end
fibo_function.set_return result fibo_function.set_return result
l.pop [ count , f1 , f2 , :pc]
fibo_function fibo_function
end end

View File

@ -35,8 +35,7 @@ module Vm
attr_reader :name , :next , :codes , :function , :assigns , :uses attr_reader :name , :next , :codes , :function , :assigns , :uses
attr_accessor :branch attr_accessor :branch
def reachable def reachable ret = []
ret = []
add_next ret add_next ret
add_branch ret add_branch ret
ret ret
@ -98,14 +97,14 @@ module Vm
return if @next.nil? return if @next.nil?
return if ret.include? @next return if ret.include? @next
ret << @next ret << @next
ret + @next.reachable @next.reachable ret
end end
# helper for determining reachable blocks # helper for determining reachable blocks
def add_branch ret def add_branch ret
return if @branch.nil? return if @branch.nil?
return if ret.include? @branch return if ret.include? @branch
ret << @branch ret << @branch
ret + @branch.reachable @branch.reachable ret
end end
end end
end end

View File

@ -13,7 +13,7 @@ module Vm
@super_class = super_class @super_class = super_class
@meta_class = MetaClass.new(self) @meta_class = MetaClass.new(self)
end end
attr_reader :name , :functions , :meta_class attr_reader :name , :functions , :meta_class , :context
def add_function function def add_function function
raise "not a function #{function}" unless function.is_a? Function raise "not a function #{function}" unless function.is_a? Function

View File

@ -31,12 +31,13 @@ module Vm
@classes = {} @classes = {}
@context = Context.new(self) @context = Context.new(self)
@context.current_class = get_or_create_class :Object @context.current_class = get_or_create_class :Object
@main = Function.new("main")
@context.function = @main
#global objects (data) #global objects (data)
@objects = [] @objects = []
@entry = Core::Kernel::main_start Vm::Block.new("main_entry",nil,nil) @entry = RegisterMachine.instance.main_start @context
#main gets executed between entry and exit #main gets executed between entry and exit
@main = Block.new("main",nil,nil) @exit = RegisterMachine.instance.main_exit @context
@exit = Core::Kernel::main_exit Vm::Block.new("main_exit",nil,nil)
boot_classes boot_classes
end end
attr_reader :context , :main , :classes , :entry , :exit attr_reader :context , :main , :classes , :entry , :exit

View File

@ -48,11 +48,11 @@ module Vm
end end
end end
set_return return_type set_return return_type
@exit = Core::Kernel::function_exit( Vm::Block.new("exit" , self , nil) , name ) @exit = RegisterMachine.instance.function_exit( Vm::Block.new("exit" , self , nil) , name )
@return = Block.new("return", self , @exit) @return = Block.new("return", self , @exit)
@body = Block.new("body", self , @return) @body = Block.new("body", self , @return)
@insert_at = @body @insert_at = @body
@entry = Core::Kernel::function_entry( Vm::Block.new("entry" , self , @body) ,name ) @entry = RegisterMachine.instance.function_entry( Vm::Block.new("entry" , self , @body) ,name )
@locals = [] @locals = []
@linked = false # incase link is called twice, we only calculate locals once @linked = false # incase link is called twice, we only calculate locals once
end end
@ -153,7 +153,6 @@ module Vm
# to the current block # to the current block
# also symbols are supported and wrapped as register usages (for bare metal programming) # also symbols are supported and wrapped as register usages (for bare metal programming)
def method_missing(meth, *args, &block) def method_missing(meth, *args, &block)
puts "passing #{meth} , #{args.length} #{args}"
add_code RegisterMachine.instance.send(meth , *args) add_code RegisterMachine.instance.send(meth , *args)
end end
@ -169,7 +168,7 @@ module Vm
if push = b.call_block? if push = b.call_block?
locals = locals_at b locals = locals_at b
if(locals.empty?) if(locals.empty?)
puts "Empty #{b}" puts "Empty #{b.name}"
else else
puts "PUSH #{push}" puts "PUSH #{push}"
push.set_registers(locals) push.set_registers(locals)