unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Edebug & lexical scope
@ 2012-05-18 13:30 egnarts-ms
  2012-05-18 19:54 ` Stefan Monnier
  0 siblings, 1 reply; 4+ messages in thread
From: egnarts-ms @ 2012-05-18 13:30 UTC (permalink / raw)
  To: Emacs-devel


Hi,

Currently (Emacs 24.0.97) Edebug cannot evaluate lexical variables when it
is suspended (by "e" or "M-:"). To be more precise: when you have
"lexical-binding" variable set to non-nil in a buffer, and you instrument a
defun from this buffer, and then debug it with Edebug, and you're suspended
at some stop point inside this defun, you cannot see the value of a
(lexical) variable.

Example:

(defun solve-square-equation (a b c)
  (if (= a 0.0)
      (/ (- c) b)
    (let ((D (- (* b b) (* 4 (* a c)))))
      (cond
        ((= D 0.0)
         (/ (- b) (* 2 a)))
        ((< D 0.0)
         nil)
        (t
         (let ((sqD (sqrt D)))
           (list (/ (+ (- b) sqD) (* 2 a))
                 (/ (- (- b) sqD) (* 2 a)))))))))


It is impossible to see the value of D when the program is stopped in any of
the cond's branches.

The reason for that is simple: when you are asking Edebug to evaluate
something, it does so by calling `eval', and the latter just binds
Qinternal_interpreter_environment (internal variable holding the current
lexical environment, or nil in dynamic scoping) to "(t)" (provided that
lexical scoping is on). So the values of all lexical variables are lost.

Nevertheless, when you press "G" or "c", the execution resumes and those
lexical variables are perfectly accessible.  By all evidence, it is just due
to the fact that Qinternal_interpreter_environment gets unbound, and takes
on its previous value (which is what we would also like to access when
evaluating by "M-:").

It seems that I've managed to make M-: evaluate lexical variables. I've
created the following C subroutine; it does the same job as `eval', but
first of all it scans "specpdl" (the stack of bindings of symbols) searching
for the most recent value of Qinternal_interpreter_environment which is not
eq to nil. (That is, we want to find out the most recent lexical environment
to which Qinternal_interpreter_environment was bound by some code upward the
stack.) If that value is found, Qinternal_interpreter_environment gets bound
to it again, and usual `eval_sub' is called. Otherwise, `eval_sub' is called
as well, but this would be in dynamic environment now.

DEFUN ("eval-in-most-recent-lex-env", Seval_in_mo....) (Lisp_Object form)
  {
    struct specbinding* ptr = specpdl_ptr;
    while (ptr != specpdl)
      {
        if (EQ (ptr->symbol, Qinternal_interpreter_environment) &&
            !EQ (ptr->old_value, Qnil))
         {
           break;
         }
       --ptr;
      }
    if (ptr != specpdl)
      {
        int count = SPECPDL_INDEX ();
        specbind (Qinternal_interpreter_environment, ptr->old_value);
        return unbind_to (count, eval_sub (form));
      }
    return eval_sub (form);
  }

The second step is pretty easy: there's a function named `edebug-eval'. One
should just change it to call `eval-in-most-recent-lex-env' rather than
`eval'.

That seems to work fine in Emacs 24.0.97 pretest.

I'd be very glad to hear any critics or comments.



Best regards,
  egnarts-ms.
-- 
View this message in context: http://old.nabble.com/Edebug---lexical-scope-tp33870303p33870303.html
Sent from the Emacs - Dev mailing list archive at Nabble.com.




^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Edebug & lexical scope
  2012-05-18 13:30 Edebug & lexical scope egnarts-ms
@ 2012-05-18 19:54 ` Stefan Monnier
  2012-05-19  8:57   ` egnarts-ms
  0 siblings, 1 reply; 4+ messages in thread
From: Stefan Monnier @ 2012-05-18 19:54 UTC (permalink / raw)
  To: egnarts-ms; +Cc: Emacs-devel

> Currently (Emacs 24.0.97) Edebug cannot evaluate lexical variables when it
> is suspended (by "e" or "M-:").

Indeed.  The same holds for the normal (backtrace-style) debugger.

> It seems that I've managed to make M-: evaluate lexical variables.  I've
> created the following C subroutine; it does the same job as `eval', but
> first of all it scans "specpdl" (the stack of bindings of symbols) searching
> for the most recent value of Qinternal_interpreter_environment which is not
> eq to nil.

Thanks.  This is a good way to fix the problem (tho it still doesn't
solve the issue for the case of the normal debugger where you want to
look at the local variable of a lexical-binding byte-code routine,
because in that case the var names are purely gone).

The only problem with it is that it relies on all the stack frames (until
the interesting ones) using dynamic binding.  E.g. if/when we switch
edebug to lexical-binding we'll have a problem.

Also in the case of the normal debugger, we would generally want to be
able to get the value of a variable in a particular stack frame.

So it would be better to have an "eval-in-frame" which receives some
description of the stack frame to use (and of course, more primitives to
get a handle of the current stack frame as well as the Nth previous one).


        Stefan



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Edebug & lexical scope
  2012-05-18 19:54 ` Stefan Monnier
@ 2012-05-19  8:57   ` egnarts-ms
  2012-05-19 18:51     ` Stefan Monnier
  0 siblings, 1 reply; 4+ messages in thread
From: egnarts-ms @ 2012-05-19  8:57 UTC (permalink / raw)
  To: Emacs-devel


Stefan,

thank you very much for your reply. It was important for me to know comments
of a competent person.


Stefan Monnier wrote:
> 
> Also in the case of the normal debugger, we would generally want to be
> able to get the value of a variable in a particular stack frame.
> 
> So it would be better to have an "eval-in-frame" which receives some
> description of the stack frame to use (and of course, more primitives to
> get a handle of the current stack frame as well as the Nth previous one).
> 

AFAIK, currently it is not possible to see values of lexical variables in a
particular stack frame, in normal debugger, right ? We can just press "e"
and evaluate something, but during this evaluation all the dynamic variables
will hold the same values as they hold in the topmost stack frame (where
we're suspended).
-- 
View this message in context: http://old.nabble.com/Edebug---lexical-scope-tp33870303p33874033.html
Sent from the Emacs - Dev mailing list archive at Nabble.com.




^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Edebug & lexical scope
  2012-05-19  8:57   ` egnarts-ms
@ 2012-05-19 18:51     ` Stefan Monnier
  0 siblings, 0 replies; 4+ messages in thread
From: Stefan Monnier @ 2012-05-19 18:51 UTC (permalink / raw)
  To: egnarts-ms; +Cc: Emacs-devel

> AFAIK, currently it is not possible to see values of lexical variables in a
> particular stack frame, in normal debugger, right ? We can just press "e"
> and evaluate something, but during this evaluation all the dynamic variables
> will hold the same values as they hold in the topmost stack frame (where
> we're suspended).

Indeed, there is no current feature to execute in a particular
stack frame.  In most cases this doesn't matter much in the case of
dynamic scoping; even in those cases where a later binding hides an
earlier one it's very frequent that both bindings have the exact same
value (typically an argument passed through a few levels of function
calls, with the same name at each stage).

With lexical scoping, this becomes more important.
Actually a good eval-in-stack-frame might even want to first undo the
corresponding let-bindings as well as save-excursions and friends, but
it would require more significant changes.


        Stefan



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2012-05-19 18:51 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-05-18 13:30 Edebug & lexical scope egnarts-ms
2012-05-18 19:54 ` Stefan Monnier
2012-05-19  8:57   ` egnarts-ms
2012-05-19 18:51     ` Stefan Monnier

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).