about summary refs log blame commit diff
path: root/src/libexpr/eval.hh
blob: 4706602d59fa2a0db313764e558b3c45ff1c4a57 (plain) (tree)
1
2
3
4
5
6
7
8
9




                
                   
                     

 



               














































                                                                       
                          















































                                                      
 






                                                    

                                         
 

                                                                  
                                        
 
                 
 

                                                           

 

                 
                      
                                                           
                           
 


                              
 

                             
                
 



                                                                






















                                                                      











                                                                         







                                                                 

                                           







                                                                 


  
     


                                            
                                                                     


                                                                
                                               
 
                       

                                                                
                                       
                                         
                                              
 



                                                                      
                                                                      


                                                                      
      
 


                                       
 

 

                      
#ifndef __EVAL_H
#define __EVAL_H

#include <map>

#include "aterm.hh"
#include "nixexpr.hh"


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;
        const char * path;
        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;
}


static inline void mkPath(Value & v, const char * s)
{
    v.type = tPath;
    v.path = s;
}


typedef std::map<Path, PathSet> DrvRoots;
typedef std::map<Path, Hash> DrvHashes;

/* Cache for calls to addToStore(); maps source paths to the store
   paths. */
typedef std::map<Path, Path> SrcToStore;

struct EvalState;


std::ostream & operator << (std::ostream & str, Value & v);


struct EvalState 
{
    DrvRoots drvRoots;
    DrvHashes drvHashes; /* normalised derivation hashes */
    SrcToStore srcToStore; 

    unsigned long nrValues;
    unsigned long nrEnvs;
    unsigned long nrEvaluated;

    bool allowUnsafeEquality;

    EvalState();

    /* Evaluate an expression read from the given file to normal
       form. */
    void evalFile(const Path & path, Value & v);

    /* 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);

    /* String coercion.  Converts strings, paths and derivations to a
       string.  If `coerceMore' is set, also converts nulls, integers,
       booleans and lists to a string.  If `copyToStore' is set,
       referenced paths are copied to the Nix store as a side effect.q */
    string coerceToString(Value & v, PathSet & context,
        bool coerceMore = false, bool copyToStore = true);

    /* Path coercion.  Converts strings, paths and derivations to a
       path.  The result is guaranteed to be a canonicalised, absolute
       path.  Nothing is copied to the store. */
    Path coerceToPath(Value & v, PathSet & context);

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);

/* Evaluate an expression, and recursively evaluate list elements and
   attributes.  If `canonicalise' is true, we remove things like
   position information and make sure that attribute sets are in
   sorded order. */
Expr strictEvalExpr(EvalState & state, Expr e);

/* Specific results. */
string evalString(EvalState & state, Expr e, PathSet & context);
string evalStringNoCtx(EvalState & state, Expr e);
int evalInt(EvalState & state, Expr e);
bool evalBool(EvalState & state, Expr e);
ATermList evalList(EvalState & state, Expr e);

/* Flatten nested lists into a single list (or expand a singleton into
   a list). */
ATermList flattenList(EvalState & state, Expr e);

/* Automatically call a function for which each argument has a default
   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);


}


#endif /* !__EVAL_H */