private static bool MergeClassTablesWithNewClass(ISealableDictionary <string, IImportedClass> importedClassTable, string className, IImportedClass mergedClassItem, IImport importLocation, BaseNode.ImportType mergedImportType, IErrorList errorList) { bool Success = true; foreach (KeyValuePair <string, IImportedClass> ImportedEntry in importedClassTable) { IImportedClass ClassItem = ImportedEntry.Value; if (ClassItem.Item == mergedClassItem.Item) { string OldName = ImportedEntry.Key; errorList.AddError(new ErrorClassAlreadyImported(importLocation, OldName, className)); Success = false; break; } } // First time this class is imported, use the merge import type specification and location since they are known. if (Success) { mergedClassItem.SetImportType(mergedImportType); mergedClassItem.SetImportLocation(importLocation); importedClassTable.Add(className, mergedClassItem); } return(Success); }
/// <summary> /// Merges a class import with previous imports. /// </summary> /// <param name="importedClassTable">The already resolved imports.</param> /// <param name="mergedClassTable">The new classes to import.</param> /// <param name="importLocation">The import location.</param> /// <param name="mergedImportType">The import specification for all <paramref name="mergedClassTable"/>.</param> /// <param name="errorList">List of errors found.</param> /// <returns>True if the merge is successful.</returns> public static bool MergeClassTables(ISealableDictionary <string, IImportedClass> importedClassTable, ISealableDictionary <string, IImportedClass> mergedClassTable, IImport importLocation, BaseNode.ImportType mergedImportType, IErrorList errorList) { bool Success = true; foreach (KeyValuePair <string, IImportedClass> Entry in mergedClassTable) { string ClassName = Entry.Key; IImportedClass MergedClassItem = Entry.Value; // The merged class may have an import specification already, but if so it must match the one used here. // We can assume we use mergedImportType after this. if (MergedClassItem.IsTypeAssigned && MergedClassItem.ImportType != mergedImportType) { errorList.AddError(new ErrorImportTypeConflict(importLocation, ClassName)); Success = false; } // If a class is already imported with this name somehow. if (importedClassTable.ContainsKey(ClassName)) { // It must be the same class. IImportedClass ClassItem = importedClassTable[ClassName]; if (ClassItem.Item != MergedClassItem.Item) { errorList.AddError(new ErrorNameAlreadyUsed(importLocation, ClassName)); Success = false; continue; } // If the already existing imported class has a specification, it must match the one use for merge. if (ClassItem.IsTypeAssigned) { if (ClassItem.ImportType != mergedImportType) { errorList.AddError(new ErrorImportTypeConflict(importLocation, ClassName)); Success = false; continue; } } else { ClassItem.SetImportType(mergedImportType); } // If the import location isn't specified yet, use the imported library. if (!ClassItem.IsLocationAssigned) { ClassItem.SetImportLocation(importLocation); } } else { // New class, at least by name. Make sure it's not an already imported class using a different name. Success &= MergeClassTablesWithNewClass(importedClassTable, ClassName, MergedClassItem, importLocation, mergedImportType, errorList); } } Debug.Assert(Success || !errorList.IsEmpty); return(Success); }
/// <summary> /// Initializes a new instance of the <see cref="ImportedClass"/> class. /// </summary> /// <param name="other">The other imported class.</param> public ImportedClass(IImportedClass other) { Item = other.Item; IsTypeAssigned = other.IsTypeAssigned; if (IsTypeAssigned) { _ImportType = other.ImportType; } IsLocationAssigned = other.IsLocationAssigned; if (IsLocationAssigned) { _ImportLocation = other.ImportLocation; } }
/// <summary> /// Checks for errors before applying a rule. /// </summary> /// <param name="node">The node instance to check.</param> /// <param name="dataList">Optional data collected during inspection of sources.</param> /// <param name="data">Private data to give to Apply() upon return.</param> /// <returns>True if an error occured.</returns> public override bool CheckConsistency(IInheritance node, IDictionary <ISourceTemplate, object> dataList, out object data) { bool Success = true; IClass EmbeddingClass = node.EmbeddingClass; IIdentifier ClassIdentifier = null; IClass BaseClass = null; if (node.ParentType is ISimpleType AsSimpleType) { ClassIdentifier = (IIdentifier)AsSimpleType.ClassIdentifier; } else if (node.ParentType is IGenericType AsGenericType) { ClassIdentifier = (IIdentifier)AsGenericType.ClassIdentifier; } if (ClassIdentifier != null) { Debug.Assert(ClassIdentifier.ValidText.IsAssigned); string ValidIdentifier = ClassIdentifier.ValidText.Item; ISealableDictionary <string, IImportedClass> ImportedClassTable = EmbeddingClass.ImportedClassTable; if (ValidIdentifier.ToUpperInvariant() == LanguageClasses.Any.Name.ToUpperInvariant()) { BaseClass = Class.ClassAny; } else if (ValidIdentifier.ToUpperInvariant() == LanguageClasses.AnyReference.Name.ToUpperInvariant()) { BaseClass = Class.ClassAnyReference; } else if (ValidIdentifier.ToUpperInvariant() == LanguageClasses.AnyValue.Name.ToUpperInvariant()) { BaseClass = Class.ClassAnyValue; } else if (ImportedClassTable.ContainsKey(ValidIdentifier)) { IImportedClass Imported = ImportedClassTable[ValidIdentifier]; BaseClass = Imported.Item; } } data = BaseClass; return(Success); }
/// <summary> /// Validates a class import clauses. /// </summary> /// <param name="libraryTable">Imported libraries.</param> /// <param name="classTable">Imported classes.</param> /// <param name="errorList">List of errors found.</param> /// <returns>True if imports are valid.</returns> public virtual bool CheckClassConsistency(ISealableDictionary <string, ISealableDictionary <string, ILibrary> > libraryTable, ISealableDictionary <string, ISealableDictionary <string, IClass> > classTable, IErrorList errorList) { bool Success = true; // Process all import clauses separately. foreach (IImport ImportItem in ImportList) { if (!ImportItem.CheckImportConsistency(libraryTable, out ILibrary MatchingLibrary, errorList)) { Success = false; continue; } if (ImportedLibraryList.Contains(MatchingLibrary)) { Success = false; errorList.AddError(new ErrorDuplicateImport((IIdentifier)ImportItem.LibraryIdentifier, MatchingLibrary.ValidLibraryName, MatchingLibrary.ValidSourceName)); continue; } if (!Library.MergeImports(ImportedClassTable, ImportItem, MatchingLibrary, errorList)) { Success = false; continue; } ImportedLibraryList.Add(MatchingLibrary); } // Check import specifications. foreach (KeyValuePair <string, IImportedClass> Entry in ImportedClassTable) { IImportedClass Imported = Entry.Value; if (Imported.Item == this) { string NewName = Entry.Key; if (NewName != ValidClassName) { Success = false; errorList.AddError(new ErrorNameChanged(Imported.ImportLocation, ValidClassName, NewName)); } if (Imported.IsTypeAssigned && Imported.ImportType != BaseNode.ImportType.Latest) { Success = false; errorList.AddError(new ErrorImportTypeConflict(Imported.ImportLocation, ValidClassName)); } break; } } // If not referenced by an imported library, a class should be able to reference itself. if (!ImportedClassTable.ContainsKey(ValidClassName)) { IImportedClass SelfImport = new ImportedClass(this, BaseNode.ImportType.Latest); ImportedClassTable.Add(ValidClassName, SelfImport); #if COVERAGE string ImportString = SelfImport.ToString(); #endif } foreach (KeyValuePair <string, IImportedClass> Entry in ImportedClassTable) { IImportedClass Imported = Entry.Value; Imported.SetParentSource(this); } ImportedClassTable.Seal(); Debug.Assert(Success || !errorList.IsEmpty); return(Success); }
private bool IsTypeReady(ISimpleType node, out object data) { data = null; bool IsReady = true; ITypeName ValidTypeName = null; ICompiledType ValidType = null; IError Error = null; IClass EmbeddingClass = node.EmbeddingClass; IFeature EmbeddingFeature = node.EmbeddingFeature; IIdentifier ClassIdentifier = (IIdentifier)node.ClassIdentifier; Debug.Assert(ClassIdentifier.ValidText.IsAssigned); string ValidIdentifier = ClassIdentifier.ValidText.Item; ISealableDictionary <string, IImportedClass> ImportedClassTable = EmbeddingClass.ImportedClassTable; ISealableDictionary <string, ICompiledType> LocalGenericTable = EmbeddingClass.LocalGenericTable; ISealableDictionary <IFeatureName, ISealableDictionary <string, IClass> > LocalExportTable = EmbeddingClass.LocalExportTable; ISealableDictionary <IFeatureName, ITypedefType> LocalTypedefTable = EmbeddingClass.LocalTypedefTable; ISealableDictionary <IFeatureName, IDiscrete> LocalDiscreteTable = EmbeddingClass.LocalDiscreteTable; ISealableDictionary <IFeatureName, IFeatureInstance> LocalFeatureTable = EmbeddingClass.LocalFeatureTable; IsReady &= ImportedClassTable.IsSealed; IsReady &= LocalGenericTable.IsSealed; IsReady &= LocalExportTable.IsSealed; IsReady &= LocalTypedefTable.IsSealed; IsReady &= LocalDiscreteTable.IsSealed; IsReady &= LocalFeatureTable.IsSealed; IsReady &= EmbeddingClass.ResolvedClassType.IsAssigned; if (IsReady) { if (ValidIdentifier.ToUpperInvariant() == LanguageClasses.Any.Name.ToUpperInvariant()) { GetBaseClassType(Class.ClassAny, out ValidTypeName, out ValidType); } else if (ValidIdentifier.ToUpperInvariant() == LanguageClasses.AnyReference.Name.ToUpperInvariant()) { GetBaseClassType(Class.ClassAnyReference, out ValidTypeName, out ValidType); } else if (ValidIdentifier.ToUpperInvariant() == LanguageClasses.AnyValue.Name.ToUpperInvariant()) { GetBaseClassType(Class.ClassAnyValue, out ValidTypeName, out ValidType); } else if (ImportedClassTable.ContainsKey(ValidIdentifier)) { IImportedClass Imported = ImportedClassTable[ValidIdentifier]; IClass BaseClass = Imported.Item; IsReady = CheckValidityAsClass(BaseClass, out ValidTypeName, out ValidType, out bool IsInvalidGeneric); if (IsInvalidGeneric) { Error = new ErrorGenericClass(ClassIdentifier, ValidIdentifier); } } else if (LocalGenericTable.ContainsKey(ValidIdentifier)) { IFormalGenericType FormalGeneric = (IFormalGenericType)LocalGenericTable[ValidIdentifier]; GetGenericType(FormalGeneric, out ValidTypeName, out ValidType); } else if (FeatureName.TableContain(LocalTypedefTable, ValidIdentifier, out IFeatureName Key, out ITypedefType DefinedType)) { IsReady = CheckValidityAsTypedef(DefinedType, out ValidTypeName, out ValidType); } else { Error = new ErrorUnknownIdentifier(ClassIdentifier, ValidIdentifier); } }
/// <summary> /// Checks for errors before applying a rule. /// </summary> /// <param name="node">The node instance to check.</param> /// <param name="dataList">Optional data collected during inspection of sources.</param> /// <param name="data">Private data to give to Apply() upon return.</param> /// <returns>True if an error occured.</returns> public override bool CheckConsistency(IGenericType node, IDictionary <ISourceTemplate, object> dataList, out object data) { bool Success = true; data = null; IIdentifier ClassIdentifier = (IIdentifier)node.ClassIdentifier; Debug.Assert(ClassIdentifier.ValidText.IsAssigned); string ValidIdentifier = ClassIdentifier.ValidText.Item; IClass EmbeddingClass = node.EmbeddingClass; ISealableDictionary <string, IImportedClass> ImportedClassTable = EmbeddingClass.ImportedClassTable; ISealableDictionary <string, ICompiledType> ResolvedTable = new SealableDictionary <string, ICompiledType>(); ISealableDictionary <string, IObjectType> LocationTable = new SealableDictionary <string, IObjectType>(); if (!ImportedClassTable.ContainsKey(ValidIdentifier)) { AddSourceError(new ErrorUnknownIdentifier(ClassIdentifier, ValidIdentifier)); Success = false; } else { TypeArgumentStyles ArgumentStyle = TypeArgumentStyles.None; foreach (ITypeArgument Item in node.TypeArgumentList) { Success &= IsTypeArgumentValid(Item, ref ArgumentStyle); } IImportedClass Imported = ImportedClassTable[ValidIdentifier]; IClass BaseClass = Imported.Item; if (BaseClass.GenericList.Count == 0) { AddSourceError(new ErrorGenericClass(node, ValidIdentifier)); Success = false; } if (Success) { bool IsHandled = false; switch (ArgumentStyle) { case TypeArgumentStyles.None: case TypeArgumentStyles.Positional: Success = CheckPositionalTypeArgumentsValidity(node, BaseClass, ResolvedTable, LocationTable); IsHandled = true; break; case TypeArgumentStyles.Assignment: Success = CheckAssignmentTypeArgumentsValidity(node, BaseClass, ResolvedTable, LocationTable); IsHandled = true; break; } Debug.Assert(IsHandled); if (Success) { ClassType.ResolveType(EmbeddingClass.TypeTable, BaseClass, ResolvedTable, EmbeddingClass.ResolvedClassType.Item, out ITypeName ValidResolvedTypeName, out ICompiledType ValidResolvedType); data = new Tuple <IClass, TypeArgumentStyles, ISealableDictionary <string, ICompiledType>, ISealableDictionary <string, IObjectType>, ITypeName, ICompiledType>(BaseClass, ArgumentStyle, ResolvedTable, LocationTable, ValidResolvedTypeName, ValidResolvedType); } } } return(Success); }