internal override void AddDependency(QsQualifiedName identifier) { if (this.CurrentNode is null) { throw new ArgumentException("AddDependency requires CurrentNode to be non-null."); } var combination = new TypeResolutionCombination(this.ExprTypeParamResolutions); var typeRes = combination.CombinedResolutionDictionary.FilterByOrigin(identifier); this.ExprTypeParamResolutions.Clear(); var referenceRange = Range.Zero; if (this.CurrentStatementOffset.IsValue && this.CurrentExpressionRange.IsValue) { referenceRange = this.CurrentStatementOffset.Item + this.CurrentExpressionRange.Item; } var called = new CallGraphNode(identifier); var edge = new CallGraphEdge(typeRes, referenceRange); this.Graph.AddDependency(this.CurrentNode, called, edge); // If we are not processing all elements, then we need to keep track of what elements // have been processed, and which elements still need to be processed. if (this.WithTrimming && !this.RequestStack.Contains(called) && !this.ResolvedNodeSet.Contains(called)) { this.RequestStack.Push(called); } }
private (TypedExpression Id, TypedExpression Args)? IsValidScope(QsScope? scope) { // if the scope has exactly one statement in it and that statement is a call like expression statement if (scope != null && scope.Statements.Length == 1 && scope.Statements[0].Statement is QsStatementKind.QsExpressionStatement expr && expr.Item.ResolvedType.Resolution.IsUnitType && expr.Item.Expression is ExpressionKind.CallLikeExpression call && !TypedExpression.IsPartialApplication(expr.Item.Expression) && call.Item1.Expression is ExpressionKind.Identifier) { var newCallIdentifier = call.Item1; var callTypeArguments = expr.Item.TypeParameterResolutions; // This relies on anything having type parameters must be a global callable. if (newCallIdentifier.Expression is ExpressionKind.Identifier id && id.Item1 is Identifier.GlobalCallable global && callTypeArguments.Any()) { // We are dissolving the application of arguments here, so the call's type argument // resolutions have to be moved to the 'identifier' sub expression. var combination = new TypeResolutionCombination(expr.Item); var combinedTypeArguments = combination.CombinedResolutionDictionary.FilterByOrigin(global.Item); QsCompilerError.Verify(combination.IsValid, "failed to combine type parameter resolution"); var globalCallable = this.SharedState.Compilation.Namespaces .Where(ns => ns.Name.Equals(global.Item.Namespace)) .Callables() .FirstOrDefault(c => c.FullName.Name.Equals(global.Item.Name)); QsCompilerError.Verify(globalCallable != null, $"Could not find the global reference {global.Item}."); var callableTypeParameters = globalCallable.Signature.TypeParameters.Select(param => { var name = param as QsLocalSymbol.ValidName; QsCompilerError.Verify(!(name is null), "Invalid type parameter name."); return(name); }); newCallIdentifier = new TypedExpression( ExpressionKind.NewIdentifier( id.Item1, QsNullable <ImmutableArray <ResolvedType> > .NewValue( callableTypeParameters .Select(x => combinedTypeArguments[Tuple.Create(global.Item, x.Item)]).ToImmutableArray())), TypedExpression.AsTypeArguments(combinedTypeArguments), call.Item1.ResolvedType, call.Item1.InferredInformation, call.Item1.Range); } return(newCallIdentifier, call.Item2); } return(null); }
internal override void AddDependency(QsQualifiedName identifier) { if (this.CurrentNode is null) { throw new ArgumentException("AddDependency requires CurrentNode to be non-null."); } var combination = new TypeResolutionCombination(this.ExprTypeParamResolutions.Append(this.CurrentNode.ParamResolutions)); var typeRes = combination.CombinedResolutionDictionary.FilterByOrigin(identifier); this.ExprTypeParamResolutions.Clear(); var referenceRange = Range.Zero; if (this.CurrentStatementOffset.IsValue && this.CurrentExpressionRange.IsValue) { referenceRange = this.CurrentStatementOffset.Item + this.CurrentExpressionRange.Item; } this.lastReferenceRange = referenceRange; void AddEdge(QsSpecializationKind kind) => this.AddEdge(identifier, kind, typeRes, referenceRange); if (this.IsInCall) { if (this.HasAdjointDependency && this.HasControlledDependency) { AddEdge(QsSpecializationKind.QsControlledAdjoint); } else if (this.HasAdjointDependency) { AddEdge(QsSpecializationKind.QsAdjoint); } else if (this.HasControlledDependency) { AddEdge(QsSpecializationKind.QsControlled); } else { AddEdge(QsSpecializationKind.QsBody); } } else { // The callable is being used in a non-call context, such as being // assigned to a variable or passed as an argument to another callable, // which means it could get a functor applied at some later time. // We're conservative and add all possible kinds defined for the callable. foreach (var kind in this.GetSpecializationKinds(identifier)) { AddEdge(kind); } } }
/// <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); }
public override QsExpressionKind <TypedExpression, Identifier, ResolvedType> OnIdentifier(Identifier sym, QsNullable <ImmutableArray <ResolvedType> > tArgs) { if (sym is Identifier.GlobalCallable global) { // We want to skip over intrinsic callables. They will not be monomorphized. if (!this.SharedState.IntrinsicCallableSet.Contains(global.Item)) { var combination = new TypeResolutionCombination(this.SharedState.CurrentTypeParamResolutions); this.SharedState.LastCalculatedTypeResolutions = combination.CombinedResolutionDictionary; var typeRes = combination.CombinedResolutionDictionary.FilterByOrigin(global.Item); // Create a new identifier sym = this.SharedState.GetConcreteIdentifier(global, typeRes); tArgs = QsNullable <ImmutableArray <ResolvedType> > .Null; } this.SharedState.CurrentTypeParamResolutions.Clear(); } else if (sym is Identifier.LocalVariable && tArgs.IsValue && tArgs.Item.Any()) { throw new ArgumentException($"Local variables cannot have type arguments."); } return(base.OnIdentifier(sym, tArgs)); }