* Don't use ATmake / ATmatch anymore, nor the ATMatcher class.
Instead we generate data bindings (build and match functions) for the constructors specified in `constructors.def'. In particular this removes the conversions between AFuns and strings, and Nix expression evaluation now seems 3 to 4 times faster.
This commit is contained in:
		
							parent
							
								
									eb8284ddaa
								
							
						
					
					
						commit
						5fe9222b36
					
				
					 11 changed files with 410 additions and 304 deletions
				
			
		|  | @ -2,9 +2,10 @@ noinst_LIBRARIES = libexpr.a | ||||||
| 
 | 
 | ||||||
| libexpr_a_SOURCES = nixexpr.cc nixexpr.hh parser.cc parser.hh \ | libexpr_a_SOURCES = nixexpr.cc nixexpr.hh parser.cc parser.hh \ | ||||||
|  eval.cc eval.hh primops.cc \ |  eval.cc eval.hh primops.cc \ | ||||||
|  lexer-tab.c lexer-tab.h parser-tab.c parser-tab.h |  lexer-tab.c lexer-tab.h parser-tab.c parser-tab.h \ | ||||||
|  |  constructors.hh | ||||||
| 
 | 
 | ||||||
| EXTRA_DIST = lexer.l parser.y | EXTRA_DIST = lexer.l parser.y constructors.cc | ||||||
| 
 | 
 | ||||||
| AM_CXXFLAGS = \ | AM_CXXFLAGS = \ | ||||||
|  -I.. ${bdb_include} ${aterm_include} -I../libutil -I../libstore |  -I.. ${bdb_include} ${aterm_include} -I../libutil -I../libstore | ||||||
|  | @ -23,4 +24,12 @@ lexer-tab.c lexer-tab.h: lexer.l | ||||||
| 	$(flex) --outfile lexer-tab.c --header-file=lexer-tab.h lexer.l  | 	$(flex) --outfile lexer-tab.c --header-file=lexer-tab.h lexer.l  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | # ATerm helper function generation. | ||||||
|  | 
 | ||||||
|  | constructors.cc constructors.hh: aterm-helper.pl constructors.def | ||||||
|  | 	$(perl) aterm-helper.pl constructors.hh constructors.cc < constructors.def | ||||||
|  | 
 | ||||||
|  | nixexpr.hh: constructors.hh | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| CLEANFILES = | CLEANFILES = | ||||||
|  |  | ||||||
							
								
								
									
										108
									
								
								src/libexpr/aterm-helper.pl
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										108
									
								
								src/libexpr/aterm-helper.pl
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,108 @@ | ||||||
|  | #! /usr/bin/perl -w | ||||||
|  | 
 | ||||||
|  | die if scalar @ARGV != 2; | ||||||
|  | 
 | ||||||
|  | my $syms = ""; | ||||||
|  | my $init = ""; | ||||||
|  | 
 | ||||||
|  | open HEADER, ">$ARGV[0]"; | ||||||
|  | open IMPL, ">$ARGV[1]"; | ||||||
|  | 
 | ||||||
|  | while (<STDIN>) { | ||||||
|  |     next if (/^\s*$/); | ||||||
|  |      | ||||||
|  |     if (/^\s*(\w+)\s*\|([^\|]*)\|\s*(\w+)\s*\|\s*(\w+)?/) { | ||||||
|  |         my $const = $1; | ||||||
|  |         my @types = split ' ', $2; | ||||||
|  |         my $result = $3; | ||||||
|  |         my $funname = $4; | ||||||
|  |         $funname = $const unless defined $funname; | ||||||
|  | 
 | ||||||
|  |         my $formals = ""; | ||||||
|  |         my $formals2 = ""; | ||||||
|  |         my $args = ""; | ||||||
|  |         my $unpack = ""; | ||||||
|  |         my $n = 1; | ||||||
|  |         foreach my $type (@types) { | ||||||
|  |             $args .= ", "; | ||||||
|  |             if ($type eq "string") { | ||||||
|  | #                $args .= "(ATerm) ATmakeAppl0(ATmakeAFun((char *) e$n, 0, ATtrue))"; | ||||||
|  | #                $type = "const char *"; | ||||||
|  |                 $type = "ATerm"; | ||||||
|  |                 $args .= "e$n"; | ||||||
|  |             } elsif ($type eq "int") { | ||||||
|  |                 $args .= "(ATerm) ATmakeInt(e$n)"; | ||||||
|  |             } elsif ($type eq "ATermList" || $type eq "ATermBlob") { | ||||||
|  |                 $args .= "(ATerm) e$n"; | ||||||
|  |             } else { | ||||||
|  |                 $args .= "e$n"; | ||||||
|  |             } | ||||||
|  |             $formals .= ", " if $formals ne ""; | ||||||
|  |             $formals .= "$type e$n"; | ||||||
|  |             $formals2 .= ", "; | ||||||
|  |             $formals2 .= "$type & e$n"; | ||||||
|  |             my $m = $n - 1; | ||||||
|  |             if ($type eq "int") { | ||||||
|  |                 $unpack .= "    e$n = ATgetInt((ATermInt) ATgetArgument(e, $m));\n"; | ||||||
|  |             } elsif ($type eq "ATermList") { | ||||||
|  |                 $unpack .= "    e$n = (ATermList) ATgetArgument(e, $m);\n"; | ||||||
|  |             } elsif ($type eq "ATermBlob") { | ||||||
|  |                 $unpack .= "    e$n = (ATermBlob) ATgetArgument(e, $m);\n"; | ||||||
|  |             } else { | ||||||
|  |                 $unpack .= "    e$n = ATgetArgument(e, $m);\n"; | ||||||
|  |             } | ||||||
|  |             $n++; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         my $arity = scalar @types; | ||||||
|  | 
 | ||||||
|  |         print HEADER "extern AFun sym$funname;\n\n"; | ||||||
|  |          | ||||||
|  |         print IMPL "AFun sym$funname = 0;\n"; | ||||||
|  |          | ||||||
|  |         print HEADER "static inline $result make$funname($formals) {\n"; | ||||||
|  |         print HEADER "    return (ATerm) ATmakeAppl$arity(sym$funname$args);\n"; | ||||||
|  |         print HEADER "}\n\n"; | ||||||
|  | 
 | ||||||
|  |         print HEADER "#ifdef __cplusplus\n"; | ||||||
|  |         print HEADER "static inline bool match$funname(ATerm e$formals2) {\n"; | ||||||
|  |         print HEADER "    if (ATgetAFun(e) != sym$funname) return false;\n"; | ||||||
|  |         print HEADER "$unpack"; | ||||||
|  |         print HEADER "    return true;\n"; | ||||||
|  |         print HEADER "}\n"; | ||||||
|  |         print HEADER "#endif\n\n\n"; | ||||||
|  | 
 | ||||||
|  |         $init .= "    sym$funname = ATmakeAFun(\"$const\", $arity, ATfalse);\n"; | ||||||
|  |         $init .= "    ATprotectAFun(sym$funname);\n"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     elsif (/^\s*(\w+)\s*=\s*(.*)$/) { | ||||||
|  |         my $name = $1; | ||||||
|  |         my $value = $2; | ||||||
|  |         print HEADER "extern ATerm $name;\n"; | ||||||
|  |         print IMPL "ATerm $name = 0;\n"; | ||||||
|  |         $init .= "    $name = $value;\n"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     else { | ||||||
|  |         die "bad line: `$_'"; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | print HEADER "void initSyms();\n\n"; | ||||||
|  | 
 | ||||||
|  | print HEADER "static inline ATerm string2ATerm(const char * s) {\n"; | ||||||
|  | print HEADER "    return (ATerm) ATmakeAppl0(ATmakeAFun((char *) s, 0, ATtrue));\n"; | ||||||
|  | print HEADER "}\n\n"; | ||||||
|  | 
 | ||||||
|  | print HEADER "static inline const char * aterm2String(ATerm t) {\n"; | ||||||
|  | print HEADER "    return (const char *) ATgetName(ATgetAFun(t));\n"; | ||||||
|  | print HEADER "}\n\n"; | ||||||
|  | 
 | ||||||
|  | print IMPL "\n"; | ||||||
|  | print IMPL "void initSyms() {\n"; | ||||||
|  | print IMPL "$init"; | ||||||
|  | print IMPL "}\n"; | ||||||
|  | 
 | ||||||
|  | close HEADER; | ||||||
|  | close IMPL; | ||||||
							
								
								
									
										53
									
								
								src/libexpr/constructors.def
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/libexpr/constructors.def
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,53 @@ | ||||||
|  | Pos | string int int | Pos | | ||||||
|  | NoPos | | Pos | | ||||||
|  | 
 | ||||||
|  | Function | ATermList Expr Pos | Expr | | ||||||
|  | Function1 | string Expr Pos | Expr | | ||||||
|  | Assert | Expr Expr Pos | Expr | | ||||||
|  | With | Expr Expr Pos | Expr | | ||||||
|  | If | Expr Expr Expr | Expr | | ||||||
|  | OpNot | Expr | Expr | | ||||||
|  | OpEq | Expr Expr | Expr | | ||||||
|  | OpNEq | Expr Expr | Expr | | ||||||
|  | OpAnd | Expr Expr | Expr | | ||||||
|  | OpOr | Expr Expr | Expr | | ||||||
|  | OpImpl | Expr Expr | Expr | | ||||||
|  | OpUpdate | Expr Expr | Expr | | ||||||
|  | SubPath | Expr Expr | Expr | | ||||||
|  | OpHasAttr | Expr string | Expr | | ||||||
|  | OpPlus | Expr Expr | Expr | | ||||||
|  | Call | Expr Expr | Expr | | ||||||
|  | Select | Expr string | Expr | | ||||||
|  | Var | string | Expr | | ||||||
|  | Int | int | Expr | | ||||||
|  | Str | string | Expr | | ||||||
|  | Path | string | Expr | | ||||||
|  | Uri | string | Expr | | ||||||
|  | List | ATermList | Expr | | ||||||
|  | BlackHole | | Expr | | ||||||
|  | Undefined | | Expr | | ||||||
|  | PrimOp | int ATermBlob ATermList | Expr | | ||||||
|  | Attrs | ATermList | Expr | | ||||||
|  | Closed | Expr | Expr | | ||||||
|  | Rec | ATermList ATermList | Expr | | ||||||
|  | Bool | ATerm | Expr | | ||||||
|  | Null | | Expr | | ||||||
|  | 
 | ||||||
|  | Bind | string Expr Pos | ATerm | | ||||||
|  | Bind | string Expr | ATerm | Bind2 | ||||||
|  | Inherit | Expr ATermList Pos | ATerm | | ||||||
|  | 
 | ||||||
|  | Scope | | Expr | | ||||||
|  | 
 | ||||||
|  | NoDefFormal | string | ATerm | | ||||||
|  | DefFormal | string Expr | ATerm | | ||||||
|  | 
 | ||||||
|  | True | | ATerm | | ||||||
|  | False | | ATerm | | ||||||
|  | 
 | ||||||
|  | PrimOpDef | int ATermBlob | ATerm | | ||||||
|  | 
 | ||||||
|  | AttrRHS | Expr Pos | ATerm | | ||||||
|  | 
 | ||||||
|  | eTrue = makeBool(makeTrue()) | ||||||
|  | eFalse = makeBool(makeFalse()) | ||||||
|  | @ -1,15 +1,17 @@ | ||||||
| #include "eval.hh" | #include "eval.hh" | ||||||
| #include "parser.hh" | #include "parser.hh" | ||||||
|  | #include "constructors.hh" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| EvalState::EvalState() | EvalState::EvalState() | ||||||
|     : normalForms(32768, 50) |     : normalForms(32768, 50) | ||||||
| { | { | ||||||
|     blackHole = ATmake("BlackHole()"); |     blackHole = makeBlackHole(); | ||||||
|     if (!blackHole) throw Error("cannot build black hole"); |  | ||||||
|      |      | ||||||
|     nrEvaluated = nrCached = 0; |     nrEvaluated = nrCached = 0; | ||||||
| 
 | 
 | ||||||
|  |     initSyms(); | ||||||
|  | 
 | ||||||
|     addPrimOps(); |     addPrimOps(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -17,24 +19,22 @@ EvalState::EvalState() | ||||||
| void EvalState::addPrimOp(const string & name, | void EvalState::addPrimOp(const string & name, | ||||||
|     unsigned int arity, PrimOp primOp) |     unsigned int arity, PrimOp primOp) | ||||||
| { | { | ||||||
|     primOps.set(name, ATmake("(<int>, <term>)", |     primOps.set(name, makePrimOpDef(arity, ATmakeBlob(0, (void *) primOp))); | ||||||
|         arity, ATmakeBlob(0, (void *) primOp))); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Substitute an argument set into the body of a function. */ | /* Substitute an argument set into the body of a function. */ | ||||||
| static Expr substArgs(Expr body, ATermList formals, Expr arg) | static Expr substArgs(Expr body, ATermList formals, Expr arg) | ||||||
| { | { | ||||||
|     ATMatcher m; |  | ||||||
|     ATermMap subs; |     ATermMap subs; | ||||||
|     Expr undefined = ATmake("Undefined"); |     Expr undefined = makeUndefined(); | ||||||
| 
 | 
 | ||||||
|     /* Get the formal arguments. */ |     /* Get the formal arguments. */ | ||||||
|     for (ATermIterator i(formals); i; ++i) { |     for (ATermIterator i(formals); i; ++i) { | ||||||
|         Expr name, def; |         Expr name, def; | ||||||
|         if (atMatch(m, *i) >> "NoDefFormal" >> name) |         if (matchNoDefFormal(*i, name)) | ||||||
|             subs.set(name, undefined); |             subs.set(name, undefined); | ||||||
|         else if (atMatch(m, *i) >> "DefFormal" >> name >> def) |         else if (matchDefFormal(*i, name, def)) | ||||||
|             subs.set(name, def); |             subs.set(name, def); | ||||||
|         else abort(); /* can't happen */ |         else abort(); /* can't happen */ | ||||||
|     } |     } | ||||||
|  | @ -69,38 +69,32 @@ static Expr substArgs(Expr body, ATermList formals, Expr arg) | ||||||
|    (e.x) (e.y); y = e.x;}'. */ |    (e.x) (e.y); y = e.x;}'. */ | ||||||
| ATerm expandRec(ATerm e, ATermList rbnds, ATermList nrbnds) | ATerm expandRec(ATerm e, ATermList rbnds, ATermList nrbnds) | ||||||
| { | { | ||||||
|     ATMatcher m; |  | ||||||
|     ATerm name; |     ATerm name; | ||||||
|     Expr e2; |     Expr e2; | ||||||
|  |     Pos pos; | ||||||
| 
 | 
 | ||||||
|     /* Create the substitution list. */ |     /* Create the substitution list. */ | ||||||
|     ATermMap subs; |     ATermMap subs; | ||||||
|     for (ATermIterator i(rbnds); i; ++i) { |     for (ATermIterator i(rbnds); i; ++i) { | ||||||
|         if (!(atMatch(m, *i) >> "Bind" >> name >> e2)) |         if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */ | ||||||
|             abort(); /* can't happen */ |         subs.set(name, makeSelect(e, name)); | ||||||
|         subs.set(name, ATmake("Select(<term>, <term>)", e, name)); |  | ||||||
|     } |     } | ||||||
|     for (ATermIterator i(nrbnds); i; ++i) { |     for (ATermIterator i(nrbnds); i; ++i) { | ||||||
|         if (!(atMatch(m, *i) >> "Bind" >> name >> e2)) |         if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */ | ||||||
|             abort(); /* can't happen */ |  | ||||||
|         subs.set(name, e2); |         subs.set(name, e2); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* Create the non-recursive set. */ |     /* Create the non-recursive set. */ | ||||||
|     ATermMap as; |     ATermMap as; | ||||||
|     for (ATermIterator i(rbnds); i; ++i) { |     for (ATermIterator i(rbnds); i; ++i) { | ||||||
|         ATerm pos; |         if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */ | ||||||
|         if (!(atMatch(m, *i) >> "Bind" >> name >> e2 >> pos)) |         as.set(name, makeAttrRHS(substitute(subs, e2), pos)); | ||||||
|             abort(); /* can't happen */ |  | ||||||
|         as.set(name, ATmake("(<term>, <term>)", substitute(subs, e2), pos)); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* Copy the non-recursive bindings.  !!! inefficient */ |     /* Copy the non-recursive bindings.  !!! inefficient */ | ||||||
|     for (ATermIterator i(nrbnds); i; ++i) { |     for (ATermIterator i(nrbnds); i; ++i) { | ||||||
|         ATerm pos; |         if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */ | ||||||
|         if (!(atMatch(m, *i) >> "Bind" >> name >> e2 >> pos)) |         as.set(name, makeAttrRHS(e2, pos)); | ||||||
|             abort(); /* can't happen */ |  | ||||||
|         as.set(name, ATmake("(<term>, <term>)", e2, pos)); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return makeAttrs(as); |     return makeAttrs(as); | ||||||
|  | @ -122,82 +116,73 @@ static Expr updateAttrs(Expr e1, Expr e2) | ||||||
| string evalString(EvalState & state, Expr e) | string evalString(EvalState & state, Expr e) | ||||||
| { | { | ||||||
|     e = evalExpr(state, e); |     e = evalExpr(state, e); | ||||||
|     ATMatcher m; |     ATerm s; | ||||||
|     string s; |     if (!matchStr(e, s)) throw Error("string expected"); | ||||||
|     if (!(atMatch(m, e) >> "Str" >> s)) |     return aterm2String(s); | ||||||
|         throw Error("string expected"); |  | ||||||
|     return s; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| Path evalPath(EvalState & state, Expr e) | Path evalPath(EvalState & state, Expr e) | ||||||
| { | { | ||||||
|     e = evalExpr(state, e); |     e = evalExpr(state, e); | ||||||
|     ATMatcher m; |     ATerm s; | ||||||
|     string s; |     if (!matchPath(e, s)) throw Error("path expected"); | ||||||
|     if (!(atMatch(m, e) >> "Path" >> s)) |     return aterm2String(s); | ||||||
|         throw Error("path expected"); |  | ||||||
|     return s; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| bool evalBool(EvalState & state, Expr e) | bool evalBool(EvalState & state, Expr e) | ||||||
| { | { | ||||||
|     e = evalExpr(state, e); |     e = evalExpr(state, e); | ||||||
|     ATMatcher m; |     if (e == eTrue) return true; | ||||||
|     if (atMatch(m, e) >> "Bool" >> "True") return true; |     else if (e == eFalse) return false; | ||||||
|     else if (atMatch(m, e) >> "Bool" >> "False") return false; |  | ||||||
|     else throw Error("boolean expected"); |     else throw Error("boolean expected"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| Expr evalExpr2(EvalState & state, Expr e) | Expr evalExpr2(EvalState & state, Expr e) | ||||||
| { | { | ||||||
|     ATMatcher m; |  | ||||||
|     Expr e1, e2, e3, e4; |     Expr e1, e2, e3, e4; | ||||||
|     ATerm name, pos; |     ATerm name, pos; | ||||||
|  |     AFun sym = ATgetAFun(e); | ||||||
| 
 | 
 | ||||||
|     /* Normal forms. */ |     /* Normal forms. */ | ||||||
|     string cons; |     if (sym == symStr || | ||||||
|     if (atMatch(m, e) >> cons && |         sym == symPath || | ||||||
|         (cons == "Str" || |         sym == symSubPath || | ||||||
|          cons == "Path" || |         sym == symUri || | ||||||
|          cons == "SubPath" || |         sym == symNull || | ||||||
|          cons == "Uri" || |         sym == symInt || | ||||||
|          cons == "Null" || |         sym == symBool || | ||||||
|          cons == "Int" || |         sym == symFunction || | ||||||
|          cons == "Bool" || |         sym == symFunction1 || | ||||||
|          cons == "Function" || |         sym == symAttrs || | ||||||
|          cons == "Function1" || |         sym == symList || | ||||||
|          cons == "Attrs" || |         sym == symPrimOp) | ||||||
|          cons == "List" || |  | ||||||
|          cons == "PrimOp")) |  | ||||||
|         return e; |         return e; | ||||||
| 
 |      | ||||||
|     /* The `Closed' constructor is just a way to prevent substitutions
 |     /* The `Closed' constructor is just a way to prevent substitutions
 | ||||||
|        into expressions not containing free variables. */ |        into expressions not containing free variables. */ | ||||||
|     if (atMatch(m, e) >> "Closed" >> e1) |     if (matchClosed(e, e1)) | ||||||
|         return evalExpr(state, e1); |         return evalExpr(state, e1); | ||||||
| 
 | 
 | ||||||
|     /* Any encountered variables must be primops (since undefined
 |     /* Any encountered variables must be primops (since undefined
 | ||||||
|        variables are detected after parsing). */ |        variables are detected after parsing). */ | ||||||
|     if (atMatch(m, e) >> "Var" >> name) { |     if (matchVar(e, name)) { | ||||||
|         ATerm primOp = state.primOps.get(name); |         ATerm primOp = state.primOps.get(name); | ||||||
|         if (!primOp) |         if (!primOp) | ||||||
|             throw Error(format("impossible: undefined variable `%1%'") % name); |             throw Error(format("impossible: undefined variable `%1%'") % name); | ||||||
|         int arity; |         int arity; | ||||||
|         ATerm fun; |         ATermBlob fun; | ||||||
|         if (!(atMatch(m, primOp) >> "" >> arity >> fun)) abort(); |         if (!matchPrimOpDef(primOp, arity, fun)) abort(); | ||||||
|         if (arity == 0) |         if (arity == 0) | ||||||
|             return ((PrimOp) ATgetBlobData((ATermBlob) fun)) |             return ((PrimOp) ATgetBlobData(fun)) (state, ATermVector()); | ||||||
|                 (state, ATermVector()); |  | ||||||
|         else |         else | ||||||
|             return ATmake("PrimOp(<int>, <term>, <term>)", |             return makePrimOp(arity, fun, ATempty); | ||||||
|                 arity, fun, ATempty); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* Function application. */ |     /* Function application. */ | ||||||
|     if (atMatch(m, e) >> "Call" >> e1 >> e2) { |     if (matchCall(e, e1, e2)) { | ||||||
| 
 | 
 | ||||||
|         ATermList formals; |         ATermList formals; | ||||||
|         ATerm pos; |         ATerm pos; | ||||||
|  | @ -207,9 +192,9 @@ Expr evalExpr2(EvalState & state, Expr e) | ||||||
| 
 | 
 | ||||||
|         /* Is it a primop or a function? */ |         /* Is it a primop or a function? */ | ||||||
|         int arity; |         int arity; | ||||||
|         ATerm fun; |         ATermBlob fun; | ||||||
|         ATermList args; |         ATermList args; | ||||||
|         if (atMatch(m, e1) >> "PrimOp" >> arity >> fun >> args) { |         if (matchPrimOp(e1, arity, fun, args)) { | ||||||
|             args = ATinsert(args, e2); |             args = ATinsert(args, e2); | ||||||
|             if (ATgetLength(args) == arity) { |             if (ATgetLength(args) == arity) { | ||||||
|                 /* Put the arguments in a vector in reverse (i.e.,
 |                 /* Put the arguments in a vector in reverse (i.e.,
 | ||||||
|  | @ -221,11 +206,10 @@ Expr evalExpr2(EvalState & state, Expr e) | ||||||
|                     (state, args2); |                     (state, args2); | ||||||
|             } else |             } else | ||||||
|                 /* Need more arguments, so propagate the primop. */ |                 /* Need more arguments, so propagate the primop. */ | ||||||
|                 return ATmake("PrimOp(<int>, <term>, <term>)", |                 return makePrimOp(arity, fun, args); | ||||||
|                     arity, fun, args); |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         else if (atMatch(m, e1) >> "Function" >> formals >> e4 >> pos) { |         else if (matchFunction(e1, formals, e4, pos)) { | ||||||
|             e2 = evalExpr(state, e2); |             e2 = evalExpr(state, e2); | ||||||
|             try { |             try { | ||||||
|                 return evalExpr(state, substArgs(e4, formals, e2)); |                 return evalExpr(state, substArgs(e4, formals, e2)); | ||||||
|  | @ -235,7 +219,7 @@ Expr evalExpr2(EvalState & state, Expr e) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|         else if (atMatch(m, e1) >> "Function1" >> name >> e4 >> pos) { |         else if (matchFunction1(e1, name, e4, pos)) { | ||||||
|             try { |             try { | ||||||
|                 ATermMap subs; |                 ATermMap subs; | ||||||
|                 subs.set(name, e2); |                 subs.set(name, e2); | ||||||
|  | @ -250,9 +234,9 @@ Expr evalExpr2(EvalState & state, Expr e) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* Attribute selection. */ |     /* Attribute selection. */ | ||||||
|     string s1; |     if (matchSelect(e, e1, name)) { | ||||||
|     if (atMatch(m, e) >> "Select" >> e1 >> s1) { |  | ||||||
|         ATerm pos; |         ATerm pos; | ||||||
|  |         string s1 = aterm2String(name); | ||||||
|         Expr a = queryAttr(evalExpr(state, e1), s1, pos); |         Expr a = queryAttr(evalExpr(state, e1), s1, pos); | ||||||
|         if (!a) throw Error(format("attribute `%1%' missing") % s1); |         if (!a) throw Error(format("attribute `%1%' missing") % s1); | ||||||
|         try { |         try { | ||||||
|  | @ -265,11 +249,11 @@ Expr evalExpr2(EvalState & state, Expr e) | ||||||
| 
 | 
 | ||||||
|     /* Mutually recursive sets. */ |     /* Mutually recursive sets. */ | ||||||
|     ATermList rbnds, nrbnds; |     ATermList rbnds, nrbnds; | ||||||
|     if (atMatch(m, e) >> "Rec" >> rbnds >> nrbnds) |     if (matchRec(e, rbnds, nrbnds)) | ||||||
|         return expandRec(e, rbnds, nrbnds); |         return expandRec(e, rbnds, nrbnds); | ||||||
| 
 | 
 | ||||||
|     /* Conditionals. */ |     /* Conditionals. */ | ||||||
|     if (atMatch(m, e) >> "If" >> e1 >> e2 >> e3) { |     if (matchIf(e, e1, e2, e3)) { | ||||||
|         if (evalBool(state, e1)) |         if (evalBool(state, e1)) | ||||||
|             return evalExpr(state, e2); |             return evalExpr(state, e2); | ||||||
|         else |         else | ||||||
|  | @ -277,14 +261,14 @@ Expr evalExpr2(EvalState & state, Expr e) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* Assertions. */ |     /* Assertions. */ | ||||||
|     if (atMatch(m, e) >> "Assert" >> e1 >> e2 >> pos) { |     if (matchAssert(e, e1, e2, pos)) { | ||||||
|         if (!evalBool(state, e1)) |         if (!evalBool(state, e1)) | ||||||
|             throw Error(format("assertion failed at %1%") % showPos(pos)); |             throw Error(format("assertion failed at %1%") % showPos(pos)); | ||||||
|         return evalExpr(state, e2); |         return evalExpr(state, e2); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* Withs. */ |     /* Withs. */ | ||||||
|     if (atMatch(m, e) >> "With" >> e1 >> e2 >> pos) { |     if (matchWith(e, e1, e2, pos)) { | ||||||
|         ATermMap attrs; |         ATermMap attrs; | ||||||
|         try { |         try { | ||||||
|             e1 = evalExpr(state, e1); |             e1 = evalExpr(state, e1); | ||||||
|  | @ -304,51 +288,51 @@ Expr evalExpr2(EvalState & state, Expr e) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* Generic equality. */ |     /* Generic equality. */ | ||||||
|     if (atMatch(m, e) >> "OpEq" >> e1 >> e2) |     if (matchOpEq(e, e1, e2)) | ||||||
|         return makeBool(evalExpr(state, e1) == evalExpr(state, e2)); |         return makeBool(evalExpr(state, e1) == evalExpr(state, e2)); | ||||||
| 
 | 
 | ||||||
|     /* Generic inequality. */ |     /* Generic inequality. */ | ||||||
|     if (atMatch(m, e) >> "OpNEq" >> e1 >> e2) |     if (matchOpNEq(e, e1, e2)) | ||||||
|         return makeBool(evalExpr(state, e1) != evalExpr(state, e2)); |         return makeBool(evalExpr(state, e1) != evalExpr(state, e2)); | ||||||
| 
 | 
 | ||||||
|     /* Negation. */ |     /* Negation. */ | ||||||
|     if (atMatch(m, e) >> "OpNot" >> e1) |     if (matchOpNot(e, e1)) | ||||||
|         return makeBool(!evalBool(state, e1)); |         return makeBool(!evalBool(state, e1)); | ||||||
| 
 | 
 | ||||||
|     /* Implication. */ |     /* Implication. */ | ||||||
|     if (atMatch(m, e) >> "OpImpl" >> e1 >> e2) |     if (matchOpImpl(e, e1, e2)) | ||||||
|         return makeBool(!evalBool(state, e1) || evalBool(state, e2)); |         return makeBool(!evalBool(state, e1) || evalBool(state, e2)); | ||||||
| 
 | 
 | ||||||
|     /* Conjunction (logical AND). */ |     /* Conjunction (logical AND). */ | ||||||
|     if (atMatch(m, e) >> "OpAnd" >> e1 >> e2) |     if (matchOpAnd(e, e1, e2)) | ||||||
|         return makeBool(evalBool(state, e1) && evalBool(state, e2)); |         return makeBool(evalBool(state, e1) && evalBool(state, e2)); | ||||||
| 
 | 
 | ||||||
|     /* Disjunction (logical OR). */ |     /* Disjunction (logical OR). */ | ||||||
|     if (atMatch(m, e) >> "OpOr" >> e1 >> e2) |     if (matchOpOr(e, e1, e2)) | ||||||
|         return makeBool(evalBool(state, e1) || evalBool(state, e2)); |         return makeBool(evalBool(state, e1) || evalBool(state, e2)); | ||||||
| 
 | 
 | ||||||
|     /* Attribute set update (//). */ |     /* Attribute set update (//). */ | ||||||
|     if (atMatch(m, e) >> "OpUpdate" >> e1 >> e2) |     if (matchOpUpdate(e, e1, e2)) | ||||||
|         return updateAttrs(evalExpr(state, e1), evalExpr(state, e2)); |         return updateAttrs(evalExpr(state, e1), evalExpr(state, e2)); | ||||||
| 
 | 
 | ||||||
|     /* Attribute existence test (?). */ |     /* Attribute existence test (?). */ | ||||||
|     if (atMatch(m, e) >> "OpHasAttr" >> e1 >> name) { |     if (matchOpHasAttr(e, e1, name)) { | ||||||
|         ATermMap attrs; |         ATermMap attrs; | ||||||
|         queryAllAttrs(evalExpr(state, e1), attrs); |         queryAllAttrs(evalExpr(state, e1), attrs); | ||||||
|         return makeBool(attrs.get(name) != 0); |         return makeBool(attrs.get(name) != 0); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* String or path concatenation. */ |     /* String or path concatenation. */ | ||||||
|     if (atMatch(m, e) >> "OpPlus" >> e1 >> e2) { |     if (matchOpPlus(e, e1, e2)) { | ||||||
|         e1 = evalExpr(state, e1); |         e1 = evalExpr(state, e1); | ||||||
|         e2 = evalExpr(state, e2); |         e2 = evalExpr(state, e2); | ||||||
|         string s1, s2; |         ATerm s1, s2; | ||||||
|         if (atMatch(m, e1) >> "Str" >> s1 && |         if (matchStr(e1, s1) && matchStr(e2, s2)) | ||||||
|             atMatch(m, e2) >> "Str" >> s2) |             return makeStr(string2ATerm(( | ||||||
|             return makeString(s1 + s2); |                 (string) aterm2String(s1) + (string) aterm2String(s2)).c_str())); | ||||||
|         else if (atMatch(m, e1) >> "Path" >> s1 && |         else if (matchPath(e1, s1) && matchPath(e2, s2)) | ||||||
|             atMatch(m, e2) >> "Path" >> s2) |             return makePath(string2ATerm(canonPath( | ||||||
|             return makePath(canonPath(s1 + "/" + s2)); |                 (string) aterm2String(s1) + "/" + (string) aterm2String(s2)).c_str())); | ||||||
|         else throw Error("wrong argument types in `+' operator"); |         else throw Error("wrong argument types in `+' operator"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -2,6 +2,10 @@ | ||||||
| #include "storeexpr.hh" | #include "storeexpr.hh" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | #include "constructors.hh" | ||||||
|  | #include "constructors.cc" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| ATermMap::ATermMap(unsigned int initialSize, unsigned int maxLoadPct) | ATermMap::ATermMap(unsigned int initialSize, unsigned int maxLoadPct) | ||||||
| { | { | ||||||
|     this->maxLoadPct = maxLoadPct; |     this->maxLoadPct = maxLoadPct; | ||||||
|  | @ -38,7 +42,7 @@ void ATermMap::set(ATerm key, ATerm value) | ||||||
| 
 | 
 | ||||||
| void ATermMap::set(const string & key, ATerm value) | void ATermMap::set(const string & key, ATerm value) | ||||||
| { | { | ||||||
|     set(string2ATerm(key), value); |     set(string2ATerm(key.c_str()), value); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -50,7 +54,7 @@ ATerm ATermMap::get(ATerm key) const | ||||||
| 
 | 
 | ||||||
| ATerm ATermMap::get(const string & key) const | ATerm ATermMap::get(const string & key) const | ||||||
| { | { | ||||||
|     return get(string2ATerm(key)); |     return get(string2ATerm(key.c_str())); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -62,7 +66,7 @@ void ATermMap::remove(ATerm key) | ||||||
| 
 | 
 | ||||||
| void ATermMap::remove(const string & key) | void ATermMap::remove(const string & key) | ||||||
| { | { | ||||||
|     remove(string2ATerm(key)); |     remove(string2ATerm(key.c_str())); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -94,28 +98,14 @@ void ATermMap::reset() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ATerm string2ATerm(const string & s) |  | ||||||
| { |  | ||||||
|     return (ATerm) ATmakeAppl0(ATmakeAFun((char *) s.c_str(), 0, ATtrue)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| string aterm2String(ATerm t) |  | ||||||
| { |  | ||||||
|     return ATgetName(ATgetAFun(t)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| string showPos(ATerm pos) | string showPos(ATerm pos) | ||||||
| { | { | ||||||
|     ATMatcher m; |     ATerm path; | ||||||
|     Path path; |  | ||||||
|     int line, column; |     int line, column; | ||||||
|     if (atMatch(m, pos) >> "NoPos") |     if (matchNoPos(pos)) return "undefined position"; | ||||||
|         return "undefined position"; |     if (!matchPos(pos, path, line, column)) | ||||||
|     if (!(atMatch(m, pos) >> "Pos" >> path >> line >> column)) |  | ||||||
|         throw badTerm("position expected", pos); |         throw badTerm("position expected", pos); | ||||||
|     return (format("`%1%', line %2%") % path % line).str(); |     return (format("`%1%', line %2%") % aterm2String(path) % line).str(); | ||||||
| } | } | ||||||
|      |      | ||||||
| 
 | 
 | ||||||
|  | @ -150,18 +140,16 @@ ATerm bottomupRewrite(TermFun & f, ATerm e) | ||||||
| 
 | 
 | ||||||
| void queryAllAttrs(Expr e, ATermMap & attrs, bool withPos) | void queryAllAttrs(Expr e, ATermMap & attrs, bool withPos) | ||||||
| { | { | ||||||
|     ATMatcher m; |  | ||||||
|     ATermList bnds; |     ATermList bnds; | ||||||
|     if (!(atMatch(m, e) >> "Attrs" >> bnds)) |     if (!matchAttrs(e, bnds)) | ||||||
|         throw Error("attribute set expected"); |         throw Error("attribute set expected"); | ||||||
| 
 | 
 | ||||||
|     for (ATermIterator i(bnds); i; ++i) { |     for (ATermIterator i(bnds); i; ++i) { | ||||||
|         string s; |         ATerm name; | ||||||
|         Expr e; |         Expr e; | ||||||
|         ATerm pos; |         ATerm pos; | ||||||
|         if (!(atMatch(m, *i) >> "Bind" >> s >> e >> pos)) |         if (!matchBind(*i, name, e, pos)) abort(); /* can't happen */ | ||||||
|             abort(); /* can't happen */ |         attrs.set(name, withPos ? makeAttrRHS(e, pos) : e); | ||||||
|         attrs.set(s, withPos ? ATmake("(<term>, <term>)", e, pos) : e); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -175,18 +163,16 @@ Expr queryAttr(Expr e, const string & name) | ||||||
| 
 | 
 | ||||||
| Expr queryAttr(Expr e, const string & name, ATerm & pos) | Expr queryAttr(Expr e, const string & name, ATerm & pos) | ||||||
| { | { | ||||||
|     ATMatcher m; |  | ||||||
|     ATermList bnds; |     ATermList bnds; | ||||||
|     if (!(atMatch(m, e) >> "Attrs" >> bnds)) |     if (!matchAttrs(e, bnds)) | ||||||
|         throw Error("attribute set expected"); |         throw Error("attribute set expected"); | ||||||
| 
 | 
 | ||||||
|     for (ATermIterator i(bnds); i; ++i) { |     for (ATermIterator i(bnds); i; ++i) { | ||||||
|         string s; |         ATerm name2, pos2; | ||||||
|         Expr e; |         Expr e; | ||||||
|         ATerm pos2; |         if (!matchBind(*i, name2, e, pos2)) | ||||||
|         if (!(atMatch(m, *i) >> "Bind" >> s >> e >> pos2)) |  | ||||||
|             abort(); /* can't happen */ |             abort(); /* can't happen */ | ||||||
|         if (s == name) { |         if (aterm2String(name2) == name) { | ||||||
|             pos = pos2; |             pos = pos2; | ||||||
|             return e; |             return e; | ||||||
|         } |         } | ||||||
|  | @ -198,17 +184,15 @@ Expr queryAttr(Expr e, const string & name, ATerm & pos) | ||||||
| 
 | 
 | ||||||
| Expr makeAttrs(const ATermMap & attrs) | Expr makeAttrs(const ATermMap & attrs) | ||||||
| { | { | ||||||
|     ATMatcher m; |  | ||||||
|     ATermList bnds = ATempty; |     ATermList bnds = ATempty; | ||||||
|     for (ATermIterator i(attrs.keys()); i; ++i) { |     for (ATermIterator i(attrs.keys()); i; ++i) { | ||||||
|         Expr e; |         Expr e; | ||||||
|         ATerm pos; |         ATerm pos; | ||||||
|         if (!(atMatch(m, attrs.get(*i)) >> "" >> e >> pos)) |         if (!matchAttrRHS(attrs.get(*i), e, pos)) | ||||||
|             abort(); /* can't happen */ |             abort(); /* can't happen */ | ||||||
|         bnds = ATinsert(bnds,  |         bnds = ATinsert(bnds, makeBind(*i, e, pos)); | ||||||
|             ATmake("Bind(<term>, <term>, <term>)", *i, e, pos)); |  | ||||||
|     } |     } | ||||||
|     return ATmake("Attrs(<term>)", ATreverse(bnds)); |     return makeAttrs(ATreverse(bnds)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -216,57 +200,53 @@ Expr substitute(const ATermMap & subs, Expr e) | ||||||
| { | { | ||||||
|     checkInterrupt(); |     checkInterrupt(); | ||||||
| 
 | 
 | ||||||
|     ATMatcher m; |     ATerm name, pos, e2; | ||||||
|     ATerm name, pos; |  | ||||||
| 
 | 
 | ||||||
|     /* As an optimisation, don't substitute in subterms known to be
 |     /* As an optimisation, don't substitute in subterms known to be
 | ||||||
|        closed. */ |        closed. */ | ||||||
|     if (atMatch(m, e) >> "Closed") return e; |     if (matchClosed(e, e2)) return e; | ||||||
| 
 | 
 | ||||||
|     if (atMatch(m, e) >> "Var" >> name) { |     if (matchVar(e, name)) { | ||||||
|         Expr sub = subs.get(name); |         Expr sub = subs.get(name); | ||||||
|         return sub ? ATmake("Closed(<term>)", sub) : e; |         return sub ? makeClosed(sub) : e; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* In case of a function, filter out all variables bound by this
 |     /* In case of a function, filter out all variables bound by this
 | ||||||
|        function. */ |        function. */ | ||||||
|     ATermList formals; |     ATermList formals; | ||||||
|     ATerm body; |     ATerm body, def; | ||||||
|     if (atMatch(m, e) >> "Function" >> formals >> body >> pos) { |     if (matchFunction(e, formals, body, pos)) { | ||||||
|         ATermMap subs2(subs); |         ATermMap subs2(subs); | ||||||
|         for (ATermIterator i(formals); i; ++i) { |         for (ATermIterator i(formals); i; ++i) { | ||||||
|             if (!(atMatch(m, *i) >> "NoDefFormal" >> name) && |             if (!matchNoDefFormal(*i, name) && | ||||||
|                 !(atMatch(m, *i) >> "DefFormal" >> name)) |                 !matchDefFormal(*i, name, def)) | ||||||
|                 abort(); |                 abort(); | ||||||
|             subs2.remove(name); |             subs2.remove(name); | ||||||
|         } |         } | ||||||
|         return ATmake("Function(<term>, <term>, <term>)", |         return makeFunction( | ||||||
|             substitute(subs, (ATerm) formals), |             (ATermList) substitute(subs, (ATerm) formals), | ||||||
|             substitute(subs2, body), pos); |             substitute(subs2, body), pos); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (atMatch(m, e) >> "Function1" >> name >> body >> pos) { |     if (matchFunction1(e, name, body, pos)) { | ||||||
|         ATermMap subs2(subs); |         ATermMap subs2(subs); | ||||||
|         subs2.remove(name); |         subs2.remove(name); | ||||||
|         return ATmake("Function1(<term>, <term>, <term>)", name, |         return makeFunction1(name, substitute(subs2, body), pos); | ||||||
|             substitute(subs2, body), pos); |  | ||||||
|     } |     } | ||||||
|          |          | ||||||
|     /* Idem for a mutually recursive attribute set. */ |     /* Idem for a mutually recursive attribute set. */ | ||||||
|     ATermList rbnds, nrbnds; |     ATermList rbnds, nrbnds; | ||||||
|     if (atMatch(m, e) >> "Rec" >> rbnds >> nrbnds) { |     if (matchRec(e, rbnds, nrbnds)) { | ||||||
|         ATermMap subs2(subs); |         ATermMap subs2(subs); | ||||||
|         for (ATermIterator i(rbnds); i; ++i) |         for (ATermIterator i(rbnds); i; ++i) | ||||||
|             if (atMatch(m, *i) >> "Bind" >> name) |             if (matchBind(*i, name, e2, pos)) subs2.remove(name); | ||||||
|                 subs2.remove(name); |  | ||||||
|             else abort(); /* can't happen */ |             else abort(); /* can't happen */ | ||||||
|         for (ATermIterator i(nrbnds); i; ++i) |         for (ATermIterator i(nrbnds); i; ++i) | ||||||
|             if (atMatch(m, *i) >> "Bind" >> name) |             if (matchBind(*i, name, e2, pos)) subs2.remove(name); | ||||||
|                 subs2.remove(name); |  | ||||||
|             else abort(); /* can't happen */ |             else abort(); /* can't happen */ | ||||||
|         return ATmake("Rec(<term>, <term>)", |         return makeRec( | ||||||
|             substitute(subs2, (ATerm) rbnds), |             (ATermList) substitute(subs2, (ATerm) rbnds), | ||||||
|             substitute(subs, (ATerm) nrbnds)); |             (ATermList) substitute(subs, (ATerm) nrbnds)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (ATgetType(e) == AT_APPL) { |     if (ATgetType(e) == AT_APPL) { | ||||||
|  | @ -293,24 +273,23 @@ Expr substitute(const ATermMap & subs, Expr e) | ||||||
| 
 | 
 | ||||||
| void checkVarDefs(const ATermMap & defs, Expr e) | void checkVarDefs(const ATermMap & defs, Expr e) | ||||||
| { | { | ||||||
|     ATMatcher m; |     ATerm name, pos, value; | ||||||
|     ATerm name; |  | ||||||
|     ATermList formals; |     ATermList formals; | ||||||
|     ATerm with, body; |     ATerm with, body; | ||||||
|     ATermList rbnds, nrbnds; |     ATermList rbnds, nrbnds; | ||||||
| 
 | 
 | ||||||
|     if (atMatch(m, e) >> "Var" >> name) { |     if (matchVar(e, name)) { | ||||||
|         if (!defs.get(name)) |         if (!defs.get(name)) | ||||||
|             throw Error(format("undefined variable `%1%'") |             throw Error(format("undefined variable `%1%'") | ||||||
|                 % aterm2String(name)); |                 % aterm2String(name)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     else if (atMatch(m, e) >> "Function" >> formals >> body) { |     else if (matchFunction(e, formals, body, pos)) { | ||||||
|         ATermMap defs2(defs); |         ATermMap defs2(defs); | ||||||
|         for (ATermIterator i(formals); i; ++i) { |         for (ATermIterator i(formals); i; ++i) { | ||||||
|             Expr deflt; |             Expr deflt; | ||||||
|             if (!(atMatch(m, *i) >> "NoDefFormal" >> name)) |             if (!matchNoDefFormal(*i, name)) | ||||||
|                 if (atMatch(m, *i) >> "DefFormal" >> name >> deflt) |                 if (matchDefFormal(*i, name, deflt)) | ||||||
|                     checkVarDefs(defs, deflt); |                     checkVarDefs(defs, deflt); | ||||||
|                 else |                 else | ||||||
|                     abort(); |                     abort(); | ||||||
|  | @ -319,29 +298,27 @@ void checkVarDefs(const ATermMap & defs, Expr e) | ||||||
|         checkVarDefs(defs2, body); |         checkVarDefs(defs2, body); | ||||||
|     } |     } | ||||||
|          |          | ||||||
|     else if (atMatch(m, e) >> "Function1" >> name >> body) { |     else if (matchFunction1(e, name, body, pos)) { | ||||||
|         ATermMap defs2(defs); |         ATermMap defs2(defs); | ||||||
|         defs2.set(name, (ATerm) ATempty); |         defs2.set(name, (ATerm) ATempty); | ||||||
|         checkVarDefs(defs2, body); |         checkVarDefs(defs2, body); | ||||||
|     } |     } | ||||||
|          |          | ||||||
|     else if (atMatch(m, e) >> "Rec" >> rbnds >> nrbnds) { |     else if (matchRec(e, rbnds, nrbnds)) { | ||||||
|         checkVarDefs(defs, (ATerm) nrbnds); |         checkVarDefs(defs, (ATerm) nrbnds); | ||||||
|         ATermMap defs2(defs); |         ATermMap defs2(defs); | ||||||
|         for (ATermIterator i(rbnds); i; ++i) { |         for (ATermIterator i(rbnds); i; ++i) { | ||||||
|             if (!(atMatch(m, *i) >> "Bind" >> name)) |             if (!matchBind(*i, name, value, pos)) abort(); /* can't happen */ | ||||||
|                 abort(); /* can't happen */ |  | ||||||
|             defs2.set(name, (ATerm) ATempty); |             defs2.set(name, (ATerm) ATempty); | ||||||
|         } |         } | ||||||
|         for (ATermIterator i(nrbnds); i; ++i) { |         for (ATermIterator i(nrbnds); i; ++i) { | ||||||
|             if (!(atMatch(m, *i) >> "Bind" >> name)) |             if (!matchBind(*i, name, value, pos)) abort(); /* can't happen */ | ||||||
|                 abort(); /* can't happen */ |  | ||||||
|             defs2.set(name, (ATerm) ATempty); |             defs2.set(name, (ATerm) ATempty); | ||||||
|         } |         } | ||||||
|         checkVarDefs(defs2, (ATerm) rbnds); |         checkVarDefs(defs2, (ATerm) rbnds); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     else if (atMatch(m, e) >> "With" >> with >> body) { |     else if (matchWith(e, with, body, pos)) { | ||||||
|         /* We can't check the body without evaluating the definitions
 |         /* We can't check the body without evaluating the definitions
 | ||||||
|            (which is an arbitrary expression), so we don't do that |            (which is an arbitrary expression), so we don't do that | ||||||
|            here but only when actually evaluating the `with'. */ |            here but only when actually evaluating the `with'. */ | ||||||
|  | @ -362,17 +339,5 @@ void checkVarDefs(const ATermMap & defs, Expr e) | ||||||
| 
 | 
 | ||||||
| Expr makeBool(bool b) | Expr makeBool(bool b) | ||||||
| { | { | ||||||
|     return b ? ATmake("Bool(True)") : ATmake("Bool(False)"); |     return b ? eTrue : eFalse; | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| Expr makeString(const string & s) |  | ||||||
| { |  | ||||||
|     return ATmake("Str(<str>)", s.c_str()); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| Expr makePath(const Path & path) |  | ||||||
| { |  | ||||||
|     return ATmake("Path(<str>)", path.c_str()); |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -13,6 +13,8 @@ | ||||||
|    normals forms efficiently. */ |    normals forms efficiently. */ | ||||||
| typedef ATerm Expr; | typedef ATerm Expr; | ||||||
| 
 | 
 | ||||||
|  | typedef ATerm Pos; | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| /* Mappings from ATerms to ATerms.  This is just a wrapper around
 | /* Mappings from ATerms to ATerms.  This is just a wrapper around
 | ||||||
|    ATerm tables. */ |    ATerm tables. */ | ||||||
|  | @ -53,11 +55,6 @@ private: | ||||||
| typedef vector<ATerm> ATermVector; | typedef vector<ATerm> ATermVector; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Convert a string to an ATerm (i.e., a quoted nullary function
 |  | ||||||
|    applicaton). */ |  | ||||||
| ATerm string2ATerm(const string & s); |  | ||||||
| string aterm2String(ATerm t); |  | ||||||
| 
 |  | ||||||
| /* Show a position. */ | /* Show a position. */ | ||||||
| string showPos(ATerm pos); | string showPos(ATerm pos); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ | ||||||
| 
 | 
 | ||||||
| #include "aterm.hh" | #include "aterm.hh" | ||||||
| #include "parser.hh" | #include "parser.hh" | ||||||
|  | #include "constructors.hh" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| struct ParseData  | struct ParseData  | ||||||
|  | @ -45,28 +46,24 @@ void parseError(ParseData * data, char * error, int line, int column) | ||||||
|          |          | ||||||
| ATerm fixAttrs(int recursive, ATermList as) | ATerm fixAttrs(int recursive, ATermList as) | ||||||
| { | { | ||||||
|     ATMatcher m; |  | ||||||
|     ATermList bs = ATempty, cs = ATempty; |     ATermList bs = ATempty, cs = ATempty; | ||||||
|     ATermList * is = recursive ? &cs : &bs; |     ATermList * is = recursive ? &cs : &bs; | ||||||
|     for (ATermIterator i(as); i; ++i) { |     for (ATermIterator i(as); i; ++i) { | ||||||
|         ATermList names; |         ATermList names; | ||||||
|         Expr src; |         Expr src; | ||||||
|         ATerm pos; |         ATerm pos; | ||||||
|         if (atMatch(m, *i) >> "Inherit" >> src >> names >> pos) { |         if (matchInherit(*i, src, names, pos)) { | ||||||
|             bool fromScope = atMatch(m, src) >> "Scope"; |             bool fromScope = matchScope(src); | ||||||
|             for (ATermIterator j(names); j; ++j) { |             for (ATermIterator j(names); j; ++j) { | ||||||
|                 Expr rhs = fromScope |                 Expr rhs = fromScope ? makeVar(*j) : makeSelect(src, *j); | ||||||
|                     ? ATmake("Var(<term>)", *j) |                 *is = ATinsert(*is, makeBind(*j, rhs, pos)); | ||||||
|                     : ATmake("Select(<term>, <term>)", src, *j); |  | ||||||
|                 *is = ATinsert(*is, ATmake("Bind(<term>, <term>, <term>)", |  | ||||||
|                                    *j, rhs, pos)); |  | ||||||
|             } |             } | ||||||
|         } else bs = ATinsert(bs, *i); |         } else bs = ATinsert(bs, *i); | ||||||
|     } |     } | ||||||
|     if (recursive) |     if (recursive) | ||||||
|         return ATmake("Rec(<term>, <term>)", bs, cs); |         return makeRec(bs, cs); | ||||||
|     else |     else | ||||||
|         return ATmake("Attrs(<term>)", bs); |         return makeAttrs(bs); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const char * getPath(ParseData * data) | const char * getPath(ParseData * data) | ||||||
|  |  | ||||||
|  | @ -15,6 +15,11 @@ | ||||||
| #include "parser-tab.h" | #include "parser-tab.h" | ||||||
| #include "lexer-tab.h" | #include "lexer-tab.h" | ||||||
| 
 | 
 | ||||||
|  | typedef ATerm Expr; | ||||||
|  | typedef ATerm Pos; | ||||||
|  |      | ||||||
|  | #include "constructors.hh" | ||||||
|  | 
 | ||||||
| void setParseResult(void * data, ATerm t); | void setParseResult(void * data, ATerm t); | ||||||
| void parseError(void * data, char * error, int line, int column); | void parseError(void * data, char * error, int line, int column); | ||||||
| ATerm absParsedPath(void * data, ATerm t); | ATerm absParsedPath(void * data, ATerm t); | ||||||
|  | @ -26,13 +31,13 @@ void yyerror(YYLTYPE * loc, yyscan_t scanner, void * data, char * s) | ||||||
|     parseError(data, s, loc->first_line, loc->first_column); |     parseError(data, s, loc->first_line, loc->first_column); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ATerm makePos(YYLTYPE * loc, void * data) | static Pos makeCurPos(YYLTYPE * loc, void * data) | ||||||
| { | { | ||||||
|     return ATmake("Pos(<str>, <int>, <int>)", |     return makePos(string2ATerm(getPath(data)), | ||||||
|         getPath(data), loc->first_line, loc->first_column); |         loc->first_line, loc->first_column); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #define CUR_POS makePos(yylocp, data) | #define CUR_POS makeCurPos(yylocp, data) | ||||||
|   |   | ||||||
| %} | %} | ||||||
| 
 | 
 | ||||||
|  | @ -65,64 +70,64 @@ expr: expr_function; | ||||||
| 
 | 
 | ||||||
| expr_function | expr_function | ||||||
|   : '{' formals '}' ':' expr_function |   : '{' formals '}' ':' expr_function | ||||||
|     { $$ = ATmake("Function(<term>, <term>, <term>)", $2, $5, CUR_POS); } |     { $$ = makeFunction($2, $5, CUR_POS); } | ||||||
|   | ID ':' expr_function |   | ID ':' expr_function | ||||||
|     { $$ = ATmake("Function1(<term>, <term>, <term>)", $1, $3, CUR_POS); } |     { $$ = makeFunction1($1, $3, CUR_POS); } | ||||||
|   | ASSERT expr ';' expr_function |   | ASSERT expr ';' expr_function | ||||||
|     { $$ = ATmake("Assert(<term>, <term>, <term>)", $2, $4, CUR_POS); } |     { $$ = makeAssert($2, $4, CUR_POS); } | ||||||
|   | WITH expr ';' expr_function |   | WITH expr ';' expr_function | ||||||
|     { $$ = ATmake("With(<term>, <term>, <term>)", $2, $4, CUR_POS); } |     { $$ = makeWith($2, $4, CUR_POS); } | ||||||
|   | expr_if |   | expr_if | ||||||
|   ; |   ; | ||||||
| 
 | 
 | ||||||
| expr_if | expr_if | ||||||
|   : IF expr THEN expr ELSE expr |   : IF expr THEN expr ELSE expr | ||||||
|     { $$ = ATmake("If(<term>, <term>, <term>)", $2, $4, $6); } |     { $$ = makeIf($2, $4, $6); } | ||||||
|   | expr_op |   | expr_op | ||||||
|   ; |   ; | ||||||
| 
 | 
 | ||||||
| expr_op | expr_op | ||||||
|   : '!' expr_op %prec NEG { $$ = ATmake("OpNot(<term>)", $2); } |   : '!' expr_op %prec NEG { $$ = makeOpNot($2); } | ||||||
|   | expr_op EQ expr_op { $$ = ATmake("OpEq(<term>, <term>)", $1, $3); } |   | expr_op EQ expr_op { $$ = makeOpEq($1, $3); } | ||||||
|   | expr_op NEQ expr_op { $$ = ATmake("OpNEq(<term>, <term>)", $1, $3); } |   | expr_op NEQ expr_op { $$ = makeOpNEq($1, $3); } | ||||||
|   | expr_op AND expr_op { $$ = ATmake("OpAnd(<term>, <term>)", $1, $3); } |   | expr_op AND expr_op { $$ = makeOpAnd($1, $3); } | ||||||
|   | expr_op OR expr_op { $$ = ATmake("OpOr(<term>, <term>)", $1, $3); } |   | expr_op OR expr_op { $$ = makeOpOr($1, $3); } | ||||||
|   | expr_op IMPL expr_op { $$ = ATmake("OpImpl(<term>, <term>)", $1, $3); } |   | expr_op IMPL expr_op { $$ = makeOpImpl($1, $3); } | ||||||
|   | expr_op UPDATE expr_op { $$ = ATmake("OpUpdate(<term>, <term>)", $1, $3); } |   | expr_op UPDATE expr_op { $$ = makeOpUpdate($1, $3); } | ||||||
|   | expr_op '~' expr_op { $$ = ATmake("SubPath(<term>, <term>)", $1, $3); } |   | expr_op '~' expr_op { $$ = makeSubPath($1, $3); } | ||||||
|   | expr_op '?' ID { $$ = ATmake("OpHasAttr(<term>, <term>)", $1, $3); } |   | expr_op '?' ID { $$ = makeOpHasAttr($1, $3); } | ||||||
|   | expr_op '+' expr_op { $$ = ATmake("OpPlus(<term>, <term>)", $1, $3); } |   | expr_op '+' expr_op { $$ = makeOpPlus($1, $3); } | ||||||
|   | expr_app |   | expr_app | ||||||
|   ; |   ; | ||||||
| 
 | 
 | ||||||
| expr_app | expr_app | ||||||
|   : expr_app expr_select |   : expr_app expr_select | ||||||
|     { $$ = ATmake("Call(<term>, <term>)", $1, $2); } |     { $$ = makeCall($1, $2); } | ||||||
|   | expr_select { $$ = $1; } |   | expr_select { $$ = $1; } | ||||||
|   ; |   ; | ||||||
| 
 | 
 | ||||||
| expr_select | expr_select | ||||||
|   : expr_select '.' ID |   : expr_select '.' ID | ||||||
|     { $$ = ATmake("Select(<term>, <term>)", $1, $3); } |     { $$ = makeSelect($1, $3); } | ||||||
|   | expr_simple { $$ = $1; } |   | expr_simple { $$ = $1; } | ||||||
|   ; |   ; | ||||||
| 
 | 
 | ||||||
| expr_simple | expr_simple | ||||||
|   : ID { $$ = ATmake("Var(<term>)", $1); } |   : ID { $$ = makeVar($1); } | ||||||
|   | INT { $$ = ATmake("Int(<term>)", $1); } |   | INT { $$ = makeInt(ATgetInt((ATermInt) $1)); } | ||||||
|   | STR { $$ = ATmake("Str(<term>)", $1); } |   | STR { $$ = makeStr($1); } | ||||||
|   | PATH { $$ = ATmake("Path(<term>)", absParsedPath(data, $1)); } |   | PATH { $$ = makePath(absParsedPath(data, $1)); } | ||||||
|   | URI { $$ = ATmake("Uri(<term>)", $1); } |   | URI { $$ = makeUri($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 '}' | ||||||
|     { $$ = ATmake("Select(<term>, \"body\")", fixAttrs(1, $3)); } |     { $$ = makeSelect(fixAttrs(1, $3), string2ATerm("body")); } | ||||||
|   | REC '{' binds '}' |   | REC '{' binds '}' | ||||||
|     { $$ = fixAttrs(1, $3); } |     { $$ = fixAttrs(1, $3); } | ||||||
|   | '{' binds '}' |   | '{' binds '}' | ||||||
|     { $$ = fixAttrs(0, $2); } |     { $$ = fixAttrs(0, $2); } | ||||||
|   | '[' expr_list ']' { $$ = ATmake("List(<term>)", $2); } |   | '[' expr_list ']' { $$ = makeList($2); } | ||||||
|   ; |   ; | ||||||
| 
 | 
 | ||||||
| binds | binds | ||||||
|  | @ -132,14 +137,14 @@ binds | ||||||
| 
 | 
 | ||||||
| bind | bind | ||||||
|   : ID '=' expr ';' |   : ID '=' expr ';' | ||||||
|     { $$ = ATmake("Bind(<term>, <term>, <term>)", $1, $3, CUR_POS); } |     { $$ = makeBind($1, $3, CUR_POS); } | ||||||
|   | INHERIT inheritsrc ids ';' |   | INHERIT inheritsrc ids ';' | ||||||
|     { $$ = ATmake("Inherit(<term>, <term>, <term>)", $2, $3, CUR_POS); } |     { $$ = makeInherit($2, $3, CUR_POS); } | ||||||
|   ; |   ; | ||||||
| 
 | 
 | ||||||
| inheritsrc | inheritsrc | ||||||
|   : '(' expr ')' { $$ = $2; } |   : '(' expr ')' { $$ = $2; } | ||||||
|   | { $$ = ATmake("Scope"); } |   | { $$ = makeScope(); } | ||||||
|   ; |   ; | ||||||
| 
 | 
 | ||||||
| ids: ids ID { $$ = ATinsert($1, $2); } | { $$ = ATempty; }; | ids: ids ID { $$ = ATinsert($1, $2); } | { $$ = ATempty; }; | ||||||
|  | @ -158,8 +163,8 @@ formals | ||||||
|   ; |   ; | ||||||
| 
 | 
 | ||||||
| formal | formal | ||||||
|   : ID { $$ = ATmake("NoDefFormal(<term>)", $1); } |   : ID { $$ = makeNoDefFormal($1); } | ||||||
|   | ID '?' expr { $$ = ATmake("DefFormal(<term>, <term>)", $1, $3); } |   | ID '?' expr { $$ = makeDefFormal($1, $3); } | ||||||
|   ; |   ; | ||||||
|    |    | ||||||
| %% | %% | ||||||
|  |  | ||||||
|  | @ -1,18 +1,18 @@ | ||||||
| #include "normalise.hh" | #include "normalise.hh" | ||||||
| #include "eval.hh" | #include "eval.hh" | ||||||
| #include "globals.hh" | #include "globals.hh" | ||||||
|  | #include "constructors.hh" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Load and evaluate an expression from path specified by the
 | /* Load and evaluate an expression from path specified by the
 | ||||||
|    argument. */  |    argument. */  | ||||||
| static Expr primImport(EvalState & state, const ATermVector & args) | static Expr primImport(EvalState & state, const ATermVector & args) | ||||||
| { | { | ||||||
|     ATMatcher m; |     ATerm path; | ||||||
|     string path; |  | ||||||
|     Expr fn = evalExpr(state, args[0]); |     Expr fn = evalExpr(state, args[0]); | ||||||
|     if (!(atMatch(m, fn) >> "Path" >> path)) |     if (!matchPath(fn, path)) | ||||||
|         throw Error("path expected"); |         throw Error("path expected"); | ||||||
|     return evalFile(state, path); |     return evalFile(state, aterm2String(path)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -86,24 +86,23 @@ static void processBinding(EvalState & state, Expr e, StoreExpr & ne, | ||||||
| { | { | ||||||
|     e = evalExpr(state, e); |     e = evalExpr(state, e); | ||||||
| 
 | 
 | ||||||
|     ATMatcher m; |     ATerm s; | ||||||
|     string s; |  | ||||||
|     ATermList es; |     ATermList es; | ||||||
|     int n; |     int n; | ||||||
|     Expr e1, e2; |     Expr e1, e2; | ||||||
| 
 | 
 | ||||||
|     if (atMatch(m, e) >> "Str" >> s) ss.push_back(s); |     if (matchStr(e, s)) ss.push_back(aterm2String(s)); | ||||||
|     else if (atMatch(m, e) >> "Uri" >> s) ss.push_back(s); |     else if (matchUri(e, s)) ss.push_back(aterm2String(s)); | ||||||
|     else if (atMatch(m, e) >> "Bool" >> "True") ss.push_back("1"); |     else if (e == eTrue) ss.push_back("1"); | ||||||
|     else if (atMatch(m, e) >> "Bool" >> "False") ss.push_back(""); |     else if (e == eFalse) ss.push_back(""); | ||||||
| 
 | 
 | ||||||
|     else if (atMatch(m, e) >> "Int" >> n) { |     else if (matchInt(e, n)) { | ||||||
|         ostringstream st; |         ostringstream st; | ||||||
|         st << n; |         st << n; | ||||||
|         ss.push_back(st.str()); |         ss.push_back(st.str()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     else if (atMatch(m, e) >> "Attrs") { |     else if (matchAttrs(e, es)) { | ||||||
|         Expr a = queryAttr(e, "type"); |         Expr a = queryAttr(e, "type"); | ||||||
|         if (a && evalString(state, a) == "derivation") { |         if (a && evalString(state, a) == "derivation") { | ||||||
|             a = queryAttr(e, "drvPath"); |             a = queryAttr(e, "drvPath"); | ||||||
|  | @ -127,30 +126,29 @@ static void processBinding(EvalState & state, Expr e, StoreExpr & ne, | ||||||
|             throw Error("invalid derivation attribute"); |             throw Error("invalid derivation attribute"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     else if (atMatch(m, e) >> "Path" >> s) { |     else if (matchPath(e, s)) { | ||||||
|         Path drvPath = copyAtom(state, s); |         Path drvPath = copyAtom(state, aterm2String(s)); | ||||||
|         ss.push_back(addInput(state, drvPath, ne)); |         ss.push_back(addInput(state, drvPath, ne)); | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     else if (atMatch(m, e) >> "List" >> es) { |     else if (matchList(e, es)) { | ||||||
|         for (ATermIterator i(es); i; ++i) { |         for (ATermIterator i(es); i; ++i) { | ||||||
|             startNest(nest, lvlVomit, format("processing list element")); |             startNest(nest, lvlVomit, format("processing list element")); | ||||||
| 	    processBinding(state, evalExpr(state, *i), ne, ss); | 	    processBinding(state, evalExpr(state, *i), ne, ss); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     else if (atMatch(m, e) >> "Null") ss.push_back(""); |     else if (matchNull(e)) ss.push_back(""); | ||||||
| 
 | 
 | ||||||
|     else if (atMatch(m, e) >> "SubPath" >> e1 >> e2) { |     else if (matchSubPath(e, e1, e2)) { | ||||||
|         Strings ss2; |         Strings ss2; | ||||||
|         processBinding(state, evalExpr(state, e1), ne, ss2); |         processBinding(state, evalExpr(state, e1), ne, ss2); | ||||||
|         if (ss2.size() != 1) |         if (ss2.size() != 1) | ||||||
|             throw Error("left-hand side of `~' operator cannot be a list"); |             throw Error("left-hand side of `~' operator cannot be a list"); | ||||||
|         e2 = evalExpr(state, e2); |         e2 = evalExpr(state, e2); | ||||||
|         if (!(atMatch(m, e2) >> "Str" >> s || |         if (!(matchStr(e2, s) || matchPath(e2, s))) | ||||||
|              (atMatch(m, e2) >> "Path" >> s))) |  | ||||||
|             throw Error("right-hand side of `~' operator must be a path or string"); |             throw Error("right-hand side of `~' operator must be a path or string"); | ||||||
|         ss.push_back(canonPath(ss2.front() + "/" + s)); |         ss.push_back(canonPath(ss2.front() + "/" + aterm2String(s))); | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     else throw Error("invalid derivation attribute"); |     else throw Error("invalid derivation attribute"); | ||||||
|  | @ -198,8 +196,7 @@ static Expr primDerivation(EvalState & state, const ATermVector & _args) | ||||||
|         ATerm value; |         ATerm value; | ||||||
|         Expr pos; |         Expr pos; | ||||||
|         ATerm rhs = attrs.get(key); |         ATerm rhs = attrs.get(key); | ||||||
|         ATMatcher m; |         if (!matchAttrRHS(rhs, value, pos)) abort(); | ||||||
|         if (!(atMatch(m, rhs) >> "" >> value >> pos)) abort(); |  | ||||||
|         startNest(nest, lvlVomit, format("processing attribute `%1%'") % key); |         startNest(nest, lvlVomit, format("processing attribute `%1%'") % key); | ||||||
| 
 | 
 | ||||||
|         Strings ss; |         Strings ss; | ||||||
|  | @ -272,10 +269,11 @@ static Expr primDerivation(EvalState & state, const ATermVector & _args) | ||||||
|     printMsg(lvlChatty, format("instantiated `%1%' -> `%2%'") |     printMsg(lvlChatty, format("instantiated `%1%' -> `%2%'") | ||||||
|         % drvName % drvPath); |         % drvName % drvPath); | ||||||
| 
 | 
 | ||||||
|     attrs.set("outPath", ATmake("(Path(<str>), NoPos)", outPath.c_str())); |     attrs.set("outPath", makeAttrRHS(makePath(string2ATerm(outPath.c_str())), makeNoPos())); | ||||||
|     attrs.set("drvPath", ATmake("(Path(<str>), NoPos)", drvPath.c_str())); |     attrs.set("drvPath", makeAttrRHS(makePath(string2ATerm(drvPath.c_str())), makeNoPos())); | ||||||
|     attrs.set("drvHash", ATmake("(<term>, NoPos)", makeString(drvHash))); |     attrs.set("drvHash", | ||||||
|     attrs.set("type", ATmake("(<term>, NoPos)", makeString("derivation"))); |         makeAttrRHS(makeStr(string2ATerm(((string) drvHash).c_str())), makeNoPos())); | ||||||
|  |     attrs.set("type", makeAttrRHS(makeStr(string2ATerm("derivation")), makeNoPos())); | ||||||
| 
 | 
 | ||||||
|     return makeAttrs(attrs); |     return makeAttrs(attrs); | ||||||
| } | } | ||||||
|  | @ -285,7 +283,7 @@ static Expr primDerivation(EvalState & state, const ATermVector & _args) | ||||||
|    following the last slash. */ |    following the last slash. */ | ||||||
| static Expr primBaseNameOf(EvalState & state, const ATermVector & args) | static Expr primBaseNameOf(EvalState & state, const ATermVector & args) | ||||||
| { | { | ||||||
|     return makeString(baseNameOf(evalString(state, args[0]))); |     return makeStr(string2ATerm(baseNameOf(evalString(state, args[0])).c_str())); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -293,12 +291,9 @@ static Expr primBaseNameOf(EvalState & state, const ATermVector & args) | ||||||
| static Expr primToString(EvalState & state, const ATermVector & args) | static Expr primToString(EvalState & state, const ATermVector & args) | ||||||
| { | { | ||||||
|     Expr arg = evalExpr(state, args[0]); |     Expr arg = evalExpr(state, args[0]); | ||||||
|     ATMatcher m; |     ATerm s; | ||||||
|     string s; |     if (matchStr(arg, s) || matchPath(arg, s) || matchUri(arg, s)) | ||||||
|     if (atMatch(m, arg) >> "Str" >> s || |         return makeStr(s); | ||||||
|         atMatch(m, arg) >> "Path" >> s || |  | ||||||
|         atMatch(m, arg) >> "Uri" >> s) |  | ||||||
|         return makeString(s); |  | ||||||
|     else throw Error("cannot coerce value to string"); |     else throw Error("cannot coerce value to string"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -306,29 +301,27 @@ static Expr primToString(EvalState & state, const ATermVector & args) | ||||||
| /* Boolean constructors. */ | /* Boolean constructors. */ | ||||||
| static Expr primTrue(EvalState & state, const ATermVector & args) | static Expr primTrue(EvalState & state, const ATermVector & args) | ||||||
| { | { | ||||||
|     return ATmake("Bool(True)"); |     return eTrue; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static Expr primFalse(EvalState & state, const ATermVector & args) | static Expr primFalse(EvalState & state, const ATermVector & args) | ||||||
| { | { | ||||||
|     return ATmake("Bool(False)"); |     return eFalse; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Return the null value. */ | /* Return the null value. */ | ||||||
| Expr primNull(EvalState & state, const ATermVector & args) | Expr primNull(EvalState & state, const ATermVector & args) | ||||||
| { | { | ||||||
|     return ATmake("Null"); |     return makeNull(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Determine whether the argument is the null value. */ | /* Determine whether the argument is the null value. */ | ||||||
| Expr primIsNull(EvalState & state, const ATermVector & args) | Expr primIsNull(EvalState & state, const ATermVector & args) | ||||||
| { | { | ||||||
|     Expr arg = evalExpr(state, args[0]); |     return makeBool(matchNull(evalExpr(state, args[0]))); | ||||||
|     ATMatcher m; |  | ||||||
|     return makeBool(atMatch(m, arg) >> "Null"); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -338,18 +331,15 @@ Expr primMap(EvalState & state, const ATermVector & args) | ||||||
|     Expr fun = evalExpr(state, args[0]); |     Expr fun = evalExpr(state, args[0]); | ||||||
|     Expr list = evalExpr(state, args[1]); |     Expr list = evalExpr(state, args[1]); | ||||||
| 
 | 
 | ||||||
|     ATMatcher m; |  | ||||||
| 
 |  | ||||||
|     ATermList list2; |     ATermList list2; | ||||||
|     if (!(atMatch(m, list) >> "List" >> list2)) |     if (!matchList(list, list2)) | ||||||
|         throw Error("`map' expects a list as its second argument"); |         throw Error("`map' expects a list as its second argument"); | ||||||
| 
 | 
 | ||||||
|     ATermList list3 = ATempty; |     ATermList list3 = ATempty; | ||||||
|     for (ATermIterator i(list2); i; ++i) |     for (ATermIterator i(list2); i; ++i) | ||||||
|         list3 = ATinsert(list3, |         list3 = ATinsert(list3, makeCall(fun, *i)); | ||||||
|             ATmake("Call(<term>, <term>)", fun, *i)); |  | ||||||
| 
 | 
 | ||||||
|     return ATmake("List(<term>)", ATreverse(list3)); |     return makeList(ATreverse(list3)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ | ||||||
| #include "parser.hh" | #include "parser.hh" | ||||||
| #include "eval.hh" | #include "eval.hh" | ||||||
| #include "help.txt.hh" | #include "help.txt.hh" | ||||||
|  | #include "constructors.hh" | ||||||
| 
 | 
 | ||||||
| #include <cerrno> | #include <cerrno> | ||||||
| #include <ctime> | #include <ctime> | ||||||
|  | @ -47,10 +48,9 @@ void printHelp() | ||||||
| 
 | 
 | ||||||
| bool parseDerivation(EvalState & state, Expr e, DrvInfo & drv) | bool parseDerivation(EvalState & state, Expr e, DrvInfo & drv) | ||||||
| { | { | ||||||
|     ATMatcher m; |     ATermList es; | ||||||
|      |  | ||||||
|     e = evalExpr(state, e); |     e = evalExpr(state, e); | ||||||
|     if (!(atMatch(m, e) >> "Attrs")) return false; |     if (!matchAttrs(e, es)) return false; | ||||||
|     Expr a = queryAttr(e, "type"); |     Expr a = queryAttr(e, "type"); | ||||||
|     if (!a || evalString(state, a) != "derivation") return false; |     if (!a || evalString(state, a) != "derivation") return false; | ||||||
| 
 | 
 | ||||||
|  | @ -82,7 +82,6 @@ bool parseDerivation(EvalState & state, Expr e, DrvInfo & drv) | ||||||
| 
 | 
 | ||||||
| bool parseDerivations(EvalState & state, Expr e, DrvInfos & drvs) | bool parseDerivations(EvalState & state, Expr e, DrvInfos & drvs) | ||||||
| { | { | ||||||
|     ATMatcher m; |  | ||||||
|     ATermList es; |     ATermList es; | ||||||
|     DrvInfo drv; |     DrvInfo drv; | ||||||
| 
 | 
 | ||||||
|  | @ -91,7 +90,7 @@ bool parseDerivations(EvalState & state, Expr e, DrvInfos & drvs) | ||||||
|     if (parseDerivation(state, e, drv))  |     if (parseDerivation(state, e, drv))  | ||||||
|         drvs[drv.drvPath] = drv; |         drvs[drv.drvPath] = drv; | ||||||
| 
 | 
 | ||||||
|     else if (atMatch(m, e) >> "Attrs") { |     else if (matchAttrs(e, es)) { | ||||||
|         ATermMap drvMap; |         ATermMap drvMap; | ||||||
|         queryAllAttrs(e, drvMap); |         queryAllAttrs(e, drvMap); | ||||||
|         for (ATermIterator i(drvMap.keys()); i; ++i) { |         for (ATermIterator i(drvMap.keys()); i; ++i) { | ||||||
|  | @ -103,7 +102,7 @@ bool parseDerivations(EvalState & state, Expr e, DrvInfos & drvs) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     else if (atMatch(m, e) >> "List" >> es) { |     else if (matchList(e, es)) { | ||||||
|         for (ATermIterator i(es); i; ++i) { |         for (ATermIterator i(es); i; ++i) { | ||||||
|             debug(format("evaluating list element")); |             debug(format("evaluating list element")); | ||||||
|             if (parseDerivation(state, *i, drv)) |             if (parseDerivation(state, *i, drv)) | ||||||
|  | @ -152,12 +151,10 @@ struct AddPos : TermFun | ||||||
| { | { | ||||||
|     ATerm operator () (ATerm e) |     ATerm operator () (ATerm e) | ||||||
|     { |     { | ||||||
|         ATMatcher m; |  | ||||||
|         ATerm x, y, z; |         ATerm x, y, z; | ||||||
|         if (atMatch(m, e) >> "Bind" >> x >> y >> z) |         if (matchBind(e, x, y, z)) return e; | ||||||
|             return e; |         if (matchBind2(e, x, y)) | ||||||
|         if (atMatch(m, e) >> "Bind" >> x >> y) |             return makeBind(x, y, makeNoPos()); | ||||||
|             return ATmake("Bind(<term>, <term>, NoPos)", x, y); |  | ||||||
|         return e; |         return e; | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
|  | @ -194,36 +191,36 @@ void createUserEnv(EvalState & state, const DrvInfos & drvs, | ||||||
|     for (DrvInfos::const_iterator i = drvs.begin();  |     for (DrvInfos::const_iterator i = drvs.begin();  | ||||||
|          i != drvs.end(); ++i) |          i != drvs.end(); ++i) | ||||||
|     { |     { | ||||||
|         ATerm t = ATmake( |         ATerm t = makeAttrs(ATmakeList6( | ||||||
|             "Attrs([" |             makeBind(string2ATerm("type"), | ||||||
|             "Bind(\"type\", Str(\"derivation\"), NoPos), " |                 makeStr(string2ATerm("derivation")), makeNoPos()), | ||||||
|             "Bind(\"name\", Str(<str>), NoPos), " |             makeBind(string2ATerm("name"), | ||||||
|             "Bind(\"system\", Str(<str>), NoPos), " |                 makeStr(string2ATerm(i->second.name.c_str())), makeNoPos()), | ||||||
|             "Bind(\"drvPath\", Path(<str>), NoPos), " |             makeBind(string2ATerm("system"), | ||||||
|             "Bind(\"drvHash\", Str(<str>), NoPos), " |                 makeStr(string2ATerm(i->second.system.c_str())), makeNoPos()), | ||||||
|             "Bind(\"outPath\", Path(<str>), NoPos)" |             makeBind(string2ATerm("drvPath"), | ||||||
|             "])", |                 makePath(string2ATerm(i->second.drvPath.c_str())), makeNoPos()), | ||||||
|             i->second.name.c_str(), |             makeBind(string2ATerm("drvHash"), | ||||||
|             i->second.system.c_str(), |                 makeStr(string2ATerm(((string) i->second.drvHash).c_str())), makeNoPos()), | ||||||
|             i->second.drvPath.c_str(), |             makeBind(string2ATerm("outPath"), | ||||||
|             ((string) i->second.drvHash).c_str(), |                 makePath(string2ATerm(i->second.outPath.c_str())), makeNoPos()) | ||||||
|             i->second.outPath.c_str()); |             )); | ||||||
|         inputs = ATinsert(inputs, t); |         inputs = ATinsert(inputs, t); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ATerm inputs2 = ATmake("List(<term>)", ATreverse(inputs)); |     ATerm inputs2 = makeList(ATreverse(inputs)); | ||||||
| 
 | 
 | ||||||
|     /* Also write a copy of the list of inputs to the store; we need
 |     /* Also write a copy of the list of inputs to the store; we need
 | ||||||
|        it for future modifications of the environment. */ |        it for future modifications of the environment. */ | ||||||
|     Path inputsFile = writeTerm(inputs2, "-env-inputs"); |     Path inputsFile = writeTerm(inputs2, "-env-inputs"); | ||||||
| 
 | 
 | ||||||
|     Expr topLevel = ATmake( |     Expr topLevel = makeCall(envBuilder, makeAttrs(ATmakeList3( | ||||||
|         "Call(<term>, Attrs([" |         makeBind(string2ATerm("system"), | ||||||
|         "Bind(\"system\", Str(<str>), NoPos), " |             makeStr(string2ATerm(thisSystem.c_str())), makeNoPos()), | ||||||
|         "Bind(\"derivations\", <term>, NoPos), " // !!! redundant
 |         makeBind(string2ATerm("derivations"), inputs2, makeNoPos()), | ||||||
|         "Bind(\"manifest\", Path(<str>), NoPos)" |         makeBind(string2ATerm("manifest"), | ||||||
|         "]))", |             makePath(string2ATerm(inputsFile.c_str())), makeNoPos()) | ||||||
|         envBuilder, thisSystem.c_str(), inputs2, inputsFile.c_str()); |         ))); | ||||||
| 
 | 
 | ||||||
|     /* Instantiate it. */ |     /* Instantiate it. */ | ||||||
|     debug(format("evaluating builder expression `%1%'") % topLevel); |     debug(format("evaluating builder expression `%1%'") % topLevel); | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ | ||||||
| #include "shared.hh" | #include "shared.hh" | ||||||
| #include "eval.hh" | #include "eval.hh" | ||||||
| #include "parser.hh" | #include "parser.hh" | ||||||
|  | #include "constructors.hh" | ||||||
| #include "help.txt.hh" | #include "help.txt.hh" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -32,7 +33,7 @@ static void printDrvPaths(EvalState & state, Expr e) | ||||||
| 
 | 
 | ||||||
|     /* !!! duplication w.r.t. parseDerivations in nix-env */ |     /* !!! duplication w.r.t. parseDerivations in nix-env */ | ||||||
| 
 | 
 | ||||||
|     if (atMatch(m, e) >> "Attrs" >> es) { |     if (matchAttrs(e, es)) { | ||||||
|         Expr a = queryAttr(e, "type"); |         Expr a = queryAttr(e, "type"); | ||||||
|         if (a && evalString(state, a) == "derivation") { |         if (a && evalString(state, a) == "derivation") { | ||||||
|             a = queryAttr(e, "drvPath"); |             a = queryAttr(e, "drvPath"); | ||||||
|  | @ -50,7 +51,7 @@ static void printDrvPaths(EvalState & state, Expr e) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (atMatch(m, e) >> "List" >> es) { |     if (matchList(e, es)) { | ||||||
|         for (ATermIterator i(es); i; ++i) |         for (ATermIterator i(es); i; ++i) | ||||||
|             printDrvPaths(state, evalExpr(state, *i)); |             printDrvPaths(state, evalExpr(state, *i)); | ||||||
|         return; |         return; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue