yaml.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #ifndef CARBON_TOOLCHAIN_BASE_YAML_H_
  5. #define CARBON_TOOLCHAIN_BASE_YAML_H_
  6. #include "common/check.h"
  7. #include "common/ostream.h"
  8. #include "llvm/ADT/StringRef.h"
  9. #include "llvm/Support/YAMLTraits.h"
  10. // This file provides adapters for outputting YAML using llvm::yaml's APIs. It
  11. // only supports output, not input. However, it addresses the mix of const and
  12. // non-const expectations of the llvm::yaml that make it difficult to otherwise
  13. // use the trait-based approach.
  14. namespace Carbon::Yaml {
  15. // Helper for printing YAML, to maintain a consistent configuration.
  16. template <typename T>
  17. inline auto Print(llvm::raw_ostream& out, T yaml) -> void {
  18. llvm::yaml::Output yout(out, /*Ctxt=*/nullptr, /*WrapColumn=*/80);
  19. yout << yaml;
  20. }
  21. // Similar to the standard Printable<T>, but relies on OutputYaml for printing.
  22. template <typename T>
  23. class Printable : public Carbon::Printable<T> {
  24. public:
  25. auto Print(llvm::raw_ostream& out) const -> void {
  26. Carbon::Yaml::Print(out, static_cast<const T*>(this)->OutputYaml());
  27. }
  28. };
  29. // Adapts a function for outputting YAML as a scalar. This currently assumes no
  30. // scalars passed through this should be quoted.
  31. class OutputScalar {
  32. public:
  33. template <typename T>
  34. explicit OutputScalar(const T& val)
  35. : output_([&](llvm::raw_ostream& out) -> void { out << val; }) {}
  36. explicit OutputScalar(const llvm::APInt& val)
  37. : output_([&](llvm::raw_ostream& out) -> void {
  38. // Carbon's plain APInt storage is typically unsigned.
  39. val.print(out, /*isSigned=*/false);
  40. }) {}
  41. explicit OutputScalar(std::function<void(llvm::raw_ostream&)> output)
  42. : output_(std::move(output)) {}
  43. auto Output(llvm::raw_ostream& out) const -> void { output_(out); }
  44. private:
  45. std::function<void(llvm::raw_ostream&)> output_;
  46. };
  47. // Adapts a function for outputting YAML as a mapping.
  48. class OutputMapping {
  49. public:
  50. class Map {
  51. public:
  52. explicit Map(llvm::yaml::IO& io) : io_(io) {}
  53. // Maps a value. This mainly takes responsibility for copying the value,
  54. // letting mapRequired take `&value`.
  55. template <typename T>
  56. auto Add(llvm::StringRef key, T value) -> void {
  57. io_.mapRequired(key.data(), value);
  58. }
  59. private:
  60. llvm::yaml::IO& io_;
  61. };
  62. explicit OutputMapping(std::function<void(OutputMapping::Map)> output)
  63. : output_(std::move(output)) {}
  64. auto Output(llvm::yaml::IO& io) -> void { output_(Map(io)); }
  65. private:
  66. std::function<void(OutputMapping::Map)> output_;
  67. };
  68. } // namespace Carbon::Yaml
  69. // Link OutputScalar to the llvm::yaml::IO API.
  70. template <>
  71. struct llvm::yaml::ScalarTraits<Carbon::Yaml::OutputScalar> {
  72. static auto output(const Carbon::Yaml::OutputScalar& value, void* /*ctxt*/,
  73. llvm::raw_ostream& out) -> void {
  74. value.Output(out);
  75. }
  76. static auto input(StringRef /*scalar*/, void* /*ctxt*/,
  77. Carbon::Yaml::OutputScalar& /*value*/) -> StringRef {
  78. CARBON_FATAL() << "Input is unsupported.";
  79. }
  80. static auto mustQuote(StringRef /*value*/) -> QuotingType {
  81. return QuotingType::None;
  82. }
  83. };
  84. static_assert(llvm::yaml::has_ScalarTraits<Carbon::Yaml::OutputScalar>::value);
  85. // Link OutputMapping to the llvm::yaml::IO API.
  86. template <>
  87. struct llvm::yaml::MappingTraits<Carbon::Yaml::OutputMapping> {
  88. static auto mapping(IO& io, Carbon::Yaml::OutputMapping& mapping) -> void {
  89. mapping.Output(io);
  90. }
  91. };
  92. static_assert(llvm::yaml::has_MappingTraits<Carbon::Yaml::OutputMapping,
  93. llvm::yaml::EmptyContext>::value);
  94. #endif // CARBON_TOOLCHAIN_BASE_YAML_H_