static_scope.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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 EXECUTABLE_SEMANTICS_AST_STATIC_SCOPE_H_
  5. #define EXECUTABLE_SEMANTICS_AST_STATIC_SCOPE_H_
  6. #include <functional>
  7. #include <string>
  8. #include <unordered_map>
  9. #include <variant>
  10. #include <vector>
  11. #include "common/check.h"
  12. #include "executable_semantics/ast/ast_node.h"
  13. #include "executable_semantics/ast/source_location.h"
  14. #include "executable_semantics/ast/value_category.h"
  15. #include "executable_semantics/common/nonnull.h"
  16. namespace Carbon {
  17. class Value;
  18. // The placeholder name exposed by anonymous NamedEntities.
  19. static constexpr std::string_view AnonymousName = "_";
  20. // True if NodeType::ImplementsCarbonNamedEntity is valid and names a type,
  21. // indicating that NodeType implements the NamedEntity interface, which means
  22. // it must define the following methods, with contracts as documented.
  23. /*
  24. // Returns the static type of an IdentifierExpression that names *this.
  25. auto static_type() const -> const Value&;
  26. // Returns the value category of an IdentifierExpression that names *this.
  27. auto value_category() const -> ValueCategory;
  28. // Returns the name of an IdentifierExpression that names *this. If *this
  29. // is anonymous, returns AnonymousName.
  30. auto name() const -> std::string_view;
  31. // If *this names a compile-time constant whose value is known, returns that
  32. // value. Otherwise returns std::nullopt.
  33. auto constant_value() const -> std::optional<Nonnull<const Value*>>;
  34. */
  35. // NodeType must be derived from AstNode.
  36. //
  37. // TODO: consider turning the above documentation into real code, as sketched
  38. // at https://godbolt.org/z/186oEozhc
  39. template <typename T, typename = void>
  40. static constexpr bool ImplementsNamedEntity = false;
  41. template <typename T>
  42. static constexpr bool
  43. ImplementsNamedEntity<T, typename T::ImplementsCarbonNamedEntity> = true;
  44. // Non-owning type-erased wrapper around a const NodeType* `node`, where
  45. // NodeType implements the NamedEntity interface.
  46. class NamedEntityView {
  47. public:
  48. // REQUIRES: node->name() != AnonymousName
  49. template <typename NodeType,
  50. typename = std::enable_if_t<ImplementsNamedEntity<NodeType>>>
  51. // NOLINTNEXTLINE(google-explicit-constructor)
  52. NamedEntityView(Nonnull<const NodeType*> node)
  53. // Type-erase NodeType, retaining a pointer to the base class AstNode
  54. // and using std::function to encapsulate the ability to call
  55. // the derived class's methods.
  56. : base_(node),
  57. name_([](const AstNode& base) -> std::string_view {
  58. return llvm::cast<NodeType>(base).name();
  59. }),
  60. static_type_([](const AstNode& base) -> const Value& {
  61. return llvm::cast<NodeType>(base).static_type();
  62. }),
  63. value_category_([](const AstNode& base) -> ValueCategory {
  64. return llvm::cast<NodeType>(base).value_category();
  65. }),
  66. constant_value_(
  67. [](const AstNode& base) -> std::optional<Nonnull<const Value*>> {
  68. return llvm::cast<NodeType>(base).constant_value();
  69. }) {
  70. CHECK(node->name() != AnonymousName)
  71. << "Entity with no name used as NamedEntity: " << *node;
  72. }
  73. NamedEntityView(const NamedEntityView&) = default;
  74. NamedEntityView(NamedEntityView&&) = default;
  75. auto operator=(const NamedEntityView&) -> NamedEntityView& = default;
  76. auto operator=(NamedEntityView&&) -> NamedEntityView& = default;
  77. // Returns `node` as an instance of the base class AstNode.
  78. auto base() const -> const AstNode& { return *base_; }
  79. // Returns node->name()
  80. auto name() const -> std::string_view { return name_(*base_); }
  81. // Returns node->static_type()
  82. auto static_type() const -> const Value& { return static_type_(*base_); }
  83. // Returns node->value_category()
  84. auto value_category() const -> ValueCategory {
  85. return value_category_(*base_);
  86. }
  87. // Returns node->constant_value()
  88. auto constant_value() const -> std::optional<Nonnull<const Value*>> {
  89. return constant_value_(*base_);
  90. }
  91. friend auto operator==(const NamedEntityView& lhs, const NamedEntityView& rhs)
  92. -> bool {
  93. return lhs.base_ == rhs.base_;
  94. }
  95. friend auto operator!=(const NamedEntityView& lhs, const NamedEntityView& rhs)
  96. -> bool {
  97. return lhs.base_ != rhs.base_;
  98. }
  99. friend auto operator<(const NamedEntityView& lhs, const NamedEntityView& rhs)
  100. -> bool {
  101. return std::less<>()(lhs.base_, rhs.base_);
  102. }
  103. private:
  104. Nonnull<const AstNode*> base_;
  105. std::function<std::string_view(const AstNode&)> name_;
  106. std::function<const Value&(const AstNode&)> static_type_;
  107. std::function<ValueCategory(const AstNode&)> value_category_;
  108. std::function<std::optional<Nonnull<const Value*>>(const AstNode&)>
  109. constant_value_;
  110. };
  111. // Maps the names visible in a given scope to the entities they name.
  112. // A scope may have parent scopes, whose names will also be visible in the
  113. // child scope.
  114. class StaticScope {
  115. public:
  116. // Defines `name` to be `entity` in this scope, or reports a compilation error
  117. // if `name` is already defined to be a different entity in this scope.
  118. void Add(std::string name, NamedEntityView entity);
  119. // Make `parent` a parent of this scope.
  120. // REQUIRES: `parent` is not already a parent of this scope.
  121. void AddParent(Nonnull<StaticScope*> parent) {
  122. parent_scopes_.push_back(parent);
  123. }
  124. // Returns the nearest definition of `name` in the ancestor graph of this
  125. // scope, or reports a compilation error at `source_loc` there isn't exactly
  126. // one such definition.
  127. auto Resolve(const std::string& name, SourceLocation source_loc) const
  128. -> NamedEntityView;
  129. private:
  130. // Equivalent to Resolve, but returns `nullopt` instead of raising an error
  131. // if no definition can be found. Still raises a compilation error if more
  132. // than one definition is found.
  133. auto TryResolve(const std::string& name, SourceLocation source_loc) const
  134. -> std::optional<NamedEntityView>;
  135. // Maps locally declared names to their entities.
  136. std::unordered_map<std::string, NamedEntityView> declared_names_;
  137. // A list of scopes used for name lookup within this scope.
  138. std::vector<Nonnull<StaticScope*>> parent_scopes_;
  139. };
  140. } // namespace Carbon
  141. #endif // EXECUTABLE_SEMANTICS_AST_STATIC_SCOPE_H_