coming together, more and more each day
This commit is contained in:
parent
f6711ea49c
commit
04af367bc0
@ -53,17 +53,18 @@ module Arm
|
|||||||
str_lit
|
str_lit
|
||||||
end
|
end
|
||||||
|
|
||||||
def function_call call
|
def function_call into , call
|
||||||
raise "Not FunctionCall #{call.inspect}" unless call.is_a? Vm::FunctionCall
|
raise "Not FunctionCall #{call.inspect}" unless call.is_a? Vm::FunctionCall
|
||||||
block.add_code bl( :left => call.function )
|
raise "Not linked #{call.inspect}" unless call.function
|
||||||
call.function.return_value
|
into.add_code bl( :left => call.function )
|
||||||
|
call.function.return_type
|
||||||
end
|
end
|
||||||
|
|
||||||
def main_start entry
|
def main_start entry
|
||||||
entry.add_code mov( :left => :fp , :right => 0 )
|
entry.add_code mov( :left => :fp , :right => 0 )
|
||||||
end
|
end
|
||||||
def main_exit exit
|
def main_exit exit
|
||||||
exit.add_code syscall(1)
|
syscall(exit , 1)
|
||||||
end
|
end
|
||||||
def function_entry block, f_name
|
def function_entry block, f_name
|
||||||
# entry.add_code push( :regs => [:lr] )
|
# entry.add_code push( :regs => [:lr] )
|
||||||
@ -72,17 +73,21 @@ module Arm
|
|||||||
def function_exit entry , f_name
|
def function_exit entry , f_name
|
||||||
entry.add_code mov( :left => :pc , :right => :lr )
|
entry.add_code mov( :left => :pc , :right => :lr )
|
||||||
end
|
end
|
||||||
def putstring
|
|
||||||
put = Vm::Block.new("putstring_code")
|
# assumes string in r0 and r1 and moves them along for the syscall
|
||||||
# should be another level of indirection, ie write(io,str)
|
def write_stdout block
|
||||||
put.add_code mov( :left => :r2 , :right => :r1 )
|
block.add_code mov( :left => :r2 , :right => :r1 )
|
||||||
put.add_code mov( :left => :r1 , :right => :r0 )
|
block.add_code mov( :left => :r1 , :right => :r0 )
|
||||||
put.add_code mov( :left => :r0 , :right => 1 ) #stdout
|
block.add_code mov( :left => :r0 , :right => 1 ) # 1 == stdout
|
||||||
put.add_code syscall(4)
|
syscall( block , 4 )
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
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
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -27,12 +27,13 @@ module Ast
|
|||||||
args << arg_value
|
args << arg_value
|
||||||
end
|
end
|
||||||
function = Vm::Function.new(name , args )
|
function = Vm::Function.new(name , args )
|
||||||
|
context.program.add_function function
|
||||||
|
|
||||||
parent_locals = context.locals
|
parent_locals = context.locals
|
||||||
parent_function = context.function
|
parent_function = context.function
|
||||||
context.locals = locals
|
context.locals = locals
|
||||||
context.function = function
|
context.function = function
|
||||||
|
|
||||||
context.program.add_function function
|
|
||||||
into = function.entry
|
into = function.entry
|
||||||
block.each do |b|
|
block.each do |b|
|
||||||
compiled = b.compile(context , into)
|
compiled = b.compile(context , into)
|
||||||
|
@ -5,14 +5,16 @@ module Ast
|
|||||||
class FuncallExpression < Expression
|
class FuncallExpression < Expression
|
||||||
attr_reader :name, :args
|
attr_reader :name, :args
|
||||||
def initialize name, args
|
def initialize name, args
|
||||||
@name , @args = name , args
|
@name , @args = name.to_sym , args
|
||||||
end
|
end
|
||||||
def compile context , into
|
def compile context , into
|
||||||
params = args.collect{ |a| a.compile(context, into) }
|
params = args.collect{ |a| a.compile(context, into) }
|
||||||
fun = Vm::FunctionCall.new( name , params )
|
function = context.program.get_or_create_function(name)
|
||||||
fun.load_args into
|
raise "Forward declaration not implemented (#{name}) #{inspect}" if function == nil
|
||||||
fun.do_call into
|
call = Vm::FunctionCall.new( name , params , function)
|
||||||
fun
|
call.load_args into
|
||||||
|
call.do_call into
|
||||||
|
call
|
||||||
end
|
end
|
||||||
|
|
||||||
def inspect
|
def inspect
|
||||||
|
@ -18,9 +18,16 @@ module Core
|
|||||||
def function_exit block , f_name
|
def function_exit block , f_name
|
||||||
Vm::CMachine.instance.function_exit block , f_name
|
Vm::CMachine.instance.function_exit block , f_name
|
||||||
end
|
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
|
def putstring
|
||||||
# should unwrap from string to char*
|
function = Vm::Function.new(:putstring , [Vm::Integer , Vm::Integer ] )
|
||||||
Vm::CMachine.instance.putstring
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ module Vm
|
|||||||
branch_body
|
branch_body
|
||||||
end
|
end
|
||||||
attr_reader :args , :entry , :exit , :body , :name
|
attr_reader :args , :entry , :exit , :body , :name
|
||||||
|
attr_accessor :return_type
|
||||||
|
|
||||||
def arity
|
def arity
|
||||||
@args.length
|
@args.length
|
||||||
|
@ -4,22 +4,22 @@ module Vm
|
|||||||
|
|
||||||
class FunctionCall < Value
|
class FunctionCall < Value
|
||||||
|
|
||||||
def initialize(name , args)
|
def initialize(name , args , function )
|
||||||
@name = name
|
@name = name
|
||||||
@args = args
|
@args = args
|
||||||
@function = nil
|
@function = function
|
||||||
end
|
end
|
||||||
attr_reader :function , :args , :name
|
attr_reader :function , :args , :name
|
||||||
|
|
||||||
def load_args into
|
def load_args into
|
||||||
args.each_with_index do |arg , index|
|
args.each_with_index do |arg , index|
|
||||||
puts "load " + arg.inspect
|
puts "load " + arg.inspect
|
||||||
into.add_code arg.move("r#{index}".to_sym)
|
arg.load( into , index )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def do_call into
|
def do_call into
|
||||||
into.add_code Machine.instance.function_call self
|
into.add_code CMachine.instance.function_call into , self
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -45,20 +45,21 @@ module Vm
|
|||||||
|
|
||||||
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
|
||||||
|
raise "syserr " unless function.name.is_a? Symbol
|
||||||
@functions << function
|
@functions << function
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_function name
|
def get_function name
|
||||||
name = name.to_sym
|
name = name.to_sym
|
||||||
@functions.detect{ |f| (f.name == name) }
|
@functions.detect{ |f| f.name == name }
|
||||||
end
|
end
|
||||||
|
|
||||||
# preferred way of creating new functions (also forward declarations, will flag unresolved later)
|
# preferred way of creating new functions (also forward declarations, will flag unresolved later)
|
||||||
def get_or_create_function name
|
def get_or_create_function name
|
||||||
fun = get_function name
|
fun = get_function name
|
||||||
unless fun
|
unless fun
|
||||||
puts @functions.inspect
|
|
||||||
fun = Core::Kernel.send(name)
|
fun = Core::Kernel.send(name)
|
||||||
|
raise "no such function '#{name}'" if fun == nil
|
||||||
@functions << fun
|
@functions << fun
|
||||||
end
|
end
|
||||||
fun
|
fun
|
||||||
|
@ -5,7 +5,7 @@ def fibonaccit(n)
|
|||||||
tmp = a
|
tmp = a
|
||||||
a = b
|
a = b
|
||||||
b = tmp + b
|
b = tmp + b
|
||||||
puts(b)
|
putstring(b)
|
||||||
n = n - 1
|
n = n - 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user