aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/eval.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/libexpr/eval.hh')
-rw-r--r--src/libexpr/eval.hh152
1 files changed, 142 insertions, 10 deletions
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index fed6d3472..8ca997f14 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -11,7 +11,101 @@ namespace nix {
class Hash;
-
+class EvalState;
+struct Env;
+struct Value;
+
+typedef ATerm Sym;
+
+typedef std::map<Sym, Value> Bindings;
+
+
+struct Env
+{
+ Env * up;
+ Bindings bindings;
+};
+
+
+typedef enum {
+ tInt = 1,
+ tBool,
+ tString,
+ tPath,
+ tNull,
+ tAttrs,
+ tList,
+ tThunk,
+ tLambda,
+ tCopy,
+ tBlackhole,
+ tPrimOp,
+ tPrimOpApp,
+} ValueType;
+
+
+typedef void (* PrimOp) (EvalState & state, Value * * args, Value & v);
+
+
+struct Value
+{
+ ValueType type;
+ union
+ {
+ int integer;
+ bool boolean;
+ struct {
+ const char * s;
+ const char * * context;
+ } string;
+ Bindings * attrs;
+ struct {
+ unsigned int length;
+ Value * elems;
+ } list;
+ struct {
+ Env * env;
+ Expr expr;
+ } thunk;
+ struct {
+ Env * env;
+ Pattern pat;
+ Expr body;
+ } lambda;
+ Value * val;
+ struct {
+ PrimOp fun;
+ unsigned int arity;
+ } primOp;
+ struct {
+ Value * left, * right;
+ unsigned int argsLeft;
+ } primOpApp;
+ };
+};
+
+
+static inline void mkInt(Value & v, int n)
+{
+ v.type = tInt;
+ v.integer = n;
+}
+
+
+static inline void mkBool(Value & v, bool b)
+{
+ v.type = tBool;
+ v.boolean = b;
+}
+
+
+static inline void mkString(Value & v, const char * s)
+{
+ v.type = tString;
+ v.string.s = s;
+ v.string.context = 0;
+}
+
typedef std::map<Path, PathSet> DrvRoots;
typedef std::map<Path, Hash> DrvHashes;
@@ -22,32 +116,69 @@ typedef std::map<Path, Path> SrcToStore;
struct EvalState;
-/* Note: using a ATermVector is safe here, since when we call a primop
- we also have an ATermList on the stack. */
-typedef Expr (* PrimOp) (EvalState &, const ATermVector & args);
+
+std::ostream & operator << (std::ostream & str, Value & v);
struct EvalState
{
- ATermMap normalForms;
- ATermMap primOps;
DrvRoots drvRoots;
DrvHashes drvHashes; /* normalised derivation hashes */
SrcToStore srcToStore;
- unsigned int nrEvaluated;
- unsigned int nrCached;
+ unsigned long nrValues;
+ unsigned long nrEnvs;
+ unsigned long nrEvaluated;
bool allowUnsafeEquality;
EvalState();
- void addPrimOps();
+ /* Evaluate an expression to normal form, storing the result in
+ value `v'. */
+ void eval(Expr e, Value & v);
+ void eval(Env & env, Expr e, Value & v);
+
+ /* Evaluation the expression, then verify that it has the expected
+ type. */
+ bool evalBool(Env & env, Expr e);
+
+ /* Evaluate an expression, and recursively evaluate list elements
+ and attributes. */
+ void strictEval(Expr e, Value & v);
+ void strictEval(Env & env, Expr e, Value & v);
+
+ /* If `v' is a thunk, enter it and overwrite `v' with the result
+ of the evaluation of the thunk. Otherwise, this is a no-op. */
+ void forceValue(Value & v);
+
+ /* Force `v', and then verify that it has the expected type. */
+ int forceInt(Value & v);
+ void forceAttrs(Value & v);
+ void forceList(Value & v);
+
+private:
+
+ /* The base environment, containing the builtin functions and
+ values. */
+ Env & baseEnv;
+
+ void createBaseEnv();
+
void addPrimOp(const string & name,
unsigned int arity, PrimOp primOp);
+
+ /* Do a deep equality test between two values. That is, list
+ elements and attributes are compared recursively. */
+ bool eqValues(Value & v1, Value & v2);
+
+ /* Allocation primitives. */
+ Value * allocValues(unsigned int count);
+ Env & allocEnv();
};
+#if 0
/* Evaluate an expression to normal form. */
Expr evalExpr(EvalState & state, Expr e);
@@ -86,11 +217,12 @@ Path coerceToPath(EvalState & state, Expr e, PathSet & context);
value or has a binding in the `args' map. Note: result is a call,
not a normal form; it should be evaluated by calling evalExpr(). */
Expr autoCallFunction(Expr e, const ATermMap & args);
+#endif
/* Print statistics. */
void printEvalStats(EvalState & state);
-
+
}