// This file implements the underlying structure of Nix attribute sets. #pragma once #include <absl/container/btree_map.h> #include <gc/gc_allocator.h> #include "nixexpr.hh" #include "symbol-table.hh" #include "types.hh" namespace nix { // TODO(tazjin): ::expr class EvalState; struct Value; /* Map one attribute name to its value. */ struct Attr { Symbol name; Value* value; // TODO(tazjin): Who owns this? Pos* pos; // TODO(tazjin): Who owns this? Attr(Symbol name, Value* value, Pos* pos = &noPos) : name(name), value(value), pos(pos){}; Attr() : pos(&noPos){}; bool operator<(const Attr& other) const { return name < other.name; } }; // TODO: remove this, it only exists briefly while I get rid of the // current Attr struct inline bool operator==(const Attr& lhs, const Attr& rhs) { return lhs.name == rhs.name; } // Convenience alias for the backing map, with the garbage-collecting // allocator explicitly specified. using AttributeMap = absl::btree_map<Symbol, Attr, std::less<Symbol>, gc_allocator<std::pair<const Symbol, Attr>>>; class Bindings { public: typedef absl::btree_map<Symbol, Attr>::iterator iterator; // Allocate a new attribute set that is visible to the garbage // collector. static Bindings* NewGC(); // Return the number of contained elements. size_t size(); // Is this attribute set empty? bool empty(); // Insert, but do not replace, values in the attribute set. void push_back(const Attr& attr); // Insert a value, or replace an existing one. void insert_or_assign(const Attr& attr); // Look up a specific element of the attribute set. iterator find(const Symbol& name); // TODO iterator begin(); iterator end(); // Merge values from other into the current attribute void merge(Bindings* other); // ??? [[deprecated]] size_t capacity(); // oh no // Attr& operator[](size_t pos); // { return attrs[pos]; } // TODO: can callers just iterate? [[deprecated]] std::vector<const Attr*> lexicographicOrder(); // oh no friend class EvalState; private: absl::btree_map<Symbol, Attr> attributes_; }; } // namespace nix