value_node.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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_VALUE_NODE_H_
  5. #define CARBON_EXPLORER_AST_VALUE_NODE_H_
  6. #include <functional>
  7. #include <optional>
  8. #include <string_view>
  9. #include "explorer/ast/ast_node.h"
  10. #include "explorer/ast/clone_context.h"
  11. #include "explorer/ast/expression_category.h"
  12. #include "explorer/base/nonnull.h"
  13. namespace Carbon {
  14. class Value;
  15. // The placeholder name exposed by anonymous ValueNodes.
  16. static constexpr std::string_view AnonymousName = "_";
  17. // ImplementsValueNode is true if NodeType::ImplementsCarbonValueNode
  18. // is valid and names a type, indicating that NodeType implements the
  19. // ValueNode interface, defined below.
  20. template <typename NodeType, typename = void>
  21. static constexpr bool ImplementsValueNode = false;
  22. // ValueNode is an interface implemented by AstNodes that can be associated
  23. // with a value, such as declarations and bindings. The interface consists of
  24. // the following methods:
  25. //
  26. // // Returns the constant associated with the node.
  27. // // This is called by the interpreter, not the type checker.
  28. // auto constant_value() const -> std::optional<Nonnull<const Value*>>;
  29. //
  30. // // Returns the symbolic compile-time identity of the node.
  31. // // This is called by the type checker, not the interpreter.
  32. // auto symbolic_identity() const -> std::optional<Nonnull<const Value*>>;
  33. //
  34. // // Returns the static type of an IdentifierExpression that names *this.
  35. // auto static_type() const -> const Value&;
  36. //
  37. // // Returns the value category of an IdentifierExpression that names *this.
  38. // auto expression_category() const -> ExpressionCategory;
  39. //
  40. // // Print the node's identity (e.g. its name).
  41. // void PrintID(llvm::raw_ostream& out) const;
  42. //
  43. // TODO: consider turning the above documentation into real code, as sketched
  44. // at https://godbolt.org/z/186oEozhc
  45. template <typename T>
  46. static constexpr bool
  47. ImplementsValueNode<T, typename T::ImplementsCarbonValueNode> = true;
  48. class ValueNodeView : public Printable<ValueNodeView> {
  49. public:
  50. template <typename NodeType,
  51. typename = std::enable_if_t<ImplementsValueNode<NodeType>>>
  52. // NOLINTNEXTLINE(google-explicit-constructor)
  53. ValueNodeView(Nonnull<const NodeType*> node)
  54. // Type-erase NodeType, retaining a pointer to the base class AstNode
  55. // and using std::function to encapsulate the ability to call
  56. // the derived class's methods.
  57. : base_(node),
  58. constant_value_(
  59. [](const AstNode& base) -> std::optional<Nonnull<const Value*>> {
  60. return llvm::cast<NodeType>(base).constant_value();
  61. }),
  62. symbolic_identity_(
  63. [](const AstNode& base) -> std::optional<Nonnull<const Value*>> {
  64. return llvm::cast<NodeType>(base).symbolic_identity();
  65. }),
  66. print_([](const AstNode& base, llvm::raw_ostream& out) -> void {
  67. // TODO: change this to print a summary of the node
  68. return llvm::cast<NodeType>(base).PrintID(out);
  69. }),
  70. static_type_([](const AstNode& base) -> const Value& {
  71. return llvm::cast<NodeType>(base).static_type();
  72. }),
  73. expression_category_([](const AstNode& base) -> ExpressionCategory {
  74. return llvm::cast<NodeType>(base).expression_category();
  75. }) {}
  76. explicit ValueNodeView(CloneContext& context, const ValueNodeView& other)
  77. : base_(context.Remap(other.base_)),
  78. // We assume the clone is the same kind of node as the original.
  79. constant_value_(other.constant_value_),
  80. symbolic_identity_(other.symbolic_identity_),
  81. print_(other.print_),
  82. static_type_(other.static_type_),
  83. expression_category_(other.expression_category_) {}
  84. ValueNodeView(const ValueNodeView&) = default;
  85. ValueNodeView(ValueNodeView&&) = default;
  86. auto operator=(const ValueNodeView&) -> ValueNodeView& = default;
  87. auto operator=(ValueNodeView&&) -> ValueNodeView& = default;
  88. // Returns `node` as an instance of the base class AstNode.
  89. auto base() const -> const AstNode& { return *base_; }
  90. // Returns node->constant_value()
  91. auto constant_value() const -> std::optional<Nonnull<const Value*>> {
  92. return constant_value_(*base_);
  93. }
  94. // Returns node->symbolic_identity()
  95. auto symbolic_identity() const -> std::optional<Nonnull<const Value*>> {
  96. return symbolic_identity_(*base_);
  97. }
  98. void Print(llvm::raw_ostream& out) const { print_(*base_, out); }
  99. // Returns node->static_type()
  100. auto static_type() const -> const Value& { return static_type_(*base_); }
  101. // Returns node->expression_category()
  102. auto expression_category() const -> ExpressionCategory {
  103. return expression_category_(*base_);
  104. }
  105. friend auto operator==(const ValueNodeView& lhs, const ValueNodeView& rhs)
  106. -> bool {
  107. return lhs.base_ == rhs.base_;
  108. }
  109. friend auto operator!=(const ValueNodeView& lhs, const ValueNodeView& rhs)
  110. -> bool {
  111. return lhs.base_ != rhs.base_;
  112. }
  113. friend auto operator<(const ValueNodeView& lhs, const ValueNodeView& rhs)
  114. -> bool {
  115. return std::less<>()(lhs.base_, rhs.base_);
  116. }
  117. friend auto hash_value(const ValueNodeView& view) -> llvm::hash_code {
  118. using llvm::hash_value;
  119. return hash_value(view.base_);
  120. }
  121. private:
  122. Nonnull<const AstNode*> base_;
  123. std::function<std::optional<Nonnull<const Value*>>(const AstNode&)>
  124. constant_value_;
  125. std::function<std::optional<Nonnull<const Value*>>(const AstNode&)>
  126. symbolic_identity_;
  127. std::function<void(const AstNode&, llvm::raw_ostream&)> print_;
  128. std::function<const Value&(const AstNode&)> static_type_;
  129. std::function<ExpressionCategory(const AstNode&)> expression_category_;
  130. };
  131. } // namespace Carbon
  132. #endif // CARBON_EXPLORER_AST_VALUE_NODE_H_