aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/fix-ng/eval.cc43
-rw-r--r--src/fix-ng/fix-expr.cc6
-rw-r--r--src/fix-ng/fix-expr.hh4
-rw-r--r--src/fix-ng/fix.sdf18
-rw-r--r--src/fix-ng/primops.cc13
-rw-r--r--src/fix-ng/primops.hh9
6 files changed, 77 insertions, 16 deletions
diff --git a/src/fix-ng/eval.cc b/src/fix-ng/eval.cc
index 770802f32..1f131fb7b 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(<term>)", &e1) ||
ATmatch(e, "Function([<list>], <term>)", &e1, &e2) ||
ATmatch(e, "Attrs([<list>])", &e1) ||
- ATmatch(e, "List([<list>])", &e1))
+ ATmatch(e, "List([<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(<term>, <term>)", &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(<term>, <term>)", &e1, &e2)) {
+ if (!evalBool(state, e1)) throw badTerm("guard failed", e);
+ return evalExpr(state, e2);
}
+ /* Generic equality. */
+ if (ATmatch(e, "OpEq(<term>, <term>)", &e1, &e2))
+ return makeBool(evalExpr(state, e1) == evalExpr(state, e2));
+
+ /* Generic inequality. */
+ if (ATmatch(e, "OpNEq(<term>, <term>)", &e1, &e2))
+ return makeBool(evalExpr(state, e1) != evalExpr(state, e2));
+
+ /* Negation. */
+ if (ATmatch(e, "OpNot(<term>)", &e1))
+ return makeBool(!evalBool(state, e1));
+
+ /* Implication. */
+ if (ATmatch(e, "OpImpl(<term>, <term>)", &e1, &e2))
+ return makeBool(!evalBool(state, e1) || evalBool(state, e2));
+
+ /* Conjunction (logical AND). */
+ if (ATmatch(e, "OpAnd(<term>, <term>)", &e1, &e2))
+ return makeBool(evalBool(state, e1) && evalBool(state, e2));
+
+ /* Disjunction (logical OR). */
+ if (ATmatch(e, "OpOr(<term>, <term>)", &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 6e73b2934..1ce4a55e4 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 93a010abe..6c1e51d9c 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 9dc04d937..0cc486e14 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 ef0fd354e..f5a278f66 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(<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 e48883b0b..775ec5568 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 */