* Finished the ATerm-less parser.
This commit is contained in:
		
							parent
							
								
									0d272fca79
								
							
						
					
					
						commit
						10e8b1fd15
					
				
					 6 changed files with 68 additions and 102 deletions
				
			
		|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue