// Copyright (c) 2020-now by the Zeek Project. See LICENSE for details. #pragma once #include #include #include #include #include #include namespace hilti::ctor { class Bitfield; namespace bitfield { /** AST node for a bitfield element. */ class BitRange final : public Node { public: ~BitRange() final; const auto& id() const { return _id; } auto expression() const { return child(0); } node::Properties properties() const final { auto p = node::Properties{{"id", _id}}; return Node::properties() + std::move(p); } static auto create(ASTContext* ctx, const ID& id, Expression* expr, Meta meta = Meta()) { return ctx->make(ctx, {expr}, id, std::move(meta)); } protected: friend class type::Bitfield; BitRange(ASTContext* ctx, Nodes children, ID id, Meta meta = Meta()) : Node(ctx, NodeTags, std::move(children), std::move(meta)), _id(std::move(id)) {} HILTI_NODE_0(ctor::bitfield::BitRange, final); private: ID _id; }; using BitRanges = NodeVector; } // namespace bitfield /** AST node for a `bitfield` type. */ class Bitfield : public Ctor { public: /** Returns all bits that the constructor initializes. */ auto bits() const { return children(1, {}); } /** Returns the underlying bitfield type. */ auto btype() const { return type()->type()->as(); } /** Returns a field initialized by the constructor by its ID. */ bitfield::BitRange* bits(const ID& id) const { for ( const auto& b : bits() ) { if ( b->id() == id ) return b; } return {}; } QualifiedType* type() const final { return child(0); } static auto create(ASTContext* ctx, const ctor::bitfield::BitRanges& bits, QualifiedType* type, const Meta& m = Meta()) { return ctx->make(ctx, node::flatten(type, bits), m); } protected: Bitfield(ASTContext* ctx, Nodes children, Meta meta) : Ctor(ctx, NodeTags, std::move(children), std::move(meta)) {} HILTI_NODE_1(ctor::Bitfield, Ctor, final); }; } // namespace hilti::ctor