-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 29-Sep-06, at 4:34 AM, Christian wrote:
At 1:17 Uhr -0500 29.09.2006, Bill Richter wrote:
Christian suggested I might have found a real bug,
The interesting bit is, that using compile-file & load Bill's program usually works, whereas with static compilation/linking not. I don't know where Gambit would differ in those two
and that I should try stripping off as much fat as possible from my program.
You should strip it more until you can say "if I leave this out, it doesn't do weird things anymore".
Here's what you should be doing in such cases:
- check which functions are really mutating, and which ones are
functions. I realize that you're using map (meant for functions) where I think for-each (meant for imperative code) is what you want (maybe the order of evaluation may be a problem!). I realize that UnSpace clearly does mutate it's argument, thus rename it to UnSpace!.
- try to find out whether ShowPossibilities mutates it's argument.
From a quick look at the code, I'd say so, but runnning it in gsi, I couldn't find a modification of it's input, strange.
- try to find out where during the runtime of the program the problem
happens. For this, outputting the relevant datastructures helps. I've put a (pp U7) between the two ShowPossibilities calls and another one after the second. After the first ShowPossibilities call U7 is containing lists (is this what you want?); then the second ShowPossibilities call runs into the error. So clearly U7 has been modified, and ShowPossibilities should be renamed to ShowPossibilities!.
Why does the same not happen in the interpreter? Before knowing that it's a Gambit bug, we have to rule out that it's from a difference between interpreter and compiler behaviour.
Trimming it further down for an hour, I realize that you're modifying quoted datastructures. IIRC, R5RS says that modifying constant datastructures is undefined, and Gambit seems to rely on them not beeing modifyed when compiling to static binaries.
Replace all quoted #(..) with (vector ..) and it works.
Christian.
Nice debugging Christian! Yes the problem comes from mutation of constants. It works in the interpreter because the interpreter does not create constants for quoted objects (the constant is created by the reader):
(define (f)
(let ((x '(111))) (set-cdr! x (cons (car x) (cdr x))) (length x)))
(f)
2
(f)
3
(f)
4
(pp f)
(lambda () (let ((x '(111 111 111 111))) (set-cdr! x (cons (car x) (cdr x))) (length x)))
If you try compiling this kind of code you will have problems because the garbage collector does not traverse constant objects (because they can only contain references to other constant objects, and they are "permanently" allocated).
I'm thinking of adding a run time check to set-c[a|d]r!, vector-set!, etc to verify that the object is mutable. This can be done quickly by checking if the object is a ___PERM object.
By the way, statically linked programs and those produced by compile- file should behave the same.
Marc