From fa18f1f184ba89b3dfe592e77a276da42d326f42 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 5 Nov 2003 16:27:40 +0000 Subject: [PATCH] * Assertions. * Logical operators (!, &&, ||, ->). --- src/fix-ng/eval.cc | 43 +++++++++++++++++++++++++++++++----------- src/fix-ng/fix-expr.cc | 6 ++++++ src/fix-ng/fix-expr.hh | 4 +++- src/fix-ng/fix.sdf | 18 +++++++++++++++++- src/fix-ng/primops.cc | 13 +++++++++++++ src/fix-ng/primops.hh | 9 ++++++--- 6 files changed, 77 insertions(+), 16 deletions(-) diff --git a/src/fix-ng/eval.cc b/src/fix-ng/eval.cc index 770802f321..1f131fb7b0 100644 --- a/src/fix-ng/eval.cc +++ b/src/fix-ng/eval.cc @@ -13,11 +13,6 @@ EvalState::EvalState() } -Expr getAttr(EvalState & state, Expr e, const string & name) -{ -} - - /* Substitute an argument set into the body of a function. */ static Expr substArgs(Expr body, ATermList formals, Expr arg) { @@ -142,7 +137,8 @@ Expr evalExpr2(EvalState & state, Expr e) ATmatch(e, "Bool()", &e1) || ATmatch(e, "Function([], )", &e1, &e2) || ATmatch(e, "Attrs([])", &e1) || - ATmatch(e, "List([])", &e1)) + ATmatch(e, "List([])", &e1) || + ATmatch(e, "Null", &e1)) return e; /* Any encountered variables must be undeclared or primops. */ @@ -163,6 +159,8 @@ Expr evalExpr2(EvalState & state, Expr e) if (primop == "derivation") return primDerivation(state, e2); if (primop == "toString") return primToString(state, e2); if (primop == "baseNameOf") return primBaseNameOf(state, e2); + if (primop == "null") return primNull(state, e2); + if (primop == "isNull") return primIsNull(state, e2); else throw badTerm("undefined variable/primop", e1); } @@ -200,13 +198,36 @@ Expr evalExpr2(EvalState & state, Expr e) return evalExpr(state, e3); } - /* Equality. Just strings for now. */ - if (ATmatch(e, "OpEq(, )", &e1, &e2)) { - string s1 = evalString(state, e1); - string s2 = evalString(state, e2); - return s1 == s2 ? ATmake("Bool(True)") : ATmake("Bool(False)"); + /* Assertions. */ + if (ATmatch(e, "Assert(, )", &e1, &e2)) { + if (!evalBool(state, e1)) throw badTerm("guard failed", e); + return evalExpr(state, e2); } + /* Generic equality. */ + if (ATmatch(e, "OpEq(, )", &e1, &e2)) + return makeBool(evalExpr(state, e1) == evalExpr(state, e2)); + + /* Generic inequality. */ + if (ATmatch(e, "OpNEq(, )", &e1, &e2)) + return makeBool(evalExpr(state, e1) != evalExpr(state, e2)); + + /* Negation. */ + if (ATmatch(e, "OpNot()", &e1)) + return makeBool(!evalBool(state, e1)); + + /* Implication. */ + if (ATmatch(e, "OpImpl(, )", &e1, &e2)) + return makeBool(!evalBool(state, e1) || evalBool(state, e2)); + + /* Conjunction (logical AND). */ + if (ATmatch(e, "OpAnd(, )", &e1, &e2)) + return makeBool(evalBool(state, e1) && evalBool(state, e2)); + + /* Disjunction (logical OR). */ + if (ATmatch(e, "OpOr(, )", &e1, &e2)) + return makeBool(evalBool(state, e1) || evalBool(state, e2)); + /* Barf. */ throw badTerm("invalid expression", e); } diff --git a/src/fix-ng/fix-expr.cc b/src/fix-ng/fix-expr.cc index 6e73b29341..1ce4a55e47 100644 --- a/src/fix-ng/fix-expr.cc +++ b/src/fix-ng/fix-expr.cc @@ -222,3 +222,9 @@ Expr substitute(const ATermMap & subs, Expr e) return e; } + + +Expr makeBool(bool b) +{ + return b ? ATmake("Bool(True)") : ATmake("Bool(False)"); +} diff --git a/src/fix-ng/fix-expr.hh b/src/fix-ng/fix-expr.hh index 93a010abed..6c1e51d9cc 100644 --- a/src/fix-ng/fix-expr.hh +++ b/src/fix-ng/fix-expr.hh @@ -45,7 +45,6 @@ public: ATerm string2ATerm(const string & s); string aterm2String(ATerm t); - /* Generic bottomup traversal over ATerms. The traversal first recursively descends into subterms, and then applies the given term function to the resulting term. */ @@ -69,5 +68,8 @@ Expr makeAttrs(const ATermMap & attrs); /* Perform a set of substitutions on an expression. */ Expr substitute(const ATermMap & subs, Expr e); +/* Create an expression representing a boolean. */ +Expr makeBool(bool b); + #endif /* !__FIXEXPR_H */ diff --git a/src/fix-ng/fix.sdf b/src/fix-ng/fix.sdf index 9dc04d9373..0cc486e14d 100644 --- a/src/fix-ng/fix.sdf +++ b/src/fix-ng/fix.sdf @@ -38,6 +38,8 @@ exports Id -> Formal {cons("NoDefFormal")} Id "?" Expr -> Formal {cons("DefFormal")} + "assert" Expr ";" Expr -> Expr {cons("Assert"), right} + "rec" "{" Binds "}" -> Expr {cons("Rec")} "let" "{" Binds "}" -> Expr {cons("LetRec")} "{" Binds "}" -> Expr {cons("Attrs")} @@ -55,7 +57,13 @@ exports "if" Expr "then" Expr "else" Expr -> Expr {cons("If")} - Expr "==" Expr -> Expr {cons("OpEq")} + Expr "==" Expr -> Expr {cons("OpEq"), non-assoc} + Expr "!=" Expr -> Expr {cons("OpNEq"), non-assoc} + + "!" Expr -> Expr {cons("OpNot")} + Expr "&&" Expr -> Expr {cons("OpAnd"), right} + Expr "||" Expr -> Expr {cons("OpOr"), right} + Expr "->" Expr -> Expr {cons("OpImpl"), right} Bool -> Expr {cons("Bool")} @@ -64,6 +72,13 @@ exports Expr "." Id -> Expr > Expr ExprList -> ExprList > Expr Expr -> Expr + > "!" Expr -> Expr + > Expr "==" Expr -> Expr + > Expr "!=" Expr -> Expr + > Expr "&&" Expr -> Expr + > Expr "||" Expr -> Expr + > Expr "->" Expr -> Expr + > "assert" Expr ";" Expr -> Expr > "{" {Formal ","}* "}" ":" Expr -> Expr @@ -78,6 +93,7 @@ exports "rec" -> Id {reject} "true" -> Id {reject} "false" -> Id {reject} + "assert" -> Id {reject} [0-9]+ -> Int diff --git a/src/fix-ng/primops.cc b/src/fix-ng/primops.cc index ef0fd354ef..f5a278f669 100644 --- a/src/fix-ng/primops.cc +++ b/src/fix-ng/primops.cc @@ -225,3 +225,16 @@ Expr primToString(EvalState & state, Expr arg) return ATmake("Str()", s); else throw badTerm("cannot coerce to string", arg); } + + +Expr primNull(EvalState & state, Expr arg) +{ + return ATmake("Null"); +} + + +Expr primIsNull(EvalState & state, Expr arg) +{ + arg = evalExpr(state, arg); + return makeBool(ATmatch(arg, "Null")); +} diff --git a/src/fix-ng/primops.hh b/src/fix-ng/primops.hh index e48883b0bb..775ec55682 100644 --- a/src/fix-ng/primops.hh +++ b/src/fix-ng/primops.hh @@ -8,7 +8,6 @@ argument. */ Expr primImport(EvalState & state, Expr arg); - /* Construct (as a unobservable) side effect) a Nix derivation expression that performs the derivation described by the argument set. Returns the original set extended with the following @@ -18,14 +17,18 @@ Expr primImport(EvalState & state, Expr arg); derivation. */ Expr primDerivation(EvalState & state, Expr args); - /* Return the base name of the given string, i.e., everything following the last slash. */ Expr primBaseNameOf(EvalState & state, Expr arg); - /* Convert the argument (which can be a path or a uri) to a string. */ Expr primToString(EvalState & state, Expr arg); +/* Return the null value. */ +Expr primNull(EvalState & state, Expr arg); + +/* Determine whether the argument is the null value. */ +Expr primIsNull(EvalState & state, Expr arg); + #endif /* !__PRIMOPS_H */