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