From 76ce9aa65450f69e65a618b45cd7e7feddf1d3e7 Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Mon, 19 May 2014 12:18:01 +0300 Subject: [PATCH] improve argument handling for puntint --- lib/core/kernel.rb | 48 ++++++++++++++++++++++------------------------ lib/vm/function.rb | 32 ++++++++++++++++++++++++------- 2 files changed, 48 insertions(+), 32 deletions(-) diff --git a/lib/core/kernel.rb b/lib/core/kernel.rb index 75feb7e2..49fa097e 100644 --- a/lib/core/kernel.rb +++ b/lib/core/kernel.rb @@ -33,47 +33,45 @@ module Core end def putint context , arg = Vm::Integer - arg = Vm::Integer.new( 0 ) - function = Vm::Function.new(:putint , [arg ] , arg ) - buffer = Vm::StringConstant.new(" ") - context.program.add_object buffer - str_addr = Vm::Integer.new(1) - context.str_addr = str_addr - reg1 = Vm::Integer.new(2) - itos_fun = context.program.get_or_create_function(:utoa) - function.body.instance_eval do - mov( reg1 , str_addr ) #move arg up - add( str_addr , buffer ,nil ) # string to write to - add( str_addr , str_addr , (buffer.length-3)) - call( itos_fun ) + putint_function = Vm::Function.new(:putint , [arg] , arg ) + buffer = Vm::StringConstant.new(" ") # create a buffer + context.program.add_object buffer # and save it (function local variable: a no no) + int = putint_function.args.first + moved_int = Vm::Integer.new(1) + utoa = context.program.get_or_create_function(:utoa) + putint_function.body.instance_eval do + mov( moved_int , int ) #move arg up + add( int , buffer ,nil ) # string to write to + add( int , int , (buffer.length-3)) + call( utoa ) # And now we "just" have to print it, using the write_stdout - add( str_addr , buffer , nil ) # string to write to - mov( reg1 , buffer.length ) + add( int , buffer , nil ) # string to write to + mov( moved_int , buffer.length ) end - ret = Vm::CMachine.instance.write_stdout(function.body) - function + Vm::CMachine.instance.write_stdout(putint_function.body) + putint_function end # The conversion to base10 is quite a bit more complicated than i thought. The bulk of it is in div10 # We set up variables, do the devision and write the result to the string # then check if were done and recurse if neccessary # As we write before we recurse (save a push) we write the number backwards + # arguments: string address , integer def utoa context - function = Vm::Function.new(:utoa , [Vm::Integer , Vm::Integer ] ) - block = function.body - str_addr = context.str_addr - number = Vm::Integer.new(str_addr.register + 1) + utoa_function = Vm::Function.new(:utoa , [Vm::Integer , Vm::Integer ] , Vm::Integer ) + str_addr = utoa_function.args[0] + number = utoa_function.args[1] remainder = Vm::Integer.new( number.register + 1) - Vm::CMachine.instance.div10( block , number , remainder ) + Vm::CMachine.instance.div10( utoa_function.body , number , remainder ) # make char out of digit (by using ascii encoding) 48 == "0" - block.instance_eval do + utoa_function.body.instance_eval do add( remainder , remainder , 48 ) strb( remainder, right: str_addr ) sub( str_addr, str_addr , 1 ) cmp( number , 0 ) - callne( function ) + callne( utoa_function ) end - return function + return utoa_function end end diff --git a/lib/vm/function.rb b/lib/vm/function.rb index 17ad6ff7..d0d02078 100644 --- a/lib/vm/function.rb +++ b/lib/vm/function.rb @@ -22,13 +22,31 @@ module Vm def initialize(name , args = [] , return_type = nil) super() @name = name - @args = args - @return_type = return_type - @entry = Core::Kernel::function_entry( Vm::Block.new("#{name}_entry") ,name ) - @exit = Core::Kernel::function_exit( Vm::Block.new("#{name}_exit") , name ) - @body = Block.new("#{name}_body") - @reg_count = 0 - branch_body + @args = Array.new(args.length) + args.each_with_index do |arg , i| + if arg.is_a?(Value) + @args[i] = arg + raise "arg in non std register #{arg.inspect}" unless i == arg.register + else + @args[i] = arg.new(i) + end + end + @return_type = return_type || Vm::Integer + if @return_type.is_a?(Value) + raise "return in non std register #{@return_type.inspect}" unless 0 == @return_type.register + else + @return_type = @return_type.new(0) + end + @entry = Core::Kernel::function_entry( Vm::Block.new("#{name}_entry") ,name ) + @exit = Core::Kernel::function_exit( Vm::Block.new("#{name}_exit") , name ) + @body = Block.new("#{name}_body") + @reg_count = 0 + branch_body + @entry = Core::Kernel::function_entry( Vm::Block.new("#{name}_entry") ,name ) + @exit = Core::Kernel::function_exit( Vm::Block.new("#{name}_exit") , name ) + @body = Block.new("#{name}_body") + @reg_count = 0 + branch_body end attr_reader :args , :entry , :exit , :body , :name attr_accessor :return_type