From 2ab4bc44c780d2e28647f7559664675b756f38b9 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 22 Sep 2006 15:29:21 +0000 Subject: [PATCH] * Builtin function `add' to add integers. * Put common test functions in tests/lang/lib.nix. --- src/libexpr/eval.cc | 10 ++++++++++ src/libexpr/eval.hh | 1 + src/libexpr/primops.cc | 9 +++++++++ tests/lang.sh | 6 +++--- tests/lang/eval-okay-arithmetic.exp | 1 + tests/lang/eval-okay-arithmetic.nix | 18 ++++++++++++++++++ tests/lang/eval-okay-flatten.nix | 15 ++------------- tests/lang/eval-okay-list.nix | 10 ++-------- tests/lang/eval-okay-map.exp | 2 +- tests/lang/eval-okay-map.nix | 4 +++- tests/lang/lib.nix | 18 ++++++++++++++++++ 11 files changed, 68 insertions(+), 26 deletions(-) create mode 100644 tests/lang/eval-okay-arithmetic.exp create mode 100644 tests/lang/eval-okay-arithmetic.nix create mode 100644 tests/lang/lib.nix diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 02df4a4a3..3334e4bbd 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -176,6 +176,16 @@ Path evalPath(EvalState & state, Expr e) } +int evalInt(EvalState & state, Expr e) +{ + e = evalExpr(state, e); + int i; + if (!matchInt(e, i)) + throw TypeError(format("value is %1% while an integer was expected") % showType(e)); + return i; +} + + bool evalBool(EvalState & state, Expr e) { e = evalExpr(state, e); diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index b34e91055..a7f4e6943 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -62,6 +62,7 @@ Expr strictEvalExpr(EvalState & state, Expr e, /* Specific results. */ string evalString(EvalState & state, Expr e); Path evalPath(EvalState & state, Expr e); +int evalInt(EvalState & state, Expr e); bool evalBool(EvalState & state, Expr e); ATermList evalList(EvalState & state, Expr e); ATerm coerceToString(Expr e); diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 190d58733..1739b6656 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -771,6 +771,14 @@ static Expr primRelativise(EvalState & state, const ATermVector & args) } +static Expr primAdd(EvalState & state, const ATermVector & args) +{ + int i1 = evalInt(state, args[0]); + int i2 = evalInt(state, args[1]); + return makeInt(i1 + i2); +} + + void EvalState::addPrimOps() { addPrimOp("builtins", 0, primBuiltins); @@ -801,6 +809,7 @@ void EvalState::addPrimOps() addPrimOp("__hasAttr", 2, primHasAttr); addPrimOp("removeAttrs", 2, primRemoveAttrs); addPrimOp("relativise", 2, primRelativise); + addPrimOp("__add", 2, primAdd); } diff --git a/tests/lang.sh b/tests/lang.sh index 6ed3a5b26..b29cd344f 100644 --- a/tests/lang.sh +++ b/tests/lang.sh @@ -27,7 +27,7 @@ done for i in lang/eval-fail-*.nix; do echo "evaluating $i (should fail)"; i=$(basename $i .nix) - if $nixinstantiate --eval-only - < lang/$i.nix; then + if $nixinstantiate --eval-only lang/$i.nix; then echo "FAIL: $i shouldn't evaluate" fail=1 fi @@ -38,7 +38,7 @@ for i in lang/eval-okay-*.nix; do i=$(basename $i .nix) if test -e lang/$i.exp; then - if ! $nixinstantiate --eval-only - < lang/$i.nix > lang/$i.out; then + if ! $nixinstantiate --eval-only lang/$i.nix > lang/$i.out; then echo "FAIL: $i should evaluate" fail=1 fi @@ -49,7 +49,7 @@ for i in lang/eval-okay-*.nix; do fi if test -e lang/$i.exp.xml; then - if ! $nixinstantiate --eval-only --xml --strict - < lang/$i.nix > lang/$i.out.xml; then + if ! $nixinstantiate --eval-only --xml --strict lang/$i.nix > lang/$i.out.xml; then echo "FAIL: $i should evaluate" fail=1 fi diff --git a/tests/lang/eval-okay-arithmetic.exp b/tests/lang/eval-okay-arithmetic.exp new file mode 100644 index 000000000..433cb1c9b --- /dev/null +++ b/tests/lang/eval-okay-arithmetic.exp @@ -0,0 +1 @@ +Int(1275) diff --git a/tests/lang/eval-okay-arithmetic.nix b/tests/lang/eval-okay-arithmetic.nix new file mode 100644 index 000000000..735f01cf4 --- /dev/null +++ b/tests/lang/eval-okay-arithmetic.nix @@ -0,0 +1,18 @@ +with import ./lib.nix; + +let { + + range = first: last: [first] ++ (if first == last then [] else range (builtins.add first 1) last); + + /* Supposedly tail recursive version: + + range_ = accum: first: last: + if first == last then ([first] ++ accum) + else range_ ([first] ++ accum) (builtins.add first 1) last; + + range = range_ []; + */ + + body = sum (range 1 50); + +} diff --git a/tests/lang/eval-okay-flatten.nix b/tests/lang/eval-okay-flatten.nix index 2019263b8..fe911e968 100644 --- a/tests/lang/eval-okay-flatten.nix +++ b/tests/lang/eval-okay-flatten.nix @@ -1,18 +1,7 @@ +with import ./lib.nix; + let { - fold = op: nul: list: - if list == [] - then nul - else op (builtins.head list) (fold op nul (builtins.tail list)); - - concat = - fold (x: y: x + y) ""; - - flatten = x: - if builtins.isList x - then fold (x: y: (flatten x) ++ y) [] x - else [x]; - l = ["1" "2" ["3" ["4"] ["5" "6"]] "7"]; body = concat (flatten l); diff --git a/tests/lang/eval-okay-list.nix b/tests/lang/eval-okay-list.nix index 72a120d0d..d433bcf90 100644 --- a/tests/lang/eval-okay-list.nix +++ b/tests/lang/eval-okay-list.nix @@ -1,13 +1,7 @@ +with import ./lib.nix; + let { - fold = op: nul: list: - if list == [] - then nul - else op (builtins.head list) (fold op nul (builtins.tail list)); - - concat = - fold (x: y: x + y) ""; - body = concat ["foo" "bar" "bla" "test"]; } \ No newline at end of file diff --git a/tests/lang/eval-okay-map.exp b/tests/lang/eval-okay-map.exp index ab8e7a278..703cb0a30 100644 --- a/tests/lang/eval-okay-map.exp +++ b/tests/lang/eval-okay-map.exp @@ -1 +1 @@ -List([Call(Function1("x",OpPlus(Var("x"),Str("bar")),Pos("(string)",1,7)),Str("foo")),Call(Function1("x",OpPlus(Var("x"),Str("bar")),Pos("(string)",1,7)),Str("bla")),Call(Function1("x",OpPlus(Var("x"),Str("bar")),Pos("(string)",1,7)),Str("xyzzy"))]) +Str("foobarblabarxyzzybar") diff --git a/tests/lang/eval-okay-map.nix b/tests/lang/eval-okay-map.nix index 924446657..a76c1d811 100644 --- a/tests/lang/eval-okay-map.nix +++ b/tests/lang/eval-okay-map.nix @@ -1 +1,3 @@ -map (x: x + "bar") [ "foo" "bla" "xyzzy" ] \ No newline at end of file +with import ./lib.nix; + +concat (map (x: x + "bar") [ "foo" "bla" "xyzzy" ]) \ No newline at end of file diff --git a/tests/lang/lib.nix b/tests/lang/lib.nix new file mode 100644 index 000000000..f888453ff --- /dev/null +++ b/tests/lang/lib.nix @@ -0,0 +1,18 @@ +rec { + + fold = op: nul: list: + if list == [] + then nul + else op (builtins.head list) (fold op nul (builtins.tail list)); + + concat = + fold (x: y: x + y) ""; + + flatten = x: + if builtins.isList x + then fold (x: y: (flatten x) ++ y) [] x + else [x]; + + sum = fold (x: y: builtins.add x y) 0; + +}