mmontone / emacs-inspector

Inspection tool for Emacs Lisp objects.
GNU General Public License v3.0
107 stars 9 forks source link

[FR] Inspect return value in debugger #9

Closed yantar92 closed 1 year ago

yantar92 commented 1 year ago

Is it possible to inspect function return value in Backtrace window? Using "i" yields "This line is not a function call".

mmontone commented 1 year ago

You have to move the cursor down to one of the backtrace frames. Then press 'I'. It doesn't work if cursor is at the top. That does work for you?

yantar92 commented 1 year ago

Mariano Montone @.***> writes:

You have to move the cursor down to one of the backtrace frames. Then press 'I'. It doesn't work if cursor is at the top. That does work for you?

Nope.

I tried:

(progn (setq yant/test-variable '(this is test)) (debug) (symbol-value 'yant/test-variable)) ; C-x C-e

Then, I made the debugger evaluate (symbol-value ...)

The result is

Debugger entered--returning value: (this is test) (symbol-value yant/test-variable) (progn (setq yant/test-variable '(this is test)) (debug) (symbol-value 'yant/test-variable)) (elisp--eval-last-sexp nil)

I moved point to (symbol-value ...) line and pressed "i" to invoke the inspector.

Result:

property list ──────────────────────────────────────────────────────────────────────────────────────────── length: 4

:frame: (t symbol-value yant/test-variable) :locals: (debugger-may-continue t inhibit-redisplay nil inhibit-debugger t inhibit-chang…

Return value is not there.

(Side note: inhibit-chang... is truncated in my setup and there is no obvious way to update the display upon maximizing the window - revert-buffer does not work.)

-- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at https://orgmode.org/. Support Org development at https://liberapay.com/org-mode, or support my work at https://liberapay.com/yantar92

mmontone commented 1 year ago

Ah. No. There's no support for return value. I can have a look.

mmontone commented 1 year ago

I don't know what would be Emacs api for return-values. The inspector currently allows inspection of frames using backtrace--locals.

yantar92 commented 1 year ago

Mariano Montone @.***> writes:

I don't know what would be Emacs api for return-values. The inspector currently allows inspection of frames using backtrace--locals.

Try to follow my steps and then evaluate e (pp (backtrace-get-frames))

then, inspect the frame list in message buffer. I can see '(this is test) there. So, information should be available.

-- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at https://orgmode.org/. Support Org development at https://liberapay.com/org-mode, or support my work at https://liberapay.com/yantar92

mmontone commented 1 year ago

I've made a change so that backtrace objects from backtrace module are inspected. I think frames are more complete like this. I can see '(this is test) now. Please let me know what you think.

yantar92 commented 1 year ago

Mariano Montone @.***> writes:

I've made a change so that backtrace objects from backtrace module are inspected. I think frames are more complete like this. I can see '(this is test) now. Please let me know what you think.

I am getting "debugger-frame-number: This line is not a function call"

-- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at https://orgmode.org/. Support Org development at https://liberapay.com/org-mode, or support my work at https://liberapay.com/yantar92

mmontone commented 1 year ago

Mm. I think you have to move down with the cursor to one of the backtrace frames. Doesn't work at the top of the debugger.

mmontone commented 1 year ago

Otherwise, please let me know what version of Emacs you are on.

mmontone commented 1 year ago

debugger-frame-number is a function in debug.el module

mmontone commented 1 year ago

I've improved the error message when trying to inspect with cursor outside a backtrace frame. That could help, perhaps.

mmontone commented 1 year ago

@yantar92 do you have any feedback?

yantar92 commented 1 year ago

Mariano Montone @.***> writes:

@yantar92 do you have any feedback?

The new error message inside debugger + debug-on-error overwrites the old backtrace, which is extremely inconvenient for a command that works with debugger backtrace buffer.

Also, I still do not understand how I can inspect the return value of a function in debugger.

-- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at https://orgmode.org/. Support Org development at https://liberapay.com/org-mode, or support my work at https://liberapay.com/yantar92

mmontone commented 1 year ago

Mariano Montone @.***> writes: @yantar92 do you have any feedback? The new error message inside debugger + debug-on-error overwrites the old backtrace, which is extremely inconvenient for a command that works with debugger backtrace buffer.

You sure are testing using latest code? I'm using user-error, that should not take you to a debugger, I believe.

I'm going to make a new release now in case you are installing from ELPA to test, but correct way is to use git as I don't release on every potential fix.

Also, I still do not understand how I can inspect the return value of a function in debugger.

You mentioned that when you evaluated (pp (backtrace-get-frames)) you could see the data you needed to see. Inspector now lets you inspect the objects returned by backtrace-get-frames, so you should see same data there. I think it is better now, as you can inspect both function args values and locals values. But, may not be not enough for what you are looking for still.

mmontone commented 1 year ago

Also, I still do not understand how I can inspect the return value of a function in debugger.

I think it is required that the calling function stores the returned value in a local. Then you can inspect the local.

yantar92 commented 1 year ago

Mariano Montone @.***> writes:

You sure are testing using latest code? I'm using [user-error...

I use git version. 4cf3941.

What I got is

Debugger entered--Lisp error: (error "This line is not a function call") (error "This line is not a function call") (debugger-frame-number) (inspector-inspect-backtrace-frame) (funcall-interactively inspector-inspect-backtrace-frame) (command-execute inspector-inspect-backtrace-frame record) (helm-M-x-execute-command inspector-inspect-backtrace-frame)

-- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at https://orgmode.org/. Support Org development at https://liberapay.com/org-mode, or support my work at https://liberapay.com/yantar92

yantar92 commented 1 year ago

Mariano Montone @.***> writes:

Also, I still do not understand how I can inspect the return value of a function in debugger.

I think it is required that the calling function stores the returned value in a local. Then you can inspect the local.

Sorry, but I don't understand what you are talking about.

I am looking from a user perspective: I have a debugger window and I step through the code. I often want to inspect the return value. I expect your package to allow me to do so with a [dwim] command. I do not want to move the point or be distracted from the actual debugging to achieve what I want.

-- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at https://orgmode.org/. Support Org development at https://liberapay.com/org-mode, or support my work at https://liberapay.com/yantar92

mmontone commented 1 year ago

Mariano Montone @.***> writes: You sure are testing using latest code? I'm using [user-error... I use git version. 4cf3941. What I got is Debugger entered--Lisp error: (error "This line is not a function call") (error "This line is not a function call") (debugger-frame-number) (inspector-inspect-backtrace-frame) (funcall-interactively inspector-inspect-backtrace-frame) (command-execute inspector-inspect-backtrace-frame record) (helm-M-x-execute-command inspector-inspect-backtrace-frame)

Ok. You are using latest. But you still get that error. Interesting that you get that error. This line here should be preventing the call to (debugger-frame-number), which is signaling the error: https://github.com/mmontone/emacs-inspector/blob/4cf394120edb22dee928e7a5edd3b4ef8f85a572/inspector.el#L719 Odd thing it works fine for me.

mmontone commented 1 year ago

Ok. Sorry. I don't know how to do more than let you inspect the backtrace frames.

Mariano Montone @.***> writes:

Also, I still do not understand how I can inspect the return value of a function in debugger. I think it is required that the calling function stores the returned value in a local. Then you can inspect the local. Sorry, but I don't understand what you are talking about. I am looking from a user perspective: I have a debugger window and I step through the code. I often want to inspect the return value. I expect your package to allow me to do so with a [dwim] command. I do not want to move the point or be distracted from the actual debugging to achieve what I want. -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at https://orgmode.org/. Support Org development at https://liberapay.com/org-mode, or support my work at https://liberapay.com/yantar92

mmontone commented 1 year ago

I've pushed an inspector-inspect-in-stack-frame command that lets you inspect the result of an evaluation inside the activation frame at point. Not sure if that helps.

yantar92 commented 1 year ago

Mariano Montone @.***> writes:

Ok. You are using latest. But you still get that error. Interesting that you get that error. This line here should be preventing the call to (debugger-frame-number), which is signaling the error: https://github.com/mmontone/emacs-inspector/blob/4cf394120edb22dee928e7a5edd3b4ef8f85a572/inspector.el#L719 Odd thing it works fine for me.

I actually do get a proper message now. I think I fetched the new version, but did not re-load it for some reason.

-- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at https://orgmode.org/. Support Org development at https://liberapay.com/org-mode, or support my work at https://liberapay.com/yantar92

mmontone commented 1 year ago

Great! Can you try inspector-inspect-in-stack-frame too? Does it help?

mmontone commented 1 year ago

I believe you are looking for a way of moving to some expression in the backtrace, and inspect it directly. I see Emacs lets you inspect the value of a variable when pressing ENTER. Perhaps you want something similar, but with the inspector. I'm not sure exactly what you are looking for. Apologies. Perhaps you can try to explain exactly the set of steps you are expecting.

yantar92 commented 1 year ago

Mariano Montone @.***> writes:

I've pushed an inspector-inspect-in-stack-frame command that lets you inspect the result of an evaluation inside the activation frame at point. Not sure if that helps.

This sounds useful as an equivalent of `debugger-eval-expression'.

However, it does not address the issue I raised in this thread - the ability to inspect last return value.

I am now looking again at the output of (pp (backtrace-get-frames)) and I notice that the frame containing return value is the following:

s(backtrace-frame t debug

          (exit #3=(this is test))
          nil
          ...
           (debugger-args exit #3#)
           (debugger-value . #3#)
                  ...
          nil nil)

There are three observations here:

  1. (nth 2 frame) is 'debug indicating that we stopped execution
  2. (nth 3 frame) contains the return value. Same for debugger-value and debugger-args debugger locals
  3. The backtrace in question is near the top of the frame list with other list elements just containing the call sequence for evaluating pp and backtrace-get-frames.

So, if you can determine that the point is at the return value, you might use `backtrace-get-frames' and check the frame near the top for return value.

-- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at https://orgmode.org/. Support Org development at https://liberapay.com/org-mode, or support my work at https://liberapay.com/yantar92

mmontone commented 1 year ago

Good. That helps. I'll have another look.

mmontone commented 1 year ago

I am now looking again at the output of (pp (backtrace-get-frames)) and I notice that the frame containing return value is the following:

s(backtrace-frame t debug

        (exit [#3](https://github.com/mmontone/emacs-inspector/issues/3)=(this is test))
        nil
        ...
         (debugger-args exit [#3](https://github.com/mmontone/emacs-inspector/issues/3)#)
         (debugger-value . [#3](https://github.com/mmontone/emacs-inspector/issues/3)#)
                  ...
        nil nil)

I'm not able to get a backtrace frame with an exit like that.

I suspect it has to do with the following:

I tried: (progn (setq yant/test-variable '(this is test)) (debug) (symbol-value 'yant/test-variable)) ; C-x C-e Then, I made the debugger evaluate (symbol-value ...)

How are you doing the "made the debugger evaluate (symbol-value ...)" ?

yantar92 commented 1 year ago

Mariano Montone @.***> writes:

I tried: (progn (setq yant/test-variable '(this is test)) (debug) (symbol-value 'yant/test-variable)) ; C-x C-e Then, I made the debugger evaluate (symbol-value ...)

How are you doing the "made the debugger evaluate (symbol-value ...)" ?

  1. M-:
  2. Insert

    (progn (setq yant/test-variable '(this is test)) (debug) (symbol-value 'yant/test-variable))

into the minibuffer

  1. debugger window will pop up
  2. d c
  3. Observe

Debugger entered--returning value: (this is test) (symbol-value yant/test-variable) (progn (setq yant/test-variable '(this is test)) (debug) (symbol-value 'yant/test-variable)) (eval-expression (progn (setq yant/test-variable '(this is test)) (debug) (symbol-value 'yant/test-variable)) nil nil 127) (funcall-interactively eval-expression (progn (setq yant/test-variable '(this is test)) (debug) (symbol-value 'yant/test-variable)) nil nil 127) (command-execute eval-expression)

-- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at https://orgmode.org/. Support Org development at https://liberapay.com/org-mode, or support my work at https://liberapay.com/yantar92

mmontone commented 1 year ago

Ok. I see the backtrace with an "exit" now.

mmontone commented 1 year ago

So, to be clearer, the debugger enters the "returning value" state after "step" and then "continue". I don't know how to determine that the debugger is in that state programmatically yet.

mmontone commented 1 year ago

So, to be clearer, the debugger enters the "returning value" state after "step" and then "continue". I don't know how to determine that the debugger is in that state programmatically yet.

I guess a way is first finding the backtrace-frame named 'debug, then look at the backtrace-frame args.

yantar92 commented 1 year ago

Mariano Montone @.***> writes:

So, to be clearer, the debugger enters the "returning value" state after "step" and then "continue". I don't know how to determine that the debugger is in that state programmatically yet.

May "exit" symbol serve as an indicator?

-- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at https://orgmode.org/. Support Org development at https://liberapay.com/org-mode, or support my work at https://liberapay.com/yantar92

mmontone commented 1 year ago

I think so. I'll implement a command that finds the debug frame and looks at 'exit and inspect it. Would that be enough?

yantar92 commented 1 year ago

Mariano Montone @.***> writes:

I think so. I'll implement a command that finds the debug frame and looks at 'exit and inspect it. Would that be enough?

I guess. I have to try first.

I am thinking about something like inspector-inspect-debugger-dwim that will inspect thing at point in the debugger window, be it return value or another debugger frame.

-- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at https://orgmode.org/. Support Org development at https://liberapay.com/org-mode, or support my work at https://liberapay.com/yantar92

mmontone commented 1 year ago

Ok. I'll implement my function first. Then we can go on from there ... The inspect-thing-at-point sounds more difficult to me.

mmontone commented 1 year ago

I've pushed a inspector-inspect-debugger-return-value command.

A more DWIM interface would need to be discussed in more detail (I'm not a heavy debugger user, so design, expected behaviour, and implementation details.)

yantar92 commented 1 year ago

Mariano Montone @.***> writes:

I've pushed a inspector-inspect-debugger-return-value command.

Thanks! It works in my testing.

Side note: is it expected that lists like '(type (:a a :b b)) are treated as property lists? It is a bit disorienting because the value I was checking is not supposed to be a property list in more general cases.

A more DWIM interface would need to be discussed in more detail (I'm not a heavy debugger user, so design, expected behaviour, and implementation details.)

I will need to play around more before I can provide something constructive here. Having an ability to inspect return value was a stumbling block for me.

I consider this particular issue resolved. dwim is getting out of the original scope.

-- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at https://orgmode.org/. Support Org development at https://liberapay.com/org-mode, or support my work at https://liberapay.com/yantar92

mmontone commented 1 year ago

Great.

About the DWIM, it could be nice. I see the debugger lets you inspect some things when pressing ENTER on things on the backtrace already. I would need to know more about how the debugger works and what would be expected behaviour for the inspector.

About the properties lists, it is not a bug, but it is not ideal in its current form. Same for association lists. You can customize inspector-use-specialized-inspectors-for-lists and set it to nil. But I see room for improvement:

I'll see if I do something about it soon.

mmontone commented 1 year ago
  • Either let the user customize the functions for detection of plists and alists.

    • Even better: provide a button in the UI to switch between plist, alist <-> proper list view.

@yantar92 I've implemented both of these now FYI.

yantar92 commented 1 year ago

Mariano Montone @.***> writes:

* Even better: provide a button in the UI to switch between plist, alist <-> proper list view.

@yantar92 I've implemented both of these now FYI.

Thanks! Looks very good.

-- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at https://orgmode.org/. Support Org development at https://liberapay.com/org-mode, or support my work at https://liberapay.com/yantar92