Пример #1
0
        internal static YamlMappingNode BuildMappingNode(string key1, string val1, string key2, string val2)
        {
            var node = new YamlMappingNode();

            node.AddStringMapping(key1, val1);
            node.AddStringMapping(key2, val2);
            return(node);
        }
        /// <summary>
        /// Merges a namespace into a TOC node.
        /// If there is an existing node with the same uid, then it is updated to reflect the data
        /// in this namespace.
        /// Otherwise, a new node is added to the sequence.
        /// </summary>
        /// <param name="toc">The TOC node to merge into.</param>
        internal void MergeNamespaceIntoToc(YamlSequenceNode toc)
        {
            bool MatchByUid(YamlNode n, string key)
            {
                var uid = new YamlScalarNode(this.uid);

                if (n is YamlMappingNode map)
                {
                    if (map.Children != null && map.Children.TryGetValue(new YamlScalarNode(Utils.UidKey), out YamlNode node))
                    {
                        if (node is YamlScalarNode valueNode)
                        {
                            return(valueNode.Equals(uid));
                        }
                    }
                }
                return(false);
            }

            var namespaceNode             = toc.Children?.SingleOrDefault(c => MatchByUid(c, this.uid)) as YamlMappingNode;
            YamlSequenceNode itemListNode = null;

            if (namespaceNode == null)
            {
                namespaceNode = new YamlMappingNode();
                namespaceNode.AddStringMapping(Utils.UidKey, this.uid);
                namespaceNode.AddStringMapping(Utils.NameKey, this.name);
                toc.Add(namespaceNode);
            }
            else
            {
                YamlNode itemsNode;
                if (namespaceNode.Children.TryGetValue(new YamlScalarNode(Utils.ItemsKey), out itemsNode))
                {
                    itemListNode = itemsNode as YamlSequenceNode;
                }
            }
            if (itemListNode == null)
            {
                itemListNode = new YamlSequenceNode();
                namespaceNode.Add(Utils.ItemsKey, itemListNode);
            }

            foreach (var item in items)
            {
                if (!itemListNode.Children.Any(c => MatchByUid(c, item.Uid)))
                {
                    itemListNode.Add(Utils.BuildMappingNode(Utils.NameKey, item.Name, Utils.UidKey, item.Uid));
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Writes the full representation of this UDT to a text stream.
        /// </summary>
        /// <param name="text">The text stream to output to</param>
        internal override void WriteToFile(TextWriter text)
        {
            var rootNode = new YamlMappingNode();

            rootNode.AddStringMapping(Utils.UidKey, this.uid);
            rootNode.AddStringMapping(Utils.NameKey, this.name);
            rootNode.AddStringMapping(Utils.TypeKey, this.itemType);
            rootNode.AddStringMapping(Utils.NamespaceKey, this.namespaceName.AsObsoleteUid());
            if (!string.IsNullOrEmpty(this.comments.Documentation))
            {
                rootNode.AddStringMapping(Utils.SummaryKey, this.comments.Documentation);
            }

            // UDTs get fancy treatment of examples
            if (!string.IsNullOrEmpty(this.comments.Remarks) || !string.IsNullOrEmpty(this.comments.Example))
            {
                var rems = this.comments.Remarks;
                if (!string.IsNullOrEmpty(this.comments.Example))
                {
                    // \r instead of \n because the YAML.Net serialization doubles \n.
                    // In the file the newline is correct; YAML.Net serializes \r as \n.
                    rems += "\r\r### Examples\r" + this.comments.Example;
                }
                rootNode.AddStringMapping(Utils.RemarksKey, rems);
            }

            rootNode.Add(Utils.SyntaxKey, this.syntax);
            if (!string.IsNullOrEmpty(this.comments.References))
            {
                rootNode.AddStringMapping(Utils.ReferencesKey, this.comments.References);
            }
            if (this.comments.SeeAlso.Count > 0)
            {
                rootNode.Add(Utils.SeeAlsoKey, Utils.BuildSequenceNode(this.comments.SeeAlso));
            }

            var doc    = new YamlDocument(rootNode);
            var stream = new YamlStream(doc);

            text.WriteLine("### " + Utils.QsYamlMime + Utils.AutogenerationWarning);
            stream.Save(text, false);
        }
Пример #4
0
        /// <summary>
        /// Writes a YAML representation of this callable to a text writer.
        /// </summary>
        /// <param name="text">The writer to output to</param>
        internal override void WriteToFile(TextWriter text)
        {
            YamlNode BuildInputNode()
            {
                var inputNode = new YamlMappingNode();

                inputNode.AddStringMapping(Utils.ContentsKey, inputContent);

                var typesNode = new YamlSequenceNode();

                inputNode.Add(Utils.TypesListKey, typesNode);

                foreach (var declaration in SyntaxGenerator.ExtractItems(callable.ArgumentTuple))
                {
                    var argNode = new YamlMappingNode();
                    var argName = ((QsLocalSymbol.ValidName)declaration.VariableName).Item.Value;
                    argNode.AddStringMapping(Utils.NameKey, argName);
                    if (comments.Input.TryGetValue(argName, out string summary))
                    {
                        argNode.AddStringMapping(Utils.SummaryKey, summary);
                    }
                    Utils.ResolvedTypeToYaml(declaration.Type, argNode);
                    typesNode.Add(argNode);
                }

                return(inputNode);
            }

            YamlNode BuildOutputNode()
            {
                var outputNode = new YamlMappingNode();

                outputNode.AddStringMapping(Utils.ContentsKey, outputType);

                var typesNode = new YamlSequenceNode();

                outputNode.Add(Utils.TypesListKey, typesNode);

                var outputTypeNode = new YamlMappingNode();

                typesNode.Add(outputTypeNode);

                if (!string.IsNullOrEmpty(this.comments.Output))
                {
                    outputTypeNode.AddStringMapping(Utils.SummaryKey, this.comments.Output);
                }
                Utils.ResolvedTypeToYaml(callable.Signature.ReturnType, outputTypeNode);

                return(outputNode);
            }

            var rootNode = new YamlMappingNode();

            rootNode.AddStringMapping(Utils.UidKey, uid);
            rootNode.AddStringMapping(Utils.NameKey, name);
            rootNode.AddStringMapping(Utils.TypeKey, itemType);
            rootNode.AddStringMapping(Utils.NamespaceKey, namespaceName);
            if (!string.IsNullOrWhiteSpace(comments.Documentation))
            {
                rootNode.AddStringMapping(Utils.SummaryKey, comments.Documentation);
            }
            if (!string.IsNullOrWhiteSpace(comments.Remarks))
            {
                rootNode.AddStringMapping(Utils.RemarksKey, comments.Remarks);
            }
            if (!string.IsNullOrWhiteSpace(comments.Example))
            {
                rootNode.AddStringMapping(Utils.ExamplesKey, comments.Example);
            }
            rootNode.AddStringMapping(Utils.SyntaxKey, syntax);
            if (!string.IsNullOrWhiteSpace(comments.References))
            {
                rootNode.AddStringMapping(Utils.ReferencesKey, comments.References);
            }
            rootNode.Add(Utils.InputKey, BuildInputNode());
            rootNode.Add(Utils.OutputKey, BuildOutputNode());
            if (comments.TypeParameters.Count > 0)
            {
                rootNode.Add(Utils.TypeParamsKey, Utils.BuildSequenceMappingNode(comments.TypeParameters));
            }
            if (functors.Count > 0)
            {
                rootNode.Add(Utils.FunctorsKey, Utils.BuildSequenceNode(functors));
            }
            if (comments.SeeAlso.Count > 0)
            {
                rootNode.Add(Utils.SeeAlsoKey, Utils.BuildSequenceNode(comments.SeeAlso));
            }

            var doc    = new YamlDocument(rootNode);
            var stream = new YamlStream(doc);

            text.WriteLine("### " + Utils.QsYamlMime);
            stream.Save(text, false);
        }
Пример #5
0
        /// <summary>
        /// Populates a YAML mapping node with information describing a Q# resolved type.
        /// </summary>
        /// <param name="t">The resolved type to describe</param>
        /// <param name="map">The YAML node to populate</param>
        internal static void ResolvedTypeToYaml(ResolvedType t, YamlMappingNode map)
        {
            IEnumerable <ResolvedType> FlattenType(ResolvedType ty)
            {
                var resol = ty.Resolution;

                if (resol.IsTupleType)
                {
                    var elements = ((QsTypeKind.TupleType)resol).Item;
                    foreach (var element in elements)
                    {
                        foreach (var subelement in FlattenType(element))
                        {
                            yield return(subelement);
                        }
                    }
                }
                else
                {
                    yield return(ty);
                }
            }

            void CallableCore(ResolvedType inputType, ResolvedType outputType, IEnumerable <QsFunctor> functors)
            {
                var types = new YamlSequenceNode();
                var input = new YamlMappingNode();

                input.Add("types", types);
                foreach (var argType in FlattenType(inputType))
                {
                    var argNode = new YamlMappingNode();
                    ResolvedTypeToYaml(argType, argNode);
                    types.Add(argNode);
                }
                map.Add("input", input);
                var otypes = new YamlSequenceNode();
                var output = new YamlMappingNode();

                output.Add("types", otypes);
                var otype = new YamlMappingNode();

                ResolvedTypeToYaml(outputType, otype);
                otypes.Add(otype);
                map.Add("output", output);
            }

            var resolution = t.Resolution;

            if (resolution.IsUnitType)
            {
                map.AddStringMapping("isPrimitive", "true");
                map.AddStringMapping("uid", "Unit");
            }
            else if (resolution.IsInt || resolution.IsBigInt || resolution.IsDouble || resolution.IsBool || resolution.IsString ||
                     resolution.IsQubit || resolution.IsResult || resolution.IsPauli || resolution.IsRange)
            {
                map.AddStringMapping("isPrimitive", "true");
                map.AddStringMapping("uid", ResolvedTypeToString(t));
            }
            else if (resolution.IsArrayType)
            {
                map.AddStringMapping("isArray", "true");
                var elementType = ((QsTypeKind.ArrayType)resolution).Item;
                if (elementType.Resolution.IsArrayType)
                {
                    var seq  = new YamlSequenceNode();
                    var node = new YamlMappingNode();
                    ResolvedTypeToYaml(elementType, node);
                    seq.Add(node);
                    map.Add(BuildStringNode("types"), seq);
                }
                else
                {
                    ResolvedTypeToYaml(elementType, map);
                }
            }
            else if (resolution.IsTupleType)
            {
                var elements = ((QsTypeKind.TupleType)resolution).Item;
                var seq      = new YamlSequenceNode();
                foreach (var element in elements)
                {
                    var node = new YamlMappingNode();
                    ResolvedTypeToYaml(element, node);
                    seq.Add(node);
                }
                map.Add(BuildStringNode("types"), seq);
            }
            else if (resolution.IsUserDefinedType)
            {
                var udtName = ((QsTypeKind.UserDefinedType)resolution).Item;
                map.AddStringMapping("uid", (udtName.Namespace + "." + udtName.Name).ToLowerInvariant());
            }
            else if (resolution.IsTypeParameter)
            {
                var typeParam = ((QsTypeKind.TypeParameter)resolution).Item;
                map.AddStringMapping("uid", "'" + typeParam.TypeName);
                map.AddStringMapping("isLocal", "true");
            }
            else if (resolution.IsOperation)
            {
                var op         = (QsTypeKind.Operation)resolution;
                var inputType  = op.Item1.Item1;
                var outputType = op.Item1.Item2;
                var functors   = op.Item2.Characteristics.SupportedFunctors.ValueOr(ImmutableHashSet <QsFunctor> .Empty);

                map.AddStringMapping("isOperation", "true");
                CallableCore(inputType, outputType, functors);
                if (!functors.IsEmpty)
                {
                    var seq = new YamlSequenceNode();
                    map.Add("functors", seq);
                    foreach (var f in functors)
                    {
                        if (f.IsAdjoint)
                        {
                            seq.AddString("Adjoint");
                        }
                        else if (f.IsControlled)
                        {
                            seq.AddString("Controlled");
                        }
                    }
                }
            }
            else if (resolution.IsFunction)
            {
                var fct        = (QsTypeKind.Function)resolution;
                var inputType  = fct.Item1;
                var outputType = fct.Item2;

                map.AddStringMapping("isFunction", "true");
                CallableCore(inputType, outputType, Enumerable.Empty <QsFunctor>());
            }
        }
Пример #6
0
        /// <summary>
        /// Merges a namespace into a TOC node.
        /// If there is an existing node with the same uid, then it is updated to reflect the data
        /// in this namespace.
        /// Otherwise, a new node is added to the sequence.
        /// </summary>
        /// <param name="toc">The TOC node to merge into.</param>
        internal void MergeNamespaceIntoToc(YamlSequenceNode toc)
        {
            bool MatchByUid(YamlNode n, string key)
            {
                var uid = new YamlScalarNode(this.uid);

                if (n is YamlMappingNode map)
                {
                    if (map.Children != null && map.Children.TryGetValue(new YamlScalarNode(Utils.UidKey), out YamlNode node))
                    {
                        if (node is YamlScalarNode valueNode)
                        {
                            return(valueNode.Equals(uid));
                        }
                    }
                }
                return(false);
            }

            string?TryGetUid(YamlNode node)
            {
                if (node is YamlMappingNode mappingNode)
                {
                    mappingNode.Children.TryGetValue(Utils.UidKey, out var uidNode);
                    return((uidNode as YamlScalarNode)?.Value);
                }
                else
                {
                    return(null);
                }
            }

            string?TryGetName(YamlNode node)
            {
                if (node is YamlMappingNode mappingNode)
                {
                    mappingNode.Children.TryGetValue(Utils.NameKey, out var nameNode);
                    return((nameNode as YamlScalarNode)?.Value);
                }
                else
                {
                    return(null);
                }
            }

            int CompareUids(YamlNode node1, YamlNode node2) =>
            string.Compare(
                TryGetUid(node1),
                TryGetUid(node2));

            var namespaceNode             = toc.Children.SingleOrDefault(c => MatchByUid(c, this.uid)) as YamlMappingNode;
            YamlSequenceNode?itemListNode = null;

            if (namespaceNode == null)
            {
                namespaceNode = new YamlMappingNode();
                namespaceNode.AddStringMapping(Utils.UidKey, this.uid);
                namespaceNode.AddStringMapping(Utils.NameKey, this.name);
                toc.Add(namespaceNode);
                toc.Children.Sort((node1, node2) => CompareUids(node1, node2));
            }
            else
            {
                YamlNode itemsNode;
                if (namespaceNode.Children.TryGetValue(new YamlScalarNode(Utils.ItemsKey), out itemsNode))
                {
                    itemListNode = itemsNode as YamlSequenceNode;
                }
            }
            if (itemListNode == null)
            {
                itemListNode = new YamlSequenceNode();
                namespaceNode.Add(Utils.ItemsKey, itemListNode);
            }

            var itemsByUid = this.items
                             .GroupBy(item => item.Uid)
                             .ToDictionary(
                group => group.Key,
                group => group
                .Select(item => item.Name)
                .Single());

            // Update itemsByUid with any items that may already exist.
            foreach (var existingChild in itemListNode.Children)
            {
                var uid = TryGetUid(existingChild);
                if (uid != null)
                {
                    itemsByUid[uid] = TryGetName(existingChild) ?? "";
                }
            }

            itemListNode.Children.Clear();
            foreach (var(uid, name) in itemsByUid.OrderBy(item => item.Key))
            {
                itemListNode.Add(Utils.BuildMappingNode(
                                     Utils.NameKey, name, Utils.UidKey, uid));
            }
        }