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); } } }
// private methods private static ArgumentTuple BuildSpecArgTuple(ArgumentTuple callableArg, QsSpecializationKind specKind) => specKind.IsQsControlled || specKind.IsQsControlledAdjoint ? SyntaxGenerator.WithControlQubits( callableArg, QsNullable <Position> .Null, QsLocalSymbol.NewValidName(InternalUse.ControlQubitsName), QsNullable <DataTypes.Range> .Null) : callableArg;
/// <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)); }
/// <summary> /// Handles adding the dependencies for specializations marked as self-inverse. /// </summary> internal void AddSelfInverseDependency(QsQualifiedName identifier, QsSpecializationKind targetSpec) { if (this.CurrentNode is null) { throw new ArgumentException("AddDependency requires CurrentNode to be non-null."); } var combination = new TypeResolutionCombination(new[] { this.CurrentNode.ParamResolutions }); var typeRes = combination.CombinedResolutionDictionary.FilterByOrigin(identifier); this.AddEdge(identifier, targetSpec, typeRes, this.lastReferenceRange); }
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); } }
/// <summary> /// Given a sequence of specialziations, returns the implementation of the given kind, or null if no such specialization exists. /// Throws an ArgumentException if more than one specialization of that kind exist. /// Throws an ArgumentNullException if the sequence of specializations is null, or contains any entries that are null. /// </summary> private static QsSpecialization GetSpecialization(this IEnumerable <QsSpecialization> specs, QsSpecializationKind kind) { if (specs == null || specs.Any(s => s == null)) { throw new ArgumentNullException(nameof(specs)); } specs = specs.Where(spec => spec.Kind == kind); if (specs.Count() > 1) { throw new ArgumentException("several specializations of the given kind exist"); } return(specs.Any() ? specs.Single() : null); }
/// <summary> /// Returns the suffix used to distinguish the generated callables for each functor specialization. /// </summary> public static string SpecializationSuffix(QsSpecializationKind kind) => kind.IsQsBody ? "__Body" : kind.IsQsAdjoint ? "__Adj" : kind.IsQsControlled ? "__Ctl" : kind.IsQsControlledAdjoint ? "__CtlAdj" : $"__{kind}";