aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2003-08-14 12:37:31 +0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2003-08-14 12:37:31 +0000
commitdc0ef2ca98ddf21586b68089d28df59ef3e756dd (patch)
treeb1ef4212f87f6b22f60ca3a89e938bafa6223afc
parent2e16ff22ac6f3a4ea6684026a609856f29d86499 (diff)
* Detect infinite loops using blackholing.
-rw-r--r--src/fix.cc16
-rw-r--r--testpkgs/infrec/infrec.fix1
2 files changed, 14 insertions, 3 deletions
diff --git a/src/fix.cc b/src/fix.cc
index 5405190f3..e50d77620 100644
--- a/src/fix.cc
+++ b/src/fix.cc
@@ -18,6 +18,13 @@ struct EvalState
NormalForms normalForms;
PkgPaths pkgPaths;
PkgHashes pkgHashes; /* normalised package hashes */
+ Expr blackHole;
+
+ EvalState()
+ {
+ blackHole = ATmake("BlackHole()");
+ if (!blackHole) throw Error("cannot build black hole");
+ }
};
@@ -64,8 +71,6 @@ static Expr substExpr(string x, Expr rep, Expr e)
}
}
- /* ??? unfair substitutions? */
-
/* Generically substitute in subterms. */
if (ATgetType(e) == AT_APPL) {
@@ -345,9 +350,14 @@ static Expr evalExpr(EvalState & state, Expr e)
/* Consult the memo table to quickly get the normal form of
previously evaluated expressions. */
NormalForms::iterator i = state.normalForms.find(e);
- if (i != state.normalForms.end()) return i->second;
+ if (i != state.normalForms.end()) {
+ if (i->second == state.blackHole)
+ throw badTerm("infinite recursion", e);
+ return i->second;
+ }
/* Otherwise, evaluate and memoize. */
+ state.normalForms[e] = state.blackHole;
Expr nf = evalExpr2(state, e);
state.normalForms[e] = nf;
return nf;
diff --git a/testpkgs/infrec/infrec.fix b/testpkgs/infrec/infrec.fix
new file mode 100644
index 000000000..7db7c99ad
--- /dev/null
+++ b/testpkgs/infrec/infrec.fix
@@ -0,0 +1 @@
+IncludeFix("infrec/infrec.fix")