rename for_type to self_type

and split a base class off TypedMethod
This commit is contained in:
Torsten Ruger
2018-07-06 20:01:17 +03:00
parent 3f80953385
commit acd5cd8f30
19 changed files with 103 additions and 75 deletions

57
lib/parfait/callable.rb Normal file
View File

@@ -0,0 +1,57 @@
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
#
class Callable < Object
attr_reader :self_type , :arguments_type , :frame_type , :binary , :blocks
def initialize( self_type , arguments_type , frame_type)
super()
raise "No class #{self}" unless self_type
raise "For type, not class #{self_type}" unless self_type.is_a?(Type)
@self_type = self_type
init(arguments_type, frame_type)
end
def ==(other)
@self_type == other.self_type
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
@arguments_type = arguments_type
@frame_type = frame_type
@binary = BinaryCode.new(0)
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
@frame_type = @frame_type.add_instance_variable(name,type)
end
def each_binary( &block )
bin = binary
while(bin) do
block.call( bin )
bin = bin.next
end
end
end
end

View File

@@ -83,7 +83,7 @@ module Parfait
found = get_method( method_name )
if found
#puts "redefining method #{method_name}" #TODO, this surely must get more complicated
raise "attempt to redifine method for different type " unless self == found.for_type
raise "attempt to redifine method for different type " unless self == found.self_type
found.init(arguments , frame)
return found
else
@@ -94,7 +94,7 @@ module Parfait
def add_method( method )
raise "not a method #{method.class} #{method.inspect}" unless method.is_a? TypedMethod
raise "syserr #{method.name.class}" unless method.name.is_a? Symbol
if self.is_a?(Class) and (method.for_type != self)
if self.is_a?(Class) and (method.self_type != self)
raise "Adding to wrong class, should be #{method.for_class}"
end
if get_method( method.name )

View File

@@ -1,7 +1,8 @@
require_relative "callable"
# A TypedMethod is static object that primarily holds the executable code.
# It is called typed, because all arguments and variables it uses are "typed",
# that is to say the names are known and form a type (not that the types of the
# variables are known). The objects type is known too, which means all instances
# variables are known). The object's type is known too, which means all instances
# variable names are known (not their respective type).
# It's relation to the method a ruby programmer knows (called VoolMethod) is many to one,
@@ -13,50 +14,24 @@
# - binary: The binary (jumpable) code that the instructions get assembled into
# - 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
# - for_type: The Type the Method is for
# - self_type: The Type the Method is for
module Parfait
class TypedMethod < Object
class TypedMethod < Callable
attr_reader :name , :for_type
attr_reader :arguments_type , :frame_type , :binary , :next_method
attr_reader :name , :next_method
def initialize( type , name , arguments_type , frame_type)
super()
raise "No class #{name}" unless type
raise "For type, not class #{type}" unless type.is_a?(Type)
@for_type = type
def initialize( self_type , name , arguments_type , frame_type)
@name = name
init(arguments_type, frame_type)
super(self_type , arguments_type , frame_type)
end
def ==(other)
return false unless other.is_a?(TypedMethod)
return false if @name != other.name
@for_type == other.for_type
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
@arguments_type = arguments_type
@frame_type = frame_type
@binary = BinaryCode.new(0)
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
@frame_type = @frame_type.add_instance_variable(name,type)
super
end
def rxf_reference_name
@@ -64,16 +39,9 @@ module Parfait
end
def inspect
"#{@for_type.object_class.name}:#{name}(#{arguments_type.inspect})"
"#{@self_type.object_class.name}:#{name}(#{arguments_type.inspect})"
end
def each_binary( &block )
bin = binary
while(bin) do
block.call( bin )
bin = bin.next
end
end
def each_method( &block )
block.call( self )
next_method.each_method( &block ) if next_method

View File

@@ -28,8 +28,8 @@ module Parfait
type.create_method( @name , @args_type , @frame_type)
end
def compiler_for(for_type)
typed_method = create_typed_method(for_type)
def compiler_for(self_type)
typed_method = create_typed_method(self_type)
compiler = Risc::MethodCompiler.new( typed_method )
head = source.to_mom( compiler )
compiler.add_mom(head)