diff options
author | Eelco Dolstra <e.dolstra@tudelft.nl> | 2003-08-14 12:37:31 +0000 |
---|---|---|
committer | Eelco Dolstra <e.dolstra@tudelft.nl> | 2003-08-14 12:37:31 +0000 |
commit | dc0ef2ca98ddf21586b68089d28df59ef3e756dd (patch) | |
tree | b1ef4212f87f6b22f60ca3a89e938bafa6223afc | |
parent | 2e16ff22ac6f3a4ea6684026a609856f29d86499 (diff) |
* Detect infinite loops using blackholing.
-rw-r--r-- | src/fix.cc | 16 | ||||
-rw-r--r-- | testpkgs/infrec/infrec.fix | 1 |
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") |