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)); } } }
/// <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); }
/// <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); }
/// <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>()); } }
/// <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)); } }