This is the mail archive of the guile@cygnus.com mailing list for the Guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: corrupt environment?



emanual> I'm running into a strange problem that I can't figure out,
emanual> shown by the following example:

I discovered this bug about two years ago.  Here is an example that
doesn't SET! a global variable, and shows better what the problem is:

  guile> (let()
  guile>   (define x 1) (define (y) x)
  guile>   (display (list x (y)))(newline)
  guile>   (define z 5)
  guile>   (display (list x (y)))(newline))
  (1 1)
  (1 #<procedure y ()>)

The first time (Y) is evaluated the memo-izer notes that X is the
second value on the stack and clobbers the definition of Y with
this 'optimization'.  Then Z is pushed, and Y is broken.

thi> i remember that guile had a problem where it did not properly handle
thi> the (improper usage) case where there were other expressions before
thi> the define form...

When I first pointed this out, I got replies saying the the above is
not legal R4RS Scheme.  We agree on that.  I thought that the consensus
was that the above behaviour nevertheless is a bug in Guile.  At that
time I relaxed, assuming that someone who understood eval.c better than
I would fix it.  Sorry, I should have made a patch.

emanual> Yes, changing the code around did help.  I guess I didn't read
emanual> the R5RS carefully enough.

If Guile printed a message like:
--  Syntax Error, internal definition may not follow expression
then it would be up to you to read until you understood why.  Without
the message, I don't think this can be called programmer error.
It should be fixed.  But what does "fix" mean?

The quick fix would be to print an error message.  This might break
some existing code, but either the fix would be simple, just move
the defintions to the top, or the existing code contains an
unmanifest bug.  So this message _should_ be printed, if not always
at least when Guile operates in strict RnRS mode.

thi> nested `define' forms are syntactic sugar.

In particular
  (let() (define pi 3) (define twopi (* 2 pi)) (/ twopi))
is equivalent to
  (letrec ((pi 3) (twopi (* 2 pi))) (/ twopi))
which is again
    (let ((pi ?) (twopi ?))
       (permute (set! pi 3) (set! twopi (* 2 pi)))
       (/ twopi))
where PERMUTE is a macro that permutes its arguments in an arbitrary
implementation dependant way.

Therefore the original is non-portable, and could produce an error,
-- variable pi has no value assigned

This is not what would be expected by a programmer who is
tempted to mix commands in with the local definitions.
So if such mixing is not to be an error, then it should be
proclaimed, as an extension to Scheme, that Guile evaluates
internal defines in the order written.  (Except, possibly,
in strict RnRS mode.)

thi> i believe someone wrote a macro that would allow you to place
thi> define forms arbitrarily in a scope, not just at the beginning.

If it works by sorting the forms so that the definitions are moved
ahead of the commands, then this is dangerous.  I would rather
see an error message than to have my code silently permuted.
If it works by correctly doing the above 'de-sugaring' transform
then it should be a permanent part of the evaluator.

emanual> I think I'll try to find it, because I do the above all
emanual> over the code and don't feel like fixing it all if
emanual> there's a easier way :-)

Good luck, but I think the reason this has gone unfixed for so
long is that it is not a simple patch.  The real source of the
problem is that Guile has the macro-expansion, syntax checking,
and optimization phase too much interwingled with execution.
We don't want to slow the interpreter by making it check syntax
every time the procedure is called.

-- 
     -- Keith Wright  <kwright@free-comp-shop.com>

Programmer in Chief, Free Computer Shop <http://www.free-comp-shop.com>
         ---  Food, Shelter, Source code.  ---

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]