Exemplo n.º 1
0
 /// <summary>
 /// Constructs a DocCallable instance given a namespace name and a callable object.
 /// </summary>
 /// <param name="ns">The name of the namespace where this callable is defined</param>
 /// <param name="callableObj">The compiled callable</param>
 internal DocCallable(string ns, QsCallable callableObj)
     : base(
         ns,
         callableObj.FullName.Name,
         callableObj.Kind.IsFunction ? Utils.FunctionKind : Utils.OperationKind,
         callableObj.Documentation,
         callableObj.Attributes)
 {
     this.syntax       = Utils.CallableToSyntax(callableObj);
     this.inputContent = Utils.CallableToArguments(callableObj);
     this.outputType   = Utils.ResolvedTypeToString(callableObj.Signature.ReturnType);
     this.functors     = new List <string>();
     foreach (var functor in callableObj.Signature.Information.Characteristics.SupportedFunctors.ValueOr(ImmutableHashSet <QsFunctor> .Empty))
     {
         if (functor.IsAdjoint)
         {
             this.functors.Add(Functors.Adjoint);
         }
         else if (functor.IsControlled)
         {
             this.functors.Add(Functors.Controlled);
         }
     }
     this.callable = callableObj;
 }
Exemplo n.º 2
0
 private static List <Parameter> GetParams(QsCallable callable)
 {
     return(SyntaxGenerator.ExtractItems(callable.ArgumentTuple)
            .Where(sym => !sym.Type.Resolution.IsUnitType)
            .Select(sym => MakeParameter(sym))
            .ToList());
 }
Exemplo n.º 3
0
            public override QsCallable OnCallableDeclaration(QsCallable callable)
            {
                callable = base.OnCallableDeclaration(callable);
                // If the callable didn't come from a Q# source file, then it
                // came in from a reference, and shouldn't be documented in this
                // project.
                if (!callable.IsInCompilationUnit())
                {
                    return(callable);
                }

                var isDeprecated = callable.IsDeprecated(out var replacement);
                var docComment   = new DocComment(
                    callable.Documentation, callable.FullName.Name,
                    deprecated: isDeprecated,
                    replacement: replacement
                    );
                var callableName =
                    $"{callable.FullName.Namespace}.{callable.FullName.Name}";

                // Validate input and type parameter names.
                var inputDeclarations = callable.ArgumentTuple.ToDictionaryOfDeclarations();

                this.ValidateNames(
                    callableName,
                    "input",
                    name => inputDeclarations.ContainsKey(name),
                    docComment.Input.Keys,
                    range: null, // TODO: provide more exact locations once supported by DocParser.
                    source: callable.SourceFile
                    );
                this.ValidateNames(
                    callableName,
                    "type parameter",
                    name => callable.Signature.TypeParameters.Any(
                        typeParam =>
                        typeParam is QsLocalSymbol.ValidName validName &&
                        validName.Item == name.TrimStart('\'')
                        ),
                    docComment.TypeParameters.Keys,
                    range: null, // TODO: provide more exact locations once supported by DocParser.
                    source: callable.SourceFile
                    );

                this.writer?.WriteOutput(callable, docComment)?.Wait();

                return(callable
                       .AttributeBuilder()
                       .MaybeWithSimpleDocumentationAttribute("Summary", docComment.Summary)
                       .MaybeWithSimpleDocumentationAttribute("Description", docComment.Description)
                       .MaybeWithSimpleDocumentationAttribute("Remarks", docComment.Remarks)
                       .MaybeWithSimpleDocumentationAttribute("References", docComment.References)
                       .WithListOfDocumentationAttributes("SeeAlso", docComment.SeeAlso)
                       .WithListOfDocumentationAttributes("Example", docComment.Examples)
                       .WithDocumentationAttributesFromDictionary("Input", docComment.Input)
                       .MaybeWithSimpleDocumentationAttribute("Output", docComment.Output)
                       .WithDocumentationAttributesFromDictionary("TypeParameter", docComment.TypeParameters)
                       .Build());
            }
Exemplo n.º 4
0
 public override QsCallable beforeCallable(QsCallable c)
 {
     if (this.IsRelevant(c.SourceFile) && c.FullName.Equals(this.IdentifierName))
     {
         this.DeclarationLocation = new Tuple <NonNullable <string>, QsLocation>(c.SourceFile, c.Location);
     }
     return(base.beforeCallable(c));
 }
Exemplo n.º 5
0
            public override QsCallable OnCallableDeclaration(QsCallable c)
            {
                this.SharedState.SetCurrentCallable(c.FullName);
                c = base.OnCallableDeclaration(c);
                this.SharedState.SetCurrentCallable(null);
                var comment = $" {String.Join(", ", this.SharedState.IdentifiersInCallable(c.FullName))}";

                return(AddComments(c, " Contained identifiers:", comment, ""));
            }
 public override QsCallable OnCallableDeclaration(QsCallable c)
 {
     if (!this.SharedState.WithTrimming)
     {
         var node = new CallGraphNode(c.FullName);
         this.SharedState.CurrentNode = node;
         this.SharedState.Graph.AddNode(node);
     }
     return(base.OnCallableDeclaration(c));
 }
Exemplo n.º 7
0
            public override QsCallable OnCallableDeclaration(QsCallable c)
            {
                if (!c.SourceFile.EndsWith(".qs", StringComparison.OrdinalIgnoreCase))
                {
                    return(c);
                }
                Console.WriteLine($"Callable: {c.FullName} in {c.SourceFile}");
                var transformed = c.ToCaseDriveAccessModifier();

                Console.WriteLine($" modifier: {c.Modifiers.Access} -> modifier: {transformed.Modifiers.Access}");
                return(transformed);
            }
Exemplo n.º 8
0
        /// <summary>
        /// Generates a syntax string for a callable.
        /// This is, more or less, the same as the start of the callable definition, before the
        /// first opening {.
        /// </summary>
        /// <param name="callable">The callable (operation or function) to create a syntax string for</param>
        /// <returns>The syntax string</returns>
        internal static string CallableToSyntax(QsCallable callable)
        {
            var sb = new StringBuilder();

            sb.Append(callable.Kind == QsCallableKind.Function ? "function " : "operation ");
            sb.Append(callable.FullName.Name);
            sb.Append(" ");
            sb.Append(CallableToArguments(callable));
            sb.Append(" : ");
            sb.Append(ResolvedTypeToString(callable.Signature.ReturnType));
            return(sb.ToString());
        }
Exemplo n.º 9
0
        public override QsCallable OnCallableDeclaration(QsCallable c)
        {
            if (this.SharedState.Functions.IsBuiltIn(c.FullName))
            {
                return(c);
            }

            this.context.SetCurrentCallable(c);
            c = base.OnCallableDeclaration(c);
            this.context.SetCurrentCallable(null);
            return(c);
        }
 public override QsCallable OnCallableDeclaration(QsCallable c)
 {
     // Don't validate intrinsics
     if (this.SharedState.IntrinsicCallableSet.Contains(c.FullName))
     {
         return(c);
     }
     else
     {
         return(base.OnCallableDeclaration(c));
     }
 }
Exemplo n.º 11
0
 public override QsCallable onCallableImplementation(QsCallable c)
 {
     if (!this.IsRelevant(c.SourceFile) || c.Location.IsNull)
     {
         return(c);
     }
     if (c.FullName.Equals(this.IdentifierName))
     {
         this.DeclarationLocation = new Tuple <NonNullable <string>, QsLocation>(c.SourceFile, c.Location.Item);
     }
     return(base.onCallableImplementation(c));
 }
        public override QsCallable OnCallableDeclaration(QsCallable c)
        {
            var unmangledName = NameDecorator.OriginalNameFromMonomorphized(c.FullName);

            if (this.SharedState.Functions.BuiltIn.ContainsKey(unmangledName))
            {
                return(c);
            }

            this.context.SetCurrentCallable(c);
            c = base.OnCallableDeclaration(c);
            this.context.SetCurrentCallable(null);
            return(c);
        }
Exemplo n.º 13
0
        public static QsCallable ToCaseDriveAccessModifier(this QsCallable c)
        {
            var accessModifier = char.IsUpper(c.FullName.Name[0]) ? AccessModifier.DefaultAccess : AccessModifier.Internal;

            if (accessModifier.IsDefaultAccess == c.Modifiers.Access.IsDefaultAccess)
            {
                return(c);
            }

            return(new QsCallable(
                       c.Kind, c.FullName, c.Attributes, new Modifiers(accessModifier),
                       c.SourceFile, c.Location,
                       c.Signature, c.ArgumentTuple, c.Specializations,
                       c.Documentation, c.Comments));
        }
Exemplo n.º 14
0
            private (QsCallable, ResolvedType) GenerateOperation(QsScope contents)
            {
                var newName = UniqueVariableNames.PrependGuid(this.CurrentCallable.Callable.FullName);

                var knownVariables = contents.KnownSymbols.Variables;

                var parameters = QsTuple <LocalVariableDeclaration <QsLocalSymbol> > .NewQsTuple(knownVariables
                                                                                                 .Select(var => QsTuple <LocalVariableDeclaration <QsLocalSymbol> > .NewQsTupleItem(new LocalVariableDeclaration <QsLocalSymbol>(
                                                                                                                                                                                        QsLocalSymbol.NewValidName(var.VariableName),
                                                                                                                                                                                        var.Type,
                                                                                                                                                                                        new InferredExpressionInformation(false, false),
                                                                                                                                                                                        var.Position,
                                                                                                                                                                                        var.Range)))
                                                                                                 .ToImmutableArray());

                var paramTypes = ResolvedType.New(ResolvedTypeKind.UnitType);

                if (knownVariables.Length == 1)
                {
                    paramTypes = knownVariables.First().Type;
                }
                else if (knownVariables.Length > 1)
                {
                    paramTypes = ResolvedType.New(ResolvedTypeKind.NewTupleType(knownVariables
                                                                                .Select(var => var.Type)
                                                                                .ToImmutableArray()));
                }

                var(signature, specializations) = this.MakeSpecializations(newName, paramTypes, SpecializationImplementation.NewProvided(parameters, contents));

                var generatedCallable = new QsCallable(
                    QsCallableKind.Operation,
                    newName,
                    ImmutableArray <QsDeclarationAttribute> .Empty,
                    new Modifiers(AccessModifier.Internal),
                    this.CurrentCallable.Callable.SourceFile,
                    QsNullable <QsLocation> .Null,
                    signature,
                    parameters,
                    specializations.ToImmutableArray(),
                    ImmutableArray <string> .Empty,
                    QsComments.Empty);

                // Change the origin of all type parameter references to use the new name and make all variables immutable
                generatedCallable = UpdateGeneratedOp.Apply(generatedCallable, knownVariables, this.CurrentCallable.Callable.FullName, newName);

                return(generatedCallable, signature.ArgumentType);
            }
Exemplo n.º 15
0
        /// <summary>
        /// Returns a formatted argument string for a Q# callable.
        /// </summary>
        /// <param name="callable">The operation or function to create an argument string for</param>
        /// <returns>The argument string</returns>
        internal static string CallableToArguments(QsCallable callable)
        {
            void ProcessTuple(StringBuilder builder, QsTuple <LocalVariableDeclaration <QsLocalSymbol> > tuple, bool topLevel)
            {
                if (tuple.IsQsTupleItem)
                {
                    var item = ((QsTuple <LocalVariableDeclaration <QsLocalSymbol> > .QsTupleItem)tuple).Item;
                    if (topLevel)
                    {
                        builder.Append('(');
                    }
                    // Assumes that the symbol will never be invalid
                    builder.Append(((QsLocalSymbol.ValidName)item.VariableName).Item);
                    builder.Append(" : ");
                    builder.Append(ResolvedTypeToString(item.Type));
                    if (topLevel)
                    {
                        builder.Append(')');
                    }
                }
                else
                {
                    var items = ((QsTuple <LocalVariableDeclaration <QsLocalSymbol> > .QsTuple)tuple).Item;
                    builder.Append('(');
                    var first = true;
                    foreach (var item in items)
                    {
                        if (!first)
                        {
                            builder.Append(", ");
                        }
                        first = false;
                        ProcessTuple(builder, item, false);
                    }
                    builder.Append(')');
                }
            }

            var args = callable.ArgumentTuple;
            var sb   = new StringBuilder();

            ProcessTuple(sb, args, true);
            return(sb.ToString());
        }
Exemplo n.º 16
0
 internal CallableDetails(QsCallable callable)
 {
     this.Callable = callable;
     // ToDo: this may need to be adapted once we support type specializations
     this.Adjoint           = callable.Specializations.FirstOrDefault(spec => spec.Kind == QsSpecializationKind.QsAdjoint);
     this.Controlled        = callable.Specializations.FirstOrDefault(spec => spec.Kind == QsSpecializationKind.QsControlled);
     this.ControlledAdjoint = callable.Specializations.FirstOrDefault(spec => spec.Kind == QsSpecializationKind.QsControlledAdjoint);
     // ToDo: this may need to be per-specialization
     this.TypeParameters = callable.Signature.TypeParameters.Any(param => param.IsValidName)
     ? QsNullable <ImmutableArray <ResolvedType> > .NewValue(callable.Signature.TypeParameters
                                                             .Where(param => param.IsValidName)
                                                             .Select(param =>
                                                                     ResolvedType.New(ResolvedTypeKind.NewTypeParameter(new QsTypeParameter(
                                                                                                                            callable.FullName,
                                                                                                                            ((QsLocalSymbol.ValidName)param).Item,
                                                                                                                            QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null))))
                                                             .ToImmutableArray())
     : QsNullable <ImmutableArray <ResolvedType> > .Null;
 }
                public override QsCallable OnCallableDeclaration(QsCallable c)
                {
                    var relevantAccessModifiers = this.SharedState.GetAccessModifiers.Apply(this.SharedState.TypeParams.Values)
                                                  .Append(c.Access);

                    c = new QsCallable(
                        c.Kind,
                        c.FullName,
                        c.Attributes,
                        relevantAccessModifiers.Min(),
                        c.Source,
                        c.Location,
                        c.Signature,
                        c.ArgumentTuple,
                        c.Specializations,
                        c.Documentation,
                        c.Comments);

                    return(base.OnCallableDeclaration(c));
                }
Exemplo n.º 18
0
        /// <summary>
        ///     Given a documentation comment describing a Q# function or operation
        ///     declaration, writes a Markdown file documenting that callable
        ///     declaration to <see cref="OutputPath" />.
        /// </summary>
        /// <param name="callable">The Q# callable being documented.</param>
        /// <param name="docComment">
        ///     The API documentation comment describing <paramref name="callable"/>.
        /// </param>
        /// <returns>A <see cref="Task"/> representing the result of the asynchronous operation.</returns>
        public async Task WriteOutput(QsCallable callable, DocComment docComment)
        {
            // Make a new Markdown document for the type declaration.
            var kind = callable.Kind.Tag switch
            {
                QsCallableKind.Tags.Function => "function",
                QsCallableKind.Tags.Operation => "operation",
                QsCallableKind.Tags.TypeConstructor => "type constructor",
                _ => "<unknown>",
            };
            var title  = $@"{callable.FullName.Name} {kind}";
            var header = new Dictionary <string, object>
            {
                // DocFX metadata
                ["uid"]   = callable.FullName.ToString(),
                ["title"] = title,

                // docs.ms metadata
                ["ms.date"]  = DateTime.Today.ToString(),
                ["ms.topic"] = "article",

                // Q# metadata
                ["qsharp.kind"]      = kind,
                ["qsharp.namespace"] = callable.FullName.Namespace,
                ["qsharp.name"]      = callable.FullName.Name,
                ["qsharp.summary"]   = docComment.Summary,
            };
            var document = $@"
# {title}

Namespace: [{callable.FullName.Namespace}](xref:{callable.FullName.Namespace})
{this.packageLink}

{docComment.Summary}

```{this.LanguageMode}
{
    callable.Kind.Tag switch
    {
        QsCallableKind.Tags.Function => "function ",
        QsCallableKind.Tags.Operation => "operation ",
        QsCallableKind.Tags.TypeConstructor => "newtype ",
        _ => ""
    }
}{callable.ToSyntax()}
```
"
                           .MaybeWithSection("Description", docComment.Description)
                           .MaybeWithSection(
                "Input",
                string.Join("\n", callable.ArgumentTuple.InputDeclarations().Select(
                                (item) =>
            {
                (var inputName, var resolvedType) = item;
                var documentation = docComment.Input.TryGetValue(inputName, out var inputComment)
                            ? inputComment
                            : string.Empty;
                return($"### {inputName} : {resolvedType.ToMarkdownLink()}\n\n{documentation}\n\n");
            }
                                ))
                )
                           .WithSection($"Output : {callable.Signature.ReturnType.ToMarkdownLink()}", docComment.Output)
                           .MaybeWithSection(
                "Type Parameters",
                string.Join("\n", callable.Signature.TypeParameters.Select(
                                typeParam =>
                                typeParam is QsLocalSymbol.ValidName name
                        ? $@"### '{name.Item}{"\n\n"}{(
                            docComment.TypeParameters.TryGetValue($"'{name.Item}", out var comment)
                            ? comment
                            : string.Empty
                          )}"
                        : string.Empty
                                ))
                )
                           .MaybeWithSection("Remarks", docComment.Remarks)
                           .MaybeWithSection("References", docComment.References)
                           .MaybeWithSection(
                "See Also",
                string.Join("\n", docComment.SeeAlso.Select(
                                seeAlso => AsSeeAlsoLink(seeAlso, callable.FullName.Namespace)
                                ))
                )
                           .WithYamlHeader(header);

            // Open a file to write the new doc to.
            await this.WriteAllTextAsync(
                $"{callable.FullName.Namespace}.{callable.FullName.Name}.md",
                document
                );
        }
Exemplo n.º 19
0
 public override QsCallable OnCallableDeclaration(QsCallable c) =>
 c.AddAttributes(this.SharedState.AttributeSelection
                 .Where(entry => entry.Item2(c))
                 .Select(entry => entry.Item1));
            public static QsCallable Apply(QsCallable callable, TypeParameterResolutions typeParams, GetAccessModifiers getAccessModifiers)
            {
                var filter = new ReplaceTypeParamImplementations(typeParams, getAccessModifiers);

                return(filter.Namespaces.OnCallableDeclaration(callable));
            }
Exemplo n.º 21
0
        public void ExcludeInaccessible()
        {
            var elements = new[] { Access.Public, Access.Internal }
            .SelectMany(access =>
            {
                var source = new Source("Tests.qs", QsNullable <string> .Null);
                var unit   = ResolvedType.New(QsType.UnitType);

                var signature = new ResolvedSignature(
                    Array.Empty <QsLocalSymbol>().ToImmutableArray(),
                    unit,
                    unit,
                    CallableInformation.NoInformation);
                var argumentTuple = QsTuple <ArgDeclType> .NewQsTuple(ImmutableArray.Create <QsTuple <ArgDeclType> >());
                var callable      = new QsCallable(
                    kind: QsCallableKind.Operation,
                    fullName: MakeFullName(access + "Operation"),
                    attributes: ImmutableArray <QsDeclarationAttribute> .Empty,
                    access,
                    source: source,
                    location: ZeroLocation,
                    signature: signature,
                    argumentTuple: argumentTuple,
                    specializations: ImmutableArray.Create <QsSpecialization>(),
                    documentation: ImmutableArray.Create <string>(),
                    comments: QsComments.Empty);

                var typeItems = QsTuple <QsTypeItem> .NewQsTuple(
                    ImmutableArray.Create(QsTuple <QsTypeItem> .NewQsTupleItem(QsTypeItem.NewAnonymous(unit))));
                var type = new QsCustomType(
                    fullName: MakeFullName(access + "Type"),
                    attributes: ImmutableArray <QsDeclarationAttribute> .Empty,
                    access,
                    source: source,
                    location: ZeroLocation,
                    type: unit,
                    typeItems: typeItems,
                    documentation: ImmutableArray.Create <string>(),
                    comments: QsComments.Empty);
                return(new[]
                {
                    QsNamespaceElement.NewQsCallable(callable),
                    QsNamespaceElement.NewQsCustomType(type)
                });
            });
            var emptyLookup = Array.Empty <ImmutableArray <string> >().ToLookup(x => "");
            var ns          = new QsNamespace(CanonName, elements.ToImmutableArray(), emptyLookup);
            var docNs       = new DocNamespace(ns);
            var stream      = new MemoryStream();

#pragma warning disable 618 // WriteToStream is obsolete.
            docNs.WriteToStream(stream, null);
#pragma warning restore 618

            var expected = @"### YamlMime:QSharpNamespace
# This file is automatically generated.
# Please do not modify this file manually, or your changes may be lost when
# documentation is rebuilt.

uid: microsoft.quantum.canon
name: Microsoft.Quantum.Canon
operations:
- uid: microsoft.quantum.canon.publicoperation
  summary: ''
newtypes:
- uid: microsoft.quantum.canon.publictype
  summary: ''
...
";
            var actual   = Encoding.UTF8.GetString(stream.ToArray());
            Assert.Equal(expected, actual);
        }
Exemplo n.º 22
0
 private static QsCallable AddComments(QsCallable c, params string[] comments) =>
 new QsCallable(
     c.Kind, c.FullName, c.Attributes, c.Modifiers,
     c.SourceFile, c.Location,
     c.Signature, c.ArgumentTuple, c.Specializations,
     c.Documentation, new QsComments(c.Comments.OpeningComments.AddRange(comments), c.Comments.ClosingComments));
 public override QsCallable OnFunction(QsCallable c) => c; // Prevent anything in functions from being considered
Exemplo n.º 24
0
            public static QsCallable Apply(QsCallable qsCallable, ImmutableArray <LocalVariableDeclaration <NonNullable <string> > > parameters, QsQualifiedName oldName, QsQualifiedName newName)
            {
                var filter = new UpdateGeneratedOp(parameters, oldName, newName);

                return(filter.Namespaces.OnCallableDeclaration(qsCallable));
            }
Exemplo n.º 25
0
 /// <inheritdoc/>
 public override QsCallable OnCallableDeclaration(QsCallable c)
 {
     this.SharedState.CurrentCallable = new LiftContent.CallableDetails(c);
     return(base.OnCallableDeclaration(c));
 }
            public static QsCallable Apply(QsCallable current, GetConcreteIdentifierFunc getConcreteIdentifier, ImmutableHashSet <QsQualifiedName> intrinsicCallableSet)
            {
                var filter = new ReplaceTypeParamCalls(getConcreteIdentifier, intrinsicCallableSet);

                return(filter.Namespaces.OnCallableDeclaration(current));
            }
Exemplo n.º 27
0
            /// <summary>
            /// Generates a new operation with the body's contents. All the known variables at the
            /// start of the block will become parameters to the new operation, and the operation
            /// will have all the valid type parameters of the calling context as type parameters.
            /// The generated operation is returned, along with a call to the new operation is
            /// also returned with all the type parameters and known variables being forwarded to
            /// the new operation as arguments.
            ///
            /// The given body should be validated with the SharedState.IsValidScope before using this function.
            /// </summary>
            public bool LiftBody(QsScope body, out QsCallable callable, out QsStatement callStatement)
            {
                if (!this.IsValidScope)
                {
                    callable      = null;
                    callStatement = null;
                    return(false);
                }

                var(generatedOp, originalArgumentType) = this.GenerateOperation(body);
                var generatedOpType = ResolvedType.New(ResolvedTypeKind.NewOperation(
                                                           Tuple.Create(
                                                               originalArgumentType,
                                                               ResolvedType.New(ResolvedTypeKind.UnitType)),
                                                           generatedOp.Signature.Information));

                // Forward the type parameters of the parent callable to the type arguments of the call to the generated operation.
                var typeArguments = this.CurrentCallable.TypeParameters;
                var generatedOpId = new TypedExpression(
                    ExpressionKind.NewIdentifier(
                        Identifier.NewGlobalCallable(generatedOp.FullName),
                        typeArguments),
                    typeArguments.IsNull
                        ? TypeArgsResolution.Empty
                        : typeArguments.Item
                    .Select(type => Tuple.Create(generatedOp.FullName, ((ResolvedTypeKind.TypeParameter)type.Resolution).Item.TypeName, type))
                    .ToImmutableArray(),
                    generatedOpType,
                    new InferredExpressionInformation(false, false),
                    QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null);

                var             knownSymbols = body.KnownSymbols.Variables;
                TypedExpression arguments    = null;

                if (knownSymbols.Any())
                {
                    var argumentArray = knownSymbols
                                        .Select(var => new TypedExpression(
                                                    ExpressionKind.NewIdentifier(
                                                        Identifier.NewLocalVariable(var.VariableName),
                                                        QsNullable <ImmutableArray <ResolvedType> > .Null),
                                                    TypeArgsResolution.Empty,
                                                    var.Type,
                                                    var.InferredInformation,
                                                    QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null))
                                        .ToImmutableArray();

                    arguments = new TypedExpression(
                        ExpressionKind.NewValueTuple(argumentArray),
                        TypeArgsResolution.Empty,
                        ResolvedType.New(ResolvedTypeKind.NewTupleType(argumentArray.Select(expr => expr.ResolvedType).ToImmutableArray())),
                        new InferredExpressionInformation(false, argumentArray.Any(exp => exp.InferredInformation.HasLocalQuantumDependency)),
                        QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null);
                }
                else
                {
                    arguments = new TypedExpression(
                        ExpressionKind.UnitValue,
                        TypeArgsResolution.Empty,
                        ResolvedType.New(ResolvedTypeKind.UnitType),
                        new InferredExpressionInformation(false, false),
                        QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null);
                }

                var call = new TypedExpression(
                    ExpressionKind.NewCallLikeExpression(generatedOpId, arguments),
                    typeArguments.IsNull
                        ? TypeArgsResolution.Empty
                        : typeArguments.Item
                    .Select(type => Tuple.Create(this.CurrentCallable.Callable.FullName, ((ResolvedTypeKind.TypeParameter)type.Resolution).Item.TypeName, type))
                    .ToImmutableArray(),
                    ResolvedType.New(ResolvedTypeKind.UnitType),
                    new InferredExpressionInformation(false, true),
                    QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null);

                // set output parameters
                callable      = generatedOp;
                callStatement = new QsStatement(
                    QsStatementKind.NewQsExpressionStatement(call),
                    LocalDeclarations.Empty,
                    QsNullable <QsLocation> .Null,
                    QsComments.Empty);

                return(true);
            }
Exemplo n.º 28
0
 public override QsCallable onOperation(QsCallable c) =>
 this.IsRelevant(c.SourceFile) ? base.onOperation(c) : c;
Exemplo n.º 29
0
        public void ParseOp()
        {
            ArgDeclType BuildArgument(string name, ResolvedType t)
            {
                var validName = QsLocalSymbol.NewValidName(NonNullable <string> .New(name));
                var info      = new InferredExpressionInformation(false, false);

                return(new ArgDeclType(validName, t, info, QsNullable <Tuple <int, int> > .Null, EmptyRange));
            }

            string[] comments =
            {
                "# Summary",
                "Convenience function that performs state preparation by applying a ",
                "`statePrepUnitary` on the input state, followed by adiabatic state ",
                "preparation using a `adiabaticUnitary`, and finally phase estimation ",
                "with respect to `qpeUnitary`on the resulting state using a ",
                "`phaseEstAlgorithm`.",
                "",
                "# Input",
                "## statePrepUnitary",
                "An oracle representing state preparation for the initial dynamical",
                "generator.",
                "## adiabaticUnitary",
                "An oracle representing the adiabatic evolution algorithm to be used",
                "to implement the sweeps to the final state of the algorithm.",
                "## qpeUnitary",
                "An oracle representing a unitary operator $U$ representing evolution",
                "for time $\\delta t$ under a dynamical generator with ground state",
                "$\\ket{\\phi}$ and ground state energy $E = \\phi\\\\,\\delta t$.",
                "## phaseEstAlgorithm",
                "An operation that performs phase estimation on a given unitary operation.",
                "See [iterative phase estimation](/quantum/libraries/characterization#iterative-phase-estimation)",
                "for more details.",
                "## qubits",
                "A register of qubits to be used to perform the simulation.",
                "",
                "# Output",
                "An estimate $\\hat{\\phi}$ of the ground state energy $\\phi$",
                "of the generator represented by $U$."
            };
            string expected = @"### YamlMime:QSharpType
uid: microsoft.quantum.canon.adiabaticstateenergyunitary
name: AdiabaticStateEnergyUnitary
type: operation
namespace: Microsoft.Quantum.Canon
summary: |-
  Convenience function that performs state preparation by applying a
  `statePrepUnitary` on the input state, followed by adiabatic state
  preparation using a `adiabaticUnitary`, and finally phase estimation
  with respect to `qpeUnitary`on the resulting state using a
  `phaseEstAlgorithm`.
syntax: 'operation AdiabaticStateEnergyUnitary (statePrepUnitary : (Qubit[] => Unit), adiabaticUnitary : (Qubit[] => Unit), qpeUnitary : (Qubit[] => Unit is Adj + Ctl), phaseEstAlgorithm : ((Microsoft.Quantum.Canon.DiscreteOracle, Qubit[]) => Double), qubits : Qubit[]) : Double'
input:
  content: '(statePrepUnitary : (Qubit[] => Unit), adiabaticUnitary : (Qubit[] => Unit), qpeUnitary : (Qubit[] => Unit is Adj + Ctl), phaseEstAlgorithm : ((Microsoft.Quantum.Canon.DiscreteOracle, Qubit[]) => Double), qubits : Qubit[])'
  types:
  - name: statePrepUnitary
    summary: |-
      An oracle representing state preparation for the initial dynamical
      generator.
    isOperation: true
    input:
      types:
      - isArray: true
        isPrimitive: true
        uid: Qubit
    output:
      types:
      - isPrimitive: true
        uid: Unit
  - name: adiabaticUnitary
    summary: |-
      An oracle representing the adiabatic evolution algorithm to be used
      to implement the sweeps to the final state of the algorithm.
    isOperation: true
    input:
      types:
      - isArray: true
        isPrimitive: true
        uid: Qubit
    output:
      types:
      - isPrimitive: true
        uid: Unit
  - name: qpeUnitary
    summary: |-
      An oracle representing a unitary operator $U$ representing evolution
      for time $\delta t$ under a dynamical generator with ground state
      $\ket{\phi}$ and ground state energy $E = \phi\\,\delta t$.
    isOperation: true
    input:
      types:
      - isArray: true
        isPrimitive: true
        uid: Qubit
    output:
      types:
      - isPrimitive: true
        uid: Unit
    functors:
    - Adjoint
    - Controlled
  - name: phaseEstAlgorithm
    summary: |-
      An operation that performs phase estimation on a given unitary operation.
      See [iterative phase estimation](/quantum/libraries/characterization#iterative-phase-estimation)
      for more details.
    isOperation: true
    input:
      types:
      - uid: microsoft.quantum.canon.discreteoracle
      - isArray: true
        isPrimitive: true
        uid: Qubit
    output:
      types:
      - isPrimitive: true
        uid: Double
  - name: qubits
    summary: A register of qubits to be used to perform the simulation.
    isArray: true
    isPrimitive: true
    uid: Qubit
output:
  content: Double
  types:
  - summary: |-
      An estimate $\hat{\phi}$ of the ground state energy $\phi$
      of the generator represented by $U$.
    isPrimitive: true
    uid: Double
...
";

            var qubitArrayType = ResolvedType.New(QsType.NewArrayType(ResolvedType.New(QsType.Qubit)));
            var unitType       = ResolvedType.New(QsType.UnitType);
            var doubleType     = ResolvedType.New(QsType.Double);
            var oracleType     = ResolvedType.New(QsType.NewUserDefinedType(new UserDefinedType(CanonName,
                                                                                                NonNullable <string> .New("DiscreteOracle"),
                                                                                                QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null)));
            var noInfo = CallableInformation.NoInformation;
            var acFunctors = ResolvedCharacteristics.FromProperties(new[] { OpProperty.Adjointable, OpProperty.Controllable });
            var acInfo = new CallableInformation(acFunctors, InferredCallableInformation.NoInformation);
            var qubitToUnitOp = ResolvedType.New(QsType.NewOperation(new SigTypeTuple(qubitArrayType, unitType), noInfo));
            var qubitToUnitOpAC = ResolvedType.New(QsType.NewOperation(new SigTypeTuple(qubitArrayType, unitType), acInfo));
            var phaseEstArgs = new ResolvedType[] { oracleType, qubitArrayType }.ToImmutableArray();
            var phaseEstArgTuple = ResolvedType.New(QsType.NewTupleType(phaseEstArgs));
            var phaseEstOp       = ResolvedType.New(QsType.NewOperation(new SigTypeTuple(phaseEstArgTuple, doubleType), noInfo));

            var typeParams = new QsLocalSymbol[] { }.ToImmutableArray();
            var argTypes = new ResolvedType[] { qubitToUnitOp, qubitToUnitOp, qubitToUnitOpAC, phaseEstOp, qubitArrayType }.ToImmutableArray();
            var argTupleType = ResolvedType.New(QsType.NewTupleType(argTypes));
            var signature    = new ResolvedSignature(typeParams, argTupleType, doubleType, noInfo);

            var args = new List <ArgDeclType> {
                BuildArgument("statePrepUnitary", qubitToUnitOp),
                BuildArgument("adiabaticUnitary", qubitToUnitOp),
                BuildArgument("qpeUnitary", qubitToUnitOpAC),
                BuildArgument("phaseEstAlgorithm", phaseEstOp),
                BuildArgument("qubits", qubitArrayType)
            }
            .ConvertAll(arg => QsTuple <ArgDeclType> .NewQsTupleItem(arg))
            .ToImmutableArray();
            var argTuple = QsTuple <ArgDeclType> .NewQsTuple(args);

            var specs = new QsSpecialization[] { }.ToImmutableArray();

            var qsCallable = new QsCallable(QsCallableKind.Operation,
                                            MakeFullName("AdiabaticStateEnergyUnitary"),
                                            ImmutableArray <QsDeclarationAttribute> .Empty,
                                            NonNullable <string> .New("Techniques.qs"),
                                            ZeroLocation,
                                            signature,
                                            argTuple,
                                            specs,
                                            comments.ToImmutableArray(),
                                            QsComments.Empty);
            var callable = new DocCallable("Microsoft.Quantum.Canon", qsCallable);

            var stream = new StringWriter();

            callable.WriteToFile(stream);
            var s = stream.ToString();

            Assert.Equal(expected, s);
        }
        /// <summary>
        /// Creates a separate callable for each intrinsic specialization,
        /// and replaces the specialization implementations of the original callable with a call to these.
        /// Self adjoint generation directives in intrinsic callables are replaced by a provided implementation.
        /// Type constructors and generic callables or callables that already define a target instruction name are left unchanged.
        /// </summary>
        /// <exception cref="ArgumentException">
        /// An intrinsic callable contains non-intrinsic specializations
        /// or a non-intrinsic callable contains intrinsic specializations,
        /// or the a callable doesn't have a body specialization.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// A specialization has explicit type arguments;
        /// Monomorphization needs to run before separating target instructions.
        /// </exception>
        private static QsNamespace LiftIntrinsicSpecializations(QsNamespace ns)
        {
            var elements = ImmutableArray.CreateBuilder <QsNamespaceElement>();

            foreach (var element in ns.Elements)
            {
                if (element is QsNamespaceElement.QsCallable c &&
                    c.Item.Signature.TypeParameters.Length == 0 &&
                    !c.Item.Kind.IsTypeConstructor)
                {
                    if (c.Item.IsIntrinsic)
                    {
                        QsCallable callable = c.Item;
                        if (!callable.Specializations.Any(spec => spec.Kind.IsQsBody))
                        {
                            throw new ArgumentException("missing body specialization");
                        }
                        else if (callable.Specializations.Any(spec => spec.TypeArguments.IsValue))
                        {
                            throw new InvalidOperationException("specialization with type arguments");
                        }
                        else if (callable.Specializations.Length == 1 && callable.Attributes.Any(BuiltIn.DefinesTargetInstruction))
                        {
                            elements.Add(element);
                        }
                        else
                        {
                            QsQualifiedName GeneratedName(QsSpecializationKind kind) =>
                            new QsQualifiedName(callable.FullName.Namespace, $"{callable.FullName.Name}{SpecializationSuffix(kind)}");

                            var specializations = ImmutableArray.CreateRange(callable.Specializations.Select(spec =>
                            {
                                var inferredInfo = spec.Signature.Information.InferredInformation;
                                if (!inferredInfo.IsIntrinsic && !inferredInfo.IsSelfAdjoint)
                                {
                                    throw new ArgumentException("non-intrinsic specialization for intrinsic callable");
                                }

                                // Get the correct argument tuple both for the added intrinsic callable
                                // and the generated provided specialization that replaces the intrinsic one.
                                var argTuple = BuildSpecArgTuple(callable.ArgumentTuple, spec.Kind);

                                // Create a separate callable for that specialization,
                                // unless the specialization is not needed for a self-adjoint callable.

                                var genCallableSignature = new ResolvedSignature(
                                    ImmutableArray <QsLocalSymbol> .Empty,
                                    spec.Signature.ArgumentType,
                                    spec.Signature.ReturnType,
                                    new CallableInformation(
                                        ResolvedCharacteristics.Empty,
                                        new InferredCallableInformation(isIntrinsic: true, isSelfAdjoint: false)));
                                var genCallableName = GeneratedName(
                                    inferredInfo.IsSelfAdjoint && spec.Kind.IsQsAdjoint ? QsSpecializationKind.QsBody :
                                    inferredInfo.IsSelfAdjoint && spec.Kind.IsQsControlledAdjoint ? QsSpecializationKind.QsControlled :
                                    spec.Kind);

                                if (!inferredInfo.IsSelfAdjoint || spec.Kind.IsQsBody || spec.Kind.IsQsControlled)
                                {
                                    var genCallableBody = new QsSpecialization(
                                        QsSpecializationKind.QsBody,
                                        genCallableName,
                                        spec.Attributes,
                                        spec.Source,
                                        QsNullable <QsLocation> .Null,
                                        spec.TypeArguments,
                                        genCallableSignature,
                                        SpecializationImplementation.Intrinsic,
                                        spec.Documentation,
                                        spec.Comments);
                                    var genCallable = new QsCallable(
                                        callable.Kind,
                                        genCallableName,
                                        callable.Attributes,
                                        callable.Access,
                                        spec.Source,
                                        spec.Location,
                                        genCallableSignature,
                                        argTuple,
                                        ImmutableArray.Create(genCallableBody),
                                        ImmutableArray <string> .Empty,
                                        QsComments.Empty);
                                    elements.Add(QsNamespaceElement.NewQsCallable(genCallable));
                                }

                                // Create a specialization that calls into the generated callable,
                                // or the corresponding callable no callable for the specialization
                                // has been added due to hte operation being self-adjoint.

                                var genCallableType =
                                    callable.Kind == QsCallableKind.Operation
                                    ? OperationTypeFromSignature(genCallableSignature)
                                    : TypeKind.NewFunction(genCallableSignature.ArgumentType, genCallableSignature.ReturnType);
                                var call = SyntaxGenerator.CallNonGeneric(
                                    IdentifierForCallable(genCallableName, genCallableType),
                                    SyntaxGenerator.ArgumentTupleAsExpression(argTuple));
                                var statement = new QsStatement(
                                    QsStatementKind.NewQsReturnStatement(call),
                                    LocalDeclarations.Empty,
                                    QsNullable <QsLocation> .Null,
                                    QsComments.Empty);
                                var localDeclarations = new LocalDeclarations(
                                    SyntaxGenerator.ValidDeclarations(SyntaxGenerator.ExtractItems(argTuple)));

                                return(spec.WithImplementation(SpecializationImplementation.NewProvided(
                                                                   argTuple,
                                                                   new QsScope(ImmutableArray.Create(statement), localDeclarations))));
                            }));

                            // Create a callable that contains all specializations that
                            // call into the generated callables for each specialization.

                            var inlineAttribute = AttributeUtils.BuildAttribute(BuiltIn.Inline.FullName, SyntaxGenerator.UnitValue);
                            var signature       = new ResolvedSignature(
                                ImmutableArray <QsLocalSymbol> .Empty,
                                callable.Signature.ArgumentType,
                                callable.Signature.ReturnType,
                                new CallableInformation(
                                    callable.Signature.Information.Characteristics,
                                    new InferredCallableInformation(isSelfAdjoint: callable.IsSelfAdjoint, isIntrinsic: false)));
                            var redirect = new QsCallable(
                                callable.Kind,
                                callable.FullName,
                                ImmutableArray.Create(inlineAttribute),
                                callable.Access,
                                callable.Source,
                                callable.Location,
                                signature,
                                callable.ArgumentTuple,
                                specializations,
                                callable.Documentation,
                                callable.Comments);
                            elements.Add(QsNamespaceElement.NewQsCallable(redirect));
                        }
                    }
                    else if (c.Item.Specializations.Any(spec => spec.Implementation.IsIntrinsic))
                    {
                        throw new ArgumentException("intrinsic specialization for non-intrinsic callable");
                    }
                    else
                    {
                        elements.Add(element);
                    }
                }