From 04af367bc0e116b736456aed1260e08670929a47 Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Tue, 13 May 2014 21:06:12 +0300 Subject: [PATCH] coming together, more and more each day --- lib/arm/arm_machine.rb | 31 ++++++++++++++++++------------- lib/ast/function_expression.rb | 3 ++- lib/ast/operator_expressions.rb | 12 +++++++----- lib/core/kernel.rb | 11 +++++++++-- lib/vm/function.rb | 1 + lib/vm/function_call.rb | 8 ++++---- lib/vm/program.rb | 5 +++-- test/runners/fibo_while.rb | 2 +- 8 files changed, 45 insertions(+), 28 deletions(-) diff --git a/lib/arm/arm_machine.rb b/lib/arm/arm_machine.rb index ace8e619..a1eb4247 100644 --- a/lib/arm/arm_machine.rb +++ b/lib/arm/arm_machine.rb @@ -53,17 +53,18 @@ module Arm str_lit end - def function_call call + def function_call into , call raise "Not FunctionCall #{call.inspect}" unless call.is_a? Vm::FunctionCall - block.add_code bl( :left => call.function ) - call.function.return_value + raise "Not linked #{call.inspect}" unless call.function + into.add_code bl( :left => call.function ) + call.function.return_type end def main_start entry entry.add_code mov( :left => :fp , :right => 0 ) end def main_exit exit - exit.add_code syscall(1) + syscall(exit , 1) end def function_entry block, f_name # entry.add_code push( :regs => [:lr] ) @@ -72,17 +73,21 @@ module Arm def function_exit entry , f_name entry.add_code mov( :left => :pc , :right => :lr ) end - def putstring - put = Vm::Block.new("putstring_code") - # should be another level of indirection, ie write(io,str) - put.add_code mov( :left => :r2 , :right => :r1 ) - put.add_code mov( :left => :r1 , :right => :r0 ) - put.add_code mov( :left => :r0 , :right => 1 ) #stdout - put.add_code syscall(4) + + # assumes string in r0 and r1 and moves them along for the syscall + def write_stdout block + block.add_code mov( :left => :r2 , :right => :r1 ) + block.add_code mov( :left => :r1 , :right => :r0 ) + block.add_code mov( :left => :r0 , :right => 1 ) # 1 == stdout + syscall( block , 4 ) end + private - def syscall num - [mov( :left => :r7 , :right => num ) , swi( :left => 0 )] + + def syscall block , num + block.add_code mov( :left => :r7 , :right => num ) + block.add_code swi( :left => 0 ) + Vm::Integer.new(0) #small todo, is this actually correct for all (that they return int) end end diff --git a/lib/ast/function_expression.rb b/lib/ast/function_expression.rb index b98fce24..701a1671 100644 --- a/lib/ast/function_expression.rb +++ b/lib/ast/function_expression.rb @@ -27,12 +27,13 @@ module Ast args << arg_value end function = Vm::Function.new(name , args ) + context.program.add_function function + parent_locals = context.locals parent_function = context.function context.locals = locals context.function = function - context.program.add_function function into = function.entry block.each do |b| compiled = b.compile(context , into) diff --git a/lib/ast/operator_expressions.rb b/lib/ast/operator_expressions.rb index 4a287363..2688dc21 100644 --- a/lib/ast/operator_expressions.rb +++ b/lib/ast/operator_expressions.rb @@ -5,14 +5,16 @@ module Ast class FuncallExpression < Expression attr_reader :name, :args def initialize name, args - @name , @args = name , args + @name , @args = name.to_sym , args end def compile context , into params = args.collect{ |a| a.compile(context, into) } - fun = Vm::FunctionCall.new( name , params ) - fun.load_args into - fun.do_call into - fun + function = context.program.get_or_create_function(name) + raise "Forward declaration not implemented (#{name}) #{inspect}" if function == nil + call = Vm::FunctionCall.new( name , params , function) + call.load_args into + call.do_call into + call end def inspect diff --git a/lib/core/kernel.rb b/lib/core/kernel.rb index 032a4a0f..79e1adbf 100644 --- a/lib/core/kernel.rb +++ b/lib/core/kernel.rb @@ -18,9 +18,16 @@ module Core def function_exit block , f_name Vm::CMachine.instance.function_exit block , f_name end + + #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 def putstring - # should unwrap from string to char* - Vm::CMachine.instance.putstring + function = Vm::Function.new(:putstring , [Vm::Integer , Vm::Integer ] ) + block = function.body + # should be another level of indirection, ie write(io,str) + ret = Vm::CMachine.instance.write_stdout(block) + function.return_type = ret + function end end diff --git a/lib/vm/function.rb b/lib/vm/function.rb index b411aa3f..f98fe423 100644 --- a/lib/vm/function.rb +++ b/lib/vm/function.rb @@ -29,6 +29,7 @@ module Vm branch_body end attr_reader :args , :entry , :exit , :body , :name + attr_accessor :return_type def arity @args.length diff --git a/lib/vm/function_call.rb b/lib/vm/function_call.rb index 15d85f8a..e19502f9 100644 --- a/lib/vm/function_call.rb +++ b/lib/vm/function_call.rb @@ -4,22 +4,22 @@ module Vm class FunctionCall < Value - def initialize(name , args) + def initialize(name , args , function ) @name = name @args = args - @function = nil + @function = function end attr_reader :function , :args , :name def load_args into args.each_with_index do |arg , index| puts "load " + arg.inspect - into.add_code arg.move("r#{index}".to_sym) + arg.load( into , index ) end end def do_call into - into.add_code Machine.instance.function_call self + into.add_code CMachine.instance.function_call into , self end end end diff --git a/lib/vm/program.rb b/lib/vm/program.rb index 13927f41..c9ec6bc9 100644 --- a/lib/vm/program.rb +++ b/lib/vm/program.rb @@ -45,20 +45,21 @@ module Vm def add_function function raise "not a function #{function}" unless function.is_a? Function + raise "syserr " unless function.name.is_a? Symbol @functions << function end def get_function name name = name.to_sym - @functions.detect{ |f| (f.name == name) } + @functions.detect{ |f| f.name == name } end # preferred way of creating new functions (also forward declarations, will flag unresolved later) def get_or_create_function name fun = get_function name unless fun - puts @functions.inspect fun = Core::Kernel.send(name) + raise "no such function '#{name}'" if fun == nil @functions << fun end fun diff --git a/test/runners/fibo_while.rb b/test/runners/fibo_while.rb index 922ea5ab..42aa382a 100644 --- a/test/runners/fibo_while.rb +++ b/test/runners/fibo_while.rb @@ -5,7 +5,7 @@ def fibonaccit(n) tmp = a a = b b = tmp + b - puts(b) + putstring(b) n = n - 1 end end