forked from lix-project/lix
* 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
|
@ -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…
Reference in a new issue