forked from lix-project/lix
* Finished the ATerm-less parser.
This commit is contained in:
parent
0d272fca79
commit
10e8b1fd15
|
@ -56,7 +56,7 @@ void run(Strings args)
|
||||||
doTest(state, "let id = x: x; in [1 2] == [(id 1) (id 2)]");
|
doTest(state, "let id = x: x; in [1 2] == [(id 1) (id 2)]");
|
||||||
doTest(state, "let id = x: x; in [1 2] == [(id 1) (id 3)]");
|
doTest(state, "let id = x: x; in [1 2] == [(id 1) (id 3)]");
|
||||||
doTest(state, "[1 2] == [3 (let x = x; in x)]");
|
doTest(state, "[1 2] == [3 (let x = x; in x)]");
|
||||||
//doTest(state, "{ x = 1; y.z = 2; } == { y = { z = 2; }; x = 1; }");
|
doTest(state, "{ x = 1; y.z = 2; } == { y = { z = 2; }; x = 1; }");
|
||||||
doTest(state, "{ x = 1; y = 2; } == { x = 2; }");
|
doTest(state, "{ x = 1; y = 2; } == { x = 2; }");
|
||||||
doTest(state, "{ x = [ 1 2 ]; } == { x = [ 1 ] ++ [ 2 ]; }");
|
doTest(state, "{ x = [ 1 2 ]; } == { x = [ 1 ] ++ [ 2 ]; }");
|
||||||
doTest(state, "1 != 1");
|
doTest(state, "1 != 1");
|
||||||
|
@ -84,7 +84,7 @@ void run(Strings args)
|
||||||
doTest(state, "let as = { x = 1; }; bs = rec { inherit (as) x; y = x; }; in bs.y");
|
doTest(state, "let as = { x = 1; }; bs = rec { inherit (as) x; y = x; }; in bs.y");
|
||||||
doTest(state, "let as = rec { inherit (y) x; y = { x = 1; }; }; in as.x");
|
doTest(state, "let as = rec { inherit (y) x; y = { x = 1; }; }; in as.x");
|
||||||
doTest(state, "builtins.toXML 123");
|
doTest(state, "builtins.toXML 123");
|
||||||
//doTest(state, "builtins.toXML { a.b = \"x\" + \"y\"; c = [ 1 2 ] ++ [ 3 4 ]; }");
|
doTest(state, "builtins.toXML { a.b = \"x\" + \"y\"; c = [ 1 2 ] ++ [ 3 4 ]; }");
|
||||||
|
|
||||||
state.printStats();
|
state.printStats();
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,7 @@ std::ostream & operator << (std::ostream & str, Value & v)
|
||||||
str << "]";
|
str << "]";
|
||||||
break;
|
break;
|
||||||
case tThunk:
|
case tThunk:
|
||||||
|
case tCopy:
|
||||||
str << "<CODE>";
|
str << "<CODE>";
|
||||||
break;
|
break;
|
||||||
case tLambda:
|
case tLambda:
|
||||||
|
@ -160,6 +161,16 @@ LocalNoInlineNoReturn(void throwTypeError(const char * s, const string & s2))
|
||||||
throw TypeError(format(s) % s2);
|
throw TypeError(format(s) % s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LocalNoInlineNoReturn(void throwTypeError(const char * s, const Pos & pos, const string & s2))
|
||||||
|
{
|
||||||
|
throw TypeError(format(s) % pos % s2);
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalNoInlineNoReturn(void throwTypeError(const char * s, const Pos & pos))
|
||||||
|
{
|
||||||
|
throw TypeError(format(s) % pos);
|
||||||
|
}
|
||||||
|
|
||||||
LocalNoInlineNoReturn(void throwAssertionError(const char * s, const Pos & pos))
|
LocalNoInlineNoReturn(void throwAssertionError(const char * s, const Pos & pos))
|
||||||
{
|
{
|
||||||
throw AssertionError(format(s) % pos);
|
throw AssertionError(format(s) % pos);
|
||||||
|
@ -175,6 +186,11 @@ LocalNoInline(void addErrorPrefix(Error & e, const char * s, const string & s2))
|
||||||
e.addPrefix(format(s) % s2);
|
e.addPrefix(format(s) % s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LocalNoInline(void addErrorPrefix(Error & e, const char * s, const Pos & pos))
|
||||||
|
{
|
||||||
|
e.addPrefix(format(s) % pos);
|
||||||
|
}
|
||||||
|
|
||||||
LocalNoInline(void addErrorPrefix(Error & e, const char * s, const string & s2, const string & s3))
|
LocalNoInline(void addErrorPrefix(Error & e, const char * s, const string & s2, const string & s3))
|
||||||
{
|
{
|
||||||
e.addPrefix(format(s) % s2 % s3);
|
e.addPrefix(format(s) % s2 % s3);
|
||||||
|
@ -424,6 +440,11 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
|
||||||
Value & v2 = (*v.attrs)[i->first];
|
Value & v2 = (*v.attrs)[i->first];
|
||||||
mkThunk(v2, env, i->second);
|
mkThunk(v2, env, i->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (list<string>::iterator, i, inherited) {
|
||||||
|
Value & v2 = (*v.attrs)[*i];
|
||||||
|
mkCopy(v2, *lookupVar(&env, *i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -555,7 +576,8 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v)
|
||||||
nrValues++;
|
nrValues++;
|
||||||
|
|
||||||
if (j == arg.attrs->end()) {
|
if (j == arg.attrs->end()) {
|
||||||
if (!i->def) throwTypeError("the argument named `%1%' required by the function is missing", i->name);
|
if (!i->def) throwTypeError("function at %1% called without required argument `%2%'",
|
||||||
|
fun.lambda.fun->pos, i->name);
|
||||||
mkThunk(v, env2, i->def);
|
mkThunk(v, env2, i->def);
|
||||||
} else {
|
} else {
|
||||||
attrsUsed++;
|
attrsUsed++;
|
||||||
|
@ -568,10 +590,15 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v)
|
||||||
TODO: show the names of the expected/unexpected
|
TODO: show the names of the expected/unexpected
|
||||||
arguments. */
|
arguments. */
|
||||||
if (!fun.lambda.fun->formals->ellipsis && attrsUsed != arg.attrs->size())
|
if (!fun.lambda.fun->formals->ellipsis && attrsUsed != arg.attrs->size())
|
||||||
throwTypeError("function called with unexpected argument");
|
throwTypeError("function at %1% called with unexpected argument", fun.lambda.fun->pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
eval(env2, fun.lambda.fun->body, v);
|
eval(env2, fun.lambda.fun->body, v);
|
||||||
|
} catch (Error & e) {
|
||||||
|
addErrorPrefix(e, "while evaluating the function at %1%:\n", fun.lambda.fun->pos);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ void ExprAttrs::show(std::ostream & str)
|
||||||
if (recursive) str << "rec ";
|
if (recursive) str << "rec ";
|
||||||
str << "{ ";
|
str << "{ ";
|
||||||
foreach (list<string>::iterator, i, inherited)
|
foreach (list<string>::iterator, i, inherited)
|
||||||
str << "inherited " << *i << "; ";
|
str << "inherit " << *i << "; ";
|
||||||
foreach (Attrs::iterator, i, attrs)
|
foreach (Attrs::iterator, i, attrs)
|
||||||
str << i->first << " = " << *i->second << "; ";
|
str << i->first << " = " << *i->second << "; ";
|
||||||
str << "}";
|
str << "}";
|
||||||
|
|
|
@ -44,99 +44,38 @@ struct ParseData
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
static string showAttrPath(const vector<string> & attrPath)
|
||||||
static string showAttrPath(ATermList attrPath)
|
|
||||||
{
|
{
|
||||||
string s;
|
string s;
|
||||||
for (ATermIterator i(attrPath); i; ++i) {
|
foreach (vector<string>::const_iterator, i, attrPath) {
|
||||||
if (!s.empty()) s += '.';
|
if (!s.empty()) s += '.';
|
||||||
s += aterm2String(*i);
|
s += *i;
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct Tree
|
static void addAttr(ExprAttrs * attrs, const vector<string> & attrPath, Expr * e, const Pos & pos)
|
||||||
{
|
{
|
||||||
Expr leaf; ATerm pos; bool recursive;
|
unsigned int n = 0;
|
||||||
typedef std::map<ATerm, Tree> Children;
|
foreach (vector<string>::const_iterator, i, attrPath) {
|
||||||
Children children;
|
n++;
|
||||||
Tree() { leaf = 0; recursive = true; }
|
if (attrs->attrs[*i]) {
|
||||||
};
|
ExprAttrs * attrs2 = dynamic_cast<ExprAttrs *>(attrs->attrs[*i]);
|
||||||
|
if (!attrs2)
|
||||||
|
throw ParseError(format("attribute `%1%' at %2% already defined at <SOMEWHERE>")
|
||||||
static ATermList buildAttrs(const Tree & t, ATermList & nonrec)
|
% showAttrPath(attrPath) % pos);
|
||||||
{
|
attrs = attrs2;
|
||||||
ATermList res = ATempty;
|
} else {
|
||||||
for (Tree::Children::const_reverse_iterator i = t.children.rbegin();
|
if (n == attrPath.size())
|
||||||
i != t.children.rend(); ++i)
|
attrs->attrs[*i] = e;
|
||||||
if (!i->second.recursive)
|
else {
|
||||||
nonrec = ATinsert(nonrec, makeBind(i->first, i->second.leaf, i->second.pos));
|
ExprAttrs * nested = new ExprAttrs;
|
||||||
else
|
attrs->attrs[*i] = nested;
|
||||||
res = ATinsert(res, i->second.leaf
|
attrs = nested;
|
||||||
? makeBind(i->first, i->second.leaf, i->second.pos)
|
|
||||||
: makeBind(i->first, makeAttrs(buildAttrs(i->second, nonrec)), makeNoPos()));
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static void fixAttrs(ExprAttrs & attrs)
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
Tree attrs;
|
|
||||||
|
|
||||||
/* This ATermMap is needed to ensure that the `leaf' fields in the
|
|
||||||
Tree nodes are not garbage collected. */
|
|
||||||
ATermMap gcRoots;
|
|
||||||
|
|
||||||
for (ATermIterator i(as); i; ++i) {
|
|
||||||
ATermList names, attrPath; Expr src, e; ATerm name, pos;
|
|
||||||
|
|
||||||
if (matchInherit(*i, src, names, pos)) {
|
|
||||||
bool fromScope = matchScope(src);
|
|
||||||
for (ATermIterator j(names); j; ++j) {
|
|
||||||
if (attrs.children.find(*j) != attrs.children.end())
|
|
||||||
throw ParseError(format("duplicate definition of attribute `%1%' at %2%")
|
|
||||||
% showAttrPath(ATmakeList1(*j)) % showPos(pos));
|
|
||||||
Tree & t(attrs.children[*j]);
|
|
||||||
Expr leaf = fromScope ? makeVar(*j) : makeSelect(src, *j);
|
|
||||||
gcRoots.set(leaf, leaf);
|
|
||||||
t.leaf = leaf;
|
|
||||||
t.pos = pos;
|
|
||||||
if (recursive && fromScope) t.recursive = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (matchBindAttrPath(*i, attrPath, e, pos)) {
|
|
||||||
|
|
||||||
Tree * t(&attrs);
|
|
||||||
|
|
||||||
for (ATermIterator j(attrPath); j; ) {
|
|
||||||
name = *j; ++j;
|
|
||||||
if (t->leaf) throw ParseError(format("attribute set containing `%1%' at %2% already defined at %3%")
|
|
||||||
% showAttrPath(attrPath) % showPos(pos) % showPos(t->pos));
|
|
||||||
t = &(t->children[name]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t->leaf)
|
|
||||||
throw ParseError(format("duplicate definition of attribute `%1%' at %2% and %3%")
|
|
||||||
% showAttrPath(attrPath) % showPos(pos) % showPos(t->pos));
|
|
||||||
if (!t->children.empty())
|
|
||||||
throw ParseError(format("duplicate definition of attribute `%1%' at %2%")
|
|
||||||
% showAttrPath(attrPath) % showPos(pos));
|
|
||||||
|
|
||||||
t->leaf = e; t->pos = pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
else abort(); /* can't happen */
|
|
||||||
}
|
|
||||||
|
|
||||||
ATermList nonrec = ATempty;
|
|
||||||
ATermList rec = buildAttrs(attrs, nonrec);
|
|
||||||
|
|
||||||
return recursive ? makeRec(rec, nonrec) : makeAttrs(rec);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -307,7 +246,7 @@ void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * err
|
||||||
char * id;
|
char * id;
|
||||||
char * path;
|
char * path;
|
||||||
char * uri;
|
char * uri;
|
||||||
std::list<std::string> * ids;
|
std::vector<std::string> * ids;
|
||||||
std::vector<nix::Expr *> * string_parts;
|
std::vector<nix::Expr *> * string_parts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,7 +299,7 @@ expr_function
|
||||||
| WITH expr ';' expr_function
|
| WITH expr ';' expr_function
|
||||||
{ $$ = new ExprWith(CUR_POS, $2, $4); }
|
{ $$ = new ExprWith(CUR_POS, $2, $4); }
|
||||||
| LET binds IN expr_function
|
| LET binds IN expr_function
|
||||||
{ $2->attrs["<let-body>"] = $4; $2->recursive = true; fixAttrs(*$2); $$ = new ExprSelect($2, "<let-body>"); }
|
{ $2->attrs["<let-body>"] = $4; $2->recursive = true; $$ = new ExprSelect($2, "<let-body>"); }
|
||||||
| expr_if
|
| expr_if
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -418,11 +357,11 @@ expr_simple
|
||||||
/* Let expressions `let {..., body = ...}' are just desugared
|
/* Let expressions `let {..., body = ...}' are just desugared
|
||||||
into `(rec {..., body = ...}).body'. */
|
into `(rec {..., body = ...}).body'. */
|
||||||
| LET '{' binds '}'
|
| LET '{' binds '}'
|
||||||
{ fixAttrs(*$3); $3->recursive = true; $$ = new ExprSelect($3, "body"); }
|
{ $3->recursive = true; $$ = new ExprSelect($3, "body"); }
|
||||||
| REC '{' binds '}'
|
| REC '{' binds '}'
|
||||||
{ fixAttrs(*$3); $3->recursive = true; $$ = $3; }
|
{ $3->recursive = true; $$ = $3; }
|
||||||
| '{' binds '}'
|
| '{' binds '}'
|
||||||
{ fixAttrs(*$2); $$ = $2; }
|
{ $$ = $2; }
|
||||||
| '[' expr_list ']' { $$ = $2; }
|
| '[' expr_list ']' { $$ = $2; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -439,16 +378,16 @@ ind_string_parts
|
||||||
;
|
;
|
||||||
|
|
||||||
binds
|
binds
|
||||||
: binds ID '=' expr ';' { $$ = $1; $$->attrs[$2] = $4; }
|
: binds attrpath '=' expr ';' { $$ = $1; addAttr($$, *$2, $4, CUR_POS); }
|
||||||
| binds INHERIT ids ';'
|
| binds INHERIT ids ';'
|
||||||
{ $$ = $1;
|
{ $$ = $1;
|
||||||
foreach (list<string>::iterator, i, *$3)
|
foreach (vector<string>::iterator, i, *$3)
|
||||||
$$->inherited.push_back(*i);
|
$$->inherited.push_back(*i);
|
||||||
}
|
}
|
||||||
| binds INHERIT '(' expr ')' ids ';'
|
| binds INHERIT '(' expr ')' ids ';'
|
||||||
{ $$ = $1;
|
{ $$ = $1;
|
||||||
/* !!! Should ensure sharing of the expression in $4. */
|
/* !!! Should ensure sharing of the expression in $4. */
|
||||||
foreach (list<string>::iterator, i, *$6)
|
foreach (vector<string>::iterator, i, *$6)
|
||||||
$$->attrs[*i] = new ExprSelect($4, *i);
|
$$->attrs[*i] = new ExprSelect($4, *i);
|
||||||
}
|
}
|
||||||
| { $$ = new ExprAttrs; }
|
| { $$ = new ExprAttrs; }
|
||||||
|
@ -456,12 +395,12 @@ binds
|
||||||
|
|
||||||
ids
|
ids
|
||||||
: ids ID { $$ = $1; $1->push_back($2); /* !!! dangerous */ }
|
: ids ID { $$ = $1; $1->push_back($2); /* !!! dangerous */ }
|
||||||
| { $$ = new list<string>; }
|
| { $$ = new vector<string>; }
|
||||||
;
|
;
|
||||||
|
|
||||||
attrpath
|
attrpath
|
||||||
: attrpath '.' ID { $$ = ATinsert($1, $3); }
|
: attrpath '.' ID { $$ = $1; $1->push_back($3); }
|
||||||
| ID { $$ = ATmakeList1($1); }
|
| ID { $$ = new vector<string>; $$->push_back($1); }
|
||||||
;
|
;
|
||||||
|
|
||||||
expr_list
|
expr_list
|
||||||
|
|
|
@ -1023,8 +1023,8 @@ void EvalState::createBaseEnv()
|
||||||
/* Add a wrapper around the derivation primop that computes the
|
/* Add a wrapper around the derivation primop that computes the
|
||||||
`drvPath' and `outPath' attributes lazily. */
|
`drvPath' and `outPath' attributes lazily. */
|
||||||
string s = "attrs: let res = derivationStrict attrs; in attrs // { drvPath = res.drvPath; outPath = res.outPath; type = \"derivation\"; }";
|
string s = "attrs: let res = derivationStrict attrs; in attrs // { drvPath = res.drvPath; outPath = res.outPath; type = \"derivation\"; }";
|
||||||
//mkThunk(v, baseEnv, parseExprFromString(s, "/"));
|
mkThunk(v, baseEnv, parseExprFromString(s, "/"));
|
||||||
//addConstant("derivation", v);
|
addConstant("derivation", v);
|
||||||
|
|
||||||
// Miscellaneous
|
// Miscellaneous
|
||||||
addPrimOp("import", 1, prim_import);
|
addPrimOp("import", 1, prim_import);
|
||||||
|
|
|
@ -177,7 +177,7 @@ static void initAndRun(int argc, char * * argv)
|
||||||
if (lt != "") setLogType(lt);
|
if (lt != "") setLogType(lt);
|
||||||
|
|
||||||
/* ATerm stuff. !!! find a better place to put this */
|
/* ATerm stuff. !!! find a better place to put this */
|
||||||
//initDerivationsHelpers();
|
initDerivationsHelpers();
|
||||||
|
|
||||||
/* Put the arguments in a vector. */
|
/* Put the arguments in a vector. */
|
||||||
Strings args, remaining;
|
Strings args, remaining;
|
||||||
|
@ -335,7 +335,7 @@ int main(int argc, char * * argv)
|
||||||
|
|
||||||
/* ATerm setup. */
|
/* ATerm setup. */
|
||||||
ATerm bottomOfStack;
|
ATerm bottomOfStack;
|
||||||
//ATinit(argc, argv, &bottomOfStack);
|
ATinit(argc, argv, &bottomOfStack);
|
||||||
|
|
||||||
/* Turn on buffering for cerr. */
|
/* Turn on buffering for cerr. */
|
||||||
#if HAVE_PUBSETBUF
|
#if HAVE_PUBSETBUF
|
||||||
|
|
Loading…
Reference in a new issue