presto-main/src/main/java/io/prestosql/sql/relational/optimizer/ExpressionOptimizer.java/ExpressionOptimizer/visitCall
class ExpressionOptimizer:        @Override
        public RowExpression visitCall(CallExpression call, Void context)
        {
            if (call.getResolvedFunction().getSignature().getName().equals(mangleOperatorName(CAST))) {
                call = rewriteCast(call);
            }

            List<RowExpression> arguments = call.getArguments().stream()
                    .map(argument -> argument.accept(this, context))
                    .collect(toImmutableList());

            // TODO: optimize function calls with lambda arguments. For example, apply(x -> x + 2, 1)
            FunctionMetadata functionMetadata = metadata.getFunctionMetadata(call.getResolvedFunction());
            if (Iterables.all(arguments, instanceOf(ConstantExpression.class)) && functionMetadata.isDeterministic()) {
                MethodHandle method = metadata.getScalarFunctionImplementation(call.getResolvedFunction()).getMethodHandle();

                if (method.type().parameterCount() > 0 && method.type().parameterType(0) == ConnectorSession.class) {
                    method = method.bindTo(session);
                }

                int index = 0;
                List<Object> constantArguments = new ArrayList<>();
                for (RowExpression argument : arguments) {
                    Object value = ((ConstantExpression) argument).getValue();
                    // if any argument is null, return null
                    if (value == null && !functionMetadata.getArgumentDefinitions().get(index).isNullable()) {
                        return constantNull(call.getType());
                    }
                    constantArguments.add(value);
                    index++;
                }

                try {
                    return constant(method.invokeWithArguments(constantArguments), call.getType());
                }
                catch (Throwable e) {
                    if (e instanceof InterruptedException) {
                        Thread.currentThread().interrupt();
                    }
                    // Do nothing. As a result, this specific tree will be left untouched. But irrelevant expressions will continue to get evaluated and optimized.
                }
            }

            return call(call.getResolvedFunction(), metadata.getType(call.getResolvedFunction().getSignature().getReturnType()), arguments);
        }