﻿This file is part of Silk.NET.

You may modify and distribute Silk.NET under the terms
of the MIT license. See the LICENSE file for details.

This file is for code that was developed but never used, but could be useful in the future.



bool CanBeConstant(ClangSharp.Type type, Expr initExpr)
{
    while (true)
    {
        switch (type)
        {
            case AttributedType attributedType:
                type = attributedType.ModifiedType;
                continue;
            case AutoType autoType:
                type = autoType.CanonicalType;
                continue;
            case BuiltinType builtinType:
                switch (type.Kind)
                {
                    case CXTypeKind.CXType_Bool:
                    case CXTypeKind.CXType_Char_U:
                    case CXTypeKind.CXType_UChar:
                    case CXTypeKind.CXType_Char16:
                    case CXTypeKind.CXType_UShort:
                    case CXTypeKind.CXType_UInt:
                    case CXTypeKind.CXType_ULong:
                    case CXTypeKind.CXType_ULongLong:
                    case CXTypeKind.CXType_Char_S:
                    case CXTypeKind.CXType_SChar:
                    case CXTypeKind.CXType_WChar:
                    case CXTypeKind.CXType_Short:
                    case CXTypeKind.CXType_Int:
                    case CXTypeKind.CXType_Long:
                    case CXTypeKind.CXType_LongLong:
                    case CXTypeKind.CXType_Float:
                    case CXTypeKind.CXType_Double:
                    {
                        return IsConstant(initExpr);
                    }
                }

                break;
            case ElaboratedType elaboratedType:
                type = elaboratedType.NamedType;
                continue;
            case EnumType enumType:
                type = enumType.Decl.IntegerType;
                continue;
            case TypedefType typedefType:
                type = typedefType.Decl.UnderlyingType;
                continue;
        }

        return false;
        break;
    }
}

bool IsConstant(Expr initExpr)
{
    // ReSharper disable once SwitchStatementHandlesSomeKnownEnumValuesWithDefault
    switch (initExpr.StmtClass)
    {
        // case CX_StmtClass.CX_StmtClass_BinaryConditionalOperator:

        case CX_StmtClass.CX_StmtClass_ConditionalOperator:
        {
            return false;
        }

        // case CX_StmtClass.CX_StmtClass_AddrLabelExpr:
        // case CX_StmtClass.CX_StmtClass_ArrayInitIndexExpr:
        // case CX_StmtClass.CX_StmtClass_ArrayInitLoopExpr:
        // case CX_StmtClass.CX_StmtClass_ArraySubscriptExpr:
        // case CX_StmtClass.CX_StmtClass_ArrayTypeTraitExpr:
        // case CX_StmtClass.CX_StmtClass_AsTypeExpr:
        // case CX_StmtClass.CX_StmtClass_AtomicExpr:

        case CX_StmtClass.CX_StmtClass_BinaryOperator:
        {
            var binaryOperator = (BinaryOperator) initExpr;
            return IsConstant(binaryOperator.LHS) && IsConstant(binaryOperator.RHS);
        }

        // case CX_StmtClass.CX_StmtClass_CompoundAssignOperator:
        // case CX_StmtClass.CX_StmtClass_BlockExpr:
        // case CX_StmtClass.CX_StmtClass_CXXBindTemporaryExpr:

        case CX_StmtClass.CX_StmtClass_CXXBoolLiteralExpr:
        {
            return true;
        }

        // case CX_StmtClass.CX_StmtClass_CXXConstructExpr:
        // case CX_StmtClass.CX_StmtClass_CXXTemporaryObjectExpr:
        // case CX_StmtClass.CX_StmtClass_CXXDefaultArgExpr:
        // case CX_StmtClass.CX_StmtClass_CXXDefaultInitExpr:
        // case CX_StmtClass.CX_StmtClass_CXXDeleteExpr:
        // case CX_StmtClass.CX_StmtClass_CXXDependentScopeMemberExpr:
        // case CX_StmtClass.CX_StmtClass_CXXFoldExpr:
        // case CX_StmtClass.CX_StmtClass_CXXInheritedCtorInitExpr:
        // case CX_StmtClass.CX_StmtClass_CXXNewExpr:
        // case CX_StmtClass.CX_StmtClass_CXXNoexceptExpr:

        case CX_StmtClass.CX_StmtClass_CXXNullPtrLiteralExpr:
        {
            return true;
        }

        // case CX_StmtClass.CX_StmtClass_CXXPseudoDestructorExpr:
        // case CX_StmtClass.CX_StmtClass_CXXRewrittenBinaryOperator:
        // case CX_StmtClass.CX_StmtClass_CXXScalarValueInitExpr:
        // case CX_StmtClass.CX_StmtClass_CXXStdInitializerListExpr:
        // case CX_StmtClass.CX_StmtClass_CXXThisExpr:
        // case CX_StmtClass.CX_StmtClass_CXXThrowExpr:
        // case CX_StmtClass.CX_StmtClass_CXXTypeidExpr:
        // case CX_StmtClass.CX_StmtClass_CXXUnresolvedConstructExpr:
        // case CX_StmtClass.CX_StmtClass_CXXUuidofExpr:

        case CX_StmtClass.CX_StmtClass_CallExpr:
        {
            return false;
        }

        // case CX_StmtClass.CX_StmtClass_CUDAKernelCallExpr:
        // case CX_StmtClass.CX_StmtClass_CXXMemberCallExpr:

        // TODO investigate case CX_StmtClass.CX_StmtClass_CXXOperatorCallExpr:
        // TODO investigate {
        // TODO investigate     var cxxOperatorCall = (CXXOperatorCallExpr) initExpr;

        // TODO investigate     if (cxxOperatorCall.CalleeDecl is FunctionDecl functionDecl)
        // TODO investigate     {
        // TODO investigate         var functionDeclName = GetCursorName(functionDecl);

        // TODO investigate         if (IsEnumOperator(functionDecl, functionDeclName))
        // TODO investigate         {
        // TODO investigate             return true;
        // TODO investigate         }
        // TODO investigate     }

        // TODO investigate     return false;
        // TODO investigate }

        // case CX_StmtClass.CX_StmtClass_UserDefinedLiteral:
        // case CX_StmtClass.CX_StmtClass_BuiltinBitCastExpr:

        case CX_StmtClass.CX_StmtClass_CStyleCastExpr:
        case CX_StmtClass.CX_StmtClass_CXXStaticCastExpr:
        case CX_StmtClass.CX_StmtClass_CXXFunctionalCastExpr:
        {
            var cxxFunctionalCastExpr = (ExplicitCastExpr) initExpr;
            return IsConstant(cxxFunctionalCastExpr.SubExprAsWritten);
        }

        // case CX_StmtClass.CX_StmtClass_CXXConstCastExpr:
        // case CX_StmtClass.CX_StmtClass_CXXDynamicCastExpr:
        // case CX_StmtClass.CX_StmtClass_CXXReinterpretCastExpr:
        // case CX_StmtClass.CX_StmtClass_ObjCBridgedCastExpr:

        case CX_StmtClass.CX_StmtClass_ImplicitCastExpr:
        {
            var implicitCastExpr = (ImplicitCastExpr) initExpr;
            return IsConstant(implicitCastExpr.SubExprAsWritten);
        }

        case CX_StmtClass.CX_StmtClass_CharacterLiteral:
        {
            return true;
        }

        // case CX_StmtClass.CX_StmtClass_ChooseExpr:
        // case CX_StmtClass.CX_StmtClass_CompoundLiteralExpr:
        // case CX_StmtClass.CX_StmtClass_ConceptSpecializationExpr:
        // case CX_StmtClass.CX_StmtClass_ConvertVectorExpr:
        // case CX_StmtClass.CX_StmtClass_CoawaitExpr:
        // case CX_StmtClass.CX_StmtClass_CoyieldExpr:

        case CX_StmtClass.CX_StmtClass_DeclRefExpr:
        {
            var declRefExpr = (DeclRefExpr) initExpr;
            return (declRefExpr.Decl is EnumConstantDecl) ||
                   ((declRefExpr.Decl is VarDecl varDecl) && varDecl.HasInit && IsConstant(varDecl.Init));
        }

        // case CX_StmtClass.CX_StmtClass_DependentCoawaitExpr:
        // case CX_StmtClass.CX_StmtClass_DependentScopeDeclRefExpr:
        // case CX_StmtClass.CX_StmtClass_DesignatedInitExpr:
        // case CX_StmtClass.CX_StmtClass_DesignatedInitUpdateExpr:
        // case CX_StmtClass.CX_StmtClass_ExpressionTraitExpr:
        // case CX_StmtClass.CX_StmtClass_ExtVectorElementExpr:
        // case CX_StmtClass.CX_StmtClass_FixedPointLiteral:

        case CX_StmtClass.CX_StmtClass_FloatingLiteral:
        {
            return true;
        }

        // case CX_StmtClass.CX_StmtClass_ConstantExpr:
        // case CX_StmtClass.CX_StmtClass_ExprWithCleanups:
        // case CX_StmtClass.CX_StmtClass_FunctionParmPackExpr:
        // case CX_StmtClass.CX_StmtClass_GNUNullExpr:
        // case CX_StmtClass.CX_StmtClass_GenericSelectionExpr:
        // case CX_StmtClass.CX_StmtClass_ImaginaryLiteral:
        // case CX_StmtClass.CX_StmtClass_ImplicitValueInitExpr:
        // case CX_StmtClass.CX_StmtClass_InitListExpr:

        case CX_StmtClass.CX_StmtClass_IntegerLiteral:
        {
            return true;
        }

        // case CX_StmtClass.CX_StmtClass_LambdaExpr:
        // case CX_StmtClass.CX_StmtClass_MSPropertyRefExpr:
        // case CX_StmtClass.CX_StmtClass_MSPropertySubscriptExpr:
        // case CX_StmtClass.CX_StmtClass_MaterializeTemporaryExpr:

        case CX_StmtClass.CX_StmtClass_MemberExpr:
        {
            return false;
        }

        // case CX_StmtClass.CX_StmtClass_NoInitExpr:
        // case CX_StmtClass.CX_StmtClass_OMPArraySectionExpr:
        // case CX_StmtClass.CX_StmtClass_ObjCArrayLiteral:
        // case CX_StmtClass.CX_StmtClass_ObjCAvailabilityCheckExpr:
        // case CX_StmtClass.CX_StmtClass_ObjCBoolLiteralExpr:
        // case CX_StmtClass.CX_StmtClass_ObjCBoxedExpr:
        // case CX_StmtClass.CX_StmtClass_ObjCDictionaryLiteral:
        // case CX_StmtClass.CX_StmtClass_ObjCEncodeExpr:
        // case CX_StmtClass.CX_StmtClass_ObjCIndirectCopyRestoreExpr:
        // case CX_StmtClass.CX_StmtClass_ObjCIsaExpr:
        // case CX_StmtClass.CX_StmtClass_ObjCIvarRefExpr:
        // case CX_StmtClass.CX_StmtClass_ObjCMessageExpr:
        // case CX_StmtClass.CX_StmtClass_ObjCPropertyRefExpr:
        // case CX_StmtClass.CX_StmtClass_ObjCProtocolExpr:
        // case CX_StmtClass.CX_StmtClass_ObjCSelectorExpr:
        // case CX_StmtClass.CX_StmtClass_ObjCStringLiteral:
        // case CX_StmtClass.CX_StmtClass_ObjCSubscriptRefExpr:
        // case CX_StmtClass.CX_StmtClass_OffsetOfExpr:
        // case CX_StmtClass.CX_StmtClass_OpaqueValueExpr:
        // case CX_StmtClass.CX_StmtClass_UnresolvedLookupExpr:
        // case CX_StmtClass.CX_StmtClass_UnresolvedMemberExpr:
        // case CX_StmtClass.CX_StmtClass_PackExpansionExpr:

        case CX_StmtClass.CX_StmtClass_ParenExpr:
        {
            var parenExpr = (ParenExpr) initExpr;
            return IsConstant(parenExpr.SubExpr);
        }

        // case CX_StmtClass.CX_StmtClass_ParenListExpr:
        // case CX_StmtClass.CX_StmtClass_PredefinedExpr:
        // case CX_StmtClass.CX_StmtClass_PseudoObjectExpr:
        // case CX_StmtClass.CX_StmtClass_RequiresExpr:
        // case CX_StmtClass.CX_StmtClass_ShuffleVectorExpr:
        // case CX_StmtClass.CX_StmtClass_SizeOfPackExpr:
        // case CX_StmtClass.CX_StmtClass_SourceLocExpr:
        // case CX_StmtClass.CX_StmtClass_StmtExpr:

        case CX_StmtClass.CX_StmtClass_StringLiteral:
        {
            return true;
        }

        // case CX_StmtClass.CX_StmtClass_SubstNonTypeTemplateParmExpr:
        // case CX_StmtClass.CX_StmtClass_SubstNonTypeTemplateParmPackExpr:
        // case CX_StmtClass.CX_StmtClass_TypeTraitExpr:
        // case CX_StmtClass.CX_StmtClass_TypoExpr:

        case CX_StmtClass.CX_StmtClass_UnaryExprOrTypeTraitExpr:
        {
            var unaryExprOrTypeTraitExpr = (UnaryExprOrTypeTraitExpr) initExpr;
            var argumentType = unaryExprOrTypeTraitExpr.TypeOfArgument;

            long size32;
            long size64;

            long alignment32 = -1;
            long alignment64 = -1;

            GetTypeSize
            (
                unaryExprOrTypeTraitExpr, argumentType, ref alignment32, ref alignment64, out size32,
                out size64
            );

            switch (unaryExprOrTypeTraitExpr.Kind)
            {
                case CX_UnaryExprOrTypeTrait.CX_UETT_SizeOf:
                {
                    return (size32 == size64);
                }

                case CX_UnaryExprOrTypeTrait.CX_UETT_AlignOf:
                case CX_UnaryExprOrTypeTrait.CX_UETT_PreferredAlignOf:
                {
                    return (alignment32 == alignment64);
                }

                default:
                {
                    return false;
                }
            }
        }

        case CX_StmtClass.CX_StmtClass_UnaryOperator:
        {
            var unaryOperator = (UnaryOperator) initExpr;
            return IsConstant(unaryOperator.SubExpr);
        }

        // case CX_StmtClass.CX_StmtClass_VAArgExpr:

        default:
        {
            Console.WriteLine
            (
                $"Unsupported statement class: '{initExpr.StmtClassName}'. Generated bindings may not be complete. ({initExpr.Location})"
            );
            return false;
        }
    }
}