2018-03-11 12:32:42 +01:00
|
|
|
module Risc
|
2016-12-09 12:56:13 +01:00
|
|
|
|
2018-06-30 22:26:28 +02:00
|
|
|
# MethodCompiler (old name) is used to generate risc instructions for methods
|
2018-03-11 12:32:42 +01:00
|
|
|
# and to instantiate the methods correctly. Most of the init is typed layer stuff,
|
|
|
|
# but there is some logic too.
|
2015-10-28 20:36:41 +01:00
|
|
|
|
2018-07-10 21:02:11 +02:00
|
|
|
class MethodCompiler < CallableCompiler
|
2015-05-08 14:10:30 +02:00
|
|
|
|
2017-01-17 20:23:58 +01:00
|
|
|
def initialize( method )
|
2018-07-30 09:26:11 +02:00
|
|
|
super(method)
|
2015-09-19 17:56:18 +02:00
|
|
|
end
|
2018-06-29 12:03:19 +02:00
|
|
|
|
2018-08-01 15:27:34 +02:00
|
|
|
#include block_compilers constants
|
|
|
|
def constants
|
|
|
|
block_compilers.inject(@constants.dup){|all, compiler| all += compiler.constants}
|
|
|
|
end
|
|
|
|
|
2018-07-10 21:02:11 +02:00
|
|
|
def source_name
|
2018-07-30 09:26:11 +02:00
|
|
|
"#{@callable.self_type.name}.#{@callable.name}"
|
2018-07-10 21:02:11 +02:00
|
|
|
end
|
2018-07-30 09:26:11 +02:00
|
|
|
|
2018-07-09 18:32:17 +02:00
|
|
|
def get_method
|
2018-07-30 09:26:11 +02:00
|
|
|
@callable
|
2018-07-09 18:32:17 +02:00
|
|
|
end
|
2018-07-30 09:26:11 +02:00
|
|
|
|
2018-07-09 18:32:17 +02:00
|
|
|
# sometimes the method is used as source (tb reviewed)
|
|
|
|
def source
|
2018-07-30 09:26:11 +02:00
|
|
|
@callable
|
2018-07-09 18:32:17 +02:00
|
|
|
end
|
2018-07-30 09:26:11 +02:00
|
|
|
|
2018-06-29 12:03:19 +02:00
|
|
|
# helper method for builtin mainly
|
|
|
|
# the class_name is a symbol, which is resolved to the instance_type of that class
|
|
|
|
#
|
2018-07-09 15:48:23 +02:00
|
|
|
# return compiler_for_type with the resolved type
|
2018-06-29 12:03:19 +02:00
|
|
|
#
|
|
|
|
def self.compiler_for_class( class_name , method_name , args , frame )
|
2015-10-28 20:36:41 +01:00
|
|
|
raise "create_method #{class_name}.#{class_name.class}" unless class_name.is_a? Symbol
|
2016-12-30 13:10:49 +01:00
|
|
|
clazz = Parfait.object_space.get_class_by_name! class_name
|
2018-07-09 15:48:23 +02:00
|
|
|
compiler_for_type( clazz.instance_type , method_name , args , frame)
|
2015-10-28 20:36:41 +01:00
|
|
|
end
|
|
|
|
|
2018-07-09 18:32:17 +02:00
|
|
|
def add_method_to( target )
|
2018-07-30 09:26:11 +02:00
|
|
|
target.add_method( @callable )
|
2018-07-09 18:32:17 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
def create_block(arg_type , frame_type)
|
2018-07-30 09:26:11 +02:00
|
|
|
@callable.create_block(arg_type ,frame_type)
|
2018-07-09 18:32:17 +02:00
|
|
|
end
|
2018-07-30 09:26:11 +02:00
|
|
|
|
2016-12-14 12:24:42 +01:00
|
|
|
# create a method for the given type ( Parfait type object)
|
2015-10-28 20:36:41 +01:00
|
|
|
# method_name is a Symbol
|
2016-12-14 12:24:42 +01:00
|
|
|
# args a hash that will be converted to a type
|
|
|
|
# the created method is set as the current and the given type too
|
2018-06-29 12:03:19 +02:00
|
|
|
# return the compiler
|
2018-07-09 15:48:23 +02:00
|
|
|
def self.compiler_for_type( type , method_name , args , frame)
|
2016-12-14 12:24:42 +01:00
|
|
|
raise "create_method #{type.inspect} is not a Type" unless type.is_a? Parfait::Type
|
2018-03-18 17:38:35 +01:00
|
|
|
raise "Args must be Type #{args}" unless args.is_a?(Parfait::Type)
|
2015-10-28 20:36:41 +01:00
|
|
|
raise "create_method #{method_name}.#{method_name.class}" unless method_name.is_a? Symbol
|
2018-03-18 17:38:35 +01:00
|
|
|
method = type.create_method( method_name , args , frame)
|
2017-01-17 20:23:58 +01:00
|
|
|
self.new(method)
|
2015-10-28 20:36:41 +01:00
|
|
|
end
|
2018-07-09 15:48:23 +02:00
|
|
|
|
2018-07-09 16:53:56 +02:00
|
|
|
# determine how given name need to be accsessed.
|
|
|
|
# For methods the options are args or frame
|
|
|
|
def slot_type_for(name)
|
2018-07-30 09:26:11 +02:00
|
|
|
if @callable.arguments_type.variable_index(name)
|
2018-07-09 16:53:56 +02:00
|
|
|
type = :arguments
|
|
|
|
else
|
|
|
|
type = :frame
|
|
|
|
end
|
|
|
|
[type , name]
|
|
|
|
end
|
|
|
|
|
2018-07-09 15:48:23 +02:00
|
|
|
def add_block_compiler(compiler)
|
|
|
|
@block_compilers << compiler
|
|
|
|
end
|
|
|
|
|
2018-07-09 16:53:56 +02:00
|
|
|
# return true or false if the given name is in scope (arg/local)
|
|
|
|
def in_scope?(name)
|
2018-07-30 09:26:11 +02:00
|
|
|
ret = true if @callable.arguments_type.variable_index(name)
|
|
|
|
ret = @callable.frame_type.variable_index(name) unless ret
|
2018-07-09 16:53:56 +02:00
|
|
|
ret
|
|
|
|
end
|
|
|
|
|
2015-05-08 14:10:30 +02:00
|
|
|
end
|
|
|
|
end
|