a start on dynamic dispatch (wip)
This commit is contained in:
@ -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
|
||||
|
Reference in New Issue
Block a user