예제 #1
0
        /// <summary>
        /// Gets the common base types for all specializations.
        /// </summary>
        /// <param name="factory">The user type factory.</param>
        private string[] GetCommonBaseTypesForAllSpecializations(UserTypeFactory factory)
        {
            // If we don't have specializations, we cannot continue
            if (!SpecializedTypes.Any())
            {
                return(null);
            }

            // Do this for every template argument
            string[] results = new string[NumberOfTemplateArguments];

            for (int i = 0; i < NumberOfTemplateArguments; i++)
            {
                // Get all specializations for current template argument
                Symbol[] specializedSymbols = SpecializedTypes.Select(r => r.templateArgumentsAsSymbols[i]).ToArray();
                TypeOfSpecializationType specializationType = TypeOfSpecializationType.Unmatched;
                UserType commonType = null;

                foreach (Symbol type in specializedSymbols)
                {
                    // Check base type
                    if (type.Tag == Dia2Lib.SymTagEnum.SymTagBaseType || type.Tag == Dia2Lib.SymTagEnum.SymTagEnum)
                    {
                        if (type.Name != "void")
                        {
                            specializationType = TypeOfSpecializationType.Anything;
                            break;
                        }
                        else
                        {
                            specializationType = TypeOfSpecializationType.Variable;
                            continue;
                        }
                    }

                    // Check pointer, array and function types, they inherit Variable
                    if (type.Tag == Dia2Lib.SymTagEnum.SymTagPointerType || type.Tag == Dia2Lib.SymTagEnum.SymTagArrayType || type.Tag == Dia2Lib.SymTagEnum.SymTagFunctionType)
                    {
                        specializationType = TypeOfSpecializationType.Variable;
                        continue;
                    }

                    if (type.Tag != Dia2Lib.SymTagEnum.SymTagUDT)
                    {
                        throw new NotImplementedException("Unexpected symbol type " + type.Tag + ". Symbol name: " + type.Name);
                    }

                    // Check if type has user type
                    UserType userType = type.UserType;

                    if (userType == null)
                    {
                        // TODO: This shouldn't happen
                        specializationType = TypeOfSpecializationType.Variable;
                        continue;
                    }

                    if (specializationType == TypeOfSpecializationType.Variable)
                    {
                        continue;
                    }

                    // If user type is template, get parent template type (one that describes all specializations)
                    var templateType = userType as TemplateUserType;

                    if (templateType != null)
                    {
                        userType = templateType.TemplateType;
                    }

                    if (specializationType == TypeOfSpecializationType.Unmatched)
                    {
                        specializationType = TypeOfSpecializationType.UserType;
                        commonType         = userType;
                        continue;
                    }

                    // Try to find common type for commonType and userType
                    var  commonTypeBases = ExtractAllBaseClasses(commonType);
                    var  userTypeBases   = ExtractAllBaseClasses(userType);
                    bool found           = false;

                    foreach (var ct in commonTypeBases)
                    {
                        foreach (var ut in userTypeBases)
                        {
                            if (ut == ct)
                            {
                                found      = true;
                                commonType = ut;
                                break;
                            }
                        }

                        if (found)
                        {
                            break;
                        }
                    }

                    if (!found)
                    {
                        specializationType = TypeOfSpecializationType.Variable;
                    }
                }

                // Save result based on specialization type
                string userTypeName       = null;
                var    templateCommonType = commonType as TemplateUserType;

                switch (specializationType)
                {
                case TypeOfSpecializationType.Anything:
                    userTypeName = null;
                    break;

                case TypeOfSpecializationType.Variable:
                    userTypeName = "Variable";
                    break;

                case TypeOfSpecializationType.UserType:
                    if (templateCommonType != null)
                    {
                        // Common specialization is template type. In order to use it, we need to take specialization from this type
                        // and not the one that engine picked up as generalization.
                        UserType        templateArgumentUserType = templateArgumentsAsUserTypes[i];
                        List <UserType> baseClasses = ExtractAllBaseClasses(templateArgumentUserType);

                        foreach (UserType baseClass in baseClasses)
                        {
                            TemplateUserType templateBaseClass = baseClass as TemplateUserType;

                            if (templateBaseClass != null && templateCommonType == templateBaseClass.TemplateType)
                            {
                                templateCommonType = templateBaseClass;
                                break;
                            }
                        }

                        // In order to use template as specialization, we need to have all arguments coming from our template arguments.
                        // If not, we cannot trust them and should continue with the base classes.
                        var  tree = new TemplateTypeTree(templateCommonType, factory);
                        bool ok   = true;

                        do
                        {
                            // Check if all arguments are coming from our template arguments.
                            ok = true;
                            foreach (var args in tree.SpecializedArguments)
                            {
                                if (args != null)
                                {
                                    foreach (var arg in args)
                                    {
                                        if (!(arg is TemplateArgumentTreeType) && !(arg is UserTypeTree && ((UserTypeTree)arg).UserType is TemplateArgumentUserType))
                                        {
                                            ok = false;
                                            break;
                                        }
                                    }
                                }
                            }

                            if (!ok)
                            {
                                // Find base class that we should continue with
                                UserType nextBaseClass = null;
                                Symbol   symbol        = templateCommonType.Symbol;

                                while (nextBaseClass == null)
                                {
                                    if (symbol.BaseClasses == null || symbol.BaseClasses.Length == 0)
                                    {
                                        // We have finished all
                                        break;
                                    }

                                    if (symbol.BaseClasses.Length > 1)
                                    {
                                        // We cannot match common type with multi-inheritance
                                        break;
                                    }

                                    symbol        = symbol.BaseClasses[0];
                                    nextBaseClass = symbol?.UserType;
                                }

                                // No base class, use Variable
                                if (nextBaseClass == null)
                                {
                                    userTypeName = "Variable";
                                    break;
                                }
                                else if (nextBaseClass is TemplateUserType)
                                {
                                    // Base class is template, continue with checks
                                    templateCommonType = (TemplateUserType)nextBaseClass;
                                    tree = new TemplateTypeTree(templateCommonType, factory);
                                }
                                else
                                {
                                    // Base class is not template, so we can stop testing it.
                                    userTypeName = nextBaseClass.FullClassName;
                                    break;
                                }
                            }
                        }while (!ok);

                        // All checks passed for this template user type, use it.
                        if (ok)
                        {
                            userTypeName = tree.GetTypeString();
                        }
                    }
                    else
                    {
                        userTypeName = commonType.FullClassName;
                    }
                    break;

                case TypeOfSpecializationType.Unmatched:
                default:
                    throw new NotImplementedException("Unexpected specialization type " + specializationType + " for template type " + ClassName);
                }

                results[i] = userTypeName;
            }

            return(results);
        }
예제 #2
0
        /// <summary>
        /// Gets the common base types for all specializations.
        /// </summary>
        /// <param name="factory">The user type factory.</param>
        private string[] GetCommonBaseTypesForAllSpecializations(UserTypeFactory factory)
        {
            // If we don't have specializations, we cannot continue
            if (!SpecializedTypes.Any())
            {
                return(null);
            }

            // Do this for every template argument
            string[] results = new string[NumberOfTemplateArguments];

            for (int i = 0; i < NumberOfTemplateArguments; i++)
            {
                // Get all specializations for current template argument
                Symbol[] specializedSymbols = SpecializedTypes.Select(r => r.templateArgumentsAsSymbols[i]).ToArray();
                TypeOfSpecializationType specializationType = TypeOfSpecializationType.Unmatched;
                UserType commonType = null;

                foreach (Symbol type in specializedSymbols)
                {
                    // Check base type
                    if (type.Tag == Dia2Lib.SymTagEnum.SymTagBaseType || type.Tag == Dia2Lib.SymTagEnum.SymTagEnum)
                    {
                        if (type.Name != "void")
                        {
                            specializationType = TypeOfSpecializationType.Anything;
                            break;
                        }
                        else
                        {
                            specializationType = TypeOfSpecializationType.Variable;
                            continue;
                        }
                    }

                    // Check pointer, array and function types, they inherit Variable
                    if (type.Tag == Dia2Lib.SymTagEnum.SymTagPointerType || type.Tag == Dia2Lib.SymTagEnum.SymTagArrayType || type.Tag == Dia2Lib.SymTagEnum.SymTagFunctionType)
                    {
                        specializationType = TypeOfSpecializationType.Variable;
                        continue;
                    }

                    if (type.Tag != Dia2Lib.SymTagEnum.SymTagUDT)
                    {
                        throw new NotImplementedException("Unexpected symbol type " + type.Tag + ". Symbol name: " + type.Name);
                    }

                    // Check if type has user type
                    UserType userType = type.UserType;

                    if (userType == null)
                    {
                        // TODO: This shouldn't happen
                        //specializationType = TypeOfSpecializationType.Variable;
                        //continue;
                        throw new Exception("This should never happen");
                    }

                    if (specializationType == TypeOfSpecializationType.Variable)
                    {
                        continue;
                    }

                    // If user type is template, get parent template type (one that describes all specializations)
                    var templateType = userType as TemplateUserType;

                    if (templateType != null)
                    {
                        userType = templateType.TemplateType;
                    }

                    if (specializationType == TypeOfSpecializationType.Unmatched)
                    {
                        specializationType = TypeOfSpecializationType.UserType;
                        commonType         = userType;
                        continue;
                    }

                    // Try to find common type for commonType and userType
                    var  commonTypeBases = ExtractAllBaseClasses(commonType);
                    var  userTypeBases   = ExtractAllBaseClasses(userType);
                    bool found           = false;

                    foreach (var ct in commonTypeBases)
                    {
                        foreach (var ut in userTypeBases)
                        {
                            if (ut == ct)
                            {
                                found      = true;
                                commonType = ut;
                                break;
                            }
                        }

                        if (found)
                        {
                            break;
                        }
                    }

                    if (!found)
                    {
                        specializationType = TypeOfSpecializationType.Variable;
                    }
                }

                // Save result based on specialization type
                string userTypeName;
                var    templateCommonType = commonType as TemplateUserType;

                switch (specializationType)
                {
                case TypeOfSpecializationType.Anything:
                    userTypeName = null;
                    break;

                case TypeOfSpecializationType.Variable:
                    userTypeName = "Variable";
                    break;

                case TypeOfSpecializationType.UserType:
                    if (templateCommonType != null)
                    {
                        userTypeName = new TemplateTypeTree(templateCommonType, factory).GetTypeString();
                    }
                    else
                    {
                        userTypeName = commonType.FullClassName;
                    }
                    break;

                case TypeOfSpecializationType.Unmatched:
                default:
                    throw new NotImplementedException("Unexpected specialization type " + specializationType + " for template type " + ClassName);
                }

                results[i] = userTypeName;
            }

            return(results);
        }