Subject: bug#25965: closed (Re: bug#25965: 26.0.50; iter-lambda may evaluate certain forms twice)

From: [email-masked] (GNU bug Tracking System)
Date: Thu, 05 Oct 2017 19:53:02 +0000

Your bug report

#25965: 26.0.50; iter-lambda may evaluate certain forms twice 

which was filed against the emacs package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
25965: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=25965
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: bug#25965: 26.0.50; iter-lambda may evaluate certain forms twice
From: Gemini Lasswell <[email-masked]>
To: Daniel Colascione <[email-masked]>
Cc: [email-masked], Stefan Monnier <[email-masked]>, Andreas Politz <[email-masked]>
Date: Thu, 05 Oct 2017 12:51:55 -0700
List-Id: <debbugs-submit.debbugs.gnu.org>

Pushed to emacs-26.

Subject: 26.0.50; iter-lambda may evaluate certain forms twice
From: Andreas Politz <[email-masked]>
To: [email-masked]
Date: Sat, 04 Mar 2017 09:02:32 +0100
List-Id: <debbugs-submit.debbugs.gnu.org>

Here is an example where the behavior occurs.

#+BEGIN_SRC emacs-lisp
  ;; -*- lexical-binding: t -*-
  (iter-next
   (funcall (iter-lambda ()
              (let* ((fill-column 10) ;;any special variable will do
                     (i 0)
                     (j (setq i (1+ i))))
                (iter-yield i)))))
  ;; => 2
#+END_SRC

But the result should be 1.  Looking at the expanded code, we see i
incremented indeed twice.

#+BEGIN_SRC emacs-lisp
  ;; ....
  (setq cps-state-atom--1522
        #'(lambda nil
            (setq cps-current-value--1513
                  (let
                      ((fill-column cps-binding-fill-column--1516))
                    (unwind-protect
                        (prog1
                            (setq cps-binding-i--1517
                                  (1+ cps-binding-i--1517))
                          (setq cps-current-state--1514 cps-state-let*--1521))
                      (setq cps-binding-fill-column--1516 fill-column))
                    (prog1
                        (setq cps-binding-i--1517
                              (1+ cps-binding-i--1517))
                      (setq cps-current-state--1514 cps-state-let*--1521))))))
  ;; ...
#+END_SRC

The unwind-protect form is created in this function.

#+BEGIN_SRC emacs-lisp
  (defun cps--make-dynamic-binding-wrapper (dynamic-var static-var)
    (cl-assert lexical-binding)
    (lambda (form)
      `(let ((,dynamic-var ,static-var))
         (unwind-protect ; Update the static shadow after evaluation is done
              ,form
           (setf ,static-var ,dynamic-var))
         ,form)))
#+END_SRC

And it seems to me that the second occurrence of ,form is just an
error.

By the way, why is debugging these generators made so difficult (via the
implementation of cps--gensym) ?

-ap