diff --git a/src/libexpr/attr-set.cc b/src/libexpr/attr-set.cc new file mode 100644 index 000000000..9ac5e6031 --- /dev/null +++ b/src/libexpr/attr-set.cc @@ -0,0 +1,59 @@ +#include "attr-set.hh" +#include "eval.hh" + +#include + + +namespace nix { + + +static void * allocBytes(size_t n) +{ + void * p; +#if HAVE_BOEHMGC + p = GC_malloc(n); +#else + p = malloc(n); +#endif + if (!p) throw std::bad_alloc(); + return p; +} + + +/* Allocate a new array of attributes for an attribute set with a specific + capacity. The space is implicitly reserved after the Bindings + structure. */ +Bindings * EvalState::allocBindings(Bindings::size_t capacity) +{ + return new (allocBytes(sizeof(Bindings) + sizeof(Attr) * capacity)) Bindings(capacity); +} + + +void EvalState::mkAttrs(Value & v, unsigned int expected) +{ + clearValue(v); + v.type = tAttrs; + v.attrs = allocBindings(expected); + nrAttrsets++; + nrAttrsInAttrsets += expected; +} + + +/* Create a new attribute named 'name' on an existing attribute set stored + in 'vAttrs' and return the newly allocated Value which is associated with + this attribute. */ +Value * EvalState::allocAttr(Value & vAttrs, const Symbol & name) +{ + Value * v = allocValue(); + vAttrs.attrs->push_back(Attr(name, v)); + return v; +} + + +void Bindings::sort() +{ + std::sort(begin(), end()); +} + + +} diff --git a/src/libexpr/attr-set.hh b/src/libexpr/attr-set.hh new file mode 100644 index 000000000..7cf6a9c58 --- /dev/null +++ b/src/libexpr/attr-set.hh @@ -0,0 +1,82 @@ +#pragma once + +#include "nixexpr.hh" +#include "symbol-table.hh" + +#include + +namespace nix { + + +class EvalState; +struct Value; + +/* Map one attribute name to its value. */ +struct Attr +{ + Symbol name; + Value * value; + Pos * pos; + Attr(Symbol name, Value * value, Pos * pos = &noPos) + : name(name), value(value), pos(pos) { }; + Attr() : pos(&noPos) { }; + bool operator < (const Attr & a) const + { + return name < a.name; + } +}; + +/* Bindings contains all the attributes of an attribute set. It is defined + by its size and its capacity, the capacity being the number of Attr + elements allocated after this structure, while the size corresponds to + the number of elements already inserted in this structure. */ +class Bindings +{ +public: + typedef uint32_t size_t; + +private: + size_t size_, capacity_; + Attr attrs[0]; + + Bindings(size_t capacity) : size_(0), capacity_(capacity) { } + Bindings(const Bindings & bindings) = delete; + +public: + size_t size() const { return size_; } + + bool empty() const { return !size_; } + + typedef Attr * iterator; + + void push_back(const Attr & attr) + { + assert(size_ < capacity_); + attrs[size_++] = attr; + } + + iterator find(const Symbol & name) + { + Attr key(name, 0); + iterator i = std::lower_bound(begin(), end(), key); + if (i != end() && i->name == name) return i; + return end(); + } + + iterator begin() { return &attrs[0]; } + iterator end() { return &attrs[size_]; } + + Attr & operator[](size_t pos) + { + return attrs[pos]; + } + + void sort(); + + size_t capacity() { return capacity_; } + + friend class EvalState; +}; + + +} diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index d61ee7e80..eab38c9da 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -55,12 +55,6 @@ static void * allocBytes(size_t n) } -void Bindings::sort() -{ - std::sort(begin(), end()); -} - - static void printValue(std::ostream & str, std::set & active, const Value & v) { if (active.find(&v) != active.end()) { @@ -503,20 +497,6 @@ Env & EvalState::allocEnv(unsigned int size) } -Value * EvalState::allocAttr(Value & vAttrs, const Symbol & name) -{ - Value * v = allocValue(); - vAttrs.attrs->push_back(Attr(name, v)); - return v; -} - - -Bindings * EvalState::allocBindings(Bindings::size_t capacity) -{ - return new (allocBytes(sizeof(Bindings) + sizeof(Attr) * capacity)) Bindings(capacity); -} - - void EvalState::mkList(Value & v, unsigned int length) { clearValue(v); @@ -527,16 +507,6 @@ void EvalState::mkList(Value & v, unsigned int length) } -void EvalState::mkAttrs(Value & v, unsigned int expected) -{ - clearValue(v); - v.type = tAttrs; - v.attrs = allocBindings(expected); - nrAttrsets++; - nrAttrsInAttrsets += expected; -} - - unsigned long nrThunks = 0; static inline void mkThunk(Value & v, Env & env, Expr * expr) diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 627fae3ff..1b546f89c 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -1,5 +1,6 @@ #pragma once +#include "attr-set.hh" #include "value.hh" #include "nixexpr.hh" #include "symbol-table.hh" @@ -18,70 +19,6 @@ namespace nix { class EvalState; -struct Attr -{ - Symbol name; - Value * value; - Pos * pos; - Attr(Symbol name, Value * value, Pos * pos = &noPos) - : name(name), value(value), pos(pos) { }; - Attr() : pos(&noPos) { }; - bool operator < (const Attr & a) const - { - return name < a.name; - } -}; - - -class Bindings -{ -public: - typedef uint32_t size_t; - -private: - size_t size_, capacity_; - Attr attrs[0]; - - Bindings(size_t capacity) : size_(0), capacity_(capacity) { } - Bindings(const Bindings & bindings) = delete; - -public: - size_t size() const { return size_; } - - bool empty() const { return !size_; } - - typedef Attr * iterator; - - void push_back(const Attr & attr) - { - assert(size_ < capacity_); - attrs[size_++] = attr; - } - - iterator find(const Symbol & name) - { - Attr key(name, 0); - iterator i = std::lower_bound(begin(), end(), key); - if (i != end() && i->name == name) return i; - return end(); - } - - iterator begin() { return &attrs[0]; } - iterator end() { return &attrs[size_]; } - - Attr & operator[](size_t pos) - { - return attrs[pos]; - } - - void sort(); - - size_t capacity() { return capacity_; } - - friend class EvalState; -}; - - typedef void (* PrimOpFun) (EvalState & state, const Pos & pos, Value * * args, Value & v);