* Drop ATmake / ATMatcher also in handling store expressions.
This commit is contained in:
parent
ed09821859
commit
a69534fc21
19 changed files with 118 additions and 258 deletions
|
@ -1,6 +1,8 @@
|
||||||
SUBDIRS = bin2c boost libutil libstore libmain nix-store nix-hash \
|
SUBDIRS = bin2c boost libutil libstore libmain nix-store nix-hash \
|
||||||
libexpr nix-instantiate nix-env log2xml
|
libexpr nix-instantiate nix-env log2xml
|
||||||
|
|
||||||
|
EXTRA_DIST = aterm-helper.pl
|
||||||
|
|
||||||
SETUID_PROGS = nix-store nix-instantiate nix-env
|
SETUID_PROGS = nix-store nix-instantiate nix-env
|
||||||
install-exec-hook:
|
install-exec-hook:
|
||||||
if SETUID_HACK
|
if SETUID_HACK
|
||||||
|
|
|
@ -1,9 +1,41 @@
|
||||||
#! /usr/bin/perl -w
|
#! /usr/bin/perl -w
|
||||||
|
|
||||||
|
# This program generates C/C++ code for efficiently manipulating
|
||||||
|
# ATerms. It generates functions to build and match ATerms according
|
||||||
|
# to a set of constructor definitions defined in a file read from
|
||||||
|
# standard input. A constructor is defined by a line with the
|
||||||
|
# following format:
|
||||||
|
#
|
||||||
|
# SYM | ARGS | TYPE | FUN?
|
||||||
|
#
|
||||||
|
# where SYM is the name of the constructor, ARGS is a
|
||||||
|
# whitespace-separated list of argument types, TYPE is the type of the
|
||||||
|
# resulting ATerm (which should be `ATerm' or a type synonym for
|
||||||
|
# `ATerm'), and the optional FUN is used to construct the names of the
|
||||||
|
# build and match functions (it defaults to SYM; overriding it is
|
||||||
|
# useful if there are overloaded constructors, e.g., with different
|
||||||
|
# arities). Note that SYM may be empty.
|
||||||
|
#
|
||||||
|
# A line of the form
|
||||||
|
#
|
||||||
|
# VAR = EXPR
|
||||||
|
#
|
||||||
|
# causes a ATerm variable to be generated that is initialised to the
|
||||||
|
# value EXPR.
|
||||||
|
#
|
||||||
|
# Finally, a line of the form
|
||||||
|
#
|
||||||
|
# init NAME
|
||||||
|
#
|
||||||
|
# causes the initialisation function to be called `NAME'. This
|
||||||
|
# function must be called before any of the build/match functions or
|
||||||
|
# the generated variables are used.
|
||||||
|
|
||||||
die if scalar @ARGV != 2;
|
die if scalar @ARGV != 2;
|
||||||
|
|
||||||
my $syms = "";
|
my $syms = "";
|
||||||
my $init = "";
|
my $init = "";
|
||||||
|
my $initFun = "init";
|
||||||
|
|
||||||
open HEADER, ">$ARGV[0]";
|
open HEADER, ">$ARGV[0]";
|
||||||
open IMPL, ">$ARGV[1]";
|
open IMPL, ">$ARGV[1]";
|
||||||
|
@ -11,7 +43,7 @@ open IMPL, ">$ARGV[1]";
|
||||||
while (<STDIN>) {
|
while (<STDIN>) {
|
||||||
next if (/^\s*$/);
|
next if (/^\s*$/);
|
||||||
|
|
||||||
if (/^\s*(\w+)\s*\|([^\|]*)\|\s*(\w+)\s*\|\s*(\w+)?/) {
|
if (/^\s*(\w*)\s*\|([^\|]*)\|\s*(\w+)\s*\|\s*(\w+)?/) {
|
||||||
my $const = $1;
|
my $const = $1;
|
||||||
my @types = split ' ', $2;
|
my @types = split ' ', $2;
|
||||||
my $result = $3;
|
my $result = $3;
|
||||||
|
@ -30,6 +62,8 @@ while (<STDIN>) {
|
||||||
# $type = "const char *";
|
# $type = "const char *";
|
||||||
$type = "ATerm";
|
$type = "ATerm";
|
||||||
$args .= "e$n";
|
$args .= "e$n";
|
||||||
|
# !!! in the matcher, we should check that the
|
||||||
|
# argument is a string (i.e., a nullary application).
|
||||||
} elsif ($type eq "int") {
|
} elsif ($type eq "int") {
|
||||||
$args .= "(ATerm) ATmakeInt(e$n)";
|
$args .= "(ATerm) ATmakeInt(e$n)";
|
||||||
} elsif ($type eq "ATermList" || $type eq "ATermBlob") {
|
} elsif ($type eq "ATermList" || $type eq "ATermBlob") {
|
||||||
|
@ -42,6 +76,7 @@ while (<STDIN>) {
|
||||||
$formals2 .= ", ";
|
$formals2 .= ", ";
|
||||||
$formals2 .= "$type & e$n";
|
$formals2 .= "$type & e$n";
|
||||||
my $m = $n - 1;
|
my $m = $n - 1;
|
||||||
|
# !!! more checks here
|
||||||
if ($type eq "int") {
|
if ($type eq "int") {
|
||||||
$unpack .= " e$n = ATgetInt((ATermInt) ATgetArgument(e, $m));\n";
|
$unpack .= " e$n = ATgetInt((ATermInt) ATgetArgument(e, $m));\n";
|
||||||
} elsif ($type eq "ATermList") {
|
} elsif ($type eq "ATermList") {
|
||||||
|
@ -84,12 +119,16 @@ while (<STDIN>) {
|
||||||
$init .= " $name = $value;\n";
|
$init .= " $name = $value;\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
elsif (/^\s*init\s+(\w+)\s*$/) {
|
||||||
|
$initFun = $1;
|
||||||
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
die "bad line: `$_'";
|
die "bad line: `$_'";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
print HEADER "void initSyms();\n\n";
|
print HEADER "void $initFun();\n\n";
|
||||||
|
|
||||||
print HEADER "static inline ATerm string2ATerm(const char * s) {\n";
|
print HEADER "static inline ATerm string2ATerm(const char * s) {\n";
|
||||||
print HEADER " return (ATerm) ATmakeAppl0(ATmakeAFun((char *) s, 0, ATtrue));\n";
|
print HEADER " return (ATerm) ATmakeAppl0(ATmakeAFun((char *) s, 0, ATtrue));\n";
|
||||||
|
@ -100,7 +139,7 @@ print HEADER " return (const char *) ATgetName(ATgetAFun(t));\n";
|
||||||
print HEADER "}\n\n";
|
print HEADER "}\n\n";
|
||||||
|
|
||||||
print IMPL "\n";
|
print IMPL "\n";
|
||||||
print IMPL "void initSyms() {\n";
|
print IMPL "void $initFun() {\n";
|
||||||
print IMPL "$init";
|
print IMPL "$init";
|
||||||
print IMPL "}\n";
|
print IMPL "}\n";
|
||||||
|
|
|
@ -3,10 +3,9 @@ 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
|
nixexpr-ast.hh
|
||||||
|
|
||||||
EXTRA_DIST = lexer.l parser.y constructors.def constructors.cc \
|
EXTRA_DIST = lexer.l parser.y nixexpr-ast.def nixexpr-ast.cc
|
||||||
aterm-helper.pl
|
|
||||||
|
|
||||||
AM_CXXFLAGS = \
|
AM_CXXFLAGS = \
|
||||||
-I.. ${bdb_include} ${aterm_include} -I../libutil -I../libstore
|
-I.. ${bdb_include} ${aterm_include} -I../libutil -I../libstore
|
||||||
|
@ -27,10 +26,10 @@ lexer-tab.c lexer-tab.h: lexer.l
|
||||||
|
|
||||||
# ATerm helper function generation.
|
# ATerm helper function generation.
|
||||||
|
|
||||||
constructors.cc constructors.hh: aterm-helper.pl constructors.def
|
nixexpr-ast.cc nixexpr-ast.hh: ../aterm-helper.pl nixexpr-ast.def
|
||||||
$(perl) aterm-helper.pl constructors.hh constructors.cc < constructors.def
|
$(perl) ../aterm-helper.pl nixexpr-ast.hh nixexpr-ast.cc < nixexpr-ast.def
|
||||||
|
|
||||||
nixexpr.hh: constructors.hh
|
nixexpr.hh: nixexpr-ast.hh
|
||||||
|
|
||||||
|
|
||||||
CLEANFILES =
|
CLEANFILES =
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "eval.hh"
|
#include "eval.hh"
|
||||||
#include "parser.hh"
|
#include "parser.hh"
|
||||||
#include "constructors.hh"
|
#include "nixexpr-ast.hh"
|
||||||
|
|
||||||
|
|
||||||
EvalState::EvalState()
|
EvalState::EvalState()
|
||||||
|
@ -10,7 +10,7 @@ EvalState::EvalState()
|
||||||
|
|
||||||
nrEvaluated = nrCached = 0;
|
nrEvaluated = nrCached = 0;
|
||||||
|
|
||||||
initSyms();
|
initNixExprHelpers();
|
||||||
|
|
||||||
addPrimOps();
|
addPrimOps();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
init initNixExprHelpers
|
||||||
|
|
||||||
Pos | string int int | Pos |
|
Pos | string int int | Pos |
|
||||||
NoPos | | Pos |
|
NoPos | | Pos |
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
#include "storeexpr.hh"
|
#include "storeexpr.hh"
|
||||||
|
|
||||||
|
|
||||||
#include "constructors.hh"
|
#include "nixexpr-ast.hh"
|
||||||
#include "constructors.cc"
|
#include "nixexpr-ast.cc"
|
||||||
|
|
||||||
|
|
||||||
ATermMap::ATermMap(unsigned int initialSize, unsigned int maxLoadPct)
|
ATermMap::ATermMap(unsigned int initialSize, unsigned int maxLoadPct)
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
#include "aterm.hh"
|
#include "aterm.hh"
|
||||||
#include "parser.hh"
|
#include "parser.hh"
|
||||||
#include "constructors.hh"
|
#include "nixexpr-ast.hh"
|
||||||
|
|
||||||
|
|
||||||
struct ParseData
|
struct ParseData
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
typedef ATerm Expr;
|
typedef ATerm Expr;
|
||||||
typedef ATerm Pos;
|
typedef ATerm Pos;
|
||||||
|
|
||||||
#include "constructors.hh"
|
#include "nixexpr-ast.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);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "normalise.hh"
|
#include "normalise.hh"
|
||||||
#include "eval.hh"
|
#include "eval.hh"
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "constructors.hh"
|
#include "nixexpr-ast.hh"
|
||||||
|
|
||||||
|
|
||||||
/* Load and evaluate an expression from path specified by the
|
/* Load and evaluate an expression from path specified by the
|
||||||
|
|
|
@ -55,6 +55,9 @@ void checkStoreNotSymlink(Path path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void initStoreExprHelpers();
|
||||||
|
|
||||||
|
|
||||||
/* Initialize and reorder arguments, then call the actual argument
|
/* Initialize and reorder arguments, then call the actual argument
|
||||||
processor. */
|
processor. */
|
||||||
static void initAndRun(int argc, char * * argv)
|
static void initAndRun(int argc, char * * argv)
|
||||||
|
@ -101,6 +104,9 @@ static void initAndRun(int argc, char * * argv)
|
||||||
string lt = getEnv("NIX_LOG_TYPE");
|
string lt = getEnv("NIX_LOG_TYPE");
|
||||||
if (lt != "") setLogType(lt);
|
if (lt != "") setLogType(lt);
|
||||||
|
|
||||||
|
/* ATerm stuff. !!! find a better place to put this */
|
||||||
|
initStoreExprHelpers();
|
||||||
|
|
||||||
/* Put the arguments in a vector. */
|
/* Put the arguments in a vector. */
|
||||||
Strings args, remaining;
|
Strings args, remaining;
|
||||||
while (argc--) args.push_back(*argv++);
|
while (argc--) args.push_back(*argv++);
|
||||||
|
|
|
@ -5,7 +5,14 @@ libstore_a_SOURCES = \
|
||||||
normalise.cc misc.cc normalise.hh \
|
normalise.cc misc.cc normalise.hh \
|
||||||
globals.cc globals.hh db.cc db.hh \
|
globals.cc globals.hh db.cc db.hh \
|
||||||
references.cc references.hh pathlocks.cc pathlocks.hh \
|
references.cc references.hh pathlocks.cc pathlocks.hh \
|
||||||
gc.cc gc.hh
|
gc.cc gc.hh storeexpr-ast.hh
|
||||||
|
|
||||||
|
EXTRA_DIST = storeexpr-ast.def storeexpr-ast.cc
|
||||||
|
|
||||||
AM_CXXFLAGS = -Wall \
|
AM_CXXFLAGS = -Wall \
|
||||||
-I.. ${bdb_include} ${aterm_include} -I../libutil
|
-I.. ${bdb_include} ${aterm_include} -I../libutil
|
||||||
|
|
||||||
|
storeexpr-ast.cc storeexpr-ast.hh: ../aterm-helper.pl storeexpr-ast.def
|
||||||
|
$(perl) ../aterm-helper.pl storeexpr-ast.hh storeexpr-ast.cc < storeexpr-ast.def
|
||||||
|
|
||||||
|
storeexpr.cc: storeexpr-ast.hh
|
7
src/libstore/storeexpr-ast.def
Normal file
7
src/libstore/storeexpr-ast.def
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
init initStoreExprHelpers
|
||||||
|
|
||||||
|
Closure | ATermList ATermList | ATerm |
|
||||||
|
Derive | ATermList ATermList string string ATermList ATermList | ATerm |
|
||||||
|
|
||||||
|
| string string | ATerm | EnvBinding |
|
||||||
|
| string ATermList | ATerm | ClosureElem |
|
|
@ -2,6 +2,9 @@
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "store.hh"
|
#include "store.hh"
|
||||||
|
|
||||||
|
#include "storeexpr-ast.hh"
|
||||||
|
#include "storeexpr-ast.cc"
|
||||||
|
|
||||||
|
|
||||||
Hash hashTerm(ATerm t)
|
Hash hashTerm(ATerm t)
|
||||||
{
|
{
|
||||||
|
@ -29,10 +32,11 @@ Path writeTerm(ATerm t, const string & suffix)
|
||||||
|
|
||||||
static void parsePaths(ATermList paths, PathSet & out)
|
static void parsePaths(ATermList paths, PathSet & out)
|
||||||
{
|
{
|
||||||
ATMatcher m;
|
|
||||||
for (ATermIterator i(paths); i; ++i) {
|
for (ATermIterator i(paths); i; ++i) {
|
||||||
string s;
|
if (ATgetType(*i) != AT_APPL)
|
||||||
if (!(atMatch(m, *i) >> s))
|
throw badTerm("not a path", *i);
|
||||||
|
string s = aterm2String(*i);
|
||||||
|
if (s.size() == 0 || s[0] != '/')
|
||||||
throw badTerm("not a path", *i);
|
throw badTerm("not a path", *i);
|
||||||
out.insert(s);
|
out.insert(s);
|
||||||
}
|
}
|
||||||
|
@ -69,21 +73,20 @@ static void checkClosure(const Closure & closure)
|
||||||
static bool parseClosure(ATerm t, Closure & closure)
|
static bool parseClosure(ATerm t, Closure & closure)
|
||||||
{
|
{
|
||||||
ATermList roots, elems;
|
ATermList roots, elems;
|
||||||
ATMatcher m;
|
|
||||||
|
|
||||||
if (!(atMatch(m, t) >> "Closure" >> roots >> elems))
|
if (!matchClosure(t, roots, elems))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
parsePaths(roots, closure.roots);
|
parsePaths(roots, closure.roots);
|
||||||
|
|
||||||
for (ATermIterator i(elems); i; ++i) {
|
for (ATermIterator i(elems); i; ++i) {
|
||||||
string path;
|
ATerm path;
|
||||||
ATermList refs;
|
ATermList refs;
|
||||||
if (!(atMatch(m, *i) >> "" >> path >> refs))
|
if (!matchClosureElem(*i, path, refs))
|
||||||
throw badTerm("not a closure element", *i);
|
throw badTerm("not a closure element", *i);
|
||||||
ClosureElem elem;
|
ClosureElem elem;
|
||||||
parsePaths(refs, elem.refs);
|
parsePaths(refs, elem.refs);
|
||||||
closure.elems[path] = elem;
|
closure.elems[aterm2String(path)] = elem;
|
||||||
}
|
}
|
||||||
|
|
||||||
checkClosure(closure);
|
checkClosure(closure);
|
||||||
|
@ -93,32 +96,29 @@ static bool parseClosure(ATerm t, Closure & closure)
|
||||||
|
|
||||||
static bool parseDerivation(ATerm t, Derivation & derivation)
|
static bool parseDerivation(ATerm t, Derivation & derivation)
|
||||||
{
|
{
|
||||||
ATMatcher m;
|
|
||||||
ATermList outs, ins, args, bnds;
|
ATermList outs, ins, args, bnds;
|
||||||
string builder, platform;
|
ATerm builder, platform;
|
||||||
|
|
||||||
if (!(atMatch(m, t) >> "Derive" >> outs >> ins >> platform
|
if (!matchDerive(t, outs, ins, platform, builder, args, bnds))
|
||||||
>> builder >> args >> bnds))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
parsePaths(outs, derivation.outputs);
|
parsePaths(outs, derivation.outputs);
|
||||||
parsePaths(ins, derivation.inputs);
|
parsePaths(ins, derivation.inputs);
|
||||||
|
|
||||||
derivation.builder = builder;
|
derivation.builder = aterm2String(builder);
|
||||||
derivation.platform = platform;
|
derivation.platform = aterm2String(platform);
|
||||||
|
|
||||||
for (ATermIterator i(args); i; ++i) {
|
for (ATermIterator i(args); i; ++i) {
|
||||||
string s;
|
if (ATgetType(*i) != AT_APPL)
|
||||||
if (!(atMatch(m, *i) >> s))
|
|
||||||
throw badTerm("string expected", *i);
|
throw badTerm("string expected", *i);
|
||||||
derivation.args.push_back(s);
|
derivation.args.push_back(aterm2String(*i));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ATermIterator i(bnds); i; ++i) {
|
for (ATermIterator i(bnds); i; ++i) {
|
||||||
string s1, s2;
|
ATerm s1, s2;
|
||||||
if (!(atMatch(m, *i) >> "" >> s1 >> s2))
|
if (!matchEnvBinding(*i, s1, s2))
|
||||||
throw badTerm("tuple of strings expected", *i);
|
throw badTerm("tuple of strings expected", *i);
|
||||||
derivation.env[s1] = s2;
|
derivation.env[aterm2String(s1)] = aterm2String(s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -142,7 +142,7 @@ static ATermList unparsePaths(const PathSet & paths)
|
||||||
ATermList l = ATempty;
|
ATermList l = ATempty;
|
||||||
for (PathSet::const_iterator i = paths.begin();
|
for (PathSet::const_iterator i = paths.begin();
|
||||||
i != paths.end(); i++)
|
i != paths.end(); i++)
|
||||||
l = ATinsert(l, ATmake("<str>", i->c_str()));
|
l = ATinsert(l, string2ATerm(i->c_str()));
|
||||||
return ATreverse(l);
|
return ATreverse(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,11 +155,11 @@ static ATerm unparseClosure(const Closure & closure)
|
||||||
for (ClosureElems::const_iterator i = closure.elems.begin();
|
for (ClosureElems::const_iterator i = closure.elems.begin();
|
||||||
i != closure.elems.end(); i++)
|
i != closure.elems.end(); i++)
|
||||||
elems = ATinsert(elems,
|
elems = ATinsert(elems,
|
||||||
ATmake("(<str>, <term>)",
|
makeClosureElem(
|
||||||
i->first.c_str(),
|
string2ATerm(i->first.c_str()),
|
||||||
unparsePaths(i->second.refs)));
|
unparsePaths(i->second.refs)));
|
||||||
|
|
||||||
return ATmake("Closure(<term>, <term>)", roots, elems);
|
return makeClosure(roots, elems);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -168,20 +168,21 @@ static ATerm unparseDerivation(const Derivation & derivation)
|
||||||
ATermList args = ATempty;
|
ATermList args = ATempty;
|
||||||
for (Strings::const_iterator i = derivation.args.begin();
|
for (Strings::const_iterator i = derivation.args.begin();
|
||||||
i != derivation.args.end(); i++)
|
i != derivation.args.end(); i++)
|
||||||
args = ATinsert(args, ATmake("<str>", i->c_str()));
|
args = ATinsert(args, string2ATerm(i->c_str()));
|
||||||
|
|
||||||
ATermList env = ATempty;
|
ATermList env = ATempty;
|
||||||
for (StringPairs::const_iterator i = derivation.env.begin();
|
for (StringPairs::const_iterator i = derivation.env.begin();
|
||||||
i != derivation.env.end(); i++)
|
i != derivation.env.end(); i++)
|
||||||
env = ATinsert(env,
|
env = ATinsert(env,
|
||||||
ATmake("(<str>, <str>)",
|
makeEnvBinding(
|
||||||
i->first.c_str(), i->second.c_str()));
|
string2ATerm(i->first.c_str()),
|
||||||
|
string2ATerm(i->second.c_str())));
|
||||||
|
|
||||||
return ATmake("Derive(<term>, <term>, <str>, <str>, <term>, <term>)",
|
return makeDerive(
|
||||||
unparsePaths(derivation.outputs),
|
unparsePaths(derivation.outputs),
|
||||||
unparsePaths(derivation.inputs),
|
unparsePaths(derivation.inputs),
|
||||||
derivation.platform.c_str(),
|
string2ATerm(derivation.platform.c_str()),
|
||||||
derivation.builder.c_str(),
|
string2ATerm(derivation.builder.c_str()),
|
||||||
ATreverse(args),
|
ATreverse(args),
|
||||||
ATreverse(env));
|
ATreverse(env));
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,3 @@ libutil_a_SOURCES = util.cc util.hh hash.cc hash.hh \
|
||||||
archive.cc archive.hh md5.c md5.h aterm.cc aterm.hh
|
archive.cc archive.hh md5.c md5.h aterm.cc aterm.hh
|
||||||
|
|
||||||
AM_CXXFLAGS = -Wall -I.. ${aterm_include}
|
AM_CXXFLAGS = -Wall -I.. ${aterm_include}
|
||||||
|
|
||||||
check_PROGRAMS = test-aterm
|
|
||||||
|
|
||||||
test_aterm_SOURCES = test-aterm.cc
|
|
||||||
test_aterm_LDADD = ./libutil.a ../boost/format/libformat.a \
|
|
||||||
${aterm_lib}
|
|
||||||
|
|
||||||
|
|
|
@ -16,95 +16,6 @@ ostream & operator << (ostream & stream, ATerm e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ATMatcher & atMatch(ATMatcher & pos, ATerm t)
|
|
||||||
{
|
|
||||||
pos.t = t;
|
|
||||||
pos.pos = ATMatcher::funPos;
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline bool failed(const ATMatcher & pos)
|
|
||||||
{
|
|
||||||
return pos.pos == ATMatcher::failPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline ATMatcher & fail(ATMatcher & pos)
|
|
||||||
{
|
|
||||||
pos.pos = ATMatcher::failPos;
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ATMatcher & operator >> (ATMatcher & pos, ATerm & out)
|
|
||||||
{
|
|
||||||
out = 0;
|
|
||||||
if (failed(pos)) return pos;
|
|
||||||
if (pos.pos == ATMatcher::funPos ||
|
|
||||||
ATgetType(pos.t) != AT_APPL ||
|
|
||||||
pos.pos >= (int) ATgetArity(ATgetAFun(pos.t)))
|
|
||||||
return fail(pos);
|
|
||||||
out = ATgetArgument(pos.t, pos.pos);
|
|
||||||
pos.pos++;
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ATMatcher & operator >> (ATMatcher & pos, string & out)
|
|
||||||
{
|
|
||||||
out = "";
|
|
||||||
if (pos.pos == ATMatcher::funPos) {
|
|
||||||
if (ATgetType(pos.t) != AT_APPL) return fail(pos);
|
|
||||||
out = ATgetName(ATgetAFun(pos.t));
|
|
||||||
pos.pos = 0;
|
|
||||||
} else {
|
|
||||||
ATerm t;
|
|
||||||
pos = pos >> t;
|
|
||||||
if (failed(pos)) return pos;
|
|
||||||
if (ATgetType(t) != AT_APPL ||
|
|
||||||
ATgetArity(ATgetAFun(t)) != 0)
|
|
||||||
return fail(pos);
|
|
||||||
out = ATgetName(ATgetAFun(t));
|
|
||||||
}
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ATMatcher & operator >> (ATMatcher & pos, const string & s)
|
|
||||||
{
|
|
||||||
string s2;
|
|
||||||
pos = pos >> s2;
|
|
||||||
if (failed(pos)) return pos;
|
|
||||||
if (s != s2) return fail(pos);
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ATMatcher & operator >> (ATMatcher & pos, int & n)
|
|
||||||
{
|
|
||||||
n = 0;
|
|
||||||
ATerm t;
|
|
||||||
pos = pos >> t;
|
|
||||||
if (failed(pos)) return pos;
|
|
||||||
if (ATgetType(t) != AT_INT) return fail(pos);
|
|
||||||
n = ATgetInt((ATermInt) t);
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ATMatcher & operator >> (ATMatcher & pos, ATermList & out)
|
|
||||||
{
|
|
||||||
out = 0;
|
|
||||||
ATerm t;
|
|
||||||
pos = pos >> t;
|
|
||||||
if (failed(pos)) return pos;
|
|
||||||
if (ATgetType(t) != AT_LIST) return fail(pos);
|
|
||||||
out = (ATermList) t;
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Error badTerm(const format & f, ATerm t)
|
Error badTerm(const format & f, ATerm t)
|
||||||
{
|
{
|
||||||
char * s = ATwriteToString(t);
|
char * s = ATwriteToString(t);
|
||||||
|
|
|
@ -36,48 +36,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Type-safe matching. */
|
|
||||||
|
|
||||||
struct ATMatcher
|
|
||||||
{
|
|
||||||
ATerm t;
|
|
||||||
int pos;
|
|
||||||
const static int failPos = -2;
|
|
||||||
const static int funPos = -1;
|
|
||||||
|
|
||||||
ATMatcher() : t(0), pos(failPos)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
operator bool() const
|
|
||||||
{
|
|
||||||
return pos != failPos;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Initiate matching of a term. */
|
|
||||||
ATMatcher & atMatch(ATMatcher & pos, ATerm t);
|
|
||||||
|
|
||||||
/* Get the next argument of an application. */
|
|
||||||
ATMatcher & operator >> (ATMatcher & pos, ATerm & out);
|
|
||||||
|
|
||||||
/* Get the name of the function symbol of an application, or the next
|
|
||||||
argument of an application as a string. */
|
|
||||||
ATMatcher & operator >> (ATMatcher & pos, string & out);
|
|
||||||
|
|
||||||
/* Like the previous, but check that the string is equal to the given
|
|
||||||
string. */
|
|
||||||
ATMatcher & operator >> (ATMatcher & pos, const string & s);
|
|
||||||
|
|
||||||
/* Get the next argument of an application, and verify that it is a
|
|
||||||
integer. */
|
|
||||||
ATMatcher & operator >> (ATMatcher & pos, int & n);
|
|
||||||
|
|
||||||
/* Get the next argument of an application, and verify that it is a
|
|
||||||
list. */
|
|
||||||
ATMatcher & operator >> (ATMatcher & pos, ATermList & out);
|
|
||||||
|
|
||||||
|
|
||||||
/* Throw an exception with an error message containing the given
|
/* Throw an exception with an error message containing the given
|
||||||
aterm. */
|
aterm. */
|
||||||
Error badTerm(const format & f, ATerm t);
|
Error badTerm(const format & f, ATerm t);
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
#include "aterm.hh"
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
|
|
||||||
void runTests()
|
|
||||||
{
|
|
||||||
verbosity = lvlDebug;
|
|
||||||
|
|
||||||
ATMatcher pos;
|
|
||||||
|
|
||||||
ATerm t = ATmake("Call(Foo, Bar, \"xyz\")");
|
|
||||||
|
|
||||||
debug(format("term: %1%") % t);
|
|
||||||
|
|
||||||
string fun, arg3;
|
|
||||||
ATerm lhs, rhs;
|
|
||||||
|
|
||||||
if (!(atMatch(pos, t) >> "Call" >> lhs >> rhs >> arg3))
|
|
||||||
throw Error("should succeed");
|
|
||||||
if (arg3 != "xyz") throw Error("bad 1");
|
|
||||||
|
|
||||||
if (!(atMatch(pos, t) >> fun >> lhs >> rhs >> arg3))
|
|
||||||
throw Error("should succeed");
|
|
||||||
if (fun != "Call") throw Error("bad 2");
|
|
||||||
if (arg3 != "xyz") throw Error("bad 3");
|
|
||||||
|
|
||||||
if (!(atMatch(pos, t) >> fun >> lhs >> rhs >> "xyz"))
|
|
||||||
throw Error("should succeed");
|
|
||||||
|
|
||||||
if (atMatch(pos, t) >> fun >> lhs >> rhs >> "abc")
|
|
||||||
throw Error("should fail");
|
|
||||||
|
|
||||||
if (atMatch(pos, t) >> "Call" >> lhs >> rhs >> "abc")
|
|
||||||
throw Error("should fail");
|
|
||||||
|
|
||||||
t = ATmake("X([A, B, C], \"abc\")");
|
|
||||||
|
|
||||||
ATerm t1, t2, t3;
|
|
||||||
if (atMatch(pos, t) >> "X" >> t1 >> t2 >> t3)
|
|
||||||
throw Error("should fail");
|
|
||||||
if (!(atMatch(pos, t) >> "X" >> t1 >> t2))
|
|
||||||
throw Error("should succeed");
|
|
||||||
ATermList ts;
|
|
||||||
if (!(atMatch(pos, t) >> "X" >> ts >> t2))
|
|
||||||
throw Error("should succeed");
|
|
||||||
if (ATgetLength(ts) != 3)
|
|
||||||
throw Error("bad");
|
|
||||||
if (atMatch(pos, t) >> "X" >> t1 >> ts)
|
|
||||||
throw Error("should fail");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char * * argv)
|
|
||||||
{
|
|
||||||
ATerm bottomOfStack;
|
|
||||||
ATinit(argc, argv, &bottomOfStack);
|
|
||||||
|
|
||||||
try {
|
|
||||||
runTests();
|
|
||||||
} catch (Error & e) {
|
|
||||||
printMsg(lvlError, format("error: %1%") % e.msg());
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -6,7 +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 "nixexpr-ast.hh"
|
||||||
|
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
@ -481,20 +481,22 @@ typedef list<Strings> Table;
|
||||||
|
|
||||||
void printTable(Table & table)
|
void printTable(Table & table)
|
||||||
{
|
{
|
||||||
int nrColumns = table.size() > 0 ? table.front().size() : 0;
|
unsigned int nrColumns = table.size() > 0 ? table.front().size() : 0;
|
||||||
|
|
||||||
vector<int> widths;
|
vector<unsigned int> widths;
|
||||||
widths.resize(nrColumns);
|
widths.resize(nrColumns);
|
||||||
|
|
||||||
for (Table::iterator i = table.begin(); i != table.end(); ++i) {
|
for (Table::iterator i = table.begin(); i != table.end(); ++i) {
|
||||||
assert(i->size() == nrColumns);
|
assert(i->size() == nrColumns);
|
||||||
Strings::iterator j; int column;
|
Strings::iterator j;
|
||||||
|
unsigned int column;
|
||||||
for (j = i->begin(), column = 0; j != i->end(); ++j, ++column)
|
for (j = i->begin(), column = 0; j != i->end(); ++j, ++column)
|
||||||
if (j->size() > widths[column]) widths[column] = j->size();
|
if (j->size() > widths[column]) widths[column] = j->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Table::iterator i = table.begin(); i != table.end(); ++i) {
|
for (Table::iterator i = table.begin(); i != table.end(); ++i) {
|
||||||
Strings::iterator j; int column;
|
Strings::iterator j;
|
||||||
|
unsigned int column;
|
||||||
for (j = i->begin(), column = 0; j != i->end(); ++j, ++column)
|
for (j = i->begin(), column = 0; j != i->end(); ++j, ++column)
|
||||||
{
|
{
|
||||||
cout << *j;
|
cout << *j;
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include "shared.hh"
|
#include "shared.hh"
|
||||||
#include "eval.hh"
|
#include "eval.hh"
|
||||||
#include "parser.hh"
|
#include "parser.hh"
|
||||||
#include "constructors.hh"
|
#include "nixexpr-ast.hh"
|
||||||
#include "help.txt.hh"
|
#include "help.txt.hh"
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,7 +28,6 @@ static Expr evalStdin(EvalState & state, bool parseOnly)
|
||||||
|
|
||||||
static void printDrvPaths(EvalState & state, Expr e)
|
static void printDrvPaths(EvalState & state, Expr e)
|
||||||
{
|
{
|
||||||
ATMatcher m;
|
|
||||||
ATermList es;
|
ATermList es;
|
||||||
|
|
||||||
/* !!! duplication w.r.t. parseDerivations in nix-env */
|
/* !!! duplication w.r.t. parseDerivations in nix-env */
|
||||||
|
|
Loading…
Reference in a new issue