/// <summary> /// Checks if a node source is ready. /// </summary> /// <param name="node">The node for which the value is checked.</param> /// <param name="data">Optional data returned to the caller.</param> public override bool IsReady(TSource node, out object data) { data = null; bool Result = false; ISealableDictionary <TKey, TValue> Value = GetSourceObject(node, out bool IsInterrupted); if (!IsInterrupted && Value.IsSealed) { data = Value; Result = true; } return(Result); }
/// <summary> /// Applies the rule. /// </summary> /// <param name="node">The node instance to modify.</param> /// <param name="data">Private data from CheckConsistency().</param> public override void Apply(IOverLoopInstruction node, object data) { ISealableDictionary <string, IScopeAttributeFeature> CheckedScope = (ISealableDictionary <string, IScopeAttributeFeature>)data; node.InnerLoopScope.Merge(CheckedScope); node.InnerLoopScope.Seal(); node.LocalScope.Seal(); ScopeHolder.RecursiveAdd(CheckedScope, node.InnerScopes); IList <IScopeHolder> EmbeddingScopeList = ScopeHolder.EmbeddingScope(node); EmbeddingScopeList.Add(node); }
/// <summary> /// Resolves reference from libraries to classes and other libraries. /// </summary> /// <param name="libraryTable">The table of known libraries.</param> /// <param name="resolvedLibraryList">The list of libraries that have been resolved so far.</param> /// <param name="importChanged">Indicates that the import specifier has changed.</param> /// <param name="errorList">List of errors found.</param> /// <returns>True if the method succeeded.</returns> public virtual bool Resolve(ISealableDictionary <string, ISealableDictionary <string, ILibrary> > libraryTable, IList <ILibrary> resolvedLibraryList, ref bool importChanged, IErrorList errorList) { List <IImport> ToRemove = new List <IImport>(); bool Success = true; foreach (IImport ImportItem in ImportList) { // Check the import and obtain the matching library. if (!ImportItem.CheckImportConsistency(libraryTable, out ILibrary MatchingLibrary, errorList)) { Success = false; continue; } // You can't import the same library twice. if (ImportedLibraryList.Contains(MatchingLibrary)) { Success = false; errorList.AddError(new ErrorDuplicateImport((IIdentifier)ImportItem.LibraryIdentifier, MatchingLibrary.ValidLibraryName, MatchingLibrary.ValidSourceName)); continue; } // If the imported library hasn't been resolved yet, ignore it for now. if (!resolvedLibraryList.Contains(MatchingLibrary)) { continue; } // The imported library was resolved, merge this import with it. if (!MergeImports(ImportedClassTable, ImportItem, MatchingLibrary, errorList)) { Success = false; continue; } ImportedLibraryList.Add(MatchingLibrary); ToRemove.Add(ImportItem); importChanged = true; } foreach (IImport ImportItem in ToRemove) { ImportList.Remove(ImportItem); } Debug.Assert(Success || !errorList.IsEmpty); return(Success); }
/// <summary> /// Validates an import and return the matching library. /// </summary> /// <param name="libraryTable">Table of valid library names and their sources, updated upon return.</param> /// <param name="matchingLibrary">The matching library upon return.</param> /// <param name="errorList">List of errors found.</param> /// <returns>True if library names are valid.</returns> public virtual bool CheckImportConsistency(ISealableDictionary <string, ISealableDictionary <string, ILibrary> > libraryTable, out ILibrary matchingLibrary, IErrorList errorList) { IErrorStringValidity StringError; string ValidFromIdentifier; IIdentifier ImportLibraryIdentifier = (IIdentifier)LibraryIdentifier; ISealableDictionary <string, ILibrary> SourceNameTable; matchingLibrary = null; if (!StringValidation.IsValidIdentifier(ImportLibraryIdentifier, LibraryIdentifier.Text, out string ValidLibraryIdentifier, out StringError)) { errorList.AddError(StringError); return(false); } // Match the library name and source name. if (!libraryTable.ContainsKey(ValidLibraryIdentifier)) { errorList.AddError(new ErrorUnknownIdentifier(ImportLibraryIdentifier, ValidLibraryIdentifier)); return(false); } SourceNameTable = libraryTable[ValidLibraryIdentifier]; if (FromIdentifier.IsAssigned) { IIdentifier ImportFromIdentifier = (IIdentifier)FromIdentifier.Item; if (!StringValidation.IsValidIdentifier(ImportFromIdentifier, FromIdentifier.Item.Text, out ValidFromIdentifier, out StringError)) { errorList.AddError(StringError); return(false); } } else { ValidFromIdentifier = string.Empty; } if (!SourceNameTable.ContainsKey(ValidFromIdentifier)) { errorList.AddError(new ErrorUnknownIdentifier(ImportLibraryIdentifier, ValidLibraryIdentifier)); return(false); } matchingLibrary = SourceNameTable[ValidFromIdentifier]; return(true); }
/// <summary> /// Finds the matching nodes of a <see cref="IOldExpression"/>. /// </summary> /// <param name="node">The agent expression to check.</param> /// <param name="errorList">The list of errors found.</param> /// <param name="resolvedExpression">The result of the search.</param> public static bool ResolveCompilerReferences(IOldExpression node, IErrorList errorList, out ResolvedExpression resolvedExpression) { resolvedExpression = new ResolvedExpression(); IClass EmbeddingClass = node.EmbeddingClass; IQualifiedName Query = (IQualifiedName)node.Query; IList <IIdentifier> ValidPath = Query.ValidPath.Item; IClassType BaseType = EmbeddingClass.ResolvedClassType.Item; if (!Expression.IsLanguageTypeAvailable(LanguageClasses.Boolean.Guid, node, out ITypeName BooleanTypeName, out ICompiledType BooleanType)) { errorList.AddError(new ErrorBooleanTypeMissing(node)); return(false); } ISealableDictionary <string, IScopeAttributeFeature> LocalScope = Scope.CurrentScope(node); Debug.Assert(LocalScope != null); if (node.EmbeddingBody == null && node.EmbeddingAssertion == null) { errorList.AddError(new ErrorInvalidOldExpression(node)); return(false); } if (!ObjectType.GetQualifiedPathFinalType(EmbeddingClass, BaseType, LocalScope, ValidPath, 0, errorList, out ICompiledFeature FinalFeature, out IDiscrete FinalDiscrete, out ITypeName FinalTypeName, out ICompiledType FinalType, out bool InheritBySideAttribute)) { return(false); } if (FinalFeature == null) { errorList.AddError(new ErrorInvalidOldExpression(node)); return(false); } ObjectType.FillResultPath(EmbeddingClass, BaseType, LocalScope, ValidPath, 0, Query.ValidResultTypePath.Item); resolvedExpression.ResolvedFinalFeature = FinalFeature; resolvedExpression.ResolvedResult = new ResultType(FinalTypeName, FinalType, string.Empty); resolvedExpression.ResolvedException = new ResultException(); #if COVERAGE Debug.Assert(!node.IsComplex); #endif return(true); }
/// <summary> /// Applies the rule. /// </summary> /// <param name="node">The node instance to modify.</param> /// <param name="data">Private data from CheckConsistency().</param> public override void Apply(IQueryOverload node, object data) { IClass EmbeddingClass = node.EmbeddingClass; IFeature EmbeddingFeature = node.EmbeddingFeature; ISealableDictionary <string, IScopeAttributeFeature> CheckedScope = (ISealableDictionary <string, IScopeAttributeFeature>)data; node.LocalScope.Merge(CheckedScope); node.LocalScope.Seal(); node.FullScope.Merge(node.LocalScope); ScopeHolder.RecursiveAdd(node.FullScope, node.InnerScopes); EmbeddingClass.BodyList.Add((IBody)node.QueryBody); EmbeddingClass.QueryOverloadList.Add(node); }
/// <summary> /// Finds all single class attributes in conflict with others already defined in embedding scopes. /// </summary> /// <param name="scope">The scope where the check is performed.</param> /// <param name="innerScopeList">The list of inner scopes.</param> /// <param name="assignedSingleClassList">The list of assigned single class attributes.</param> /// <param name="source">The location where to report errors.</param> /// <param name="errorList">The list of errors found.</param> public static bool HasConflictingSingleAttributes(ISealableDictionary <string, IScopeAttributeFeature> scope, IList <IScopeHolder> innerScopeList, IList <IClass> assignedSingleClassList, ISource source, IErrorList errorList) { bool IsAssigned = false; foreach (KeyValuePair <string, IScopeAttributeFeature> ScopeNameItem in scope) { IsAssigned |= ScopeNameItem.Value.IsGroupAssigned(assignedSingleClassList, source, errorList); } foreach (IScopeHolder Item in innerScopeList) { IsAssigned |= HasConflictingSingleAttributes(scope, Item.InnerScopes, assignedSingleClassList, source, errorList); } return(IsAssigned); }
/// <summary> /// Checks if a path to a target type is made of resolved elements. /// </summary> /// <param name="path">The path to the target.</param> /// <param name="localEntityList">The list of available local variables.</param> /// <param name="localFeatureTable">The local feature table at the begining of the path.</param> /// <param name="featureTable">The feature table at the begining of the path.</param> /// <param name="errorList">The list of errors found.</param> /// <param name="resolvedPathTypeName">The target type name upon return.</param> /// <param name="resolvedPathType">The target type upon return.</param> /// <returns>True if the path could be resolved to the target.</returns> public static bool IsPathReady(IList <IIdentifier> path, List <IEntityDeclaration> localEntityList, ISealableDictionary <IFeatureName, IFeatureInstance> localFeatureTable, ISealableDictionary <IFeatureName, IFeatureInstance> featureTable, IErrorList errorList, out ITypeName resolvedPathTypeName, out ICompiledType resolvedPathType) { resolvedPathTypeName = null; resolvedPathType = null; ISealableDictionary <IFeatureName, IFeatureInstance> FeatureTable; // We start with a feature table. The full table if available, the local table otherwise. /* * if (featureTable.IsSealed) * FeatureTable = featureTable; * else if (localFeatureTable.IsSealed) * FeatureTable = localFeatureTable; * else * return false; */ if (localFeatureTable.IsSealed) { FeatureTable = localFeatureTable; } else { return(false); } Debug.Assert(path.Count > 0); bool IsInterrupted = false; bool IsReady = true; int i = 0; // If an error is found, the error will be processed in CheckConsistency. for (; i + 1 < path.Count && !IsInterrupted && IsReady; i++) { IsReady &= IsPathItemReady(path[i], path[i + 1], ref localEntityList, ref FeatureTable, errorList, ref IsInterrupted); } // This loop executes once if IsReady is true, and doesn't otherwise. for (; i < path.Count && !IsInterrupted && IsReady; i++) { IsReady &= IsLastPathItemReady(path[i], localEntityList, FeatureTable, errorList, ref IsInterrupted, out resolvedPathTypeName, out resolvedPathType); } return(IsReady || IsInterrupted); }
/// <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); }
private bool HasConflictingEntry(IClass node, ISealableDictionary <IFeatureName, ISealableDictionary <string, IClass> > mergedExportTable) { bool Result = false; foreach (IInheritance Inheritance in node.InheritanceList) { Debug.Assert(Inheritance.ExportTable.IsAssigned); ISealableDictionary <IFeatureName, ISealableDictionary <string, IClass> > InheritedExportTable = Inheritance.ExportTable.Item; foreach (KeyValuePair <IFeatureName, ISealableDictionary <string, IClass> > InstanceEntry in InheritedExportTable) { IFeatureName InstanceName = InstanceEntry.Key; ISealableDictionary <string, IClass> InstanceItem = InstanceEntry.Value; bool ConflictingEntry = false; foreach (KeyValuePair <IFeatureName, ISealableDictionary <string, IClass> > Entry in mergedExportTable) { IFeatureName LocalName = Entry.Key; ISealableDictionary <string, IClass> LocalItem = Entry.Value; if (InstanceName.Name == LocalName.Name) { if (InstanceItem != LocalItem) { AddSourceError(new ErrorDuplicateName(Inheritance, LocalName.Name)); ConflictingEntry = true; Result = true; } } else if (InstanceItem == LocalItem) { AddSourceError(new ErrorExportNameConflict(Inheritance, LocalName.Name, InstanceName.Name)); ConflictingEntry = true; Result = true; } } if (!ConflictingEntry && !mergedExportTable.ContainsKey(InstanceName)) { mergedExportTable.Add(InstanceName, InstanceItem); } } } return(Result); }
/// <summary> /// Checks if a node source is ready. /// </summary> /// <param name="node">The node for which the value is checked.</param> /// <param name="data">Optional data returned to the caller.</param> public override bool IsReady(TSource node, out object data) { data = null; bool Result = false; OnceReference <IList <IIdentifier> > Value = GetSourceObject(node, out bool IsInterrupted); if (!IsInterrupted && Value.IsAssigned) { IList <IIdentifier> Path = Value.Item; foreach (IIdentifier Identifier in Path) { Debug.Assert(Identifier.ValidText.IsAssigned); } List <IEntityDeclaration> LocalEntityList = new List <IEntityDeclaration>(); if (node.EmbeddingOverload is ICommandOverload AsCommandOverload) { LocalEntityList.AddRange(AsCommandOverload.ParameterList); } else if (node.EmbeddingOverload is IQueryOverload AsQueryOverload) { LocalEntityList.AddRange(AsQueryOverload.ParameterList); LocalEntityList.AddRange(AsQueryOverload.ResultList); } if (node.EmbeddingBody is IEffectiveBody AsEffectiveBody) { LocalEntityList.AddRange(AsEffectiveBody.EntityDeclarationList); } IClass Class = node.EmbeddingClass; ISealableDictionary <IFeatureName, IFeatureInstance> LocalFeatureTable = Class.LocalFeatureTable; ISealableDictionary <IFeatureName, IFeatureInstance> FeatureTable = Class.FeatureTable; IErrorList ErrorList = new ErrorList(); if (IsPathReady(Path, LocalEntityList, LocalFeatureTable, FeatureTable, ErrorList, out ITypeName ResolvedPathTypeName, out ICompiledType ResolvedPathType)) { data = new Tuple <IErrorList, ITypeName, ICompiledType>(ErrorList, ResolvedPathTypeName, ResolvedPathType); Result = true; } } return(Result); }
/// <summary> /// Applies the rule. /// </summary> /// <param name="node">The node instance to modify.</param> /// <param name="data">Private data from CheckConsistency().</param> public override void Apply(IClass node, object data) { ISealableDictionary <IFeatureName, IFeatureInstance> MergedFeatureTable = (ISealableDictionary <IFeatureName, IFeatureInstance>)data; IClassType ThisClassType = node.ResolvedClassType.Item; ThisClassType.FeatureTable.Merge(MergedFeatureTable); ThisClassType.FeatureTable.Seal(); node.FeatureTable.Merge(MergedFeatureTable); node.FeatureTable.Seal(); foreach (ICompiledType Item in node.GenericInstanceList) { Item.FeatureTable.Merge(MergedFeatureTable); Item.FeatureTable.Seal(); } }
private bool CheckPrecursorBodiesHaveAncestor(ISealableDictionary <IFeatureName, InheritedInstanceInfo> byNameTable, IErrorList errorList) { foreach (KeyValuePair <IFeatureName, InheritedInstanceInfo> ImportedEntry in byNameTable) { IFeatureName ImportedKey = ImportedEntry.Key; InheritedInstanceInfo ImportedInstance = ImportedEntry.Value; if (ImportedInstance.EffectiveInstance.IsAssigned) { InstanceNameInfo Item = ImportedInstance.EffectiveInstance.Item; ICompiledFeature EffectiveFeature = Item.Instance.Feature; if (EffectiveFeature.HasPrecursorBody) { bool HasEffectiveAncestor = false; foreach (InstanceNameInfo AncestorItem in ImportedInstance.PrecursorInstanceList) { if (AncestorItem == Item) { continue; } ICompiledFeature AncestorEffectiveFeature = AncestorItem.Instance.Feature; if (AncestorEffectiveFeature.IsDeferredFeature) { continue; } HasEffectiveAncestor = true; } if (!HasEffectiveAncestor) { IFeature AsFeature = EffectiveFeature as IFeature; Debug.Assert(AsFeature != null); errorList.AddError(new ErrorMissingAncestor(AsFeature, Item.Name.Name)); return(false); } } } } return(true); }
/// <summary> /// Checks if a matching function and overload exists in a type table. /// </summary> /// <param name="typeTable">The table of existing types.</param> /// <param name="overload">The overload to check.</param> /// <param name="overloadList">The list of other overloads in the candidate function type.</param> public static bool IsQueryOverloadMatching(ISealableDictionary <ITypeName, ICompiledType> typeTable, IQueryOverloadType overload, IList <IQueryOverloadType> overloadList) { bool IsMatching = false; for (int i = 0; i < overloadList.Count && !IsMatching; i++) { IQueryOverloadType Item = overloadList[i]; IsMatching = true; IsMatching &= IsParametersMatching(overload, Item); IsMatching &= IsResultsMatching(overload, Item); IsMatching &= Assertion.IsAssertionListEqual(overload.RequireList, Item.RequireList); IsMatching &= Assertion.IsAssertionListEqual(overload.EnsureList, Item.EnsureList); IsMatching &= ExceptionHandler.IdenticalExceptionSignature(overload.ExceptionIdentifierList, Item.ExceptionIdentifierList); } return(IsMatching); }
/// <summary> /// Finds all names that in conflict with others already defined in embedding scopes. /// </summary> /// <param name="source">The scope where the check is performed.</param> /// <param name="innerScopeList">The list of inner scopes.</param> /// <param name="conflictList">The list of conflicting names.</param> public static void RecursiveCheck(ISealableDictionary <string, IScopeAttributeFeature> source, IList <IScopeHolder> innerScopeList, IList <string> conflictList) { foreach (IScopeHolder Item in innerScopeList) { foreach (KeyValuePair <string, IScopeAttributeFeature> ScopeNameItem in source) { if (Item.FullScope.ContainsKey(ScopeNameItem.Key)) { if (!conflictList.Contains(ScopeNameItem.Key)) { conflictList.Add(ScopeNameItem.Key); } } } RecursiveCheck(source, Item.InnerScopes, conflictList); } }
/// <summary> /// Finds the matching nodes of a <see cref="INewExpression"/>. /// </summary> /// <param name="node">The agent expression to check.</param> /// <param name="errorList">The list of errors found.</param> /// <param name="resolvedResult">The expression result types upon return.</param> /// <param name="resolvedException">Exceptions the expression can throw upon return.</param> /// <param name="constantSourceList">Sources of the constant expression upon return, if any.</param> /// <param name="expressionConstant">The expression constant upon return.</param> /// <param name="resolvedFinalFeature">The matching feature upon return.</param> public static bool ResolveCompilerReferences(INewExpression node, IErrorList errorList, out IResultType resolvedResult, out IResultException resolvedException, out ISealableList <IExpression> constantSourceList, out ILanguageConstant expressionConstant, out ICompiledFeature resolvedFinalFeature) { resolvedResult = null; resolvedException = null; constantSourceList = new SealableList <IExpression>(); expressionConstant = NeutralLanguageConstant.NotConstant; resolvedFinalFeature = null; IClass EmbeddingClass = node.EmbeddingClass; IQualifiedName Object = (IQualifiedName)node.Object; IList <IIdentifier> ValidPath = Object.ValidPath.Item; IClassType BaseType = EmbeddingClass.ResolvedClassType.Item; if (!Expression.IsLanguageTypeAvailable(LanguageClasses.Boolean.Guid, node, out ITypeName BooleanTypeName, out ICompiledType BooleanType)) { errorList.AddError(new ErrorBooleanTypeMissing(node)); return(false); } ISealableDictionary <string, IScopeAttributeFeature> LocalScope = Scope.CurrentScope(node); if (!ObjectType.GetQualifiedPathFinalType(EmbeddingClass, BaseType, LocalScope, ValidPath, 0, errorList, out ICompiledFeature FinalFeature, out IDiscrete FinalDiscrete, out ITypeName FinalTypeName, out ICompiledType FinalType, out bool InheritBySideAttribute)) { return(false); } if (FinalFeature == null) { errorList.AddError(new ErrorConstantNewExpression(node)); return(false); } ObjectType.FillResultPath(EmbeddingClass, BaseType, LocalScope, ValidPath, 0, Object.ValidResultTypePath.Item); resolvedResult = new ResultType(BooleanTypeName, BooleanType, string.Empty); resolvedException = new ResultException(); resolvedFinalFeature = FinalFeature; #if COVERAGE Debug.Assert(!node.IsComplex); #endif return(true); }
/// <summary> /// Checks if a table of feature names contains a name, and if so returns the corresponding <see cref="IFeatureName"/> and associated value. /// </summary> /// <typeparam name="TValue">The type of the value associated to feature names in the table.</typeparam> /// <param name="table">The table.</param> /// <param name="name">The name to check.</param> /// <param name="key">The feature name found upon return.</param> /// <param name="value">The associated value.</param> public static bool TableContain <TValue>(ISealableDictionary <IFeatureName, TValue> table, string name, out IFeatureName key, out TValue value) { key = null; value = default; bool Result = false; foreach (KeyValuePair <IFeatureName, TValue> Entry in table) { if (Entry.Key.Name == name) { key = Entry.Key; value = Entry.Value; Result = true; break; } } return(Result); }
private bool ResolveIdentifierList(IList <IIdentifier> identifierList, out ISealableDictionary <string, IIdentifier> resultTable) { resultTable = new SealableDictionary <string, IIdentifier>(); foreach (IIdentifier IdentifierItem in identifierList) { string ValidText = IdentifierItem.ValidText.Item; if (resultTable.ContainsKey(ValidText)) { AddSourceError(new ErrorIdentifierAlreadyListed(IdentifierItem, ValidText)); return(false); } resultTable.Add(ValidText, IdentifierItem); } return(true); }
/// <summary> /// Applies the rule. /// </summary> /// <param name="node">The node instance to modify.</param> /// <param name="data">Private data from CheckConsistency().</param> public override void Apply(IClass node, object data) { ISealableDictionary <IFeatureName, ITypedefType> MergedTypedefTable = (ISealableDictionary <IFeatureName, ITypedefType>)data; Debug.Assert(node.ResolvedClassType.IsAssigned); IClassType ThisClassType = node.ResolvedClassType.Item; ThisClassType.TypedefTable.Merge(MergedTypedefTable); ThisClassType.TypedefTable.Seal(); node.TypedefTable.Merge(MergedTypedefTable); node.TypedefTable.Seal(); foreach (IClassType Item in node.GenericInstanceList) { Item.TypedefTable.Merge(MergedTypedefTable); Item.TypedefTable.Seal(); } }
private void CheckAllPrecursorSelectedInNameTable(ISealableDictionary <IFeatureName, InheritedInstanceInfo> byNameTable, IList <ISealableDictionary <IFeatureName, IList <ICompiledFeature> > > precursorSetList) { foreach (KeyValuePair <IFeatureName, InheritedInstanceInfo> Entry in byNameTable) { IFeatureName Key = Entry.Key; InheritedInstanceInfo Value = Entry.Value; IList <ICompiledFeature> PrecursorList = new List <ICompiledFeature>(); foreach (InstanceNameInfo PrecursorItem in Value.PrecursorInstanceList) { FillPrecursorList(PrecursorList, PrecursorItem.Instance); } bool FoundInSet = false; foreach (ISealableDictionary <IFeatureName, IList <ICompiledFeature> > PrecursorSet in precursorSetList) { foreach (KeyValuePair <IFeatureName, IList <ICompiledFeature> > SetMemberEntry in PrecursorSet) { IFeatureName SetMemberKey = SetMemberEntry.Key; IList <ICompiledFeature> SetMemberPrecursorList = SetMemberEntry.Value; if (PrecursorListIntersect(PrecursorList, SetMemberPrecursorList)) { PrecursorSet.Add(Key, PrecursorList); FoundInSet = true; break; } } if (FoundInSet) { break; } } if (!FoundInSet) { ISealableDictionary <IFeatureName, IList <ICompiledFeature> > NewSet = new SealableDictionary <IFeatureName, IList <ICompiledFeature> >(); NewSet.Add(Key, PrecursorList); precursorSetList.Add(NewSet); } } }
/// <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(IClass node, IDictionary <ISourceTemplate, object> dataList, out object data) { bool Success = true; data = null; ISealableDictionary <IFeatureName, IFeatureInstance> MergedFeatureTable = null; IList <AncestorFeatureInfo> FeatureTableList = new List <AncestorFeatureInfo>(); ListLocalAndInheritedFeatures(node, FeatureTableList); ISealableDictionary <ICompiledFeature, IList <InstanceNameInfo> > ByFeatureTable; // ICompiledFeature -> List of InstanceNameInfo ISealableDictionary <IFeatureName, InheritedInstanceInfo> ByNameTable; // FeatureName -> InheritedInstanceInfo SortByFeatureAndByName(FeatureTableList, out ByFeatureTable, out ByNameTable); if (!CheckInheritanceConsistency(ByFeatureTable, ByNameTable, node.ResolvedClassType.Item, ErrorList)) { Success = false; } else if (!CheckAllPrecursorSelected(ByNameTable, ErrorList)) { Success = false; } else if (!CheckPrecursorBodiesHaveAncestor(ByNameTable, ErrorList)) { Success = false; } else { MergeInheritedFeatures(node, ByNameTable, out MergedFeatureTable); ClassType.MergeConformingParentTypes(node, node.ResolvedClassType.Item); } if (Success) { data = MergedFeatureTable; } return(Success); }
private static ISealableDictionary <string, IScopeAttributeFeature> CurrentIndexerScope(IIndexerFeature indexerFeature, ISource childSource) { ISealableDictionary <string, IScopeAttributeFeature> Result = null; bool IsHandled = false; if (indexerFeature.GetterBody.IsAssigned && indexerFeature.GetterBody.Item == childSource) { Result = indexerFeature.FullGetScope; IsHandled = true; } else if (indexerFeature.SetterBody.IsAssigned && indexerFeature.SetterBody.Item == childSource) { Result = indexerFeature.FullSetScope; IsHandled = true; } Debug.Assert(IsHandled); return(Result); }
/// <summary> /// Applies the rule. /// </summary> /// <param name="node">The node instance to modify.</param> /// <param name="data">Private data from CheckConsistency().</param> public override void Apply(IAttachmentInstruction node, object data) { IList <ISealableDictionary <string, IScopeAttributeFeature> > CheckedScopeList = (IList <ISealableDictionary <string, IScopeAttributeFeature> >)data; Debug.Assert(CheckedScopeList.Count == node.AttachmentList.Count); node.LocalScope.Seal(); for (int i = 0; i < node.AttachmentList.Count; i++) { IAttachment AttachmentItem = node.AttachmentList[i]; ISealableDictionary <string, IScopeAttributeFeature> CheckedScope = CheckedScopeList[i]; AttachmentItem.FullScope.Merge(CheckedScope); ScopeHolder.RecursiveAdd(CheckedScope, AttachmentItem.InnerScopes); } IList <IScopeHolder> EmbeddingScopeList = ScopeHolder.EmbeddingScope(node); EmbeddingScopeList.Add(node); }
/// <summary> /// Creates an instance of a class type, or reuse an existing instance. /// </summary> /// <param name="instancingClassType">The class type to instanciate.</param> /// <param name="resolvedTypeName">The proposed type instance name.</param> /// <param name="resolvedType">The proposed type instance.</param> public void InstanciateType(ICompiledTypeWithFeature instancingClassType, ref ITypeName resolvedTypeName, ref ICompiledType resolvedType) { ISealableDictionary <ITypeName, ICompiledType> TypeTable = GetTypeTable(); Debug.Assert(TypeTable.Count == 0); if (instancingClassType is IClassType AsClassType) { ISealableDictionary <string, ICompiledType> TypeArgumentTable = AsClassType.TypeArgumentTable; foreach (KeyValuePair <string, ICompiledType> TypeArgument in TypeArgumentTable) { if (TypeArgument.Key == TypeFriendlyName) { resolvedType = TypeArgument.Value; break; } } } }
/// <summary> /// Applies the rule. /// </summary> /// <param name="node">The node instance to modify.</param> /// <param name="data">Private data from CheckConsistency().</param> public override void Apply(IClass node, object data) { ISealableDictionary <IDiscrete, string> AssignedDiscreteTable = node.AssignedDiscreteTable; Debug.Assert(AssignedDiscreteTable.Count == 0); foreach (IInheritance Inheritance in node.InheritanceList) { AssignedDiscreteTable.Merge(Inheritance.AssignedDiscreteTable); } foreach (IDiscrete Discrete in node.DiscreteList) { if (!Discrete.NumericValue.IsAssigned) { AssignedDiscreteTable.Add(Discrete, Guid.NewGuid().ToString()); } } AssignedDiscreteTable.Seal(); }
/// <summary> /// Gets the object a path is refering to. /// </summary> /// <param name="baseClass">The class where the path is used.</param> /// <param name="baseType">The type at the start of the path.</param> /// <param name="localScope">The local scope.</param> /// <param name="validPath">The path.</param> /// <param name="index">Index of the current identifier in the path.</param> /// <param name="errorList">The list of errors found.</param> /// <param name="finalFeature">The feature at the end of the path, if any, upon return.</param> /// <param name="finalDiscrete">The discrete at the end of the path, if any, upon return.</param> /// <param name="finalTypeName">The type name of the result.</param> /// <param name="finalType">The type of the result.</param> /// <param name="inheritBySideAttribute">Inherited from an effective body.</param> public static bool GetQualifiedPathFinalType(IClass baseClass, ICompiledType baseType, ISealableDictionary <string, IScopeAttributeFeature> localScope, IList <IIdentifier> validPath, int index, IErrorList errorList, out ICompiledFeature finalFeature, out IDiscrete finalDiscrete, out ITypeName finalTypeName, out ICompiledType finalType, out bool inheritBySideAttribute) { finalFeature = null; finalDiscrete = null; finalTypeName = null; finalType = null; inheritBySideAttribute = false; ISealableDictionary <IFeatureName, IFeatureInstance> FeatureTable = baseType.FeatureTable; IIdentifier ValidIdentifier = validPath[index]; string ValidText = ValidIdentifier.ValidText.Item; if (index == 0 && localScope.ContainsKey(ValidText)) { return(GetQualifiedPathFinalTypeFromLocal(baseClass, baseType, localScope, validPath, index, errorList, out finalFeature, out finalDiscrete, out finalTypeName, out finalType, out inheritBySideAttribute)); } else if (FeatureName.TableContain(FeatureTable, ValidText, out IFeatureName Key, out IFeatureInstance Instance)) { return(GetQualifiedPathFinalTypeAsFeature(baseClass, baseType, localScope, validPath, index, errorList, Instance, out finalFeature, out finalDiscrete, out finalTypeName, out finalType, out inheritBySideAttribute)); }
/// <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(IClass node, IDictionary <ISourceTemplate, object> dataList, out object data) { bool Success = true; data = null; IList <IIdentifier> ConversionList = node.ConversionList; ISealableDictionary <IFeatureName, IFeatureInstance> FeatureTable = node.FeatureTable; ISealableDictionary <IFeatureName, ICreationFeature> ConversionFromTable = new SealableDictionary <IFeatureName, ICreationFeature>(); ISealableDictionary <IFeatureName, IFunctionFeature> ConversionToTable = new SealableDictionary <IFeatureName, IFunctionFeature>(); foreach (IIdentifier Identifier in ConversionList) { Debug.Assert(Identifier.ValidText.IsAssigned); string ValidText = Identifier.ValidText.Item; if (!FeatureName.TableContain(FeatureTable, ValidText, out IFeatureName Key, out IFeatureInstance Instance)) { AddSourceError(new ErrorUnknownIdentifier(Identifier, ValidText)); Success = false; }
/// <summary> /// Checks if a matching class type exists in a type table. /// </summary> /// <param name="typeTable">The table of existing types.</param> /// <param name="baseClass">The class this is from.</param> /// <param name="typeArgumentTable">The generic arguments used when creating the class type.</param> /// <param name="resolvedTypeName">The type name upon return.</param> /// <param name="resolvedType">The type upon return.</param> public static bool TypeTableContaining(ISealableDictionary <ITypeName, ICompiledType> typeTable, IClass baseClass, ISealableDictionary <string, ICompiledType> typeArgumentTable, out ITypeName resolvedTypeName, out ICompiledType resolvedType) { resolvedTypeName = null; resolvedType = null; bool Result = false; foreach (KeyValuePair <ITypeName, ICompiledType> Entry in typeTable) { if (Entry.Value is IClassType AsClassType) { if (AsClassType.BaseClass == baseClass) { ISealableDictionary <string, ICompiledType> ResolvedTypeArgumentTable = AsClassType.TypeArgumentTable; bool AllArgumentsEqual = true; foreach (KeyValuePair <string, ICompiledType> TypeArgumentEntry in typeArgumentTable) { string GenericName = TypeArgumentEntry.Key; ICompiledType TypeArgument = TypeArgumentEntry.Value; Debug.Assert(ResolvedTypeArgumentTable.ContainsKey(GenericName)); ICompiledType ResolvedTypeArgument = ResolvedTypeArgumentTable[GenericName]; AllArgumentsEqual &= TypeArgument == ResolvedTypeArgument; } if (AllArgumentsEqual) { Debug.Assert(!Result); resolvedTypeName = Entry.Key; resolvedType = AsClassType; Result = true; } } } } return(Result); }
/// <summary> /// Creates a class type with resolved arguments. /// </summary> /// <param name="baseClass">The class this is from.</param> /// <param name="typeArgumentTable">The generic arguments used when creating the class type.</param> /// <param name="instancingClassType">The class type to instanciate.</param> /// <param name="resolvedTypeName">The type name upon return.</param> /// <param name="resolvedType">The type upon return.</param> public static void BuildType(IClass baseClass, ISealableDictionary <string, ICompiledType> typeArgumentTable, ICompiledTypeWithFeature instancingClassType, out ITypeName resolvedTypeName, out ICompiledType resolvedType) { resolvedTypeName = null; resolvedType = null; IClassType ResolvedClassType = Create(baseClass, typeArgumentTable, instancingClassType); #if COVERAGE string TypeString = ResolvedClassType.ToString(); #endif resolvedTypeName = new TypeName(ResolvedClassType.TypeFriendlyName); resolvedType = ResolvedClassType; if (baseClass.DiscreteTable.IsSealed) { ResolvedClassType.DiscreteTable.Merge(baseClass.DiscreteTable); ResolvedClassType.DiscreteTable.Seal(); } if (baseClass.ExportTable.IsSealed) { ResolvedClassType.ExportTable.Merge(baseClass.ExportTable); ResolvedClassType.ExportTable.Seal(); } if (baseClass.FeatureTable.IsSealed) { ResolvedClassType.FeatureTable.Merge(baseClass.FeatureTable); ResolvedClassType.FeatureTable.Seal(); } if (baseClass.TypedefTable.IsSealed) { ResolvedClassType.TypedefTable.Merge(baseClass.TypedefTable); ResolvedClassType.TypedefTable.Seal(); } baseClass.GenericInstanceList.Add(ResolvedClassType); }
/* * Two precursor index expressions cannot be compared because it happens only when comparing different features, and there can be only one indexer. * public static bool IsExpressionEqual(IPrecursorIndexExpression expression1, IPrecursorIndexExpression expression2) * { * bool Result = true; * * if (expression1.AncestorType.IsAssigned && expression2.AncestorType.IsAssigned) * { * IObjectType AncestorType1 = (IObjectType)expression1.AncestorType; * IObjectType AncestorType2 = (IObjectType)expression2.AncestorType; * * Debug.Assert(AncestorType1.ResolvedType.IsAssigned); * Debug.Assert(AncestorType2.ResolvedType.IsAssigned); * * Result &= AncestorType1.ResolvedType.Item == AncestorType2.ResolvedType.Item; * } * * Result &= expression1.AncestorType.IsAssigned == expression2.AncestorType.IsAssigned; * Result &= Argument.IsArgumentListEqual(expression1.ArgumentList, expression2.ArgumentList); * * return Result; * } */ /// <summary> /// Finds the matching nodes of a <see cref="IPrecursorIndexExpression"/>. /// </summary> /// <param name="node">The agent expression to check.</param> /// <param name="errorList">The list of errors found.</param> /// <param name="resolvedExpression">The result of the search.</param> public static bool ResolveCompilerReferences(IPrecursorIndexExpression node, IErrorList errorList, out ResolvedExpression resolvedExpression) { resolvedExpression = new ResolvedExpression(); IOptionalReference <BaseNode.IObjectType> AncestorType = node.AncestorType; IList <IArgument> ArgumentList = node.ArgumentList; IClass EmbeddingClass = node.EmbeddingClass; ISealableDictionary <string, IImportedClass> ClassTable = EmbeddingClass.ImportedClassTable; ISealableDictionary <IFeatureName, IFeatureInstance> FeatureTable = EmbeddingClass.FeatureTable; IFeature InnerFeature = node.EmbeddingFeature; if (InnerFeature is IIndexerFeature AsIndexerFeature) { IFeatureInstance Instance = FeatureTable[FeatureName.IndexerFeatureName]; if (!Instance.FindPrecursor(node.AncestorType, errorList, node, out IFeatureInstance SelectedPrecursor)) { return(false); } resolvedExpression.SelectedPrecursor = SelectedPrecursor; if (!ResolveSelectedPrecursor(node, SelectedPrecursor, errorList, ref resolvedExpression)) { return(false); } } else { errorList.AddError(new ErrorIndexPrecursorNotAllowedOutsideIndexer(node)); return(false); } #if COVERAGE Debug.Assert(!node.IsComplex); #endif return(true); }