Nix  2.93.0-dev
Lix: A modern, delicious implementation of the Nix package manager; unstable internal interfaces
Loading...
Searching...
No Matches
attr-set.hh
Go to the documentation of this file.
1#pragma once
3
6
7#include <algorithm>
8#include <optional>
9
10namespace nix {
11
12
13class EvalMemory;
14struct Value;
15
19struct Attr
20{
21 /* the placement of `name` and `pos` in this struct is important.
22 both of them are uint32 wrappers, they are next to each other
23 to make sure that Attr has no padding on 64 bit machines. that
24 way we keep Attr size at two words with no wasted space. */
25 Symbol name;
26 PosIdx pos;
27 Value * value;
28 Attr(Symbol name, Value * value, PosIdx pos = noPos)
29 : name(name), pos(pos), value(value) { };
30 Attr() { };
31 bool operator < (const Attr & a) const
32 {
33 return name < a.name;
34 }
35};
36
37static_assert(sizeof(Attr) == 2 * sizeof(uint32_t) + sizeof(Value *),
38 "performance of the evaluator is highly sensitive to the size of Attr. "
39 "avoid introducing any padding into Attr if at all possible, and do not "
40 "introduce new fields that need not be present for almost every instance.");
41
49{
50public:
51 using Size = uint32_t;
52 PosIdx pos;
53
54 static Bindings EMPTY;
55
56private:
57 Size size_, capacity_;
58 Attr attrs[0];
59
60 Bindings(Size capacity) : size_(0), capacity_(capacity) { }
61 Bindings(const Bindings & bindings) = delete;
62
63public:
64 Size size() const { return size_; }
65
66 bool empty() const { return !size_; }
67
68 typedef Attr * iterator;
69
70 void push_back(const Attr & attr)
71 {
72 assert(size_ < capacity_);
73 attrs[size_++] = attr;
74 }
75
76 iterator find(Symbol name)
77 {
78 Attr key(name, 0);
79 iterator i = std::lower_bound(begin(), end(), key);
80 if (i != end() && i->name == name) return i;
81 return end();
82 }
83
84 Attr * get(Symbol name)
85 {
86 Attr key(name, 0);
87 iterator i = std::lower_bound(begin(), end(), key);
88 if (i != end() && i->name == name) return &*i;
89 return nullptr;
90 }
91
92 iterator begin() { return &attrs[0]; }
93 iterator end() { return &attrs[size_]; }
94
95 Attr & operator[](Size pos)
96 {
97 return attrs[pos];
98 }
99
100 void sort();
101
102 Size capacity() { return capacity_; }
103
107 std::vector<const Attr *> lexicographicOrder(const SymbolTable & symbols) const
108 {
109 std::vector<const Attr *> res;
110 res.reserve(size_);
111 for (Size n = 0; n < size_; n++)
112 res.emplace_back(&attrs[n]);
113 std::sort(res.begin(), res.end(), [&](const Attr * a, const Attr * b) {
114 std::string_view sa = symbols[a->name], sb = symbols[b->name];
115 return sa < sb;
116 });
117 return res;
118 }
119
120 friend class EvalMemory;
121};
122
129{
130 Bindings * bindings;
131 EvalMemory & mem;
132 SymbolTable & symbols;
133
134public:
135 // needed by std::back_inserter
136 using value_type = Attr;
137
138 BindingsBuilder(EvalMemory & mem, SymbolTable & symbols, Bindings * bindings)
139 : bindings(bindings)
140 , mem(mem)
141 , symbols(symbols)
142 { }
143
144 void insert(Symbol name, Value * value, PosIdx pos = noPos)
145 {
146 insert(Attr(name, value, pos));
147 }
148
149 void insert(const Attr & attr)
150 {
151 push_back(attr);
152 }
153
154 void push_back(const Attr & attr)
155 {
156 bindings->push_back(attr);
157 }
158
159 Value & alloc(Symbol name, PosIdx pos = noPos);
160
161 Value & alloc(std::string_view name, PosIdx pos = noPos);
162
163 Bindings * finish()
164 {
165 bindings->sort();
166 return bindings;
167 }
168
169 Bindings * alreadySorted()
170 {
171 return bindings;
172 }
173};
174
175}
Definition attr-set.hh:129
Definition attr-set.hh:49
std::vector< const Attr * > lexicographicOrder(const SymbolTable &symbols) const
Definition attr-set.hh:107
Definition eval.hh:232
Definition pos-idx.hh:9
Definition symbol-table.hh:75
Definition symbol-table.hh:52
Definition attr-set.hh:20
Definition value.hh:191