| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
- // Exceptions. See /LICENSE for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- #ifndef CARBON_EXPLORER_AST_STATIC_SCOPE_H_
- #define CARBON_EXPLORER_AST_STATIC_SCOPE_H_
- #include <string>
- #include <string_view>
- #include "common/error.h"
- #include "explorer/ast/value_node.h"
- #include "explorer/base/nonnull.h"
- #include "explorer/base/source_location.h"
- #include "explorer/base/trace_stream.h"
- #include "llvm/ADT/StringMap.h"
- namespace Carbon {
- // Maps the names visible in a given scope to the entities they name.
- // A scope may have parent scopes, whose names will also be visible in the
- // child scope.
- class StaticScope {
- public:
- // The status of a name. Later enumerators with higher values correspond to
- // more completely declared names.
- enum class NameStatus {
- // The name is known to exist in this scope, and any lookups finding it
- // should be rejected because it's not declared yet.
- KnownButNotDeclared,
- // We've started processing a declaration of this name, but it's not yet
- // fully declared, so any lookups finding it should be rejected.
- DeclaredButNotUsable,
- // The name is usable in this context.
- Usable,
- };
- // Construct a root scope.
- explicit StaticScope(Nonnull<TraceStream*> trace_stream)
- : ast_node_(std::nullopt), trace_stream_(trace_stream) {}
- // Construct a scope that is nested within the given scope.
- explicit StaticScope(Nonnull<const StaticScope*> parent,
- std::optional<Nonnull<const AstNode*>> ast_node)
- : parent_scope_(parent),
- ast_node_(ast_node),
- trace_stream_(parent->trace_stream_) {}
- StaticScope() = default;
- // Defines `name` to be `entity` in this scope, or reports a compilation error
- // if `name` is already defined to be a different entity in this scope.
- // If `usable` is `false`, `name` cannot yet be referenced and `Resolve()`
- // methods will fail for it.
- auto Add(std::string_view name, ValueNodeView entity,
- NameStatus status = NameStatus::Usable) -> ErrorOr<Success>;
- template <typename Action>
- void PrintCommon(Action action) const;
- void Print(llvm::raw_ostream& out) const;
- void PrintID(llvm::raw_ostream& out) const;
- // Marks `name` as being past its point of declaration.
- void MarkDeclared(std::string_view name);
- // Marks `name` as being completely declared and hence usable.
- void MarkUsable(std::string_view name);
- // Returns the nearest declaration of `name` in the ancestor graph of this
- // scope, or reports a compilation error at `source_loc` there isn't such a
- // declaration.
- // TODO: This should also diagnose if there's a shadowed declaration of the
- // name in an enclosing scope, but does not do so yet.
- auto Resolve(std::string_view name, SourceLocation source_loc) const
- -> ErrorOr<ValueNodeView>;
- // Returns the declaration of `name` in this scope, or reports a compilation
- // error at `source_loc` if the name is not declared in this scope. If
- // `allow_undeclared` is `true`, names that have been added but not yet marked
- // declared or usable do not result in an error.
- auto ResolveHere(std::optional<ValueNodeView> this_scope,
- std::string_view name, SourceLocation source_loc,
- bool allow_undeclared) const -> ErrorOr<ValueNodeView>;
- // Returns the value node of the BindingPattern of the returned var definition
- // if it exists in the ancestor graph.
- auto ResolveReturned() const -> std::optional<ValueNodeView>;
- // Adds the value node of the BindingPattern of the returned var definition to
- // this scope. Returns a compilation error when there is an existing returned
- // var in the ancestor graph.
- auto AddReturnedVar(ValueNodeView returned_var_def_view) -> ErrorOr<Success>;
- private:
- // Equivalent to Resolve, but returns `nullopt` instead of raising an error
- // if no declaration can be found.
- auto TryResolve(std::string_view name, SourceLocation source_loc) const
- -> ErrorOr<std::optional<ValueNodeView>>;
- // Equivalent to ResolveHere, but returns `nullopt` if no definition can be
- // found. Raises an error if the name is found but is not usable yet.
- auto TryResolveHere(std::string_view name, SourceLocation source_loc,
- bool allow_undeclared) const
- -> ErrorOr<std::optional<ValueNodeView>>;
- struct Entry {
- ValueNodeView entity;
- NameStatus status;
- };
- // Maps locally declared names to their entities.
- llvm::StringMap<Entry> declared_names_;
- // The parent scope of this scope, if it not the root scope.
- std::optional<Nonnull<const StaticScope*>> parent_scope_;
- // Stores the value node of the BindingPattern of the returned var definition.
- std::optional<ValueNodeView> returned_var_def_view_;
- std::optional<Nonnull<const AstNode*>> ast_node_;
- Nonnull<TraceStream*> trace_stream_;
- };
- } // namespace Carbon
- #endif // CARBON_EXPLORER_AST_STATIC_SCOPE_H_
|