* Assertions.

* Logical operators (!, &&, ||, ->).
This commit is contained in:
Eelco Dolstra 2003-11-05 16:27:40 +00:00
parent e17e95a828
commit fa18f1f184
6 changed files with 77 additions and 16 deletions

View File

@ -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. */ /* Substitute an argument set into the body of a function. */
static Expr substArgs(Expr body, ATermList formals, Expr arg) 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, "Bool(<term>)", &e1) ||
ATmatch(e, "Function([<list>], <term>)", &e1, &e2) || ATmatch(e, "Function([<list>], <term>)", &e1, &e2) ||
ATmatch(e, "Attrs([<list>])", &e1) || ATmatch(e, "Attrs([<list>])", &e1) ||
ATmatch(e, "List([<list>])", &e1)) ATmatch(e, "List([<list>])", &e1) ||
ATmatch(e, "Null", &e1))
return e; return e;
/* Any encountered variables must be undeclared or primops. */ /* 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 == "derivation") return primDerivation(state, e2);
if (primop == "toString") return primToString(state, e2); if (primop == "toString") return primToString(state, e2);
if (primop == "baseNameOf") return primBaseNameOf(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); else throw badTerm("undefined variable/primop", e1);
} }
@ -200,13 +198,36 @@ Expr evalExpr2(EvalState & state, Expr e)
return evalExpr(state, e3); return evalExpr(state, e3);
} }
/* Equality. Just strings for now. */ /* Assertions. */
if (ATmatch(e, "OpEq(<term>, <term>)", &e1, &e2)) { if (ATmatch(e, "Assert(<term>, <term>)", &e1, &e2)) {
string s1 = evalString(state, e1); if (!evalBool(state, e1)) throw badTerm("guard failed", e);
string s2 = evalString(state, e2); return evalExpr(state, e2);
return s1 == s2 ? ATmake("Bool(True)") : ATmake("Bool(False)");
} }
/* 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. */ /* Barf. */
throw badTerm("invalid expression", e); throw badTerm("invalid expression", e);
} }

View File

@ -222,3 +222,9 @@ Expr substitute(const ATermMap & subs, Expr e)
return e; return e;
} }
Expr makeBool(bool b)
{
return b ? ATmake("Bool(True)") : ATmake("Bool(False)");
}

View File

@ -45,7 +45,6 @@ public:
ATerm string2ATerm(const string & s); ATerm string2ATerm(const string & s);
string aterm2String(ATerm t); string aterm2String(ATerm t);
/* Generic bottomup traversal over ATerms. The traversal first /* Generic bottomup traversal over ATerms. The traversal first
recursively descends into subterms, and then applies the given term recursively descends into subterms, and then applies the given term
function to the resulting term. */ function to the resulting term. */
@ -69,5 +68,8 @@ Expr makeAttrs(const ATermMap & attrs);
/* Perform a set of substitutions on an expression. */ /* Perform a set of substitutions on an expression. */
Expr substitute(const ATermMap & subs, Expr e); Expr substitute(const ATermMap & subs, Expr e);
/* Create an expression representing a boolean. */
Expr makeBool(bool b);
#endif /* !__FIXEXPR_H */ #endif /* !__FIXEXPR_H */

View File

@ -38,6 +38,8 @@ exports
Id -> Formal {cons("NoDefFormal")} Id -> Formal {cons("NoDefFormal")}
Id "?" Expr -> Formal {cons("DefFormal")} Id "?" Expr -> Formal {cons("DefFormal")}
"assert" Expr ";" Expr -> Expr {cons("Assert"), right}
"rec" "{" Binds "}" -> Expr {cons("Rec")} "rec" "{" Binds "}" -> Expr {cons("Rec")}
"let" "{" Binds "}" -> Expr {cons("LetRec")} "let" "{" Binds "}" -> Expr {cons("LetRec")}
"{" Binds "}" -> Expr {cons("Attrs")} "{" Binds "}" -> Expr {cons("Attrs")}
@ -55,7 +57,13 @@ exports
"if" Expr "then" Expr "else" Expr -> Expr {cons("If")} "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")} Bool -> Expr {cons("Bool")}
@ -64,6 +72,13 @@ exports
Expr "." Id -> Expr Expr "." Id -> Expr
> Expr ExprList -> ExprList > Expr ExprList -> ExprList
> Expr Expr -> Expr > 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 > "{" {Formal ","}* "}" ":" Expr -> Expr
@ -78,6 +93,7 @@ exports
"rec" -> Id {reject} "rec" -> Id {reject}
"true" -> Id {reject} "true" -> Id {reject}
"false" -> Id {reject} "false" -> Id {reject}
"assert" -> Id {reject}
[0-9]+ -> Int [0-9]+ -> Int

View File

@ -225,3 +225,16 @@ Expr primToString(EvalState & state, Expr arg)
return ATmake("Str(<str>)", s); return ATmake("Str(<str>)", s);
else throw badTerm("cannot coerce to string", arg); 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"));
}

View File

@ -8,7 +8,6 @@
argument. */ argument. */
Expr primImport(EvalState & state, Expr arg); Expr primImport(EvalState & state, Expr arg);
/* Construct (as a unobservable) side effect) a Nix derivation /* Construct (as a unobservable) side effect) a Nix derivation
expression that performs the derivation described by the argument expression that performs the derivation described by the argument
set. Returns the original set extended with the following set. Returns the original set extended with the following
@ -18,14 +17,18 @@ Expr primImport(EvalState & state, Expr arg);
derivation. */ derivation. */
Expr primDerivation(EvalState & state, Expr args); Expr primDerivation(EvalState & state, Expr args);
/* Return the base name of the given string, i.e., everything /* Return the base name of the given string, i.e., everything
following the last slash. */ following the last slash. */
Expr primBaseNameOf(EvalState & state, Expr arg); Expr primBaseNameOf(EvalState & state, Expr arg);
/* Convert the argument (which can be a path or a uri) to a string. */ /* Convert the argument (which can be a path or a uri) to a string. */
Expr primToString(EvalState & state, Expr arg); 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 */ #endif /* !__PRIMOPS_H */