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