rubyx/lib/register/method_source.rb

99 lines
4.1 KiB
Ruby
Raw Normal View History

2014-07-14 13:06:09 +02:00
2015-10-22 17:16:29 +02:00
module Register
# the static info of a method (with its compiled code, argument names etc ) is part of the
# runtime, ie found in Parfait::Method
2015-05-30 11:20:39 +02:00
# Code-wise Methods are made up from a list of Blocks, in a similar way blocks are made up of
# Instructions. The function starts with one block, and that has a start and end (return)
# Blocks can be linked in two ways:
# -linear: flow continues from one to the next as they are sequential both logically and
# "physically" use the block set_next for this.
# This "straight line", there must be a continuous sequence from body to return
# Linear blocks may be created from an existing block with new_block
# - branched: You create new blocks using function.new_block which gets added "after" return
# These (eg if/while) blocks may themselves have linear blocks ,but the last of these
# MUST have an uncoditional branch. And remember, all roads lead to return.
2015-07-03 19:13:03 +02:00
class MethodSource
# create method does two things
# first it creates the parfait method, for the given class, with given argument names
2015-07-03 19:13:03 +02:00
# second, it creates MethodSource and attaches it to the method
#
# compile code then works with the method, but adds code tot the info
2015-09-23 17:35:37 +02:00
def self.create_method( class_name , return_type , method_name , args)
2015-08-17 01:37:07 +02:00
raise "create_method #{class_name}.#{class_name.class}" unless class_name.is_a? Symbol
raise "create_method #{method_name}.#{method_name.class}" unless method_name.is_a? Symbol
2015-10-22 17:16:29 +02:00
clazz = Register.machine.space.get_class_by_name class_name
raise "No such class #{class_name}" unless clazz
arguments = []
args.each_with_index do | arg , index |
unless arg.is_a? Parfait::Variable
2015-10-22 17:16:29 +02:00
raise "not type #{arg}:#{arg.class}" unless Register.machine.space.get_class_by_name arg
arg = Parfait::Variable.new arg , "arg#{index}".to_sym
end
arguments << arg
end
2015-10-22 17:16:29 +02:00
method = clazz.create_instance_method( method_name , Register.new_list(arguments))
2015-09-23 17:35:37 +02:00
method.source = MethodSource.new(method , return_type)
method
2014-07-10 16:14:38 +02:00
end
# just passing the method object in for Instructions to make decisions (later)
2015-09-23 17:35:37 +02:00
def initialize method , return_type
init( method , return_type)
end
def init method , return_type = nil
2015-10-14 13:02:34 +02:00
set_return_type( return_type )
@instructions = @current = Label.new(self, "Method_#{method.name}")
add_code enter = Register.save_return(self, :message , :return_address)
add_code Label.new( method, "return")
# move the current message to new_message
add_code RegisterTransfer.new(self, Register.message_reg , Register.new_message_reg )
# and restore the message from saved value in new_message
add_code Register.get_slot(self,:new_message , :caller , :message )
#load the return address into pc, affecting return. (other cpus have commands for this, but not arm)
add_code FunctionReturn.new( self , Register.new_message_reg , Register.resolve_index(:message , :return_address) )
@current = enter
2015-06-01 07:33:51 +02:00
@constants = []
2014-07-10 16:14:38 +02:00
end
attr_reader :constants , :return_type
attr_accessor :current , :receiver , :instructions
2014-07-10 16:14:38 +02:00
2015-10-14 13:02:34 +02:00
def set_return_type type
return if type.nil?
2015-10-22 17:16:29 +02:00
raise "not type #{type}" unless Register.machine.space.get_class_by_name type
2015-10-14 13:02:34 +02:00
@return_type = type
end
# add an instruction after the current (insertion point)
# the added instruction will become the new insertion point
def add_code instruction
2015-10-22 17:16:29 +02:00
unless instruction.is_a?(Instruction)
2015-07-18 18:02:54 +02:00
raise instruction.to_s
2015-05-30 11:20:39 +02:00
end
@current.insert(instruction) #insert after current
@current = instruction
self
2014-07-10 16:14:38 +02:00
end
# set the insertion point (where code is added with add_code)
def current ins
@current = ins
self
end
def byte_length
@instructions.byte_length
end
# position of the function is the position of the entry block, is where we call
def set_position at
2014-09-11 14:19:29 +02:00
at += 8 #for the 2 header words
@instructions.set_position at
end
2015-07-18 15:12:50 +02:00
2014-07-10 16:14:38 +02:00
end
2014-07-10 16:14:38 +02:00
end