This methods handle the ==
and !=
methods and the case of the null receiver.
Note: a { is open in the generated C, that enclose and protect the effective method invocation.
Client must not forget to close the } after them.
The value returned is the result of the common special cases. If not null, client must compile it with the result of their own effective method invocation.
If before_send
can shortcut the whole message sending, a dummy if(0){
is generated to cancel the effective method invocation that will follow
TODO: find a better approach
# Handle common special cases before doing the effective method invocation
# This methods handle the `==` and `!=` methods and the case of the null receiver.
# Note: a { is open in the generated C, that enclose and protect the effective method invocation.
# Client must not forget to close the } after them.
#
# The value returned is the result of the common special cases.
# If not null, client must compile it with the result of their own effective method invocation.
#
# If `before_send` can shortcut the whole message sending, a dummy `if(0){`
# is generated to cancel the effective method invocation that will follow
# TODO: find a better approach
private fun before_send(mmethod: MMethod, arguments: Array[RuntimeVariable]): nullable RuntimeVariable
do
var res: nullable RuntimeVariable = null
var recv = arguments.first
var consider_null = not self.compiler.modelbuilder.toolcontext.opt_no_check_null.value or mmethod.name == "==" or mmethod.name == "!="
if maybe_null(recv) and consider_null then
self.add("if ({recv} == NULL) \{")
if mmethod.name == "==" or mmethod.name == "is_same_instance" then
res = self.new_var(bool_type)
var arg = arguments[1]
if arg.mcasttype isa MNullableType then
self.add("{res} = ({arg} == NULL);")
else if arg.mcasttype isa MNullType then
self.add("{res} = 1; /* is null */")
else
self.add("{res} = 0; /* {arg.inspect} cannot be null */")
end
else if mmethod.name == "!=" then
res = self.new_var(bool_type)
var arg = arguments[1]
if arg.mcasttype isa MNullableType then
self.add("{res} = ({arg} != NULL);")
else if arg.mcasttype isa MNullType then
self.add("{res} = 0; /* is null */")
else
self.add("{res} = 1; /* {arg.inspect} cannot be null */")
end
else
self.add_abort("Receiver is null")
end
self.add("\} else \{")
else
self.add("\{")
end
if not self.compiler.modelbuilder.toolcontext.opt_no_shortcut_equate.value and (mmethod.name == "==" or mmethod.name == "!=" or mmethod.name == "is_same_instance") then
# Recv is not null, thus if arg is, it is easy to conclude (and respect the invariants)
var arg = arguments[1]
if arg.mcasttype isa MNullType then
if res == null then res = self.new_var(bool_type)
if mmethod.name == "!=" then
self.add("{res} = 1; /* arg is null and recv is not */")
else # `==` and `is_same_instance`
self.add("{res} = 0; /* arg is null but recv is not */")
end
self.add("\}") # closes the null case
self.add("if (0) \{") # what follow is useless, CC will drop it
end
end
return res
end
src/compiler/separate_compiler.nit:1477,2--1537,4