/// <summary> /// Combines independent resolutions in a disjointed dictionary, resulting in a /// resolution dictionary that has type parameter keys that are not referenced /// in its values. Null mappings are removed in the resulting dictionary. /// Returns the resulting dictionary. /// </summary> private TypeParameterResolutions CombineTypeResolutionDictionary(TypeParameterResolutions independentResolutions) { var combinedBuilder = ImmutableDictionary.CreateBuilder <TypeParameterName, ResolvedType>(); foreach (var(typeParam, paramRes) in independentResolutions) { // Skip any null mappings if (paramRes is null) { continue; } // Contains a lookup of all the keys in the combined resolutions whose value needs to be updated // if a certain type parameter is resolved by the currently processed dictionary. var mayBeReplaced = GetReplaceable(combinedBuilder); // Check that we are not constricting a type parameter to another type parameter of the same callable // both before and after updating the current value with the resolutions processed so far. this.UpdateConstrictionFlag(typeParam, paramRes); var resolvedParamRes = ResolvedType.ResolveTypeParameters(combinedBuilder.ToImmutable(), paramRes); this.UpdateConstrictionFlag(typeParam, resolvedParamRes); // Do any replacements for type parameters that may be replaced with the current resolution. this.UpdatedReplaceableResolutions(mayBeReplaced, combinedBuilder, typeParam, resolvedParamRes); // Add the resolution to the current dictionary. combinedBuilder[typeParam] = resolvedParamRes; } return(combinedBuilder.ToImmutable()); }
/// <summary> /// Constructor for CallGraphEdge objects. /// Strips position info from the given type parameter resolutions. /// </summary> internal CallGraphEdge(TypeParameterResolutions paramResolutions, Range referenceRange) : base(referenceRange) { // Remove position info from type parameter resolutions this.ParamResolutions = paramResolutions.ToImmutableDictionary( kvp => kvp.Key, kvp => StripPositionInfo.Apply(kvp.Value)); }
/// <summary> /// Constructor for ConcreteCallGraphNode objects. /// Strips position info from the given type parameter resolutions. /// </summary> public ConcreteCallGraphNode(QsQualifiedName callableName, QsSpecializationKind kind, TypeParameterResolutions paramResolutions) : base(callableName) { this.Kind = kind; // Remove position info from type parameter resolutions this.ParamResolutions = paramResolutions.ToImmutableDictionary( kvp => kvp.Key, kvp => StripPositionInfo.Apply(kvp.Value)); }
private ReplaceTypeParamImplementations(TypeParameterResolutions typeParams, GetAccessModifiers getAccessModifiers) : base(new TransformationState(typeParams, getAccessModifiers)) { this.Namespaces = new NamespaceTransformation(this); this.Statements = new StatementTransformation <TransformationState>(this); this.StatementKinds = new StatementKindTransformation <TransformationState>(this); this.Expressions = new ExpressionTransformation(this); this.ExpressionKinds = new ExpressionKindTransformation <TransformationState>(this); this.Types = new TypeTransformation(this); }
public override TypeParameterResolutions OnTypeParamResolutions(TypeParameterResolutions typeParams) { if (typeParams.Any()) { var noIntrinsicRes = typeParams.Where(kvp => !this.SharedState.IntrinsicCallableSet.Contains(kvp.Key.Item1)).ToImmutableDictionary(); var intrinsicRes = typeParams.Where(kvp => this.SharedState.IntrinsicCallableSet.Contains(kvp.Key.Item1)).ToImmutableDictionary(); this.SharedState.CurrentTypeParamResolutions.Push(noIntrinsicRes); return(intrinsicRes); } else { return(typeParams); } }
// Rewrite Calls private static Identifier GetConcreteIdentifier( Dictionary <ConcreteCallGraphNode, QsQualifiedName> concreteNames, Identifier.GlobalCallable globalCallable, TypeParameterResolutions types) { if (types.IsEmpty) { return(globalCallable); } var node = new ConcreteCallGraphNode(globalCallable.Item, QsSpecializationKind.QsBody, types); if (concreteNames.TryGetValue(node, out var name)) { return(Identifier.NewGlobalCallable(name)); } else { return(globalCallable); } }
/// <summary> /// Combines the resolution dictionaries in the combination into one resolution dictionary containing /// the resolutions for all the type parameters found. /// Updates the combination with the constructed dictionary. Updates the validation flags accordingly. /// </summary> private void CombineTypeResolutions() { var combinedBuilder = ImmutableDictionary.CreateBuilder <TypeParameterName, ResolvedType>(); foreach (var resolutionDictionary in this.IndependentResolutionDictionaries) { var resolvedDictionary = this.CombineTypeResolutionDictionary(resolutionDictionary); // Contains a lookup of all the keys in the combined resolutions whose value needs to be updated // if a certain type parameter is resolved by the currently processed dictionary. var mayBeReplaced = GetReplaceable(combinedBuilder); // Do any replacements for type parameters that may be replaced with values in the current dictionary. // This needs to be done first to cover an edge case. foreach (var(typeParam, paramRes) in resolvedDictionary.Where(entry => mayBeReplaced.Contains(entry.Key))) { this.UpdatedReplaceableResolutions(mayBeReplaced, combinedBuilder, typeParam, paramRes); } // Validate and add each resolution to the result. foreach (var(typeParam, paramRes) in resolvedDictionary) { // Check that we are not constricting a type parameter to another type parameter of the same callable. this.UpdateConstrictionFlag(typeParam, paramRes); // Check that there is no conflicting resolution already defined. if (!this.combinesOverConflictingResolution) { this.combinesOverConflictingResolution = combinedBuilder.TryGetValue(typeParam, out var current) && !current.Equals(paramRes) && !IsSelfResolution(typeParam, current); } // Add the resolution to the current dictionary. combinedBuilder[typeParam] = paramRes; } } this.CombinedResolutionDictionary = this.CombineTypeResolutionDictionary(combinedBuilder.ToImmutable()); }
public override TypeParameterResolutions OnTypeParamResolutions(TypeParameterResolutions typeParams) { // We don't want to process the keys of type parameter resolutions return(typeParams.ToImmutableDictionary(kvp => kvp.Key, kvp => this.Types.OnType(kvp.Value))); }
public TransformationState(TypeParameterResolutions typeParams, GetAccessModifiers getAccessModifiers) { this.TypeParams = typeParams; this.GetAccessModifiers = getAccessModifiers; }
public static QsCallable Apply(QsCallable callable, TypeParameterResolutions typeParams, GetAccessModifiers getAccessModifiers) { var filter = new ReplaceTypeParamImplementations(typeParams, getAccessModifiers); return(filter.Namespaces.OnCallableDeclaration(callable)); }
private void AddEdge(QsQualifiedName identifier, QsSpecializationKind kind, TypeParameterResolutions typeRes, Range referenceRange) { if (this.CurrentNode is null) { throw new ArgumentException("AddEdge requires CurrentNode to be non-null."); } var called = new ConcreteCallGraphNode(identifier, kind, typeRes); var edge = new ConcreteCallGraphEdge(referenceRange); this.Graph.AddDependency(this.CurrentNode, called, edge); if (!this.RequestStack.Contains(called) && !this.ResolvedNodeSet.Contains(called)) { this.RequestStack.Push(called); } }
private void AddEdge(QsQualifiedName identifier, QsSpecializationKind kind, TypeParameterResolutions typeRes, Range referenceRange) { if (this.CurrentNode is null) { throw new ArgumentException("AddEdge requires CurrentNode to be non-null."); } // Add an edge to the specific specialization kind referenced var called = new ConcreteCallGraphNode(identifier, kind, typeRes); var edge = new ConcreteCallGraphEdge(referenceRange); this.Graph.AddDependency(this.CurrentNode, called, edge); // Add all the specializations of the referenced callable to the graph var newNodes = this.GetSpecializationKinds(identifier) .Select(specKind => new ConcreteCallGraphNode(identifier, specKind, typeRes)); foreach (var node in newNodes) { if (!this.RequestStack.Contains(node) && !this.ResolvedNodeSet.Contains(node)) { this.Graph.AddNode(node); this.RequestStack.Push(node); } } }