private T interpretNode(T columnDesc, T valueDesc)
        throws SemanticException {
      if (exprFactory.isColumnRefExpr(columnDesc)) {
        final TypeInfo info = exprFactory.getTypeInfo(columnDesc);
        switch (info.getCategory()) {
        case MAP:
        case LIST:
        case UNION:
        case STRUCT:
          return valueDesc;
        case PRIMITIVE:
          PrimitiveTypeInfo primitiveInfo = TypeInfoFactory.getPrimitiveTypeInfo(info.getTypeName().toLowerCase());
          return interpretNodeAsConstant(primitiveInfo, valueDesc);
        }
      }
      boolean columnStruct = exprFactory.isSTRUCTFuncCallExpr(columnDesc);
      if (columnStruct) {
        boolean constantValuesStruct = exprFactory.isConstantStruct(valueDesc);
        boolean valuesStruct = exprFactory.isSTRUCTFuncCallExpr(valueDesc);
        if (constantValuesStruct || valuesStruct) {
          List<T> columnChilds = exprFactory.getExprChildren(columnDesc);
          List<TypeInfo> structFieldInfos = exprFactory.getStructTypeInfoList(valueDesc);
          List<String> structFieldNames = exprFactory.getStructNameList(valueDesc);

          if (columnChilds.size() != structFieldInfos.size()) {
            throw new SemanticException(ErrorMsg.INCOMPATIBLE_STRUCT.getMsg(columnChilds + " and " + structFieldInfos));
          }

          if (constantValuesStruct) {
            List<Object> literals = (List<Object>) exprFactory.getConstantValue(valueDesc);
            List<T> constantExpressions = new ArrayList<>();
            List<TypeInfo> newStructFieldInfos = new ArrayList<>();
            for (int i = 0; i < columnChilds.size(); i++) {
              final PrimitiveTypeInfo typeInfo = TypeInfoFactory.getPrimitiveTypeInfo(
                  exprFactory.getTypeInfo(columnChilds.get(i)).getTypeName().toLowerCase());
              T constantExpression = interpretNodeAsConstant(typeInfo,
                  exprFactory.createConstantExpr(structFieldInfos.get(i), literals.get(i)));
              if (constantExpression == null) {
                constantExpression = exprFactory.createConstantExpr(typeInfo, null);
              }
              constantExpressions.add(constantExpression);
              newStructFieldInfos.add(exprFactory.getTypeInfo(constantExpression));
            }
            StructTypeInfo structTypeInfo = new StructTypeInfo();
            structTypeInfo.setAllStructFieldNames(new ArrayList<>(structFieldNames));
            structTypeInfo.setAllStructFieldTypeInfos(new ArrayList<>(newStructFieldInfos));
            return exprFactory.createStructExpr(structTypeInfo, constantExpressions);
          } else { // valuesStruct
            List<T> valueChilds = exprFactory.getExprChildren(valueDesc);
            List<T> newValueChilds = new ArrayList<>();
            List<TypeInfo> newStructFieldInfos = new ArrayList<>();
            for (int i = 0; i < columnChilds.size(); i++) {
              T newValue = interpretNode(columnChilds.get(i), valueChilds.get(i));
              newValueChilds.add(newValue);
              newStructFieldInfos.add(exprFactory.getTypeInfo(columnChilds.get(i)));
            }
            StructTypeInfo structTypeInfo = new StructTypeInfo();
            structTypeInfo.setAllStructFieldNames(new ArrayList<>(structFieldNames));
            structTypeInfo.setAllStructFieldTypeInfos(new ArrayList<>(newStructFieldInfos));
            return exprFactory.createStructExpr(structTypeInfo, newValueChilds);
          }
        }
      }
      return valueDesc;
    }
Interprets the given value as the input columnDesc if possible.
Otherwise, returns input valueDesc as is.
ql/src/java/org/apache/hadoop/hive/ql/parse/type/TypeCheckProcFactory.java