static_scope.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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 "executable_semantics/ast/ast_node.h"
  12. #include "executable_semantics/ast/source_location.h"
  13. #include "executable_semantics/common/nonnull.h"
  14. namespace Carbon {
  15. class Value;
  16. // True if NodeType::ImplementsCarbonNamedEntity is valid and names a type,
  17. // indicating that NodeType implements the NamedEntity interface. This imposes
  18. // the following requirements on NodeType, where `node` is a const instance of
  19. // NodeType:
  20. //
  21. // - NodeType is derived from AstNode.
  22. // - node.static_type() is well-formed and has type const Value&.
  23. template <typename T, typename = void>
  24. static constexpr bool ImplementsNamedEntity = false;
  25. template <typename T>
  26. static constexpr bool
  27. ImplementsNamedEntity<T, typename T::ImplementsCarbonNamedEntity> = true;
  28. // Non-owning type-erased wrapper around a const NodeType* `node`, where
  29. // NodeType implements the NamedEntity interface.
  30. class NamedEntityView {
  31. public:
  32. template <typename NodeType,
  33. typename = std::enable_if_t<ImplementsNamedEntity<NodeType>>>
  34. // NOLINTNEXTLINE(google-explicit-constructor)
  35. NamedEntityView(Nonnull<const NodeType*> node)
  36. // Type-erase NodeType, retaining a pointer to the base class AstNode
  37. // and using std::function to encapsulate the ability to call
  38. // the derived class's static_type.
  39. : base_(node), static_type_([](const AstNode& base) -> const Value& {
  40. return llvm::cast<NodeType>(base).static_type();
  41. }) {}
  42. NamedEntityView(const NamedEntityView&) = default;
  43. NamedEntityView(NamedEntityView&&) = default;
  44. auto operator=(const NamedEntityView&) -> NamedEntityView& = default;
  45. auto operator=(NamedEntityView&&) -> NamedEntityView& = default;
  46. // Returns `node` as an instance of the base class AstNode.
  47. auto base() const -> const AstNode& { return *base_; }
  48. // Returns node->static_type()
  49. auto static_type() const -> const Value& { return static_type_(*base_); }
  50. friend auto operator==(const NamedEntityView& lhs,
  51. const NamedEntityView& rhs) {
  52. return lhs.base_ == rhs.base_;
  53. }
  54. friend auto operator!=(const NamedEntityView& lhs,
  55. const NamedEntityView& rhs) {
  56. return lhs.base_ != rhs.base_;
  57. }
  58. private:
  59. Nonnull<const AstNode*> base_;
  60. std::function<const Value&(const AstNode&)> static_type_;
  61. };
  62. // Maps the names visible in a given scope to the entities they name.
  63. // A scope may have parent scopes, whose names will also be visible in the
  64. // child scope.
  65. class StaticScope {
  66. public:
  67. // Defines `name` to be `entity` in this scope, or reports a compilation error
  68. // if `name` is already defined to be a different entity in this scope.
  69. void Add(std::string name, NamedEntityView entity);
  70. // Make `parent` a parent of this scope.
  71. // REQUIRES: `parent` is not already a parent of this scope.
  72. void AddParent(Nonnull<StaticScope*> parent) {
  73. parent_scopes_.push_back(parent);
  74. }
  75. // Returns the nearest definition of `name` in the ancestor graph of this
  76. // scope, or reports a compilation error at `source_loc` there isn't exactly
  77. // one such definition.
  78. auto Resolve(const std::string& name, SourceLocation source_loc) const
  79. -> NamedEntityView;
  80. private:
  81. // Equivalent to Resolve, but returns `nullopt` instead of raising an error
  82. // if no definition can be found. Still raises a compilation error if more
  83. // than one definition is found.
  84. auto TryResolve(const std::string& name, SourceLocation source_loc) const
  85. -> std::optional<NamedEntityView>;
  86. // Maps locally declared names to their entities.
  87. std::unordered_map<std::string, NamedEntityView> declared_names_;
  88. // A list of scopes used for name lookup within this scope.
  89. std::vector<Nonnull<StaticScope*>> parent_scopes_;
  90. };
  91. } // namespace Carbon
  92. #endif // EXECUTABLE_SEMANTICS_AST_STATIC_SCOPE_H_