* Drop ATmake / ATMatcher also in handling store expressions.
This commit is contained in:
parent
ed09821859
commit
a69534fc21
|
@ -1,6 +1,8 @@
|
|||
SUBDIRS = bin2c boost libutil libstore libmain nix-store nix-hash \
|
||||
libexpr nix-instantiate nix-env log2xml
|
||||
|
||||
EXTRA_DIST = aterm-helper.pl
|
||||
|
||||
SETUID_PROGS = nix-store nix-instantiate nix-env
|
||||
install-exec-hook:
|
||||
if SETUID_HACK
|
||||
|
|
|
@ -1,9 +1,41 @@
|
|||
#! /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;
|
||||
|
||||
my $syms = "";
|
||||
my $init = "";
|
||||
my $initFun = "init";
|
||||
|
||||
open HEADER, ">$ARGV[0]";
|
||||
open IMPL, ">$ARGV[1]";
|
||||
|
@ -11,7 +43,7 @@ open IMPL, ">$ARGV[1]";
|
|||
while (<STDIN>) {
|
||||
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 @types = split ' ', $2;
|
||||
my $result = $3;
|
||||
|
@ -30,6 +62,8 @@ while (<STDIN>) {
|
|||
# $type = "const char *";
|
||||
$type = "ATerm";
|
||||
$args .= "e$n";
|
||||
# !!! in the matcher, we should check that the
|
||||
# argument is a string (i.e., a nullary application).
|
||||
} elsif ($type eq "int") {
|
||||
$args .= "(ATerm) ATmakeInt(e$n)";
|
||||
} elsif ($type eq "ATermList" || $type eq "ATermBlob") {
|
||||
|
@ -42,6 +76,7 @@ while (<STDIN>) {
|
|||
$formals2 .= ", ";
|
||||
$formals2 .= "$type & e$n";
|
||||
my $m = $n - 1;
|
||||
# !!! more checks here
|
||||
if ($type eq "int") {
|
||||
$unpack .= " e$n = ATgetInt((ATermInt) ATgetArgument(e, $m));\n";
|
||||
} elsif ($type eq "ATermList") {
|
||||
|
@ -84,12 +119,16 @@ while (<STDIN>) {
|
|||
$init .= " $name = $value;\n";
|
||||
}
|
||||
|
||||
elsif (/^\s*init\s+(\w+)\s*$/) {
|
||||
$initFun = $1;
|
||||
}
|
||||
|
||||
else {
|
||||
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 " 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 IMPL "\n";
|
||||
print IMPL "void initSyms() {\n";
|
||||
print IMPL "void $initFun() {\n";
|
||||
print IMPL "$init";
|
||||
print IMPL "}\n";
|
||||
|
|
@ -3,10 +3,9 @@ noinst_LIBRARIES = libexpr.a
|
|||
libexpr_a_SOURCES = nixexpr.cc nixexpr.hh parser.cc parser.hh \
|
||||
eval.cc eval.hh primops.cc \
|
||||
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 \
|
||||
aterm-helper.pl
|
||||
EXTRA_DIST = lexer.l parser.y nixexpr-ast.def nixexpr-ast.cc
|
||||
|
||||
AM_CXXFLAGS = \
|
||||
-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.
|
||||
|
||||
constructors.cc constructors.hh: aterm-helper.pl constructors.def
|
||||
$(perl) aterm-helper.pl constructors.hh constructors.cc < constructors.def
|
||||
nixexpr-ast.cc nixexpr-ast.hh: ../aterm-helper.pl nixexpr-ast.def
|
||||
$(perl) ../aterm-helper.pl nixexpr-ast.hh nixexpr-ast.cc < nixexpr-ast.def
|
||||
|
||||
nixexpr.hh: constructors.hh
|
||||
nixexpr.hh: nixexpr-ast.hh
|
||||
|
||||
|
||||
CLEANFILES =
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "eval.hh"
|
||||
#include "parser.hh"
|
||||
#include "constructors.hh"
|
||||
#include "nixexpr-ast.hh"
|
||||
|
||||
|
||||
EvalState::EvalState()
|
||||
|
@ -10,7 +10,7 @@ EvalState::EvalState()
|
|||
|
||||
nrEvaluated = nrCached = 0;
|
||||
|
||||
initSyms();
|
||||
initNixExprHelpers();
|
||||
|
||||
addPrimOps();
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
init initNixExprHelpers
|
||||
|
||||
Pos | string int int | Pos |
|
||||
NoPos | | Pos |
|
||||
|
|
@ -2,8 +2,8 @@
|
|||
#include "storeexpr.hh"
|
||||
|
||||
|
||||
#include "constructors.hh"
|
||||
#include "constructors.cc"
|
||||
#include "nixexpr-ast.hh"
|
||||
#include "nixexpr-ast.cc"
|
||||
|
||||
|
||||
ATermMap::ATermMap(unsigned int initialSize, unsigned int maxLoadPct)
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#include "aterm.hh"
|
||||
#include "parser.hh"
|
||||
#include "constructors.hh"
|
||||
#include "nixexpr-ast.hh"
|
||||
|
||||
|
||||
struct ParseData
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
typedef ATerm Expr;
|
||||
typedef ATerm Pos;
|
||||
|
||||
#include "constructors.hh"
|
||||
#include "nixexpr-ast.hh"
|
||||
|
||||
void setParseResult(void * data, ATerm t);
|
||||
void parseError(void * data, char * error, int line, int column);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "normalise.hh"
|
||||
#include "eval.hh"
|
||||
#include "globals.hh"
|
||||
#include "constructors.hh"
|
||||
#include "nixexpr-ast.hh"
|
||||
|
||||
|
||||
/* 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
|
||||
processor. */
|
||||
static void initAndRun(int argc, char * * argv)
|
||||
|
@ -101,6 +104,9 @@ static void initAndRun(int argc, char * * argv)
|
|||
string lt = getEnv("NIX_LOG_TYPE");
|
||||
if (lt != "") setLogType(lt);
|
||||
|
||||
/* ATerm stuff. !!! find a better place to put this */
|
||||
initStoreExprHelpers();
|
||||
|
||||
/* Put the arguments in a vector. */
|
||||
Strings args, remaining;
|
||||
while (argc--) args.push_back(*argv++);
|
||||
|
|
|
@ -5,7 +5,14 @@ libstore_a_SOURCES = \
|
|||
normalise.cc misc.cc normalise.hh \
|
||||
globals.cc globals.hh db.cc db.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 \
|
||||
-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 "store.hh"
|
||||
|
||||
#include "storeexpr-ast.hh"
|
||||
#include "storeexpr-ast.cc"
|
||||
|
||||
|
||||
Hash hashTerm(ATerm t)
|
||||
{
|
||||
|
@ -29,10 +32,11 @@ Path writeTerm(ATerm t, const string & suffix)
|
|||
|
||||
static void parsePaths(ATermList paths, PathSet & out)
|
||||
{
|
||||
ATMatcher m;
|
||||
for (ATermIterator i(paths); i; ++i) {
|
||||
string s;
|
||||
if (!(atMatch(m, *i) >> s))
|
||||
if (ATgetType(*i) != AT_APPL)
|
||||
throw badTerm("not a path", *i);
|
||||
string s = aterm2String(*i);
|
||||
if (s.size() == 0 || s[0] != '/')
|
||||
throw badTerm("not a path", *i);
|
||||
out.insert(s);
|
||||
}
|
||||
|
@ -69,21 +73,20 @@ static void checkClosure(const Closure & closure)
|
|||
static bool parseClosure(ATerm t, Closure & closure)
|
||||
{
|
||||
ATermList roots, elems;
|
||||
ATMatcher m;
|
||||
|
||||
if (!(atMatch(m, t) >> "Closure" >> roots >> elems))
|
||||
if (!matchClosure(t, roots, elems))
|
||||
return false;
|
||||
|
||||
parsePaths(roots, closure.roots);
|
||||
|
||||
for (ATermIterator i(elems); i; ++i) {
|
||||
string path;
|
||||
ATerm path;
|
||||
ATermList refs;
|
||||
if (!(atMatch(m, *i) >> "" >> path >> refs))
|
||||
if (!matchClosureElem(*i, path, refs))
|
||||
throw badTerm("not a closure element", *i);
|
||||
ClosureElem elem;
|
||||
parsePaths(refs, elem.refs);
|
||||
closure.elems[path] = elem;
|
||||
closure.elems[aterm2String(path)] = elem;
|
||||
}
|
||||
|
||||
checkClosure(closure);
|
||||
|
@ -93,32 +96,29 @@ static bool parseClosure(ATerm t, Closure & closure)
|
|||
|
||||
static bool parseDerivation(ATerm t, Derivation & derivation)
|
||||
{
|
||||
ATMatcher m;
|
||||
ATermList outs, ins, args, bnds;
|
||||
string builder, platform;
|
||||
ATerm builder, platform;
|
||||
|
||||
if (!(atMatch(m, t) >> "Derive" >> outs >> ins >> platform
|
||||
>> builder >> args >> bnds))
|
||||
if (!matchDerive(t, outs, ins, platform, builder, args, bnds))
|
||||
return false;
|
||||
|
||||
parsePaths(outs, derivation.outputs);
|
||||
parsePaths(ins, derivation.inputs);
|
||||
|
||||
derivation.builder = builder;
|
||||
derivation.platform = platform;
|
||||
derivation.builder = aterm2String(builder);
|
||||
derivation.platform = aterm2String(platform);
|
||||
|
||||
for (ATermIterator i(args); i; ++i) {
|
||||
string s;
|
||||
if (!(atMatch(m, *i) >> s))
|
||||
if (ATgetType(*i) != AT_APPL)
|
||||
throw badTerm("string expected", *i);
|
||||
derivation.args.push_back(s);
|
||||
derivation.args.push_back(aterm2String(*i));
|
||||
}
|
||||
|
||||
for (ATermIterator i(bnds); i; ++i) {
|
||||
string s1, s2;
|
||||
if (!(atMatch(m, *i) >> "" >> s1 >> s2))
|
||||
ATerm s1, s2;
|
||||
if (!matchEnvBinding(*i, s1, s2))
|
||||
throw badTerm("tuple of strings expected", *i);
|
||||
derivation.env[s1] = s2;
|
||||
derivation.env[aterm2String(s1)] = aterm2String(s2);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -142,7 +142,7 @@ static ATermList unparsePaths(const PathSet & paths)
|
|||
ATermList l = ATempty;
|
||||
for (PathSet::const_iterator i = paths.begin();
|
||||
i != paths.end(); i++)
|
||||
l = ATinsert(l, ATmake("<str>", i->c_str()));
|
||||
l = ATinsert(l, string2ATerm(i->c_str()));
|
||||
return ATreverse(l);
|
||||
}
|
||||
|
||||
|
@ -155,11 +155,11 @@ static ATerm unparseClosure(const Closure & closure)
|
|||
for (ClosureElems::const_iterator i = closure.elems.begin();
|
||||
i != closure.elems.end(); i++)
|
||||
elems = ATinsert(elems,
|
||||
ATmake("(<str>, <term>)",
|
||||
i->first.c_str(),
|
||||
makeClosureElem(
|
||||
string2ATerm(i->first.c_str()),
|
||||
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;
|
||||
for (Strings::const_iterator i = derivation.args.begin();
|
||||
i != derivation.args.end(); i++)
|
||||
args = ATinsert(args, ATmake("<str>", i->c_str()));
|
||||
args = ATinsert(args, string2ATerm(i->c_str()));
|
||||
|
||||
ATermList env = ATempty;
|
||||
for (StringPairs::const_iterator i = derivation.env.begin();
|
||||
i != derivation.env.end(); i++)
|
||||
env = ATinsert(env,
|
||||
ATmake("(<str>, <str>)",
|
||||
i->first.c_str(), i->second.c_str()));
|
||||
makeEnvBinding(
|
||||
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.inputs),
|
||||
derivation.platform.c_str(),
|
||||
derivation.builder.c_str(),
|
||||
string2ATerm(derivation.platform.c_str()),
|
||||
string2ATerm(derivation.builder.c_str()),
|
||||
ATreverse(args),
|
||||
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
|
||||
|
||||
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)
|
||||
{
|
||||
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
|
||||
aterm. */
|
||||
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 "eval.hh"
|
||||
#include "help.txt.hh"
|
||||
#include "constructors.hh"
|
||||
#include "nixexpr-ast.hh"
|
||||
|
||||
#include <cerrno>
|
||||
#include <ctime>
|
||||
|
@ -481,20 +481,22 @@ typedef list<Strings> 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);
|
||||
|
||||
for (Table::iterator i = table.begin(); i != table.end(); ++i) {
|
||||
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)
|
||||
if (j->size() > widths[column]) widths[column] = j->size();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
cout << *j;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "shared.hh"
|
||||
#include "eval.hh"
|
||||
#include "parser.hh"
|
||||
#include "constructors.hh"
|
||||
#include "nixexpr-ast.hh"
|
||||
#include "help.txt.hh"
|
||||
|
||||
|
||||
|
@ -28,7 +28,6 @@ static Expr evalStdin(EvalState & state, bool parseOnly)
|
|||
|
||||
static void printDrvPaths(EvalState & state, Expr e)
|
||||
{
|
||||
ATMatcher m;
|
||||
ATermList es;
|
||||
|
||||
/* !!! duplication w.r.t. parseDerivations in nix-env */
|
||||
|
|
Loading…
Reference in a new issue