forked from lix-project/lix
* Strings.
This commit is contained in:
parent
d96cdcea6b
commit
392811eb8f
|
@ -5,6 +5,7 @@
|
||||||
#include "nixexpr-ast.hh"
|
#include "nixexpr-ast.hh"
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
|
|
||||||
|
@ -27,6 +28,7 @@ struct Env
|
||||||
typedef enum {
|
typedef enum {
|
||||||
tInt = 1,
|
tInt = 1,
|
||||||
tBool,
|
tBool,
|
||||||
|
tString,
|
||||||
tAttrs,
|
tAttrs,
|
||||||
tList,
|
tList,
|
||||||
tThunk,
|
tThunk,
|
||||||
|
@ -48,6 +50,10 @@ struct Value
|
||||||
{
|
{
|
||||||
int integer;
|
int integer;
|
||||||
bool boolean;
|
bool boolean;
|
||||||
|
struct {
|
||||||
|
const char * s;
|
||||||
|
const char * * context;
|
||||||
|
} string;
|
||||||
Bindings * attrs;
|
Bindings * attrs;
|
||||||
struct {
|
struct {
|
||||||
unsigned int length;
|
unsigned int length;
|
||||||
|
@ -97,6 +103,14 @@ static void mkBool(Value & v, bool b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void mkString(Value & v, const char * s)
|
||||||
|
{
|
||||||
|
v.type = tString;
|
||||||
|
v.string.s = s;
|
||||||
|
v.string.context = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::ostream & operator << (std::ostream & str, Value & v)
|
std::ostream & operator << (std::ostream & str, Value & v)
|
||||||
{
|
{
|
||||||
switch (v.type) {
|
switch (v.type) {
|
||||||
|
@ -106,6 +120,9 @@ std::ostream & operator << (std::ostream & str, Value & v)
|
||||||
case tBool:
|
case tBool:
|
||||||
str << (v.boolean ? "true" : "false");
|
str << (v.boolean ? "true" : "false");
|
||||||
break;
|
break;
|
||||||
|
case tString:
|
||||||
|
str << "\"" << v.string.s << "\""; // !!! escaping
|
||||||
|
break;
|
||||||
case tAttrs:
|
case tAttrs:
|
||||||
str << "{ ";
|
str << "{ ";
|
||||||
foreach (Bindings::iterator, i, *v.attrs)
|
foreach (Bindings::iterator, i, *v.attrs)
|
||||||
|
@ -269,6 +286,13 @@ static void eval(Env & env, Expr e, Value & v)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ATerm s; ATermList context;
|
||||||
|
if (matchStr(e, s, context)) {
|
||||||
|
assert(context == ATempty);
|
||||||
|
mkString(v, ATgetName(ATgetAFun(s)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ATermList es;
|
ATermList es;
|
||||||
if (matchAttrs(e, es)) {
|
if (matchAttrs(e, es)) {
|
||||||
v.type = tAttrs;
|
v.type = tAttrs;
|
||||||
|
@ -481,6 +505,25 @@ static void eval(Env & env, Expr e, Value & v)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (matchConcatStrings(e, es)) {
|
||||||
|
unsigned int n = ATgetLength(es), j = 0;
|
||||||
|
Value vs[n];
|
||||||
|
unsigned int len = 0;
|
||||||
|
for (ATermIterator i(es); i; ++i, ++j) {
|
||||||
|
eval(env, *i, vs[j]);
|
||||||
|
if (vs[j].type != tString) throw TypeError("string expected");
|
||||||
|
len += strlen(vs[j].string.s);
|
||||||
|
}
|
||||||
|
char * s = new char[len + 1], * t = s;
|
||||||
|
for (unsigned int i = 0; i < j; ++i) {
|
||||||
|
strcpy(t, vs[i].string.s);
|
||||||
|
t += strlen(vs[i].string.s);
|
||||||
|
}
|
||||||
|
*t = 0;
|
||||||
|
mkString(v, s);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
throw Error("unsupported term");
|
throw Error("unsupported term");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -601,6 +644,8 @@ void run(Strings args)
|
||||||
doTest("true == false");
|
doTest("true == false");
|
||||||
doTest("__head [ 1 2 3 ]");
|
doTest("__head [ 1 2 3 ]");
|
||||||
doTest("__add 1 2");
|
doTest("__add 1 2");
|
||||||
|
doTest("\"foo\"");
|
||||||
|
doTest("let s = \"bar\"; in \"foo${s}\"");
|
||||||
|
|
||||||
printMsg(lvlError, format("alloced %1% values") % nrValues);
|
printMsg(lvlError, format("alloced %1% values") % nrValues);
|
||||||
printMsg(lvlError, format("alloced %1% environments") % nrEnvs);
|
printMsg(lvlError, format("alloced %1% environments") % nrEnvs);
|
||||||
|
|
Loading…
Reference in a new issue