Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support map evaluation by composite literal keys #1465

Open
maxwindiff opened this issue Jan 17, 2019 · 5 comments
Open

Support map evaluation by composite literal keys #1465

maxwindiff opened this issue Jan 17, 2019 · 5 comments

Comments

@maxwindiff
Copy link

maxwindiff commented Jan 17, 2019

  1. What version of Delve are you using (dlv version)?
$ dlv version
Delve Debugger
Version: 1.1.0
Build: $Id: 1990ba12450cab9425a2ae62e6ab988725023d5c $
  1. What version of Go are you using? (go version)?
$ go version
go version go1.11.2 linux/amd64
  1. What operating system and processor architecture are you using?

Linux/amd64

  1. What did you do?

Compile the following program, debug it with delve, try to print some map values:

package main

import "fmt"

type Pair struct {
        A, B int
}

func main() {
        m := map[Pair]string{}
        m[Pair{A: 1, B: 1}] = "x"
        m[Pair{A: 1, B: 2}] = "y"
        fmt.Println(m)
}
$ dlv debug test.go
(dlv) b main.main:4
...
(dlv) c
...
(dlv) p m[main.Pair{A: 1, B: 1}]
Command failed: expression *ast.CompositeLit not implemented
(dlv) p m[Pair{A: 1, B: 1}]
Command failed: expression *ast.CompositeLit not implemented
  1. What did you expect to see?

Print the corresponding map values.

  1. What did you see instead?

"Command failed: expression *ast.CompositeLit not implemented"

Looks like CompositeLit evaluation wasn't implemented:

return nil, fmt.Errorf("expression %T not implemented", t)

@apmattil
Copy link

any progress here ?
I think this is really important feature.. at least with cmd-line debugging.

@1Mark
Copy link

1Mark commented Mar 8, 2022

Any update on this please?

@Ap3lsin4k
Copy link

The issue expression *ast.CompositeLit not implemented is the same for GoLand.

I am encouraged to write more unit tests because the debugger is inconvenient to use. Maybe the absence of "composite literal evaluation" is a well-thought feature, not a bug 😃

@glezjose
Copy link

glezjose commented Dec 22, 2022

Any luck? Having the same issue with GoLand

aarzilli added a commit to aarzilli/delve that referenced this issue Sep 19, 2023
This commit splits expression evaluation into two parts. The first part (in
pkg/proc/evalop/evalcompile.go) "compiles" as ast.Expr into a list of
instructions (defined in pkg/proc/evalop/ops.go) for a stack machine
(defined by `proc.(*evalStack)`).
The second part is a stack machine (implemented by `proc.(*EvalScope).eval`
and `proc.(*EvalScope).evalOne`) that has two modes of operation: in the
main mode it executes inteructions from the list (by calling `evalOne`), in
the second mode it executes the call injection protocol by calling
`funcCallStep` repeatedly until it either the protocol finishes, needs more
input from the stack machine (to set call arguments) or fails.

This approach has several benefits:

- it is now possible to remove the goroutine we use to evaluate expression
  and the channel used to communicate with the Continue loop.
- every time we resume the target to execute the call injection protocol we
  need to update several local variables to match the changed state of the
  target, this is now done at the top level of the evaluation loop instead of
  being hidden inside a recurisive evaluator
- using runtime.Pin to pin addresses returned by an injected call would
  allow us to use a more natural evaluation order for function calls, which
  would solve some bugs go-delve#3310, allow users to inspect values returned by a
  call injection go-delve#1599 and allow implementing some other features go-delve#1465. Doing
  this with the recursive evaluator, while keeping backwards compatibility
  with versions of Go that do not have runtime.Pin is very hard. However after
  this change we can simply conditionally change how compileFunctionCall works
  and add some opcodes.
aarzilli added a commit to aarzilli/delve that referenced this issue Sep 22, 2023
This commit splits expression evaluation into two parts. The first part (in
pkg/proc/evalop/evalcompile.go) "compiles" as ast.Expr into a list of
instructions (defined in pkg/proc/evalop/ops.go) for a stack machine
(defined by `proc.(*evalStack)`).
The second part is a stack machine (implemented by `proc.(*EvalScope).eval`
and `proc.(*EvalScope).evalOne`) that has two modes of operation: in the
main mode it executes inteructions from the list (by calling `evalOne`), in
the second mode it executes the call injection protocol by calling
`funcCallStep` repeatedly until it either the protocol finishes, needs more
input from the stack machine (to set call arguments) or fails.

This approach has several benefits:

- it is now possible to remove the goroutine we use to evaluate expression
  and the channel used to communicate with the Continue loop.
- every time we resume the target to execute the call injection protocol we
  need to update several local variables to match the changed state of the
  target, this is now done at the top level of the evaluation loop instead of
  being hidden inside a recurisive evaluator
- using runtime.Pin to pin addresses returned by an injected call would
  allow us to use a more natural evaluation order for function calls, which
  would solve some bugs go-delve#3310, allow users to inspect values returned by a
  call injection go-delve#1599 and allow implementing some other features go-delve#1465. Doing
  this with the recursive evaluator, while keeping backwards compatibility
  with versions of Go that do not have runtime.Pin is very hard. However after
  this change we can simply conditionally change how compileFunctionCall works
  and add some opcodes.
aarzilli added a commit to aarzilli/delve that referenced this issue Oct 9, 2023
This commit splits expression evaluation into two parts. The first part (in
pkg/proc/evalop/evalcompile.go) "compiles" as ast.Expr into a list of
instructions (defined in pkg/proc/evalop/ops.go) for a stack machine
(defined by `proc.(*evalStack)`).
The second part is a stack machine (implemented by `proc.(*EvalScope).eval`
and `proc.(*EvalScope).evalOne`) that has two modes of operation: in the
main mode it executes inteructions from the list (by calling `evalOne`), in
the second mode it executes the call injection protocol by calling
`funcCallStep` repeatedly until it either the protocol finishes, needs more
input from the stack machine (to set call arguments) or fails.

This approach has several benefits:

- it is now possible to remove the goroutine we use to evaluate expression
  and the channel used to communicate with the Continue loop.
- every time we resume the target to execute the call injection protocol we
  need to update several local variables to match the changed state of the
  target, this is now done at the top level of the evaluation loop instead of
  being hidden inside a recurisive evaluator
- using runtime.Pin to pin addresses returned by an injected call would
  allow us to use a more natural evaluation order for function calls, which
  would solve some bugs go-delve#3310, allow users to inspect values returned by a
  call injection go-delve#1599 and allow implementing some other features go-delve#1465. Doing
  this with the recursive evaluator, while keeping backwards compatibility
  with versions of Go that do not have runtime.Pin is very hard. However after
  this change we can simply conditionally change how compileFunctionCall works
  and add some opcodes.
derekparker pushed a commit that referenced this issue Oct 17, 2023
* proc: use stack machine to evaluate expressions

This commit splits expression evaluation into two parts. The first part (in
pkg/proc/evalop/evalcompile.go) "compiles" as ast.Expr into a list of
instructions (defined in pkg/proc/evalop/ops.go) for a stack machine
(defined by `proc.(*evalStack)`).
The second part is a stack machine (implemented by `proc.(*EvalScope).eval`
and `proc.(*EvalScope).evalOne`) that has two modes of operation: in the
main mode it executes inteructions from the list (by calling `evalOne`), in
the second mode it executes the call injection protocol by calling
`funcCallStep` repeatedly until it either the protocol finishes, needs more
input from the stack machine (to set call arguments) or fails.

This approach has several benefits:

- it is now possible to remove the goroutine we use to evaluate expression
  and the channel used to communicate with the Continue loop.
- every time we resume the target to execute the call injection protocol we
  need to update several local variables to match the changed state of the
  target, this is now done at the top level of the evaluation loop instead of
  being hidden inside a recurisive evaluator
- using runtime.Pin to pin addresses returned by an injected call would
  allow us to use a more natural evaluation order for function calls, which
  would solve some bugs #3310, allow users to inspect values returned by a
  call injection #1599 and allow implementing some other features #1465. Doing
  this with the recursive evaluator, while keeping backwards compatibility
  with versions of Go that do not have runtime.Pin is very hard. However after
  this change we can simply conditionally change how compileFunctionCall works
  and add some opcodes.

* review round 1

* review round 2
@debemdeboas
Copy link

Incredible how such a (seemingly) simple feature has been left behind by the team!

firelizzard18 added a commit to firelizzard18/delve that referenced this issue Apr 2, 2024
This change adds support for evaluating composite
struct literals.

Updates go-delve#1465
firelizzard18 added a commit to firelizzard18/delve that referenced this issue Apr 2, 2024
This change adds support for slice and array literals.

Updates go-delve#1465
firelizzard18 added a commit to firelizzard18/delve that referenced this issue Apr 2, 2024
This change adds support for map literals.

Fixes go-delve#1465
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants