* More missing constructs.
This commit is contained in:
		
							parent
							
								
									4d6ad5be17
								
							
						
					
					
						commit
						a60317f20f
					
				
					 6 changed files with 161 additions and 138 deletions
				
			
		|  | @ -45,6 +45,7 @@ void run(Strings args) | ||||||
|     doTest(state, "({x, y, ...}@args: args.z) { x = 1; y = 2; z = 3; }"); |     doTest(state, "({x, y, ...}@args: args.z) { x = 1; y = 2; z = 3; }"); | ||||||
|     //doTest(state, "({x ? y, y ? x}: y) { }");
 |     //doTest(state, "({x ? y, y ? x}: y) { }");
 | ||||||
|     doTest(state, "let x = 1; in x"); |     doTest(state, "let x = 1; in x"); | ||||||
|  |     doTest(state, "let { x = 1; body = x; }"); | ||||||
|     doTest(state, "with { x = 1; }; x"); |     doTest(state, "with { x = 1; }; x"); | ||||||
|     doTest(state, "let x = 2; in with { x = 1; }; x"); // => 2
 |     doTest(state, "let x = 2; in with { x = 1; }; x"); // => 2
 | ||||||
|     doTest(state, "with { x = 1; }; with { x = 2; }; x"); // => 1
 |     doTest(state, "with { x = 1; }; with { x = 2; }; x"); // => 1
 | ||||||
|  | @ -65,18 +66,19 @@ void run(Strings args) | ||||||
|     doTest(state, "__head [ 1 2 3 ]"); |     doTest(state, "__head [ 1 2 3 ]"); | ||||||
|     doTest(state, "__add 1 2"); |     doTest(state, "__add 1 2"); | ||||||
|     doTest(state, "null"); |     doTest(state, "null"); | ||||||
|     //doTest(state, "\"foo\"");
 |     doTest(state, "\"foo\""); | ||||||
|     //doTest(state, "let s = \"bar\"; in \"foo${s}\"");
 |     doTest(state, "let s = \"bar\"; in \"foo${s}\""); | ||||||
|     doTest(state, "if true then 1 else 2"); |     doTest(state, "if true then 1 else 2"); | ||||||
|     doTest(state, "if false then 1 else 2"); |     doTest(state, "if false then 1 else 2"); | ||||||
|     doTest(state, "if false || true then 1 else 2"); |     doTest(state, "if false || true then 1 else 2"); | ||||||
|  |     doTest(state, "!(true || false)"); | ||||||
|     doTest(state, "let x = x; in if true || x then 1 else 2"); |     doTest(state, "let x = x; in if true || x then 1 else 2"); | ||||||
|     doTest(state, "http://nixos.org/"); |     doTest(state, "http://nixos.org/"); | ||||||
|     doTest(state, "/etc/passwd"); |     doTest(state, "/etc/passwd"); | ||||||
|     //doTest(state, "import ./foo.nix");
 |     //doTest(state, "import ./foo.nix");
 | ||||||
|     doTest(state, "map (x: __add 1 x) [ 1 2 3 ]"); |     doTest(state, "map (x: __add 1 x) [ 1 2 3 ]"); | ||||||
|     doTest(state, "map (builtins.add 1) [ 1 2 3 ]"); |     doTest(state, "map (builtins.add 1) [ 1 2 3 ]"); | ||||||
|     //doTest(state, "builtins.hasAttr \"x\" { x = 1; }");
 |     doTest(state, "builtins.hasAttr \"x\" { x = 1; }"); | ||||||
|     doTest(state, "let x = 1; as = rec { inherit x; y = as.x; }; in as.y"); |     doTest(state, "let x = 1; as = rec { inherit x; y = as.x; }; in as.y"); | ||||||
|     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"); | ||||||
|  |  | ||||||
|  | @ -160,9 +160,9 @@ LocalNoInlineNoReturn(void throwTypeError(const char * s, const string & s2)) | ||||||
|     throw TypeError(format(s) % s2); |     throw TypeError(format(s) % s2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| LocalNoInlineNoReturn(void throwAssertionError(const char * s, const string & s2)) | LocalNoInlineNoReturn(void throwAssertionError(const char * s, const Pos & pos)) | ||||||
| { | { | ||||||
|     throw AssertionError(format(s) % s2); |     throw AssertionError(format(s) % pos); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| LocalNoInline(void addErrorPrefix(Error & e, const char * s)) | LocalNoInline(void addErrorPrefix(Error & e, const char * s)) | ||||||
|  | @ -341,73 +341,13 @@ void EvalState::eval(Env & env, Expr * e, Value & v) | ||||||
|     char x; |     char x; | ||||||
|     if (&x < deepestStack) deepestStack = &x; |     if (&x < deepestStack) deepestStack = &x; | ||||||
|      |      | ||||||
|     //debug(format("eval: %1%") % e);
 |     //debug(format("eval: %1%") % *e);
 | ||||||
| 
 | 
 | ||||||
|     checkInterrupt(); |     checkInterrupt(); | ||||||
| 
 | 
 | ||||||
|     nrEvaluated++; |     nrEvaluated++; | ||||||
| 
 | 
 | ||||||
|     e->eval(*this, env, v); |     e->eval(*this, env, v); | ||||||
| 
 |  | ||||||
| #if 0 |  | ||||||
|     Sym name; |  | ||||||
|     int n; |  | ||||||
|     ATerm s; ATermList context, es; |  | ||||||
|     ATermList rbnds, nrbnds; |  | ||||||
|     Expr e1, e2, e3, fun, arg, attrs; |  | ||||||
|     Pattern pat; Expr body; Pos pos; |  | ||||||
|      |  | ||||||
|     else if (matchConcatStrings(e, es)) { |  | ||||||
|         PathSet context; |  | ||||||
|         std::ostringstream s; |  | ||||||
|          |  | ||||||
|         bool first = true, isPath = false; |  | ||||||
|         Value vStr; |  | ||||||
|          |  | ||||||
|         for (ATermIterator i(es); i; ++i) { |  | ||||||
|             eval(env, *i, vStr); |  | ||||||
| 
 |  | ||||||
|             /* If the first element is a path, then the result will
 |  | ||||||
|                also be a path, we don't copy anything (yet - that's |  | ||||||
|                done later, since paths are copied when they are used |  | ||||||
|                in a derivation), and none of the strings are allowed |  | ||||||
|                to have contexts. */ |  | ||||||
|             if (first) { |  | ||||||
|                 isPath = vStr.type == tPath; |  | ||||||
|                 first = false; |  | ||||||
|             } |  | ||||||
|              |  | ||||||
|             s << coerceToString(vStr, context, false, !isPath); |  | ||||||
|         } |  | ||||||
|          |  | ||||||
|         if (isPath && !context.empty()) |  | ||||||
|             throwEvalError("a string that refers to a store path cannot be appended to a path, in `%1%'", s.str()); |  | ||||||
| 
 |  | ||||||
|         if (isPath) |  | ||||||
|             mkPath(v, s.str().c_str()); |  | ||||||
|         else |  | ||||||
|             mkString(v, s.str(), context); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* Assertions. */ |  | ||||||
|     else if (matchAssert(e, e1, e2, pos)) { |  | ||||||
|         if (!evalBool(env, e1)) |  | ||||||
|             throwAssertionError("assertion failed at %1%", showPos(pos)); |  | ||||||
|         eval(env, e2, v); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* Negation. */ |  | ||||||
|     else if (matchOpNot(e, e1)) |  | ||||||
|         mkBool(v, !evalBool(env, e1)); |  | ||||||
| 
 |  | ||||||
|     /* Attribute existence test (?). */ |  | ||||||
|     else if (matchOpHasAttr(e, e1, name)) { |  | ||||||
|         Value vAttrs; |  | ||||||
|         eval(env, e1, vAttrs); |  | ||||||
|         forceAttrs(vAttrs); |  | ||||||
|         mkBool(v, vAttrs.attrs->find(name) != vAttrs.attrs->end()); |  | ||||||
|     } |  | ||||||
| #endif |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -516,6 +456,15 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | void ExprOpHasAttr::eval(EvalState & state, Env & env, Value & v) | ||||||
|  | { | ||||||
|  |     Value vAttrs; | ||||||
|  |     state.eval(env, e, vAttrs); | ||||||
|  |     state.forceAttrs(vAttrs); | ||||||
|  |     mkBool(v, vAttrs.attrs->find(name) != vAttrs.attrs->end()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| void ExprLambda::eval(EvalState & state, Env & env, Value & v) | void ExprLambda::eval(EvalState & state, Env & env, Value & v) | ||||||
| { | { | ||||||
|     v.type = tLambda; |     v.type = tLambda; | ||||||
|  | @ -663,6 +612,20 @@ void ExprIf::eval(EvalState & state, Env & env, Value & v) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|      |      | ||||||
|  | void ExprAssert::eval(EvalState & state, Env & env, Value & v) | ||||||
|  | { | ||||||
|  |     if (!state.evalBool(env, cond)) | ||||||
|  |         throwAssertionError("assertion failed at %1%", pos); | ||||||
|  |     state.eval(env, body, v); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  |      | ||||||
|  | void ExprOpNot::eval(EvalState & state, Env & env, Value & v) | ||||||
|  | { | ||||||
|  |     mkBool(v, !state.evalBool(env, e)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| void ExprOpEq::eval(EvalState & state, Env & env, Value & v) | void ExprOpEq::eval(EvalState & state, Env & env, Value & v) | ||||||
| { | { | ||||||
|     Value v1; state.eval(env, e1, v1); |     Value v1; state.eval(env, e1, v1); | ||||||
|  | @ -713,12 +676,6 @@ void ExprOpUpdate::eval(EvalState & state, Env & env, Value & v) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| void ExprOpConcatStrings::eval(EvalState & state, Env & env, Value & v) |  | ||||||
| { |  | ||||||
|     abort(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| void ExprOpConcatLists::eval(EvalState & state, Env & env, Value & v) | void ExprOpConcatLists::eval(EvalState & state, Env & env, Value & v) | ||||||
| { | { | ||||||
|     Value v1; state.eval(env, e1, v1); |     Value v1; state.eval(env, e1, v1); | ||||||
|  | @ -735,6 +692,39 @@ void ExprOpConcatLists::eval(EvalState & state, Env & env, Value & v) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v) | ||||||
|  | { | ||||||
|  |     PathSet context; | ||||||
|  |     std::ostringstream s; | ||||||
|  |          | ||||||
|  |     bool first = true, isPath = false; | ||||||
|  |     Value vStr; | ||||||
|  | 
 | ||||||
|  |     foreach (vector<Expr *>::iterator, i, *es) { | ||||||
|  |         state.eval(env, *i, vStr); | ||||||
|  | 
 | ||||||
|  |         /* If the first element is a path, then the result will also
 | ||||||
|  |            be a path, we don't copy anything (yet - that's done later, | ||||||
|  |            since paths are copied when they are used in a derivation), | ||||||
|  |            and none of the strings are allowed to have contexts. */ | ||||||
|  |         if (first) { | ||||||
|  |             isPath = vStr.type == tPath; | ||||||
|  |             first = false; | ||||||
|  |         } | ||||||
|  |              | ||||||
|  |         s << state.coerceToString(vStr, context, false, !isPath); | ||||||
|  |     } | ||||||
|  |          | ||||||
|  |     if (isPath && !context.empty()) | ||||||
|  |         throwEvalError("a string that refers to a store path cannot be appended to a path, in `%1%'", s.str()); | ||||||
|  | 
 | ||||||
|  |     if (isPath) | ||||||
|  |         mkPath(v, s.str().c_str()); | ||||||
|  |     else | ||||||
|  |         mkString(v, s.str(), context); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| void EvalState::forceValue(Value & v) | void EvalState::forceValue(Value & v) | ||||||
| { | { | ||||||
|     if (v.type == tThunk) { |     if (v.type == tThunk) { | ||||||
|  |  | ||||||
|  | @ -45,7 +45,6 @@ static void adjustLoc(YYLTYPE * loc, const char * s, size_t len) | ||||||
| 
 | 
 | ||||||
| static Expr * unescapeStr(const char * s) | static Expr * unescapeStr(const char * s) | ||||||
| { | { | ||||||
| #if 0 |  | ||||||
|     string t; |     string t; | ||||||
|     char c; |     char c; | ||||||
|     while ((c = *s++)) { |     while ((c = *s++)) { | ||||||
|  | @ -64,8 +63,7 @@ static Expr * unescapeStr(const char * s) | ||||||
|         } |         } | ||||||
|         else t += c; |         else t += c; | ||||||
|     } |     } | ||||||
|     return makeStr(toATerm(t), ATempty); |     return new ExprString(t); | ||||||
| #endif |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|   |   | ||||||
|  |  | ||||||
|  | @ -40,6 +40,11 @@ void ExprSelect::show(std::ostream & str) | ||||||
|     str << "(" << *e << ")." << name; |     str << "(" << *e << ")." << name; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void ExprOpHasAttr::show(std::ostream & str) | ||||||
|  | { | ||||||
|  |     str << "(" << *e << ") ? " << name; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void ExprAttrs::show(std::ostream & str) | void ExprAttrs::show(std::ostream & str) | ||||||
| { | { | ||||||
|     if (recursive) str << "rec "; |     if (recursive) str << "rec "; | ||||||
|  | @ -87,19 +92,37 @@ void ExprIf::show(std::ostream & str) | ||||||
|     str << "if " << *cond << " then " << *then << " else " << *else_; |     str << "if " << *cond << " then " << *then << " else " << *else_; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | void ExprAssert::show(std::ostream & str) | ||||||
| #if 0 |  | ||||||
| string showPos(ATerm pos) |  | ||||||
| { | { | ||||||
|     ATerm path; |     str << "assert " << *cond << "; " << *body; | ||||||
|     int line, column; | } | ||||||
|     if (matchNoPos(pos)) return "undefined position"; | 
 | ||||||
|     if (!matchPos(pos, path, line, column)) | void ExprOpNot::show(std::ostream & str) | ||||||
|         throw badTerm("position expected", pos); | { | ||||||
|     return (format("`%1%:%2%:%3%'") % aterm2String(path) % line % column).str(); |     str << "! " << *e; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ExprConcatStrings::show(std::ostream & str) | ||||||
|  | { | ||||||
|  |     bool first = true; | ||||||
|  |     foreach (vector<Expr *>::iterator, i, *es) { | ||||||
|  |         if (first) first = false; else str << " + "; | ||||||
|  |         str << **i; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | std::ostream & operator << (std::ostream & str, const Pos & pos) | ||||||
|  | { | ||||||
|  |     if (!pos.line) | ||||||
|  |         str << "undefined position"; | ||||||
|  |     else | ||||||
|  |         str << (format("`%1%:%2%:%3%'") % pos.file % pos.line % pos.column).str(); | ||||||
|  |     return str; | ||||||
|  | } | ||||||
|  |      | ||||||
|  | 
 | ||||||
|  | #if 0 | ||||||
| ATerm bottomupRewrite(TermFun & f, ATerm e) | ATerm bottomupRewrite(TermFun & f, ATerm e) | ||||||
| { | { | ||||||
|     checkInterrupt(); |     checkInterrupt(); | ||||||
|  |  | ||||||
|  | @ -24,6 +24,9 @@ struct Pos | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | std::ostream & operator << (std::ostream & str, const Pos & pos); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| /* Abstract syntax of Nix expressions. */ | /* Abstract syntax of Nix expressions. */ | ||||||
| 
 | 
 | ||||||
| struct Env; | struct Env; | ||||||
|  | @ -81,6 +84,14 @@ struct ExprSelect : Expr | ||||||
|     COMMON_METHODS |     COMMON_METHODS | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | struct ExprOpHasAttr : Expr | ||||||
|  | { | ||||||
|  |     Expr * e; | ||||||
|  |     string name; | ||||||
|  |     ExprOpHasAttr(Expr * e, const string & name) : e(e), name(name) { }; | ||||||
|  |     COMMON_METHODS | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct ExprAttrs : Expr | struct ExprAttrs : Expr | ||||||
| { | { | ||||||
|     bool recursive; |     bool recursive; | ||||||
|  | @ -139,6 +150,21 @@ struct ExprIf : Expr | ||||||
|     COMMON_METHODS |     COMMON_METHODS | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | struct ExprAssert : Expr | ||||||
|  | { | ||||||
|  |     Pos pos; | ||||||
|  |     Expr * cond, * body; | ||||||
|  |     ExprAssert(const Pos & pos, Expr * cond, Expr * body) : pos(pos), cond(cond), body(body) { }; | ||||||
|  |     COMMON_METHODS | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct ExprOpNot : Expr | ||||||
|  | { | ||||||
|  |     Expr * e; | ||||||
|  |     ExprOpNot(Expr * e) : e(e) { }; | ||||||
|  |     COMMON_METHODS | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| #define MakeBinOp(name, s) \ | #define MakeBinOp(name, s) \ | ||||||
|     struct Expr##name : Expr \ |     struct Expr##name : Expr \ | ||||||
|     { \ |     { \ | ||||||
|  | @ -158,15 +184,17 @@ MakeBinOp(OpAnd, "&&") | ||||||
| MakeBinOp(OpOr, "||") | MakeBinOp(OpOr, "||") | ||||||
| MakeBinOp(OpImpl, "->") | MakeBinOp(OpImpl, "->") | ||||||
| MakeBinOp(OpUpdate, "//") | MakeBinOp(OpUpdate, "//") | ||||||
| MakeBinOp(OpConcatStrings, "+") |  | ||||||
| MakeBinOp(OpConcatLists, "++") | MakeBinOp(OpConcatLists, "++") | ||||||
| 
 | 
 | ||||||
|  | struct ExprConcatStrings : Expr | ||||||
|  | { | ||||||
|  |     vector<Expr *> * es; | ||||||
|  |     ExprConcatStrings(vector<Expr *> * es) : es(es) { }; | ||||||
|  |     COMMON_METHODS | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| #if 0 | #if 0 | ||||||
| /* Show a position. */ |  | ||||||
| string showPos(ATerm pos); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| /* Generic bottomup traversal over ATerms.  The traversal first
 | /* Generic bottomup traversal over ATerms.  The traversal first
 | ||||||
|    recursively descends into subterms, and then applies the given term |    recursively descends into subterms, and then applies the given term | ||||||
|    function to the resulting term. */ |    function to the resulting term. */ | ||||||
|  |  | ||||||
|  | @ -20,7 +20,6 @@ | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
| 
 | 
 | ||||||
| #include "aterm.hh" |  | ||||||
| #include "util.hh" | #include "util.hh" | ||||||
|      |      | ||||||
| #include "nixexpr.hh" | #include "nixexpr.hh" | ||||||
|  | @ -116,13 +115,13 @@ static void fixAttrs(ExprAttrs & attrs) | ||||||
|             for (ATermIterator j(attrPath); j; ) { |             for (ATermIterator j(attrPath); j; ) { | ||||||
|                 name = *j; ++j; |                 name = *j; ++j; | ||||||
|                 if (t->leaf) throw ParseError(format("attribute set containing `%1%' at %2% already defined at %3%") |                 if (t->leaf) throw ParseError(format("attribute set containing `%1%' at %2% already defined at %3%") | ||||||
|                     % showAttrPath(attrPath) % showPos(pos) % showPos (t->pos)); |                     % showAttrPath(attrPath) % showPos(pos) % showPos(t->pos)); | ||||||
|                 t = &(t->children[name]); |                 t = &(t->children[name]); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (t->leaf) |             if (t->leaf) | ||||||
|                 throw ParseError(format("duplicate definition of attribute `%1%' at %2% and %3%") |                 throw ParseError(format("duplicate definition of attribute `%1%' at %2% and %3%") | ||||||
|                     % showAttrPath(attrPath) % showPos(pos) % showPos (t->pos)); |                     % showAttrPath(attrPath) % showPos(pos) % showPos(t->pos)); | ||||||
|             if (!t->children.empty()) |             if (!t->children.empty()) | ||||||
|                 throw ParseError(format("duplicate definition of attribute `%1%' at %2%") |                 throw ParseError(format("duplicate definition of attribute `%1%' at %2%") | ||||||
|                     % showAttrPath(attrPath) % showPos(pos)); |                     % showAttrPath(attrPath) % showPos(pos)); | ||||||
|  | @ -289,30 +288,11 @@ static Pos makeCurPos(YYLTYPE * loc, ParseData * data) | ||||||
| 
 | 
 | ||||||
| void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * error) | void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * error) | ||||||
| { | { | ||||||
|     data->error = (format("%1%, at `%2%':%3%:%4%") |     data->error = (format("%1%, at %2%") | ||||||
|         % error % data->path % loc->first_line % loc->first_column).str(); |         % error % makeCurPos(loc, data)).str(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Make sure that the parse stack is scanned by the ATerm garbage |  | ||||||
|    collector. */ |  | ||||||
| static void * mallocAndProtect(size_t size) |  | ||||||
| { |  | ||||||
|     void * p = malloc(size); |  | ||||||
|     if (p) ATprotectMemory(p, size); |  | ||||||
|     return p; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void freeAndUnprotect(void * p) |  | ||||||
| { |  | ||||||
|     ATunprotectMemory(p); |  | ||||||
|     free(p); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #define YYMALLOC mallocAndProtect |  | ||||||
| #define YYFREE freeAndUnprotect |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -329,18 +309,20 @@ static void freeAndUnprotect(void * p) | ||||||
|   char * path; |   char * path; | ||||||
|   char * uri; |   char * uri; | ||||||
|   std::list<std::string> * ids; |   std::list<std::string> * ids; | ||||||
|  |   std::vector<nix::Expr *> * string_parts; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| %type <e> start expr expr_function expr_if expr_op | %type <e> start expr expr_function expr_if expr_op | ||||||
| %type <e> expr_app expr_select expr_simple | %type <e> expr_app expr_select expr_simple | ||||||
| %type <list> expr_list | %type <list> expr_list | ||||||
| %type <attrs> binds | %type <attrs> binds | ||||||
| %type <ts> attrpath string_parts ind_string_parts | %type <ts> attrpath ind_string_parts | ||||||
| %type <formals> formals | %type <formals> formals | ||||||
| %type <formal> formal | %type <formal> formal | ||||||
| %type <ids> ids | %type <ids> ids | ||||||
|  | %type <string_parts> string_parts | ||||||
| %token <id> ID ATTRPATH | %token <id> ID ATTRPATH | ||||||
| %token <t> STR IND_STR | %token <e> STR IND_STR | ||||||
| %token <n> INT | %token <n> INT | ||||||
| %token <path> PATH | %token <path> PATH | ||||||
| %token <uri> URI | %token <uri> URI | ||||||
|  | @ -375,9 +357,8 @@ expr_function | ||||||
|     { $$ = new ExprLambda(CUR_POS, $5, true, $2, $7); } |     { $$ = new ExprLambda(CUR_POS, $5, true, $2, $7); } | ||||||
|   | ID '@' '{' formals '}' ':' expr_function |   | ID '@' '{' formals '}' ':' expr_function | ||||||
|     { $$ = new ExprLambda(CUR_POS, $1, true, $4, $7); } |     { $$ = new ExprLambda(CUR_POS, $1, true, $4, $7); } | ||||||
|   /* | ASSERT expr ';' expr_function |   | ASSERT expr ';' expr_function | ||||||
|     { $$ = makeAssert($2, $4, CUR_POS); } |     { $$ = new ExprAssert(CUR_POS, $2, $4); } | ||||||
|     */ |  | ||||||
|   | 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 | ||||||
|  | @ -391,18 +372,20 @@ expr_if | ||||||
|   ; |   ; | ||||||
| 
 | 
 | ||||||
| expr_op | expr_op | ||||||
|   : /* '!' expr_op %prec NEG { $$ = makeOpNot($2); } |   : '!' expr_op %prec NEG { $$ = new ExprOpNot($2); } | ||||||
|        | */ |   | expr_op EQ expr_op { $$ = new ExprOpEq($1, $3); } | ||||||
|     expr_op EQ expr_op { $$ = new ExprOpEq($1, $3); } |  | ||||||
|   | expr_op NEQ expr_op { $$ = new ExprOpNEq($1, $3); } |   | expr_op NEQ expr_op { $$ = new ExprOpNEq($1, $3); } | ||||||
|   | expr_op AND expr_op { $$ = new ExprOpAnd($1, $3); } |   | expr_op AND expr_op { $$ = new ExprOpAnd($1, $3); } | ||||||
|   | expr_op OR expr_op { $$ = new ExprOpOr($1, $3); } |   | expr_op OR expr_op { $$ = new ExprOpOr($1, $3); } | ||||||
|   | expr_op IMPL expr_op { $$ = new ExprOpImpl($1, $3); } |   | expr_op IMPL expr_op { $$ = new ExprOpImpl($1, $3); } | ||||||
|   | expr_op UPDATE expr_op { $$ = new ExprOpUpdate($1, $3); } |   | expr_op UPDATE expr_op { $$ = new ExprOpUpdate($1, $3); } | ||||||
|   /* |   | expr_op '?' ID { $$ = new ExprOpHasAttr($1, $3); } | ||||||
|   | expr_op '?' ID { $$ = makeOpHasAttr($1, $3); } |   | expr_op '+' expr_op | ||||||
|   */ |     { vector<Expr *> * l = new vector<Expr *>; | ||||||
|   | expr_op '+' expr_op { $$ = new ExprOpConcatStrings($1, $3); } |       l->push_back($1); | ||||||
|  |       l->push_back($3); | ||||||
|  |       $$ = new ExprConcatStrings(l); | ||||||
|  |     } | ||||||
|   | expr_op CONCAT expr_op { $$ = new ExprOpConcatLists($1, $3); } |   | expr_op CONCAT expr_op { $$ = new ExprOpConcatLists($1, $3); } | ||||||
|   | expr_app |   | expr_app | ||||||
|   ; |   ; | ||||||
|  | @ -421,13 +404,14 @@ expr_select | ||||||
| 
 | 
 | ||||||
| expr_simple | expr_simple | ||||||
|   : ID { $$ = new ExprVar($1); } |   : ID { $$ = new ExprVar($1); } | ||||||
|   | INT { $$ = new ExprInt($1); } /* |   | INT { $$ = new ExprInt($1); } | ||||||
|   | '"' string_parts '"' { |   | '"' string_parts '"' { | ||||||
|       /* For efficiency, and to simplify parse trees a bit. * / |       /* For efficiency, and to simplify parse trees a bit. */ | ||||||
|       if ($2 == ATempty) $$ = makeStr(toATerm(""), ATempty); |       if ($2->empty()) $$ = new ExprString(""); | ||||||
|       else if (ATgetNext($2) == ATempty) $$ = ATgetFirst($2); |       else if ($2->size() == 1) $$ = $2->front(); | ||||||
|       else $$ = makeConcatStrings(ATreverse($2)); |       else $$ = new ExprConcatStrings($2); | ||||||
|   } |   } | ||||||
|  |   /* | ||||||
|   | IND_STRING_OPEN ind_string_parts IND_STRING_CLOSE { |   | IND_STRING_OPEN ind_string_parts IND_STRING_CLOSE { | ||||||
|       $$ = stripIndentation(ATreverse($2)); |       $$ = stripIndentation(ATreverse($2)); | ||||||
|   } |   } | ||||||
|  | @ -435,12 +419,10 @@ expr_simple | ||||||
|   | PATH { $$ = new ExprPath(absPath($1, data->basePath)); } |   | PATH { $$ = new ExprPath(absPath($1, data->basePath)); } | ||||||
|   | URI { $$ = new ExprString($1); } |   | URI { $$ = new ExprString($1); } | ||||||
|   | '(' expr ')' { $$ = $2; } |   | '(' expr ')' { $$ = $2; } | ||||||
| /* |  | ||||||
|   /* 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 '}' | ||||||
|     { $$ = makeSelect(fixAttrs(true, $3), toATerm("body")); } |     { fixAttrs(*$3); $3->recursive = true; $$ = new ExprSelect($3, "body"); } | ||||||
|   */ |  | ||||||
|   | REC '{' binds '}' |   | REC '{' binds '}' | ||||||
|     { fixAttrs(*$3); $3->recursive = true; $$ = $3; } |     { fixAttrs(*$3); $3->recursive = true; $$ = $3; } | ||||||
|   | '{' binds '}' |   | '{' binds '}' | ||||||
|  | @ -449,9 +431,9 @@ expr_simple | ||||||
|   ; |   ; | ||||||
| 
 | 
 | ||||||
| string_parts | string_parts | ||||||
|   : string_parts STR { $$ = ATinsert($1, $2); } |   : string_parts STR { $$ = $1; $1->push_back($2); } | ||||||
|   | string_parts DOLLAR_CURLY expr '}' { backToString(scanner); $$ = ATinsert($1, $3); } |   | string_parts DOLLAR_CURLY expr '}' { backToString(scanner); $$ = $1; $1->push_back($3); } | ||||||
|   | { $$ = ATempty; } |   | { $$ = new vector<Expr *>; } | ||||||
|   ; |   ; | ||||||
| 
 | 
 | ||||||
| ind_string_parts | ind_string_parts | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue