aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/nixexpr.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libexpr/nixexpr.cc')
-rw-r--r--src/libexpr/nixexpr.cc75
1 files changed, 63 insertions, 12 deletions
diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc
index b0f506e65..92027a70e 100644
--- a/src/libexpr/nixexpr.cc
+++ b/src/libexpr/nixexpr.cc
@@ -156,10 +156,10 @@ Expr substitute(const ATermMap & subs, Expr e)
checkInterrupt();
ATMatcher m;
- string s;
+ ATerm name;
- if (atMatch(m, e) >> "Var" >> s) {
- Expr sub = subs.get(s);
+ if (atMatch(m, e) >> "Var" >> name) {
+ Expr sub = subs.get(name);
return sub ? sub : e;
}
@@ -170,11 +170,10 @@ Expr substitute(const ATermMap & subs, Expr e)
if (atMatch(m, e) >> "Function" >> formals >> body) {
ATermMap subs2(subs);
for (ATermIterator i(formals); i; ++i) {
- Expr def;
- if (!(atMatch(m, *i) >> "NoDefFormal" >> s) &&
- !(atMatch(m, *i) >> "DefFormal" >> s >> def))
+ if (!(atMatch(m, *i) >> "NoDefFormal" >> name) &&
+ !(atMatch(m, *i) >> "DefFormal" >> name))
abort();
- subs2.remove(s);
+ subs2.remove(name);
}
return ATmake("Function(<term>, <term>)", formals,
substitute(subs2, body));
@@ -184,12 +183,11 @@ Expr substitute(const ATermMap & subs, Expr e)
ATermList rbnds, nrbnds;
if (atMatch(m, e) >> "Rec" >> rbnds >> nrbnds) {
ATermMap subs2(subs);
- for (ATermIterator i(rbnds); i; ++i) {
- Expr e;
- if (!(atMatch(m, *i) >> "Bind" >> s >> e))
+ for (ATermIterator i(rbnds); i; ++i)
+ if (atMatch(m, *i) >> "Bind" >> name)
+ subs2.remove(name);
+ else
abort(); /* can't happen */
- subs2.remove(s);
- }
return ATmake("Rec(<term>, <term>)",
substitute(subs2, (ATerm) rbnds),
substitute(subs, (ATerm) nrbnds));
@@ -217,6 +215,59 @@ Expr substitute(const ATermMap & subs, Expr e)
}
+void checkVarDefs(const ATermMap & defs, Expr e)
+{
+ ATMatcher m;
+ ATerm name;
+ ATermList formals;
+ ATerm body;
+ ATermList rbnds, nrbnds;
+
+ if (atMatch(m, e) >> "Var" >> name) {
+ if (!defs.get(name))
+ throw Error(format("undefined variable `%1%'")
+ % aterm2String(name));
+ return;
+ }
+
+ else if (atMatch(m, e) >> "Function" >> formals >> body) {
+ ATermMap defs2(defs);
+ for (ATermIterator i(formals); i; ++i) {
+ Expr deflt;
+ if (!(atMatch(m, *i) >> "NoDefFormal" >> name))
+ if (atMatch(m, *i) >> "DefFormal" >> name >> deflt)
+ checkVarDefs(defs, deflt);
+ else
+ abort();
+ defs2.set(name, (ATerm) ATempty);
+ }
+ return checkVarDefs(defs2, body);
+ }
+
+ else if (atMatch(m, e) >> "Rec" >> rbnds >> nrbnds) {
+ checkVarDefs(defs
+ , (ATerm) nrbnds);
+ ATermMap defs2(defs);
+ for (ATermIterator i(rbnds); i; ++i) {
+ if (!(atMatch(m, *i) >> "Bind" >> name))
+ abort(); /* can't happen */
+ defs2.set(name, (ATerm) ATempty);
+ }
+ checkVarDefs(defs2, (ATerm) rbnds);
+ }
+
+ else if (ATgetType(e) == AT_APPL) {
+ int arity = ATgetArity(ATgetAFun(e));
+ for (int i = 0; i < arity; ++i)
+ checkVarDefs(defs, ATgetArgument(e, i));
+ }
+
+ else if (ATgetType(e) == AT_LIST)
+ for (ATermIterator i((ATermList) e); i; ++i)
+ checkVarDefs(defs, *i);
+}
+
+
Expr makeBool(bool b)
{
return b ? ATmake("Bool(True)") : ATmake("Bool(False)");