about summary refs log tree commit diff
path: root/src/libexpr/eval.cc
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2004-10-26T22·54+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2004-10-26T22·54+0000
commit5fe9222b36ad49d74c84edb04d6bc4a7d844be01 (patch)
treee46926a3d60274e5b2dc9e6090df2804986292b0 /src/libexpr/eval.cc
parenteb8284ddaa66448d369647f68cb9f89b93a187de (diff)
* Don't use ATmake / ATmatch anymore, nor the ATMatcher class.
  Instead we generate data bindings (build and match functions) for
  the constructors specified in `constructors.def'.  In particular
  this removes the conversions between AFuns and strings, and Nix
  expression evaluation now seems 3 to 4 times faster.

Diffstat (limited to 'src/libexpr/eval.cc')
-rw-r--r--src/libexpr/eval.cc160
1 files changed, 72 insertions, 88 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 35b9cae00b..88362333c2 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -1,15 +1,17 @@
 #include "eval.hh"
 #include "parser.hh"
+#include "constructors.hh"
 
 
 EvalState::EvalState()
     : normalForms(32768, 50)
 {
-    blackHole = ATmake("BlackHole()");
-    if (!blackHole) throw Error("cannot build black hole");
+    blackHole = makeBlackHole();
     
     nrEvaluated = nrCached = 0;
 
+    initSyms();
+
     addPrimOps();
 }
 
@@ -17,24 +19,22 @@ EvalState::EvalState()
 void EvalState::addPrimOp(const string & name,
     unsigned int arity, PrimOp primOp)
 {
-    primOps.set(name, ATmake("(<int>, <term>)",
-        arity, ATmakeBlob(0, (void *) primOp)));
+    primOps.set(name, makePrimOpDef(arity, ATmakeBlob(0, (void *) primOp)));
 }
 
 
 /* Substitute an argument set into the body of a function. */
 static Expr substArgs(Expr body, ATermList formals, Expr arg)
 {
-    ATMatcher m;
     ATermMap subs;
-    Expr undefined = ATmake("Undefined");
+    Expr undefined = makeUndefined();
 
     /* Get the formal arguments. */
     for (ATermIterator i(formals); i; ++i) {
         Expr name, def;
-        if (atMatch(m, *i) >> "NoDefFormal" >> name)
+        if (matchNoDefFormal(*i, name))
             subs.set(name, undefined);
-        else if (atMatch(m, *i) >> "DefFormal" >> name >> def)
+        else if (matchDefFormal(*i, name, def))
             subs.set(name, def);
         else abort(); /* can't happen */
     }
@@ -69,38 +69,32 @@ static Expr substArgs(Expr body, ATermList formals, Expr arg)
    (e.x) (e.y); y = e.x;}'. */
 ATerm expandRec(ATerm e, ATermList rbnds, ATermList nrbnds)
 {
-    ATMatcher m;
     ATerm name;
     Expr e2;
+    Pos pos;
 
     /* Create the substitution list. */
     ATermMap subs;
     for (ATermIterator i(rbnds); i; ++i) {
-        if (!(atMatch(m, *i) >> "Bind" >> name >> e2))
-            abort(); /* can't happen */
-        subs.set(name, ATmake("Select(<term>, <term>)", e, name));
+        if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */
+        subs.set(name, makeSelect(e, name));
     }
     for (ATermIterator i(nrbnds); i; ++i) {
-        if (!(atMatch(m, *i) >> "Bind" >> name >> e2))
-            abort(); /* can't happen */
+        if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */
         subs.set(name, e2);
     }
 
     /* Create the non-recursive set. */
     ATermMap as;
     for (ATermIterator i(rbnds); i; ++i) {
-        ATerm pos;
-        if (!(atMatch(m, *i) >> "Bind" >> name >> e2 >> pos))
-            abort(); /* can't happen */
-        as.set(name, ATmake("(<term>, <term>)", substitute(subs, e2), pos));
+        if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */
+        as.set(name, makeAttrRHS(substitute(subs, e2), pos));
     }
 
     /* Copy the non-recursive bindings.  !!! inefficient */
     for (ATermIterator i(nrbnds); i; ++i) {
-        ATerm pos;
-        if (!(atMatch(m, *i) >> "Bind" >> name >> e2 >> pos))
-            abort(); /* can't happen */
-        as.set(name, ATmake("(<term>, <term>)", e2, pos));
+        if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */
+        as.set(name, makeAttrRHS(e2, pos));
     }
 
     return makeAttrs(as);
@@ -122,82 +116,73 @@ static Expr updateAttrs(Expr e1, Expr e2)
 string evalString(EvalState & state, Expr e)
 {
     e = evalExpr(state, e);
-    ATMatcher m;
-    string s;
-    if (!(atMatch(m, e) >> "Str" >> s))
-        throw Error("string expected");
-    return s;
+    ATerm s;
+    if (!matchStr(e, s)) throw Error("string expected");
+    return aterm2String(s);
 }
 
 
 Path evalPath(EvalState & state, Expr e)
 {
     e = evalExpr(state, e);
-    ATMatcher m;
-    string s;
-    if (!(atMatch(m, e) >> "Path" >> s))
-        throw Error("path expected");
-    return s;
+    ATerm s;
+    if (!matchPath(e, s)) throw Error("path expected");
+    return aterm2String(s);
 }
 
 
 bool evalBool(EvalState & state, Expr e)
 {
     e = evalExpr(state, e);
-    ATMatcher m;
-    if (atMatch(m, e) >> "Bool" >> "True") return true;
-    else if (atMatch(m, e) >> "Bool" >> "False") return false;
+    if (e == eTrue) return true;
+    else if (e == eFalse) return false;
     else throw Error("boolean expected");
 }
 
 
 Expr evalExpr2(EvalState & state, Expr e)
 {
-    ATMatcher m;
     Expr e1, e2, e3, e4;
     ATerm name, pos;
+    AFun sym = ATgetAFun(e);
 
     /* Normal forms. */
-    string cons;
-    if (atMatch(m, e) >> cons &&
-        (cons == "Str" ||
-         cons == "Path" ||
-         cons == "SubPath" ||
-         cons == "Uri" ||
-         cons == "Null" ||
-         cons == "Int" ||
-         cons == "Bool" ||
-         cons == "Function" ||
-         cons == "Function1" ||
-         cons == "Attrs" ||
-         cons == "List" ||
-         cons == "PrimOp"))
+    if (sym == symStr ||
+        sym == symPath ||
+        sym == symSubPath ||
+        sym == symUri ||
+        sym == symNull ||
+        sym == symInt ||
+        sym == symBool ||
+        sym == symFunction ||
+        sym == symFunction1 ||
+        sym == symAttrs ||
+        sym == symList ||
+        sym == symPrimOp)
         return e;
-
+    
     /* The `Closed' constructor is just a way to prevent substitutions
        into expressions not containing free variables. */
-    if (atMatch(m, e) >> "Closed" >> e1)
+    if (matchClosed(e, e1))
         return evalExpr(state, e1);
 
     /* Any encountered variables must be primops (since undefined
        variables are detected after parsing). */
-    if (atMatch(m, e) >> "Var" >> name) {
+    if (matchVar(e, name)) {
         ATerm primOp = state.primOps.get(name);
         if (!primOp)
             throw Error(format("impossible: undefined variable `%1%'") % name);
         int arity;
-        ATerm fun;
-        if (!(atMatch(m, primOp) >> "" >> arity >> fun)) abort();
+        ATermBlob fun;
+        if (!matchPrimOpDef(primOp, arity, fun)) abort();
         if (arity == 0)
-            return ((PrimOp) ATgetBlobData((ATermBlob) fun))
-                (state, ATermVector());
+            return ((PrimOp) ATgetBlobData(fun)) (state, ATermVector());
         else
-            return ATmake("PrimOp(<int>, <term>, <term>)",
-                arity, fun, ATempty);
+            return makePrimOp(arity, fun, ATempty);
     }
 
     /* Function application. */
-    if (atMatch(m, e) >> "Call" >> e1 >> e2) {
+    if (matchCall(e, e1, e2)) {
 
         ATermList formals;
         ATerm pos;
@@ -207,9 +192,9 @@ Expr evalExpr2(EvalState & state, Expr e)
 
         /* Is it a primop or a function? */
         int arity;
-        ATerm fun;
+        ATermBlob fun;
         ATermList args;
-        if (atMatch(m, e1) >> "PrimOp" >> arity >> fun >> args) {
+        if (matchPrimOp(e1, arity, fun, args)) {
             args = ATinsert(args, e2);
             if (ATgetLength(args) == arity) {
                 /* Put the arguments in a vector in reverse (i.e.,
@@ -221,11 +206,10 @@ Expr evalExpr2(EvalState & state, Expr e)
                     (state, args2);
             } else
                 /* Need more arguments, so propagate the primop. */
-                return ATmake("PrimOp(<int>, <term>, <term>)",
-                    arity, fun, args);
+                return makePrimOp(arity, fun, args);
         }
 
-        else if (atMatch(m, e1) >> "Function" >> formals >> e4 >> pos) {
+        else if (matchFunction(e1, formals, e4, pos)) {
             e2 = evalExpr(state, e2);
             try {
                 return evalExpr(state, substArgs(e4, formals, e2));
@@ -235,7 +219,7 @@ Expr evalExpr2(EvalState & state, Expr e)
             }
         }
         
-        else if (atMatch(m, e1) >> "Function1" >> name >> e4 >> pos) {
+        else if (matchFunction1(e1, name, e4, pos)) {
             try {
                 ATermMap subs;
                 subs.set(name, e2);
@@ -250,9 +234,9 @@ Expr evalExpr2(EvalState & state, Expr e)
     }
 
     /* Attribute selection. */
-    string s1;
-    if (atMatch(m, e) >> "Select" >> e1 >> s1) {
+    if (matchSelect(e, e1, name)) {
         ATerm pos;
+        string s1 = aterm2String(name);
         Expr a = queryAttr(evalExpr(state, e1), s1, pos);
         if (!a) throw Error(format("attribute `%1%' missing") % s1);
         try {
@@ -265,11 +249,11 @@ Expr evalExpr2(EvalState & state, Expr e)
 
     /* Mutually recursive sets. */
     ATermList rbnds, nrbnds;
-    if (atMatch(m, e) >> "Rec" >> rbnds >> nrbnds)
+    if (matchRec(e, rbnds, nrbnds))
         return expandRec(e, rbnds, nrbnds);
 
     /* Conditionals. */
-    if (atMatch(m, e) >> "If" >> e1 >> e2 >> e3) {
+    if (matchIf(e, e1, e2, e3)) {
         if (evalBool(state, e1))
             return evalExpr(state, e2);
         else
@@ -277,14 +261,14 @@ Expr evalExpr2(EvalState & state, Expr e)
     }
 
     /* Assertions. */
-    if (atMatch(m, e) >> "Assert" >> e1 >> e2 >> pos) {
+    if (matchAssert(e, e1, e2, pos)) {
         if (!evalBool(state, e1))
             throw Error(format("assertion failed at %1%") % showPos(pos));
         return evalExpr(state, e2);
     }
 
     /* Withs. */
-    if (atMatch(m, e) >> "With" >> e1 >> e2 >> pos) {
+    if (matchWith(e, e1, e2, pos)) {
         ATermMap attrs;
         try {
             e1 = evalExpr(state, e1);
@@ -304,51 +288,51 @@ Expr evalExpr2(EvalState & state, Expr e)
     }
 
     /* Generic equality. */
-    if (atMatch(m, e) >> "OpEq" >> e1 >> e2)
+    if (matchOpEq(e, e1, e2))
         return makeBool(evalExpr(state, e1) == evalExpr(state, e2));
 
     /* Generic inequality. */
-    if (atMatch(m, e) >> "OpNEq" >> e1 >> e2)
+    if (matchOpNEq(e, e1, e2))
         return makeBool(evalExpr(state, e1) != evalExpr(state, e2));
 
     /* Negation. */
-    if (atMatch(m, e) >> "OpNot" >> e1)
+    if (matchOpNot(e, e1))
         return makeBool(!evalBool(state, e1));
 
     /* Implication. */
-    if (atMatch(m, e) >> "OpImpl" >> e1 >> e2)
+    if (matchOpImpl(e, e1, e2))
         return makeBool(!evalBool(state, e1) || evalBool(state, e2));
 
     /* Conjunction (logical AND). */
-    if (atMatch(m, e) >> "OpAnd" >> e1 >> e2)
+    if (matchOpAnd(e, e1, e2))
         return makeBool(evalBool(state, e1) && evalBool(state, e2));
 
     /* Disjunction (logical OR). */
-    if (atMatch(m, e) >> "OpOr" >> e1 >> e2)
+    if (matchOpOr(e, e1, e2))
         return makeBool(evalBool(state, e1) || evalBool(state, e2));
 
     /* Attribute set update (//). */
-    if (atMatch(m, e) >> "OpUpdate" >> e1 >> e2)
+    if (matchOpUpdate(e, e1, e2))
         return updateAttrs(evalExpr(state, e1), evalExpr(state, e2));
 
     /* Attribute existence test (?). */
-    if (atMatch(m, e) >> "OpHasAttr" >> e1 >> name) {
+    if (matchOpHasAttr(e, e1, name)) {
         ATermMap attrs;
         queryAllAttrs(evalExpr(state, e1), attrs);
         return makeBool(attrs.get(name) != 0);
     }
 
     /* String or path concatenation. */
-    if (atMatch(m, e) >> "OpPlus" >> e1 >> e2) {
+    if (matchOpPlus(e, e1, e2)) {
         e1 = evalExpr(state, e1);
         e2 = evalExpr(state, e2);
-        string s1, s2;
-        if (atMatch(m, e1) >> "Str" >> s1 &&
-            atMatch(m, e2) >> "Str" >> s2)
-            return makeString(s1 + s2);
-        else if (atMatch(m, e1) >> "Path" >> s1 &&
-            atMatch(m, e2) >> "Path" >> s2)
-            return makePath(canonPath(s1 + "/" + s2));
+        ATerm s1, s2;
+        if (matchStr(e1, s1) && matchStr(e2, s2))
+            return makeStr(string2ATerm((
+                (string) aterm2String(s1) + (string) aterm2String(s2)).c_str()));
+        else if (matchPath(e1, s1) && matchPath(e2, s2))
+            return makePath(string2ATerm(canonPath(
+                (string) aterm2String(s1) + "/" + (string) aterm2String(s2)).c_str()));
         else throw Error("wrong argument types in `+' operator");
     }