private TPreparedExpression assembleFunction(
      ExpressionNode functionNode,
      String functionName,
      List<ExpressionNode> argumentNodes,
      ColumnExpressionContext columnContext,
      SubqueryOperatorAssembler subqueryAssembler) {

    List<TPreparedExpression> arguments =
        assembleExpressions(argumentNodes, columnContext, subqueryAssembler);
    TValidatedScalar overload;
    SparseArray<Object> preptimeValues = null;
    if (functionNode instanceof FunctionExpression) {
      FunctionExpression fexpr = (FunctionExpression) functionNode;
      overload = fexpr.getResolved();
      preptimeValues = fexpr.getPreptimeValues();
    } else if (functionNode instanceof BooleanOperationExpression) {
      List<TPreptimeValue> inputPreptimeValues = new ArrayList<>(argumentNodes.size());
      for (ExpressionNode argument : argumentNodes) {
        inputPreptimeValues.add(argument.getPreptimeValue());
      }

      OverloadResolver<TValidatedScalar> scalarsResolver = registryService.getScalarsResolver();
      OverloadResult<TValidatedScalar> overloadResult =
          scalarsResolver.get(functionName, inputPreptimeValues);
      overload = overloadResult.getOverload();
    } else if (functionNode instanceof IfElseExpression) {
      overload = ifElseValidated;
    } else {
      throw new AssertionError(functionNode);
    }
    TInstance resultInstance = functionNode.getType();
    return new TPreparedFunction(overload, resultInstance, arguments, preptimeValues);
  }
 private TPreparedExpression tryLiteral(ExpressionNode node) {
   TPreparedExpression result = null;
   TPreptimeValue tpv = node.getPreptimeValue();
   if (tpv != null) {
     TInstance type = tpv.type();
     ValueSource value = tpv.value();
     if (type != null && value != null) result = new TPreparedLiteral(type, value);
   }
   return result;
 }