rubyx/lib/mom/method_compiler.rb
Torsten Rüger dced6b12e6 removing builtin as a concept (wip)
the "old" way of generating compilers is now obsolete
we can use ruby code with mom macros to achieve the same
Three step wip
remove old builtin
fix tests (including adding necessary methods)
fixup and inclusion of builtin code to parfait
2019-09-12 13:09:30 +03:00

99 lines
3.1 KiB
Ruby

module Mom
# MethodCompiler is used to generate Mom instructions for methods
# and to instantiate the methods correctly.
class MethodCompiler < CallableCompiler
def initialize( method )
super(method)
end
def source_name
"#{@callable.self_type.name}.#{@callable.name}"
end
def get_method
@callable
end
# sometimes the method is used as source (tb reviewed)
def source
@callable
end
# drop down to risc by converting this compilers instructions to risc.
# and the doing the same for any block_compilers
def to_risc
risc_compiler = Risc::MethodCompiler.new(@callable , mom_instructions)
instructions_to_risc(risc_compiler)
block_compilers.each do |m_comp|
risc_compiler.block_compilers << m_comp.to_risc(@callable)
end
risc_compiler
end
# helper method for builtin mainly
# the class_name is a symbol, which is resolved to the instance_type of that class
#
# return compiler_for_type with the resolved type
#
def self.compiler_for_class( class_name , method_name , args , frame )
raise "create_method #{class_name}.#{class_name.class}" unless class_name.is_a? Symbol
clazz = Parfait.object_space.get_class_by_name! class_name
compiler_for_type( clazz.instance_type , method_name , args , frame)
end
def add_method_to( target )
target.add_method( @callable )
end
def create_block(arg_type , frame_type)
@callable.create_block(arg_type ,frame_type)
end
# create a method for the given type ( Parfait type object)
# method_name is a Symbol
# args a hash that will be converted to a type
# the created method is set as the current and the given type too
# return the compiler
def self.compiler_for_type( type , method_name , args , frame)
raise "create_method #{type.inspect} is not a Type" unless type.is_a? Parfait::Type
raise "Args must be Type #{args}" unless args.is_a?(Parfait::Type)
raise "create_method #{method_name}.#{method_name.class}" unless method_name.is_a? Symbol
method = type.create_method( method_name , args , frame)
self.new(method)
end
# determine how given name need to be accsessed.
# For methods the options are args or frame
def slot_type_for(name)
if index = @callable.arguments_type.variable_index(name)
return ["arg#{index}".to_sym]
end
index = @callable.frame_type.variable_index(name)
raise "no such local or argument #{name}" unless index
return ["local#{index}".to_sym]
end
def add_block_compiler(compiler)
@block_compilers << compiler
end
# return true or false if the given name is in scope (arg/local)
def in_scope?(name)
ret = true if @callable.arguments_type.variable_index(name)
ret = @callable.frame_type.variable_index(name) unless ret
ret
end
# Only for init, as init has no return
# kind of private
def _reset_for_init
@mom_instructions = Label.new(source_name, source_name)
@current = @mom_instructions
end
end
end