2015-05-20 15:43:26 +02:00
|
|
|
# A Method (at runtime , sis in Parfait) is static object that primarily holds the executable
|
|
|
|
# code.
|
|
|
|
|
|
|
|
# For reflection also holds arguments and such
|
|
|
|
|
|
|
|
#
|
|
|
|
|
|
|
|
module Parfait
|
|
|
|
|
|
|
|
# static description of a method
|
|
|
|
# name
|
2015-09-27 13:30:41 +02:00
|
|
|
# arguments
|
2015-05-20 15:43:26 +02:00
|
|
|
# known local variable names
|
|
|
|
# executable code
|
|
|
|
|
2015-10-22 17:16:29 +02:00
|
|
|
# ps, the compiler injects its own info, see Register::MethodSource
|
2015-05-20 15:43:26 +02:00
|
|
|
|
|
|
|
|
|
|
|
class Method < Object
|
|
|
|
|
2015-09-27 13:30:41 +02:00
|
|
|
def initialize clazz , name , arguments
|
2015-05-21 20:50:17 +02:00
|
|
|
super()
|
2015-05-24 12:53:49 +02:00
|
|
|
raise "No class #{name}" unless clazz
|
2015-07-21 14:40:25 +02:00
|
|
|
self.for_class = clazz
|
|
|
|
self.name = name
|
2015-10-23 13:41:47 +02:00
|
|
|
self.binary = BinaryCode.new name
|
2015-09-27 13:30:41 +02:00
|
|
|
raise "Wrong type, expect List not #{arguments.class}" unless arguments.is_a? List
|
|
|
|
arguments.each do |var|
|
|
|
|
raise "Must be variable argument, not #{var}" unless var.is_a? Variable
|
|
|
|
end
|
|
|
|
self.arguments = arguments
|
2015-07-21 14:40:25 +02:00
|
|
|
self.locals = List.new
|
2015-05-20 15:43:26 +02:00
|
|
|
end
|
2015-10-23 13:41:47 +02:00
|
|
|
attributes [:name , :source , :instructions , :binary ,:arguments , :for_class, :locals ]
|
2015-05-20 15:43:26 +02:00
|
|
|
|
|
|
|
|
|
|
|
# determine whether this method has an argument by the name
|
|
|
|
def has_arg name
|
2015-08-17 01:37:07 +02:00
|
|
|
raise "has_arg #{name}.#{name.class}" unless name.is_a? Symbol
|
2015-09-27 15:06:48 +02:00
|
|
|
max = self.arguments.get_length
|
|
|
|
counter = 1
|
|
|
|
while( counter <= max )
|
|
|
|
if( self.arguments.get(counter).name == name)
|
|
|
|
return counter
|
|
|
|
end
|
|
|
|
counter = counter + 1
|
|
|
|
end
|
|
|
|
return nil
|
2015-05-20 15:43:26 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
# determine if method has a local variable or tmp (anonymous local) by given name
|
|
|
|
def has_local name
|
2015-08-17 01:37:07 +02:00
|
|
|
raise "has_local #{name}.#{name.class}" unless name.is_a? Symbol
|
2015-09-27 15:06:48 +02:00
|
|
|
max = self.locals.get_length
|
|
|
|
counter = 1
|
|
|
|
while( counter <= max )
|
|
|
|
if( self.locals.get(counter).name == name)
|
|
|
|
return counter
|
|
|
|
end
|
|
|
|
counter = counter + 1
|
|
|
|
end
|
|
|
|
return nil
|
2015-05-20 15:43:26 +02:00
|
|
|
end
|
|
|
|
|
2015-09-27 15:06:48 +02:00
|
|
|
def ensure_local name , type
|
2015-05-20 15:43:26 +02:00
|
|
|
index = has_local name
|
|
|
|
return index if index
|
2015-09-27 15:06:48 +02:00
|
|
|
var = Variable.new( type , name)
|
|
|
|
self.locals.push var
|
2015-07-21 14:40:25 +02:00
|
|
|
self.locals.get_length
|
2015-05-20 15:43:26 +02:00
|
|
|
end
|
|
|
|
|
2015-06-19 18:50:53 +02:00
|
|
|
def sof_reference_name
|
2015-07-21 14:40:25 +02:00
|
|
|
self.name
|
2015-06-19 18:50:53 +02:00
|
|
|
end
|
|
|
|
|
2015-09-27 15:06:48 +02:00
|
|
|
def inspect
|
|
|
|
"#{self.for_class.name}:#{name}(#{arguments.inspect})"
|
|
|
|
end
|
2015-10-28 20:38:52 +01:00
|
|
|
|
|
|
|
def total_byte_length
|
|
|
|
self.instructions.total_byte_length
|
|
|
|
end
|
|
|
|
|
|
|
|
# position of the function is the position of the entry block, is where we call
|
|
|
|
def set_position at
|
|
|
|
at += 8 #for the 2 header words
|
|
|
|
self.instructions.set_position at
|
|
|
|
end
|
|
|
|
|
2015-05-20 15:43:26 +02:00
|
|
|
end
|
|
|
|
end
|