diff options
author | Eelco Dolstra <e.dolstra@tudelft.nl> | 2005-07-25T15·05+0000 |
---|---|---|
committer | Eelco Dolstra <e.dolstra@tudelft.nl> | 2005-07-25T15·05+0000 |
commit | 991a130b1e71b3b849b3640264f8834d6e13da22 (patch) | |
tree | 1e99a52b73043814fa501c8d470a933d2bc7cded | |
parent | e6899794ae9ce3924b818721d5caff463bccd60c (diff) |
* Added a list concatenation operator:
[1 2 3] ++ [4 5 6] => [1 2 3 4 5 6]
-rw-r--r-- | src/libexpr/eval.cc | 16 | ||||
-rw-r--r-- | src/libexpr/eval.hh | 1 | ||||
-rw-r--r-- | src/libexpr/lexer.l | 1 | ||||
-rw-r--r-- | src/libexpr/nixexpr-ast.def | 1 | ||||
-rw-r--r-- | src/libexpr/parser.y | 2 | ||||
-rw-r--r-- | src/libexpr/primops.cc | 18 | ||||
-rw-r--r-- | tests/lang/eval-okay-concat.exp | 1 | ||||
-rw-r--r-- | tests/lang/eval-okay-concat.nix | 1 |
8 files changed, 29 insertions, 12 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index d4593b5c0ec0..9a6d414db706 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -140,6 +140,15 @@ bool evalBool(EvalState & state, Expr e) } +ATermList evalList(EvalState & state, Expr e) +{ + e = evalExpr(state, e); + ATermList list; + if (!matchList(e, list)) throw Error("list expected"); + return list; +} + + Expr evalExpr2(EvalState & state, Expr e) { Expr e1, e2, e3, e4; @@ -336,6 +345,13 @@ Expr evalExpr2(EvalState & state, Expr e) else throw Error("wrong argument types in `+' operator"); } + /* List concatenation. */ + if (matchOpConcat(e, e1, e2)) { + ATermList l1 = evalList(state, e1); + ATermList l2 = evalList(state, e2); + return makeList(ATconcat(l1, l2)); + } + /* Barf. */ throw badTerm("invalid expression", e); } diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 8ea0aec06cf4..5562066fda97 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -46,6 +46,7 @@ Expr evalFile(EvalState & state, const Path & path); /* Specific results. */ string evalString(EvalState & state, Expr e); Path evalPath(EvalState & state, Expr e); +ATermList evalList(EvalState & state, Expr e); /* Print statistics. */ void printEvalStats(EvalState & state); diff --git a/src/libexpr/lexer.l b/src/libexpr/lexer.l index 38d403c9fade..d5a14f517acc 100644 --- a/src/libexpr/lexer.l +++ b/src/libexpr/lexer.l @@ -59,6 +59,7 @@ inherit { return INHERIT; } \|\| { return OR; } \-\> { return IMPL; } \/\/ { return UPDATE; } +\+\+ { return CONCAT; } {ID} { yylval->t = ATmake("<str>", yytext); return ID; /* !!! alloc */ } {INT} { int n = atoi(yytext); /* !!! overflow */ diff --git a/src/libexpr/nixexpr-ast.def b/src/libexpr/nixexpr-ast.def index 19601847cf32..b384ff7c08fc 100644 --- a/src/libexpr/nixexpr-ast.def +++ b/src/libexpr/nixexpr-ast.def @@ -18,6 +18,7 @@ OpUpdate | Expr Expr | Expr | SubPath | Expr Expr | Expr | OpHasAttr | Expr string | Expr | OpPlus | Expr Expr | Expr | +OpConcat | Expr Expr | Expr | Call | Expr Expr | Expr | Select | Expr string | Expr | Var | string | Expr | diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 1f204a228009..23f1965ecd64 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -64,6 +64,7 @@ static Pos makeCurPos(YYLTYPE * loc, void * data) %right UPDATE %left NEG %left '+' +%left CONCAT %nonassoc '?' %nonassoc '~' @@ -102,6 +103,7 @@ expr_op | expr_op '~' expr_op { $$ = makeSubPath($1, $3); } | expr_op '?' ID { $$ = makeOpHasAttr($1, $3); } | expr_op '+' expr_op { $$ = makeOpPlus($1, $3); } + | expr_op CONCAT expr_op { $$ = makeOpConcat($1, $3); } | expr_app ; diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index b0986028ee24..5736a7f91619 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -414,17 +414,13 @@ static Expr primIsNull(EvalState & state, const ATermVector & args) static Expr primMap(EvalState & state, const ATermVector & args) { Expr fun = evalExpr(state, args[0]); - Expr list = evalExpr(state, args[1]); + ATermList list = evalList(state, args[1]); - ATermList list2; - if (!matchList(list, list2)) - throw Error("`map' expects a list as its second argument"); - - ATermList list3 = ATempty; - for (ATermIterator i(list2); i; ++i) - list3 = ATinsert(list3, makeCall(fun, *i)); + ATermList res = ATempty; + for (ATermIterator i(list); i; ++i) + res = ATinsert(res, makeCall(fun, *i)); - return makeList(ATreverse(list3)); + return makeList(ATreverse(res)); } @@ -449,9 +445,7 @@ static Expr primRemoveAttrs(EvalState & state, const ATermVector & args) ATermMap attrs; queryAllAttrs(evalExpr(state, args[0]), attrs, true); - ATermList list; - if (!matchList(evalExpr(state, args[1]), list)) - throw Error("`removeAttrs' expects a list as its second argument"); + ATermList list = evalList(state, args[1]); for (ATermIterator i(list); i; ++i) /* It's not an error for *i not to exist. */ diff --git a/tests/lang/eval-okay-concat.exp b/tests/lang/eval-okay-concat.exp new file mode 100644 index 000000000000..359ccef86f0f --- /dev/null +++ b/tests/lang/eval-okay-concat.exp @@ -0,0 +1 @@ +List([Int(1),Int(2),Int(3),Int(4),Int(5),Int(6),Int(7),Int(8),Int(9)]) diff --git a/tests/lang/eval-okay-concat.nix b/tests/lang/eval-okay-concat.nix new file mode 100644 index 000000000000..d158a9bf05b9 --- /dev/null +++ b/tests/lang/eval-okay-concat.nix @@ -0,0 +1 @@ +[1 2 3] ++ [4 5 6] ++ [7 8 9] |