static_scope.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  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_STATIC_SCOPE_H_
  5. #define CARBON_EXPLORER_AST_STATIC_SCOPE_H_
  6. #include <string>
  7. #include <string_view>
  8. #include "common/error.h"
  9. #include "explorer/ast/value_node.h"
  10. #include "explorer/common/nonnull.h"
  11. #include "explorer/common/source_location.h"
  12. #include "llvm/ADT/StringMap.h"
  13. namespace Carbon {
  14. // Maps the names visible in a given scope to the entities they name.
  15. // A scope may have parent scopes, whose names will also be visible in the
  16. // child scope.
  17. class StaticScope {
  18. public:
  19. // The status of a name. Later enumerators with higher values correspond to
  20. // more completely declared names.
  21. enum class NameStatus {
  22. // The name is known to exist in this scope, and any lookups finding it
  23. // should be rejected because it's not declared yet.
  24. KnownButNotDeclared,
  25. // We've started processing a declaration of this name, but it's not yet
  26. // fully declared, so any lookups finding it should be rejected.
  27. DeclaredButNotUsable,
  28. // The name is usable in this context.
  29. Usable,
  30. };
  31. // Construct a root scope.
  32. StaticScope() = default;
  33. // Construct a scope that is nested within the given scope.
  34. explicit StaticScope(Nonnull<const StaticScope*> parent)
  35. : parent_scope_(parent) {}
  36. // Defines `name` to be `entity` in this scope, or reports a compilation error
  37. // if `name` is already defined to be a different entity in this scope.
  38. // If `usable` is `false`, `name` cannot yet be referenced and `Resolve()`
  39. // methods will fail for it.
  40. auto Add(std::string_view name, ValueNodeView entity,
  41. NameStatus status = NameStatus::Usable) -> ErrorOr<Success>;
  42. // Marks `name` as being past its point of declaration.
  43. void MarkDeclared(std::string_view name);
  44. // Marks `name` as being completely declared and hence usable.
  45. void MarkUsable(std::string_view name);
  46. // Returns the nearest declaration of `name` in the ancestor graph of this
  47. // scope, or reports a compilation error at `source_loc` there isn't such a
  48. // declaration.
  49. // TODO: This should also diagnose if there's a shadowed declaration of the
  50. // name in an enclosing scope, but does not do so yet.
  51. auto Resolve(std::string_view name, SourceLocation source_loc) const
  52. -> ErrorOr<ValueNodeView>;
  53. // Returns the declaration of `name` in this scope, or reports a compilation
  54. // error at `source_loc` if the name is not declared in this scope. If
  55. // `allow_undeclared` is `true`, names that have been added but not yet marked
  56. // declared or usable do not result in an error.
  57. auto ResolveHere(std::optional<ValueNodeView> this_scope,
  58. std::string_view name, SourceLocation source_loc,
  59. bool allow_undeclared) const -> ErrorOr<ValueNodeView>;
  60. // Returns the value node of the BindingPattern of the returned var definition
  61. // if it exists in the ancestor graph.
  62. auto ResolveReturned() const -> std::optional<ValueNodeView>;
  63. // Adds the value node of the BindingPattern of the returned var definition to
  64. // this scope. Returns a compilation error when there is an existing returned
  65. // var in the ancestor graph.
  66. auto AddReturnedVar(ValueNodeView returned_var_def_view) -> ErrorOr<Success>;
  67. private:
  68. // Equivalent to Resolve, but returns `nullopt` instead of raising an error
  69. // if no declaration can be found.
  70. auto TryResolve(std::string_view name, SourceLocation source_loc) const
  71. -> ErrorOr<std::optional<ValueNodeView>>;
  72. // Equivalent to ResolveHere, but returns `nullopt` if no definition can be
  73. // found. Raises an error if the name is found but is not usable yet.
  74. auto TryResolveHere(std::string_view name, SourceLocation source_loc,
  75. bool allow_undeclared) const
  76. -> ErrorOr<std::optional<ValueNodeView>>;
  77. struct Entry {
  78. ValueNodeView entity;
  79. NameStatus status;
  80. };
  81. // Maps locally declared names to their entities.
  82. llvm::StringMap<Entry> declared_names_;
  83. // The parent scope of this scope, if it not the root scope.
  84. std::optional<Nonnull<const StaticScope*>> parent_scope_;
  85. // Stores the value node of the BindingPattern of the returned var definition.
  86. std::optional<ValueNodeView> returned_var_def_view_;
  87. };
  88. } // namespace Carbon
  89. #endif // CARBON_EXPLORER_AST_STATIC_SCOPE_H_