1
1
Fork
You've already forked debugadapter
0

ark discussion notes #24

Open
opened 2024年08月16日 01:36:05 +02:00 by dgkf · 3 comments
dgkf commented 2024年08月16日 01:36:05 +02:00 (Migrated from github.com)
Copy link

I had the pleasure of getting to chat a bit with @lionel- at posit::conf and just wanted to track a few notes that came out of the discussion.

tips for debugadapter

  • Recommendation to use later. From what I can tell, this will allow for easy management of a background thread that can affect the global environment. Quick POC:
     i <- 0
     f <- function() { i <<- i + 1; later::later(f, 1) }
     f()
     # wait n seconds.. Sys.sleep will not work because bg thread can't use interrupts
     i
     # [1] <n>
    
    looks like a totally viable solution to me. I don't really care about non-interruptable code as we just need to periodically listen for new state from the adapter at the top level. In fact, it might even offer a better alternative to running the debugger in a separate process.
  • Lionel mentioned a few edge cases where either the source isn't known (not yet sourced.. if there were other cases I forgot them)
  • Lionel mentioned foreseen challenges with getting the source from lines sent to the console from a selection, suggesting that it might require a wrapping function for sending code with a "faked" srcref.

learnings from debugadapter for ark

  • Mentioned that managing trace() insertions of browser() statements was painful. trace will affect the function's body, meaning that multiple insertions need to account for the difference between source and traced version of the code (ie, a breakpoint at line 10 in the file open in a user's editor might actually want to insert a new browser() at line 11 because a browser() statement has already been inserted at some point above). This is otherwise an attractive option, since the browser statement can be inserted at an arbitrary location (easily found with utils::findLineNum())
  • debug() simplifies this, as it will not insert code. However it introduces a new challenge - that debug() always enters the debug prompt upon entering a debugged function. Currently, I automatically step through the function until a breakpoint is hit. This still emits all the debug prompt output, so you get a bunch of messages as R steps through the lines of the function. Definitely still room for improvement.

for both.. potential bug?

  • Mentioned bug with debug(), in which the condition argument seems to have no effect. Might be a base R bug, or at least a devel R bug.
    options(browser.hook = function(hook, condition, envir) { print(condition) })
    f <- function() { print("123"); browser(condition = list(origin = "browser")) }
    debug(f, condition = list(origin = "globalenv"))
    f()
    # ...
    #> debug at #1: browser(condition = list(origin = "browser"))
    #> NULL # debug() condition output
    #> $origin # browser() condition output
    #> [1] "browser"
    
I had the pleasure of getting to chat a bit with @lionel- at `posit::conf` and just wanted to track a few notes that came out of the discussion. ### tips for `debugadapter` - Recommendation to use `later`. From what I can tell, this will allow for easy management of a background thread that can affect the global environment. Quick POC: ```r i <- 0 f <- function() { i <<- i + 1; later::later(f, 1) } f() # wait n seconds.. Sys.sleep will not work because bg thread can't use interrupts i # [1] <n> ``` looks like a totally viable solution to me. I don't really care about non-interruptable code as we just need to periodically listen for new state from the adapter at the top level. In fact, it might even offer a better alternative to running the debugger in a separate process. - Lionel mentioned a few edge cases where either the source isn't known (not yet sourced.. if there were other cases I forgot them) - Lionel mentioned foreseen challenges with getting the source from lines sent to the console from a selection, suggesting that it might require a wrapping function for sending code with a "faked" srcref. ### learnings from `debugadapter` for `ark` - Mentioned that managing `trace()` insertions of `browser()` statements was painful. `trace` will affect the function's body, meaning that multiple insertions need to account for the difference between source and traced version of the code (ie, a breakpoint at line 10 in the file open in a user's editor might actually want to insert a new `browser()` at line 11 because a `browser()` statement has already been inserted at some point above). This is otherwise an attractive option, since the browser statement can be inserted at an arbitrary location (easily found with [`utils::findLineNum()`](https://github.com/dgkf/debugadapter/blob/main/R/breakpoints.R#L69)) - `debug()` simplifies this, as it will not insert code. However it introduces a new challenge - that `debug()` always enters the debug prompt upon entering a debugged function. Currently, I automatically [step through the function until a breakpoint is hit](https://github.com/dgkf/debugadapter/blob/main/R/debug_prompt.R#L45-L46). This still emits all the debug prompt output, so you get a bunch of messages as R steps through the lines of the function. Definitely still room for improvement. ### for both.. potential bug? - Mentioned bug with `debug()`, in which the `condition` argument seems to have no effect. Might be a base R bug, or at least a devel R bug. ```r options(browser.hook = function(hook, condition, envir) { print(condition) }) f <- function() { print("123"); browser(condition = list(origin = "browser")) } debug(f, condition = list(origin = "globalenv")) f() # ... #> debug at #1: browser(condition = list(origin = "browser")) #> NULL # debug() condition output #> $origin # browser() condition output #> [1] "browser" ```
lionel- commented 2024年08月21日 18:15:07 +02:00 (Migrated from github.com)
Copy link

Another issue with debug() is that it's not really possible to use it for inserting breakpoints in anonymous / inaccessible functions, e.g. within lapply().

Another issue with `debug()` is that it's not really possible to use it for inserting breakpoints in anonymous / inaccessible functions, e.g. within `lapply()`.
dgkf commented 2024年08月21日 21:01:32 +02:00 (Migrated from github.com)
Copy link

Ah, that's a good point. You're imagining a situation like:

 1| lapply(
 2| list(1, 2, 3),
 3| function(i) {
o 4| print(i)
 5| }
 6| )

Yeah... that's going to be tedious to handle. I'd really like to avoid requiring extra code to be inserted into a snippet sent to the console, but this seems unavoidable in this case.

Have you explored how other languages handle breakpoints in non-function code? I wouldn't really expect this to even work if you're just using a simple "send to console" command. That said, I think it would definitely be a nice improvement.

Ah, that's a good point. You're imagining a situation like: ```r 1| lapply( 2| list(1, 2, 3), 3| function(i) { o 4| print(i) 5| } 6| ) ``` Yeah... that's going to be tedious to handle. I'd really like to avoid requiring extra code to be inserted into a snippet sent to the console, but this seems unavoidable in this case. Have you explored how other languages handle breakpoints in non-function code? I wouldn't really expect this to even work if you're just using a simple "send to console" command. That said, I think it would definitely be a nice improvement.
lionel- commented 2024年08月22日 09:37:50 +02:00 (Migrated from github.com)
Copy link

hmm, in emacs-lisp at least you can break anywhere in a top-level expression.

hmm, in emacs-lisp at least you can break anywhere in a top-level expression.
Sign in to join this conversation.
No Branch/Tag specified
main
add-woodpecker-ci
ci-sync-test
dev/launch-mode-2
dev/s7-test
dev/browser-relay
No results found.
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
dgkf/debugadapter#24
Reference in a new issue
dgkf/debugadapter
No description provided.
Delete branch "%!s()"

Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?