Mikael Djurfeldt <[EMAIL PROTECTED]> writes:

> Keisuke Nishida <[EMAIL PROTECTED]> writes:
> 
> > Oh, should it?  But Guile does restart it from 0:
> > 
> >   guile> (define some-cont #f)
> >   guile> (define magic-computation
> >            (let ((capture #t))
> >              (lambda (x)
> >                (if capture
> >                    (begin
> >                      (set! capture #f)
> >                      (set! some-cont (call-with-current-continuation id)))))))
> >   guile> (do ((v (make-vector 5 #f))
> >               (i 0 (1+ i)))
> >              ((= i 5))
> >            (vector-set! v i (magic-computation i))
> >            (display i))
> >   01234guile> (some-cont #f)
> >   01234guile> 
> > 
> > Which one is the correct behavior?
> 
> Miroslav is right.
> Guile is wrong.
> 
> This is a Guile bug.

Here's the Guile do code:

    case SCM_BIT8(SCM_IM_DO):
      x = SCM_CDR (x);
      proc = SCM_CAR (SCM_CDR (x)); /* inits */
      t.arg1 = SCM_EOL;         /* values */
      while (SCM_NIMP (proc))
        {
          t.arg1 = scm_cons (EVALCAR (proc, env), t.arg1);
          proc = SCM_CDR (proc);
        }
      env = EXTEND_ENV (SCM_CAR (x), t.arg1, env);
      x = SCM_CDR (SCM_CDR (x));
      while (proc = SCM_CAR (x), SCM_FALSEP (EVALCAR (proc, env)))
        {
          for (proc = SCM_CADR (x); SCM_NIMP (proc); proc = SCM_CDR (proc))
            {
              t.arg1 = SCM_CAR (proc); /* body */
              SIDEVAL (t.arg1, env);
            }
          for (t.arg1 = SCM_EOL, proc = SCM_CDDR (x);
               SCM_NIMP (proc);
               proc = SCM_CDR (proc))
            t.arg1 = scm_cons (EVALCAR (proc, env), t.arg1); /* steps */
          env = EXTEND_ENV (SCM_CAR (SCM_CAR (env)), t.arg1, SCM_CDR (env));
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The problem is here: Guile creates a *new* frame instead of mutating
the old, so call/cc will look at the fresh version of the first frame
instead of the *mutated* version of the fresh form.
        }
      x = SCM_CDR (proc);
      if (SCM_NULLP (x))
        RETURN (SCM_UNSPECIFIED);
      PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
      goto begin;

This can be fixed by mutating the frame when updating it.

Reply via email to