element.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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_EXPLORER_AST_ELEMENT_H_
  5. #define CARBON_EXPLORER_AST_ELEMENT_H_
  6. #include <optional>
  7. #include <string>
  8. #include <string_view>
  9. #include "common/ostream.h"
  10. #include "explorer/ast/ast_rtti.h"
  11. #include "explorer/base/decompose.h"
  12. #include "explorer/base/nonnull.h"
  13. #include "llvm/ADT/PointerUnion.h"
  14. namespace Carbon {
  15. class Declaration;
  16. class Value;
  17. // A NamedValue represents a value with a name, such as a single struct field.
  18. struct NamedValue : HashFromDecompose<NamedValue> {
  19. NamedValue(std::string name, Nonnull<const Value*> value)
  20. : name(std::move(name)), value(value) {}
  21. template <typename F>
  22. auto Decompose(F f) const {
  23. return f(name, value);
  24. }
  25. // The field name.
  26. std::string name;
  27. // The field's value.
  28. Nonnull<const Value*> value;
  29. };
  30. // A generic member of a type. This is can be a named, positional or other type
  31. // of member.
  32. //
  33. // Arena's canonicalization support is enabled for Element and all derived
  34. // types. As a result, all Elements must be immutable, and all their constructor
  35. // arguments must be copyable, equality-comparable, and hashable. See
  36. // Arena's documentation for details.
  37. class Element : public Printable<Element> {
  38. protected:
  39. explicit Element(ElementKind kind) : kind_(kind) {}
  40. public:
  41. using EnableCanonicalizedAllocation = void;
  42. virtual ~Element() = default;
  43. // Call `f` on this value, cast to its most-derived type. `R` specifies the
  44. // expected return type of `f`.
  45. template <typename R, typename F>
  46. auto Visit(F f) const -> R;
  47. // Prints the Member
  48. virtual void Print(llvm::raw_ostream& out) const = 0;
  49. // Return whether the member's name matches `name`.
  50. virtual auto IsNamed(std::string_view name) const -> bool = 0;
  51. // Returns the enumerator corresponding to the most-derived type of this
  52. // object.
  53. auto kind() const -> ElementKind { return kind_; }
  54. // The declared type of the member, which might include type variables.
  55. virtual auto type() const -> const Value& = 0;
  56. private:
  57. const ElementKind kind_;
  58. };
  59. // A named element of a type.
  60. //
  61. // This is either a declared member of a class, interface, or similar, or a
  62. // member of a struct with no declaration.
  63. class NamedElement : public Element {
  64. public:
  65. explicit NamedElement(Nonnull<const Declaration*> declaration);
  66. explicit NamedElement(Nonnull<const NamedValue*> struct_member);
  67. template <typename F>
  68. auto Decompose(F f) const {
  69. if (auto decl = declaration()) {
  70. return f(*decl);
  71. } else {
  72. return f(*struct_member());
  73. }
  74. }
  75. // Prints the element's name
  76. void Print(llvm::raw_ostream& out) const override;
  77. auto IsNamed(std::string_view name) const -> bool override;
  78. static auto classof(const Element* member) -> bool {
  79. return InheritsFromNamedElement(member->kind());
  80. }
  81. auto type() const -> const Value& override;
  82. // The name of the member.
  83. auto name() const -> std::string_view;
  84. // A declaration of the member, if any exists.
  85. auto declaration() const -> std::optional<Nonnull<const Declaration*>>;
  86. // A name and type pair, if this is a struct member.
  87. auto struct_member() const -> std::optional<Nonnull<const NamedValue*>>;
  88. private:
  89. const llvm::PointerUnion<Nonnull<const Declaration*>,
  90. Nonnull<const NamedValue*>>
  91. element_;
  92. };
  93. // A positional element of a type.
  94. //
  95. // This is a positional tuple element, or other index-based value.
  96. class PositionalElement : public Element {
  97. public:
  98. explicit PositionalElement(int index, Nonnull<const Value*> type)
  99. : Element(ElementKind::PositionalElement), index_(index), type_(type) {}
  100. template <typename F>
  101. auto Decompose(F f) const {
  102. return f(index_, type_);
  103. }
  104. // Prints the element
  105. void Print(llvm::raw_ostream& out) const override;
  106. // Return whether the member's name matches `name`.
  107. auto IsNamed(std::string_view name) const -> bool override;
  108. static auto classof(const Element* member) -> bool {
  109. return InheritsFromPositionalElement(member->kind());
  110. }
  111. auto index() const -> int { return index_; }
  112. auto type() const -> const Value& override { return *type_; }
  113. private:
  114. const int index_;
  115. const Nonnull<const Value*> type_;
  116. };
  117. // A base class object.
  118. //
  119. // This is the base class object of a class value.
  120. class BaseElement : public Element {
  121. public:
  122. explicit BaseElement(Nonnull<const Value*> type)
  123. : Element(ElementKind::BaseElement), type_(type) {}
  124. template <typename F>
  125. auto Decompose(F f) const {
  126. return f(type_);
  127. }
  128. // Prints the Member
  129. void Print(llvm::raw_ostream& out) const override;
  130. // Return whether the member's name matches `name`.
  131. auto IsNamed(std::string_view name) const -> bool override;
  132. static auto classof(const Element* member) -> bool {
  133. return InheritsFromBaseElement(member->kind());
  134. }
  135. auto type() const -> const Value& override { return *type_; }
  136. private:
  137. const Nonnull<const Value*> type_;
  138. };
  139. template <typename R, typename F>
  140. auto Element::Visit(F f) const -> R {
  141. switch (kind()) {
  142. case ElementKind::NamedElement:
  143. return f(static_cast<const NamedElement*>(this));
  144. case ElementKind::PositionalElement:
  145. return f(static_cast<const PositionalElement*>(this));
  146. case ElementKind::BaseElement:
  147. return f(static_cast<const BaseElement*>(this));
  148. }
  149. }
  150. } // namespace Carbon
  151. #endif // CARBON_EXPLORER_AST_ELEMENT_H_