diff options
Diffstat (limited to 'src/libexpr/eval.cc')
-rw-r--r-- | src/libexpr/eval.cc | 160 |
1 files changed, 72 insertions, 88 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 35b9cae00b7c..88362333c29d 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"); } |