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-08-04T10·59+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2004-08-04T10·59+0000
commitbbfdd64741546863c2412d780097b1fe2457395e (patch)
tree198309fd082893cfbb24f5dd044e53d1723a2b6b /src/libexpr/eval.cc
parente3a50f7e25c552a78974fae684484d27a36b7c60 (diff)
* Allow primops with more that 1 arguments.
Diffstat (limited to 'src/libexpr/eval.cc')
-rw-r--r--src/libexpr/eval.cc81
1 files changed, 37 insertions, 44 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index af0ab913cae1..37677d3cb093 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -1,20 +1,5 @@
 #include "eval.hh"
 #include "parser.hh"
-#include "primops.hh"
-
-
-static void addPrimOp(ATermMap & map, const string & name, void * f)
-{
-    map.set(name, (ATerm) ATmakeBlob(0, f));
-}
-
-
-static void * lookupPrimOp(ATermMap & map, ATerm name)
-{
-    ATermBlob b = (ATermBlob) map.get(name);
-    if (!b) return 0;
-    return ATgetBlobData(b);
-}
 
 
 EvalState::EvalState()
@@ -25,30 +10,15 @@ EvalState::EvalState()
     
     nrEvaluated = nrCached = 0;
 
-    addPrimOp0("true", primTrue);
-    addPrimOp0("false", primFalse);
-    addPrimOp0("null", primNull);
-
-    addPrimOp1("import", primImport);
-    addPrimOp1("derivation", primDerivation);
-    addPrimOp1("baseNameOf", primBaseNameOf);
-    addPrimOp1("toString", primToString);
-    addPrimOp1("isNull", primIsNull);
-
-    primOpsAll.add(primOps0);
-    primOpsAll.add(primOps1);
-}
-
-
-void EvalState::addPrimOp0(const string & name, PrimOp0 primOp)
-{
-    addPrimOp(primOps0, name, (void *) primOp);
+    addPrimOps();
 }
 
 
-void EvalState::addPrimOp1(const string & name, PrimOp1 primOp)
+void EvalState::addPrimOp(const string & name,
+    unsigned int arity, PrimOp primOp)
 {
-    addPrimOp(primOps1, name, (void *) primOp);
+    primOps.set(name, ATmake("(<int>, <term>)",
+        arity, ATmakeBlob(0, (void *) primOp)));
 }
 
 
@@ -200,7 +170,8 @@ Expr evalExpr2(EvalState & state, Expr e)
          cons == "Function" ||
          cons == "Function1" ||
          cons == "Attrs" ||
-         cons == "List"))
+         cons == "List" ||
+         cons == "PrimOp"))
         return e;
 
     /* The `Closed' constructor is just a way to prevent substitutions
@@ -208,13 +179,21 @@ Expr evalExpr2(EvalState & state, Expr e)
     if (atMatch(m, e) >> "Closed" >> e1)
         return evalExpr(state, e1);
 
-    /* Any encountered variables must be undeclared or primops. */
+    /* Any encountered variables must be primops (since undefined
+       variables are detected after parsing). */
     if (atMatch(m, e) >> "Var" >> name) {
-        PrimOp0 primOp = (PrimOp0) lookupPrimOp(state.primOps0, name);
-        if (primOp)
-            return primOp(state);
+        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();
+        if (arity == 0)
+            return ((PrimOp) ATgetBlobData((ATermBlob) fun))
+                (state, ATermVector());
         else
-            return e;
+            return ATmake("PrimOp(<int>, <term>, <term>)",
+                arity, fun, ATempty);
     }
 
     /* Function application. */
@@ -227,9 +206,23 @@ Expr evalExpr2(EvalState & state, Expr e)
         e1 = evalExpr(state, e1);
 
         /* Is it a primop or a function? */
-        if (atMatch(m, e1) >> "Var" >> name) {
-            PrimOp1 primOp = (PrimOp1) lookupPrimOp(state.primOps1, name);
-            if (primOp) return primOp(state, e2); else abort();
+        int arity;
+        ATerm fun;
+        ATermList args;
+        if (atMatch(m, e1) >> "PrimOp" >> arity >> fun >> args) {
+            args = ATinsert(args, e2);
+            if (ATgetLength(args) == arity) {
+                /* Put the arguments in a vector in reverse (i.e.,
+                   actual) order. */
+                ATermVector args2(arity);
+                for (ATermIterator i(args); i; ++i)
+                    args2[--arity] = *i;
+                return ((PrimOp) ATgetBlobData((ATermBlob) fun))
+                    (state, args2);
+            } else
+                /* Need more arguments, so propagate the primop. */
+                return ATmake("PrimOp(<int>, <term>, <list>)",
+                    arity, fun, args);
         }
 
         else if (atMatch(m, e1) >> "Function" >> formals >> e4 >> pos) {