about summary refs log tree commit diff
path: root/src/libexpr/nixexpr.hh
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2010-04-14T14·42+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2010-04-14T14·42+0000
commit9985230c00226826949473c3862c0c3afea74aaf (patch)
treed221b96649f2a134cce366efdfc5685145567aa2 /src/libexpr/nixexpr.hh
parent816dd3f0612111718c338842283c1ee6577b9f0a (diff)
* After parsing, compute level/displacement pairs for each variable
  use site, allowing environments to be stores as vectors of values
  rather than maps.  This should speed up evaluation and reduce the
  number of allocations.

Diffstat (limited to 'src/libexpr/nixexpr.hh')
-rw-r--r--src/libexpr/nixexpr.hh48
1 files changed, 39 insertions, 9 deletions
diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh
index 0e595a1b168d..0422e5cf4638 100644
--- a/src/libexpr/nixexpr.hh
+++ b/src/libexpr/nixexpr.hh
@@ -17,25 +17,29 @@ MakeError(Abort, EvalError)
 MakeError(TypeError, EvalError)
 
 
+/* Position objects. */
+
 struct Pos
 {
     string file;
     unsigned int line, column;
 };
 
-
 std::ostream & operator << (std::ostream & str, const Pos & pos);
 
 
-/* Abstract syntax of Nix expressions. */
-
 struct Env;
 struct Value;
 struct EvalState;
+struct StaticEnv;
+
+
+/* Abstract syntax of Nix expressions. */
 
 struct Expr
 {
     virtual void show(std::ostream & str);
+    virtual void bindVars(const StaticEnv & env);
     virtual void eval(EvalState & state, Env & env, Value & v);
 };
 
@@ -43,7 +47,8 @@ std::ostream & operator << (std::ostream & str, Expr & e);
 
 #define COMMON_METHODS \
     void show(std::ostream & str); \
-    void eval(EvalState & state, Env & env, Value & v);
+    void eval(EvalState & state, Env & env, Value & v); \
+    void bindVars(const StaticEnv & env);
 
 struct ExprInt : Expr
 {
@@ -76,6 +81,20 @@ struct ExprPath : Expr
 struct ExprVar : Expr
 {
     Symbol name;
+
+    /* Whether the variable comes from an environment (e.g. a rec, let
+       or function argument) or from a "with". */
+    bool fromWith;
+    
+    /* In the former case, the value is obtained by going `level'
+       levels up from the current environment and getting the
+       `displ'th value in that environment.  In the latter case, the
+       value is obtained by getting the attribute named `name' from
+       the attribute set stored in the environment that is `level'
+       levels up from the current one.*/
+    unsigned int level;
+    unsigned int displ;
+    
     ExprVar(const Symbol & name) : name(name) { };
     COMMON_METHODS
 };
@@ -186,6 +205,10 @@ struct ExprOpNot : Expr
         { \
             str << *e1 << " " s " " << *e2; \
         } \
+        void bindVars(const StaticEnv & env) \
+        { \
+            e1->bindVars(env); e2->bindVars(env); \
+        } \
         void eval(EvalState & state, Env & env, Value & v); \
     };
 
@@ -206,11 +229,18 @@ struct ExprConcatStrings : Expr
 };
 
 
-#if 0
-/* Check whether all variables are defined in the given expression.
-   Throw an exception if this isn't the case. */
-void checkVarDefs(const ATermMap & def, Expr e);
-#endif
+/* Static environments are used to map variable names onto (level,
+   displacement) pairs used to obtain the value of the variable at
+   runtime. */
+struct StaticEnv
+{
+    bool isWith;
+    const StaticEnv * up;
+    typedef std::map<Symbol, unsigned int> Vars;
+    Vars vars;
+    StaticEnv(bool isWith, const StaticEnv * up) : isWith(isWith), up(up) { };
+};
+
 
 
 }