yaml.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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<auto(llvm::raw_ostream&)->void> output)
  42. : output_(std::move(output)) {}
  43. auto Output(llvm::raw_ostream& out) const -> void { output_(out); }
  44. private:
  45. std::function<auto(llvm::raw_ostream&)->void> output_;
  46. };
  47. // Adapts a function for outputting YAML as a mapping.
  48. class OutputMapping {
  49. public:
  50. class Map {
  51. public:
  52. // `io` must not be null.
  53. explicit Map(llvm::yaml::IO* io) : io_(io) {}
  54. // Maps a value. This mainly takes responsibility for copying the value,
  55. // letting mapRequired take `&value`.
  56. template <typename T>
  57. auto Add(llvm::StringRef key, T value) -> void {
  58. io_->mapRequired(key.data(), value);
  59. }
  60. private:
  61. llvm::yaml::IO* io_;
  62. };
  63. explicit OutputMapping(std::function<auto(OutputMapping::Map)->void> output)
  64. : output_(std::move(output)) {}
  65. auto Output(llvm::yaml::IO& io) -> void { output_(Map(&io)); }
  66. private:
  67. std::function<auto(OutputMapping::Map)->void> output_;
  68. };
  69. } // namespace Carbon::Yaml
  70. // Link OutputScalar to the llvm::yaml::IO API.
  71. template <>
  72. struct llvm::yaml::ScalarTraits<Carbon::Yaml::OutputScalar> {
  73. static auto output(const Carbon::Yaml::OutputScalar& value, void* /*ctxt*/,
  74. llvm::raw_ostream& out) -> void {
  75. value.Output(out);
  76. }
  77. static auto input(StringRef /*scalar*/, void* /*ctxt*/,
  78. Carbon::Yaml::OutputScalar& /*value*/) -> StringRef {
  79. CARBON_FATAL("Input is unsupported.");
  80. }
  81. static auto mustQuote(StringRef /*value*/) -> QuotingType {
  82. return QuotingType::None;
  83. }
  84. };
  85. static_assert(llvm::yaml::has_ScalarTraits<Carbon::Yaml::OutputScalar>::value);
  86. // Link OutputMapping to the llvm::yaml::IO API.
  87. template <>
  88. struct llvm::yaml::MappingTraits<Carbon::Yaml::OutputMapping> {
  89. static auto mapping(IO& io, Carbon::Yaml::OutputMapping& mapping) -> void {
  90. mapping.Output(io);
  91. }
  92. };
  93. static_assert(llvm::yaml::has_MappingTraits<Carbon::Yaml::OutputMapping,
  94. llvm::yaml::EmptyContext>::value);
  95. #endif // CARBON_TOOLCHAIN_BASE_YAML_H_