/// <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());
        }
Пример #2
0
 /// <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));
 }
Пример #3
0
        /// <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);
                        }
                    }
                }