// Copyright (c) 2020-now by the Zeek Project. See LICENSE for details. #pragma once #include #include #include #include #include #include namespace hilti { namespace declaration { /** Linkage defining visibility/accessibility of a declaration. */ enum class Linkage { Init, /// executes automatically at startup, not otherwise accessible PreInit, /// executes automatically at load time, even before the runtime library is fully set up Struct, /// method inside a method Private, /// accessible only locally Public, /// accessible across modules }; namespace detail { constexpr util::enum_::Value Linkages[] = { {Linkage::Struct, "struct"}, {Linkage::Public, "public"}, {Linkage::Private, "private"}, {Linkage::Init, "init"}, {Linkage::PreInit, "preinit"}, }; } // namespace detail /** Returns the HILTI string representation corresponding to a linkage. */ constexpr auto to_string(Linkage f) { return util::enum_::to_string(f, detail::Linkages); } namespace linkage { /** * Parses a HILTI string representation of a linkage. * * @exception `std::out_of_range` if the string does not map to a linkage */ constexpr auto from_string(std::string_view s) { return util::enum_::from_string(s, detail::Linkages); } } // namespace linkage } // namespace declaration /** Base class for implementing declaration nodes. */ class Declaration : public Node, public node::WithDocString { public: ~Declaration() override; /** Returns the declaration's ID. */ const auto& id() const { return _id; } /** Returns the declaration's linkage. */ auto linkage() const { return _linkage; } /** * Returns the declaration's fully qualified ID once it has been set during * AST processing. The ID is guaranteed to be stable only after AST * processing has finished. Returns an empty ID if not yet set. */ const auto& fullyQualifiedID() const { return _fqid; } /** * Returns the canonical ID associated with the declaration once it has * been set during AST processing. Canonical IDs are guaranteed to be * globally unique within one instance of an AST context. However, the ID * is guaranteed to be unique and stable only once AST processing has * finished. Returns an empty ID if not yet set. */ const auto& canonicalID() const { return _canonical_id; } /** * Returns the index the AST context associates with the declaration. This * may become set during AST resolving. If not set yet, returns `None`. */ auto declarationIndex() const { return _declaration_index; } /** * Sets the declaration's ID. This clears fully-qualified and canonical IDs * as they likely need to be recomputed now. */ void setID(const ID& id) { _id = id; _fqid = {}, _canonical_id = {}; } /** Sets the declaration's linkage. */ void setLinkage(declaration::Linkage linkage) { _linkage = linkage; } /** * Sets the declaration's fully qualified ID. Should be used only by the ID * assigner during AST processing. * * @param id fully qualified ID */ void setFullyQualifiedID(ID id) { _fqid = std::move(id); } /** * Associates a canonical ID with the declaration. Should be used only by * the ID assigner during AST processing. * * @param id canonical ID, which must be globally unique for this declaration */ void setCanonicalID(ID id) { _canonical_id = std::move(id); } /** * Returns a user-friendly descriptive name for the type of object the * declaration refers to (e.g., "local variable"). This can be used in * messages to the user. */ virtual std::string_view displayName() const = 0; /** Implements the node interface. */ node::Properties properties() const override { auto p = node::Properties{{"id", _id}, {"linkage", declaration::to_string(_linkage)}, {"declaration", to_string(_declaration_index)}, {"fqid", _fqid}, {"canonical-id", _canonical_id}}; return Node::properties() + std::move(p); } Declaration(const Declaration& other) : Node(other), node::WithDocString(other) { _id = other._id; _linkage = other._linkage; // Do not copy computed state, we'll want to recompute that eventually. } Declaration(Declaration&& other) = default; Declaration& operator=(const Declaration& other) = delete; Declaration& operator=(Declaration&& other) = delete; protected: friend class ASTContext; Declaration(ASTContext* ctx, node::Tags node_tags, Nodes children, ID id, declaration::Linkage linkage, Meta meta = {}) : Node(ctx, node_tags, std::move(children), std::move(meta)), _id(std::move(id)), _linkage(linkage) {} // For the AST context to set the declaration index. void setDeclarationIndex(ast::DeclarationIndex index) { assert(index); _declaration_index = index; } std::string _dump() const override; HILTI_NODE_0(Declaration, override); private: ID _id; declaration::Linkage _linkage; ast::DeclarationIndex _declaration_index; // index registered by the context ID _fqid; // computed during AST processing ID _canonical_id; // computed during AST processing }; } // namespace hilti