2018-04-08 17:55:17 +02:00
|
|
|
module Mom
|
|
|
|
|
|
|
|
# Dynamic method resolution is at the heart of a dynamic language, and here
|
|
|
|
# is the Mom level instruction to do it.
|
|
|
|
#
|
|
|
|
# When the static type can not be determined a CacheEntry is used to store
|
|
|
|
# type and method of the resolved method. The CacheEntry is shared with
|
|
|
|
# DynamicCall instruction who is responsible for calling the method in the entry.
|
|
|
|
#
|
|
|
|
# This instruction resolves the method, in case the types don't match (and
|
|
|
|
# at least on first encouter)
|
|
|
|
#
|
|
|
|
# This used to be a method, but we don't really need the method setup etc
|
|
|
|
#
|
|
|
|
class ResolveMethod < Instruction
|
|
|
|
attr :cache_entry , :name
|
|
|
|
|
|
|
|
def initialize(name , cache_entry)
|
|
|
|
@name = name
|
|
|
|
@cache_entry = cache_entry
|
|
|
|
end
|
|
|
|
|
2018-04-19 09:00:55 +02:00
|
|
|
def to_s
|
|
|
|
"ResolveMethod #{name}"
|
|
|
|
end
|
2018-04-08 21:30:18 +02:00
|
|
|
|
|
|
|
# When the method is resolved, a cache_entry is used to hold the result.
|
|
|
|
# That cache_entry (holding type and method) is checked before, and
|
|
|
|
# needs to be updated by this instruction.
|
|
|
|
#
|
|
|
|
# We use the type stored in the cache_entry to check the methods if any of it's
|
|
|
|
# names are the same as the given @name
|
|
|
|
#
|
|
|
|
# currently a fail results in sys exit
|
2018-04-08 17:55:17 +02:00
|
|
|
def to_risc( compiler )
|
2018-04-08 21:30:18 +02:00
|
|
|
name_ = @name
|
|
|
|
cache_entry_ = @cache_entry
|
2018-08-19 12:18:25 +02:00
|
|
|
builder = compiler.builder(self)
|
2018-04-08 17:55:17 +02:00
|
|
|
builder.build do
|
2018-08-14 18:39:46 +02:00
|
|
|
word! << name_
|
|
|
|
cache_entry! << cache_entry_
|
2018-04-08 17:55:17 +02:00
|
|
|
|
2018-08-14 18:39:46 +02:00
|
|
|
type! << cache_entry[:cached_type]
|
|
|
|
callable_method! << type[:methods]
|
2018-04-08 17:55:17 +02:00
|
|
|
|
2018-04-08 21:30:18 +02:00
|
|
|
add_code while_start_label
|
|
|
|
|
2018-09-01 10:20:59 +02:00
|
|
|
object! << Parfait.object_space.nil_object
|
|
|
|
object - callable_method
|
2018-04-08 17:55:17 +02:00
|
|
|
if_zero exit_label
|
|
|
|
|
2018-08-14 18:39:46 +02:00
|
|
|
name! << callable_method[:name]
|
2018-04-08 17:55:17 +02:00
|
|
|
name - word
|
|
|
|
|
2018-04-08 21:30:18 +02:00
|
|
|
if_zero ok_label
|
2018-04-08 17:55:17 +02:00
|
|
|
|
2018-08-12 12:10:44 +02:00
|
|
|
callable_method << callable_method[:next_callable]
|
2018-04-08 17:55:17 +02:00
|
|
|
branch while_start_label
|
|
|
|
|
2018-04-08 21:30:18 +02:00
|
|
|
add_code exit_label
|
2018-11-22 08:16:56 +01:00
|
|
|
# temporary, need to raise really.
|
|
|
|
factory! << Parfait.object_space.get_factory_for(:Integer)
|
|
|
|
integer_tmp! << factory[:reserve]
|
|
|
|
Risc::Builtin::Object.emit_syscall( builder , :exit ) #uses integer_tmp
|
2018-04-08 21:30:18 +02:00
|
|
|
|
|
|
|
add_code ok_label
|
2018-07-07 08:11:09 +02:00
|
|
|
cache_entry[:cached_method] << callable_method
|
2018-04-08 17:55:17 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|