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(res: nullable RuntimeVariable, mmethod: MMethodDef, arguments: Array[RuntimeVariable]) do
var bool_type = compiler.mainmodule.bool_type
var recv = arguments.first
var consider_null = mmethod.name == "==" or mmethod.name == "!=" or mmethod.name == "is_same_instance"
if recv.mcasttype isa MNullableType or recv.mcasttype isa MNullType then
add("if ({recv} == null || {recv}.is_null()) \{")
if mmethod.name == "==" or mmethod.name == "is_same_instance" then
if res == null then res = new_var(bool_type)
var arg = arguments[1]
if arg.mcasttype isa MNullableType then
add("{res} = ({arg} == null || {arg}.is_null());")
else if arg.mcasttype isa MNullType then
add("{res} = true; /* is null */")
else
add("{res} = false; /* {arg.inspect} cannot be null */")
end
else if mmethod.name == "!=" then
if res == null then res = new_var(bool_type)
# res = self.new_var(bool_type)
var arg = arguments[1]
if arg.mcasttype isa MNullableType then
add("{res} = ({arg} != null && !{arg}.is_null());")
else if arg.mcasttype isa MNullType then
add("{res} = false; /* is null */")
else
add("{res} = true; /* {arg.inspect} cannot be null */")
end
else
add_abort("Receiver is null")
ret(null_instance)
end
add("\} else \{")
else
add "\{"
add "/* recv ({recv}) cannot be null since it's a {recv.mcasttype}"
end
if consider_null then
var arg = arguments[1]
if arg.mcasttype isa MNullType then
if res == null then res = new_var(bool_type)
if mmethod.name == "!=" then
add("{res} = true; /* arg is null and recv is not */")
else # `==` and `is_same_instance`
add("{res} = false; /* arg is null but recv is not */")
end
add("\}") # closes the null case
add("if (false) \{") # what follow is useless, Javac will drop it
end
end
end
src/compiler/java_compiler.nit:576,2--636,4