aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libexpr/eval.cc14
-rw-r--r--src/libexpr/nixexpr.cc12
-rw-r--r--src/libexpr/nixexpr.hh6
-rw-r--r--src/libexpr/parser.y2
-rw-r--r--src/libexpr/primops.cc9
5 files changed, 38 insertions, 5 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 215692aeb..4454aaec4 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -338,6 +338,20 @@ Expr evalExpr2(EvalState & state, Expr e)
return makeBool(attrs.get(name) != 0);
}
+ /* String or path concatenation. */
+ if (atMatch(m, e) >> "OpPlus" >> e1 >> e2) {
+ e1 = evalExpr(state, e1);
+ e2 = evalExpr(state, e2);
+ string s1, s2;
+ if (atMatch(m, e1) >> "Str" >> s1 &&
+ atMatch(m, e2) >> "Str" >> s2)
+ return makeString(s1 + s2);
+ else if (atMatch(m, e1) >> "Path" >> s1 &&
+ atMatch(m, e2) >> "Path" >> s2)
+ return makeString(canonPath(s1 + "/" + s2));
+ else throw Error("wrong argument types in `+' operator");
+ }
+
/* Barf. */
throw badTerm("invalid expression", e);
}
diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc
index 78f89db5e..37288804d 100644
--- a/src/libexpr/nixexpr.cc
+++ b/src/libexpr/nixexpr.cc
@@ -364,3 +364,15 @@ Expr makeBool(bool b)
{
return b ? ATmake("Bool(True)") : ATmake("Bool(False)");
}
+
+
+Expr makeString(const string & s)
+{
+ return ATmake("Str(<str>)", s.c_str());
+}
+
+
+Expr makePath(const Path & path)
+{
+ return ATmake("Path(<str>)", path.c_str());
+}
diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh
index 30145c87b..657e6055c 100644
--- a/src/libexpr/nixexpr.hh
+++ b/src/libexpr/nixexpr.hh
@@ -92,5 +92,11 @@ void checkVarDefs(const ATermMap & def, Expr e);
/* Create an expression representing a boolean. */
Expr makeBool(bool b);
+/* Create an expression representing a string. */
+Expr makeString(const string & s);
+
+/* Create an expression representing a path. */
+Expr makePath(const Path & path);
+
#endif /* !__NIXEXPR_H */
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index 88ee8326b..c56d89809 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -53,6 +53,7 @@ ATerm makePos(YYLTYPE * loc, void * data)
%nonassoc EQ NEQ
%right UPDATE
%left NEG
+%left '+'
%nonassoc '?'
%nonassoc '~'
@@ -90,6 +91,7 @@ expr_op
| expr_op UPDATE expr_op { $$ = ATmake("OpUpdate(<term>, <term>)", $1, $3); }
| expr_op '~' expr_op { $$ = ATmake("SubPath(<term>, <term>)", $1, $3); }
| expr_op '?' ID { $$ = ATmake("OpHasAttr(<term>, <term>)", $1, $3); }
+ | expr_op '+' expr_op { $$ = ATmake("OpPlus(<term>, <term>)", $1, $3); }
| expr_app
;
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 938d9bb8c..ade483dc7 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -273,8 +273,8 @@ static Expr primDerivation(EvalState & state, const ATermVector & _args)
attrs.set("outPath", ATmake("(Path(<str>), NoPos)", outPath.c_str()));
attrs.set("drvPath", ATmake("(Path(<str>), NoPos)", drvPath.c_str()));
- attrs.set("drvHash", ATmake("(Str(<str>), NoPos)", ((string) drvHash).c_str()));
- attrs.set("type", ATmake("(Str(\"derivation\"), NoPos)"));
+ attrs.set("drvHash", ATmake("(<term>, NoPos)", makeString(drvHash)));
+ attrs.set("type", ATmake("(<term>, NoPos)", makeString("derivation")));
return makeAttrs(attrs);
}
@@ -284,8 +284,7 @@ static Expr primDerivation(EvalState & state, const ATermVector & _args)
following the last slash. */
static Expr primBaseNameOf(EvalState & state, const ATermVector & args)
{
- string s = evalString(state, args[0]);
- return ATmake("Str(<str>)", baseNameOf(s).c_str());
+ return makeString(baseNameOf(evalString(state, args[0])));
}
@@ -298,7 +297,7 @@ static Expr primToString(EvalState & state, const ATermVector & args)
if (atMatch(m, arg) >> "Str" >> s ||
atMatch(m, arg) >> "Path" >> s ||
atMatch(m, arg) >> "Uri" >> s)
- return ATmake("Str(<str>)", s.c_str());
+ return makeString(s);
else throw Error("cannot coerce value to string");
}