aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2005-07-25 15:05:34 +0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2005-07-25 15:05:34 +0000
commit991a130b1e71b3b849b3640264f8834d6e13da22 (patch)
tree1e99a52b73043814fa501c8d470a933d2bc7cded /src
parente6899794ae9ce3924b818721d5caff463bccd60c (diff)
* Added a list concatenation operator:
[1 2 3] ++ [4 5 6] => [1 2 3 4 5 6]
Diffstat (limited to 'src')
-rw-r--r--src/libexpr/eval.cc16
-rw-r--r--src/libexpr/eval.hh1
-rw-r--r--src/libexpr/lexer.l1
-rw-r--r--src/libexpr/nixexpr-ast.def1
-rw-r--r--src/libexpr/parser.y2
-rw-r--r--src/libexpr/primops.cc18
6 files changed, 27 insertions, 12 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index d4593b5c0..9a6d414db 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 8ea0aec06..5562066fd 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 38d403c9f..d5a14f517 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 19601847c..b384ff7c0 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 1f204a228..23f1965ec 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 b0986028e..5736a7f91 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. */