Stepping and showing execution point now work
This commit is contained in:
@@ -11,6 +11,14 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
var ErrNotRunning = errors.New("bridge not running")
|
||||
var ErrAlreadyStarted = errors.New("bridge is already running")
|
||||
|
||||
type ExecutionPoint struct {
|
||||
File string
|
||||
Line int
|
||||
}
|
||||
|
||||
type Bridge struct {
|
||||
stdin io.Writer
|
||||
stdout *bufio.Reader
|
||||
@@ -22,6 +30,9 @@ type Bridge struct {
|
||||
outputLock *sync.RWMutex
|
||||
output []chan string
|
||||
|
||||
executionStopLock *sync.RWMutex
|
||||
executionStop []chan ExecutionPoint
|
||||
|
||||
registry map[string]chan string
|
||||
registryLock *sync.RWMutex
|
||||
|
||||
@@ -29,18 +40,15 @@ type Bridge struct {
|
||||
|
||||
callbacksLock *sync.RWMutex
|
||||
callbacks map[string]map[int]func()
|
||||
|
||||
running bool
|
||||
|
||||
path string
|
||||
}
|
||||
|
||||
func NewBridge(path string) *Bridge {
|
||||
cmd := exec.Command(
|
||||
"python",
|
||||
"-u",
|
||||
"python/pybug_runtime.py",
|
||||
path,
|
||||
)
|
||||
|
||||
return &Bridge{
|
||||
cmd: cmd,
|
||||
path: path,
|
||||
input: make(chan string),
|
||||
registry: make(map[string]chan string),
|
||||
registryLock: &sync.RWMutex{},
|
||||
@@ -51,16 +59,31 @@ func NewBridge(path string) *Bridge {
|
||||
|
||||
output: make([]chan string, 0),
|
||||
outputLock: &sync.RWMutex{},
|
||||
|
||||
executionStop: make([]chan ExecutionPoint, 0),
|
||||
executionStopLock: &sync.RWMutex{},
|
||||
|
||||
running: false,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Bridge) Start() error {
|
||||
if b.running {
|
||||
return ErrAlreadyStarted
|
||||
}
|
||||
|
||||
b.cmd = exec.Command(
|
||||
"python",
|
||||
"-u",
|
||||
"python/pybug_runtime.py",
|
||||
b.path,
|
||||
)
|
||||
|
||||
var err error
|
||||
b.stdin, err = b.cmd.StdinPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// b.cmd.Stdout = os.Stdout
|
||||
|
||||
reader, err := b.cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
@@ -73,6 +96,7 @@ func (b *Bridge) Start() error {
|
||||
return err
|
||||
}
|
||||
|
||||
b.running = true
|
||||
go b.readLoop()
|
||||
go b.writeLoop()
|
||||
|
||||
@@ -89,7 +113,21 @@ func (b *Bridge) Subscribe() chan string {
|
||||
return c
|
||||
}
|
||||
|
||||
func (b *Bridge) SubscribeStopped() chan ExecutionPoint {
|
||||
b.executionStopLock.Lock()
|
||||
defer b.executionStopLock.Unlock()
|
||||
|
||||
c := make(chan ExecutionPoint)
|
||||
b.executionStop = append(b.executionStop, c)
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (b *Bridge) Locals() (map[string]any, error) {
|
||||
if !b.running {
|
||||
return nil, ErrNotRunning
|
||||
}
|
||||
|
||||
requestId, cmd := makeCommand(LocalsCommand, map[string]any{})
|
||||
|
||||
c := b.sendCommand(requestId, cmd)
|
||||
@@ -110,8 +148,22 @@ func (b *Bridge) Locals() (map[string]any, error) {
|
||||
return vars, nil
|
||||
}
|
||||
|
||||
func (b *Bridge) Step() error {
|
||||
if !b.running {
|
||||
return ErrNotRunning
|
||||
}
|
||||
|
||||
_, cmd := makeCommand(StepCommand, nil)
|
||||
b.sendCommandNoResponse(cmd)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Bridge) Breakpoint(file string, line int) error {
|
||||
// Check if breakpoint already exists here
|
||||
if !b.running {
|
||||
return ErrNotRunning
|
||||
}
|
||||
|
||||
requestId, cmd := makeCommand(BreakCommand, map[string]any{
|
||||
"file": file,
|
||||
@@ -137,10 +189,15 @@ func (b *Bridge) Breakpoint(file string, line int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Bridge) Continue() {
|
||||
func (b *Bridge) Continue() error {
|
||||
if !b.running {
|
||||
return ErrNotRunning
|
||||
}
|
||||
|
||||
_, cmd := makeCommand(ContinueCommand, map[string]any{})
|
||||
|
||||
b.sendCommandNoResponse(cmd)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Bridge) sendCommandNoResponse(command string) {
|
||||
@@ -165,6 +222,10 @@ func (b *Bridge) writeLoop() {
|
||||
for {
|
||||
cmd := <-b.input
|
||||
|
||||
if !b.running {
|
||||
return
|
||||
}
|
||||
|
||||
slog.Info("Received command", "cmd", cmd)
|
||||
|
||||
_, err := b.stdin.Write([]byte(cmd + "\n"))
|
||||
@@ -186,6 +247,7 @@ func (b *Bridge) readLoop() {
|
||||
slog.Error("Error occured while reading from stdout", "error", err)
|
||||
continue
|
||||
} else if errors.Is(err, io.EOF) {
|
||||
b.running = false
|
||||
return
|
||||
}
|
||||
|
||||
@@ -212,28 +274,64 @@ func (b *Bridge) readLoop() {
|
||||
|
||||
c <- line
|
||||
} else {
|
||||
// TODO: set to stopped
|
||||
if event, ok := msg["event"]; !ok || event != "stopped" {
|
||||
slog.Warn("received unkown event", "msg", msg)
|
||||
}
|
||||
|
||||
file := msg["file"].(string)
|
||||
line, ok := toInt(msg["line"])
|
||||
if !ok {
|
||||
slog.Error("could not convert line to int", "line", msg["line"])
|
||||
}
|
||||
|
||||
slog.Info("received stopped event")
|
||||
b.callbacksLock.RLock()
|
||||
if callback, ok := b.callbacks[file][line]; ok {
|
||||
slog.Info("found callback, now running", "file", file, "line", line)
|
||||
go callback()
|
||||
}
|
||||
b.callbacksLock.RUnlock()
|
||||
b.handleStopped(msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Bridge) handleStopped(msg map[string]any) error {
|
||||
// TODO: set to stopped
|
||||
if event, ok := msg["event"]; !ok || event != "stopped" {
|
||||
slog.Warn("received unkown event", "msg", msg)
|
||||
return errors.New("unknown event encountered")
|
||||
}
|
||||
|
||||
file := msg["file"].(string)
|
||||
line, ok := toInt(msg["line"])
|
||||
if !ok {
|
||||
slog.Error("could not convert line to int", "line", msg["line"])
|
||||
return errors.New("could not convert line to int")
|
||||
}
|
||||
|
||||
slog.Info("received stopped event")
|
||||
b.callbacksLock.RLock()
|
||||
defer b.callbacksLock.RUnlock()
|
||||
|
||||
if callback, ok := b.callbacks[file][line]; ok {
|
||||
slog.Info("found callback, now running", "file", file, "line", line)
|
||||
go callback()
|
||||
}
|
||||
|
||||
b.executionStopLock.RLock()
|
||||
defer b.executionStopLock.RUnlock()
|
||||
|
||||
for _, c := range b.executionStop {
|
||||
c <- ExecutionPoint{
|
||||
File: file,
|
||||
Line: line,
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Bridge) OnBreakpoint(file string, line int, callback func()) {
|
||||
b.callbacksLock.Lock()
|
||||
defer b.callbacksLock.Unlock()
|
||||
|
||||
if f, ok := b.callbacks[file]; ok {
|
||||
f[line] = callback
|
||||
} else {
|
||||
b.callbacks[file] = map[int]func(){
|
||||
line: callback,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Bridge) Wait() error {
|
||||
return b.cmd.Wait()
|
||||
}
|
||||
|
||||
func toInt(v any) (int, bool) {
|
||||
switch x := v.(type) {
|
||||
case int:
|
||||
@@ -254,20 +352,3 @@ func toInt(v any) (int, bool) {
|
||||
return 0, false
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Bridge) OnBreakpoint(file string, line int, callback func()) {
|
||||
b.callbacksLock.Lock()
|
||||
defer b.callbacksLock.Unlock()
|
||||
|
||||
if f, ok := b.callbacks[file]; ok {
|
||||
f[line] = callback
|
||||
} else {
|
||||
b.callbacks[file] = map[int]func(){
|
||||
line: callback,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Bridge) Wait() error {
|
||||
return b.cmd.Wait()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user