a start on dynamic dispatch (wip)

This commit is contained in:
Torsten Ruger
2017-09-14 16:07:02 +03:00
parent be1481ce34
commit 2739747453
5 changed files with 91 additions and 8 deletions

View File

@ -28,7 +28,7 @@ module Vool
#
# A Send breaks down to 2 steps:
# - Setting up the next message, with receiver, arguments, and (importantly) return address
# - a CachedCall , or a SimpleCall, depending on weather the receiver type can be determined
# - a CachedCall , or a SimpleCall, depending on wether the receiver type can be determined
#
# FIXME: we now presume direct (assignable) values for the arguments and receiver.
# in a not so distant future, temporary variables will have to be created
@ -59,11 +59,51 @@ module Vool
Mom::Statements.new( message_setup(in_method) << Mom::SimpleCall.new( called_method) )
end
def cached_call(method)
raise "Not implemented #{method}"
Mom::Statements.new( message_setup(method) + call_instruction )
[@receiver.slot_class.new([:message , :next_message , :receiver] , @receiver) ]
# this breaks cleanly into two parts:
# - check the cached type and if neccessary update
# - call the cached method
def cached_call(in_method)
create_tmps(in_method)
Mom::Statements.new( cache_check(in_method) + call_cached_method(in_method) )
end
def flatten
raise "flat"
end
# check that current type is the cached type
# if not, change and find method for the type (simple_call to resolve_method)
# conceptually easy in ruby, but we have to compile that "easy" ruby
def cache_check(in_method)
# return if cached_type == current_type
# cached_type = current_type
# cached_method = current_type.resolve_method(method.name)
check = []
cached_type = Mom::SlotDefinition.new(:message , [:frame , type_var_name])
current_type = Mom::SlotDefinition.new(:message , [:self , :type])
cond = Mom::NotSameCheck.new(cached_type , current_type)
if_true = nil #@if_true.to_mom( in_method ) #find and assign
check << Mom::IfStatement.new( cond , if_true )
check
end
# this may look like a simple_call, but the difference is that we don't know
# the method until run-time. Alas the setup is the same
def call_cached_method(in_method)
message_setup(in_method) << Mom::DynamicCall.new( method_var_name)
end
private
# cached type and method are stored in the frame as local variables.
# this creates the varables in the frame. Names are method_var_name and type_var_name
def create_tmps(in_method)
in_method.create_tmp
end
# we store the (one!) cached mathod in the frame, under the name that this
# method returns
def method_var_name
"cached_method_#{object_id}"
end
def type_var_name
"cached_type_#{object_id}"
end
end
end