}
private TypedByteCodeNode visitFunctionBinding(CompilerContext context, FunctionBinding functionBinding, String comment)
{
List<TypedByteCodeNode> arguments = functionBinding.getArguments();
MethodType methodType = functionBinding.getCallSite().type();
Class<?> unboxedReturnType = Primitives.unwrap(methodType.returnType());
LabelNode end = new LabelNode("end");
Block block = new Block(context)
.setDescription("invoke")
.comment(comment);
ArrayList<Class<?>> stackTypes = new ArrayList<>();
for (int i = 0; i < arguments.size(); i++) {
TypedByteCodeNode argument = arguments.get(i);
Class<?> argumentType = methodType.parameterList().get(i);
block.append(coerceToType(context, argument, argumentType).getNode());
stackTypes.add(argument.getType());
block.append(ifWasNullPopAndGoto(context, end, unboxedReturnType, Lists.reverse(stackTypes)));
}
block.invokeDynamic(functionBinding.getName(), methodType, functionBinding.getBindingId());
if (functionBinding.isNullable()) {
if (unboxedReturnType.isPrimitive()) {
LabelNode notNull = new LabelNode("notNull");
block.dup(methodType.returnType())
.ifNotNullGoto(notNull)
.putVariable("wasNull", true)
.comment("swap boxed null with unboxed default")
.pop(methodType.returnType())
.pushJavaDefault(unboxedReturnType)
.gotoLabel(end)
.visitLabel(notNull)
.append(unboxPrimitive(context, unboxedReturnType));
}
else {
block.dup(methodType.returnType())
.ifNotNullGoto(end)
.putVariable("wasNull", true);
}
}
block.visitLabel(end);