2018-07-06 19:01:17 +02:00
|
|
|
module Parfait
|
|
|
|
|
|
|
|
# Callable is an interface that Blocks and CallableMethods follow
|
|
|
|
#
|
|
|
|
# This mean they share the following state
|
|
|
|
# - self_type: The type of self, ie an object describing instance valriable names
|
|
|
|
# - arguments_type: A type object describing the arguments (name+types) to be passed
|
|
|
|
# - frame_type: A type object describing the local variables that the method has
|
|
|
|
# - binary: The binary (jumpable) code that instructions get assembled into
|
|
|
|
# - blocks: linked list of blocks inside this method/block
|
2018-08-11 18:15:34 +02:00
|
|
|
# - next_callable: next block/method at same level
|
2018-07-06 19:01:17 +02:00
|
|
|
#
|
|
|
|
class Callable < Object
|
|
|
|
|
2018-08-11 18:15:34 +02:00
|
|
|
attr :type, :self_type , :arguments_type , :frame_type , :binary
|
|
|
|
attr :blocks , :name
|
|
|
|
attr :next_callable
|
|
|
|
|
|
|
|
def self.type_length
|
|
|
|
8
|
|
|
|
end
|
|
|
|
|
2018-07-30 09:21:43 +02:00
|
|
|
def initialize( name , self_type , arguments_type , frame_type)
|
2018-07-06 19:01:17 +02:00
|
|
|
super()
|
|
|
|
raise "No class #{self}" unless self_type
|
|
|
|
raise "For type, not class #{self_type}" unless self_type.is_a?(Type)
|
2018-07-30 09:21:43 +02:00
|
|
|
raise "Mixup" unless name.is_a?(Symbol)
|
2018-08-11 18:15:34 +02:00
|
|
|
self.name = name
|
|
|
|
self.self_type = self_type
|
2018-07-06 19:01:17 +02:00
|
|
|
init(arguments_type, frame_type)
|
|
|
|
end
|
|
|
|
|
|
|
|
def ==(other)
|
2018-08-11 18:15:34 +02:00
|
|
|
self_type == other.self_type
|
2018-07-06 19:01:17 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
# (re) init with given args and frame types
|
|
|
|
def init(arguments_type, frame_type)
|
|
|
|
raise "Wrong argument type, expect Type not #{arguments_type.class}" unless arguments_type.is_a? Type
|
|
|
|
raise "Wrong frame type, expect Type not #{frame_type.class}" unless frame_type.is_a? Type
|
2018-08-11 18:15:34 +02:00
|
|
|
self.arguments_type = arguments_type
|
|
|
|
self.frame_type = frame_type
|
|
|
|
self.binary = BinaryCode.new(0)
|
2018-07-06 19:01:17 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
# determine if method has a local variable or tmp (anonymous local) by given name
|
|
|
|
def has_local( name )
|
|
|
|
raise "has_local #{name}.#{name.class}" unless name.is_a? Symbol
|
|
|
|
frame_type.variable_index( name )
|
|
|
|
end
|
|
|
|
|
|
|
|
def add_local( name , type )
|
|
|
|
index = has_local( name )
|
|
|
|
return index if index
|
2018-08-11 18:15:34 +02:00
|
|
|
self.frame_type = frame_type.add_instance_variable(name,type)
|
2018-07-06 19:01:17 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
def each_binary( &block )
|
|
|
|
bin = binary
|
|
|
|
while(bin) do
|
|
|
|
block.call( bin )
|
2018-08-12 13:48:20 +02:00
|
|
|
bin = bin.next_code
|
2018-07-06 19:01:17 +02:00
|
|
|
end
|
|
|
|
end
|
2018-07-07 08:11:09 +02:00
|
|
|
|
|
|
|
def set_next( method )
|
2018-08-11 18:15:34 +02:00
|
|
|
self.next_callable = method
|
2018-07-07 08:11:09 +02:00
|
|
|
end
|
|
|
|
|
2018-07-06 19:01:17 +02:00
|
|
|
end
|
|
|
|
end
|