Skip to content

Commit

Permalink
dev: interactive debugger
Browse files Browse the repository at this point in the history
  • Loading branch information
egon committed Apr 22, 2012
1 parent 10335d1 commit 23d0825
Show file tree
Hide file tree
Showing 7 changed files with 239 additions and 40 deletions.
66 changes: 66 additions & 0 deletions src/debugger/actions.go
@@ -0,0 +1,66 @@
package debugger

import (
"os"
"fmt"
)

type Action interface {
Exec(d *Debugger)
}

type Nop struct{}
type Continue struct{}
type Watch struct{}
type Break struct{}
type Disable struct{}
type Quit struct {}

type Skip struct{
Count int
}
type Err struct {
Msg string
}

func (n Nop) Exec(d *Debugger) {}

func (c Continue) Exec(d *Debugger) {
d.control <- cBreak
}

func (s Skip) Exec(d *Debugger){
d.control <- cBreak
count := s.Count
if count > 100 {
count = 100
}
for i := 0; i < count; i += 1 {
d.control <- cBreak
}
}

func (s Watch) Exec(d *Debugger){
d.Watch <- 1
d.control <- cBreak
}

func (s Disable) Exec(d *Debugger){
d.Enabled = false
d.control <- cBreak
}

func (q Quit) Exec(d *Debugger){
os.Exit(130)
}

func (e Err) Exec(d *Debugger){
fmt.Fprintf(d.Logout, "err: %v", e.Msg)
}

func (b Break) Exec(d *Debugger){
select {
case <-d.Watch:
default:
}
}
45 changes: 45 additions & 0 deletions src/debugger/dbg/example.go
@@ -0,0 +1,45 @@
package main

import (
"debugger"
"fmt"
)

type BinOp func(int, int) int

func Adder(a int, b int) int{
return a + b
}

func AttachDebugger(d *debugger.Debugger, f BinOp) BinOp{
return func(a int, b int) int {
result := f(a, b)
d.Break(func(){
fmt.Fprintf(d.Logout,"f(%v,%v) = %v\n", a, b, result)
})
return result
}
}

func main() {
d := debugger.New()
debugger.RunShell(d)

adder := AttachDebugger(d, Adder)
done := make(chan int, 100)

for i := 0; i < 10; i += 1{
go func(a int){
fmt.Printf(".")
adder(a, a*3)
fmt.Printf("-")
done <- 1
}(i)
}

for i := 0; i < 10; i += 1{
<-done
}

print("\n\n")
}
93 changes: 64 additions & 29 deletions src/debugger/debugger.go
@@ -1,63 +1,98 @@
package debugger

type Handler func(d *Debugger, cmd string, params []string)
import (
"io"
"os"
"strings"
"strconv"
)

func DefaultHandler(d *Debugger, cmd string, params []string ){
switch cmd {
"info", "i":;
"run", "r":;
"skip", "s":;
"continue", "c", "":;
"quit", "q" :;
}
}
const (
cBreak = iota
)

type Handler func(d *Debugger, cmd string, params []string) Action

type Debugger struct{
commands chan string
Commands chan string

Enabled bool
Watch chan int
Timeout int
Handler Handler
Logout io.Writer

control chan int
lock chan int
}

func New(f Handler) *Debugger {
func New() *Debugger {
d := &Debugger{}
d.lock = make(chan int, 1)
d.lock <- 1

d.control = make(chan int, 10000)
d.Commands = make(chan string, 50)
d.Watch = make(chan int, 1)
d.Enabled = true
d.Timeout = 0
d.Handler = f
}
d.Handler = DefaultHandler
d.Logout = os.Stderr

func (d *Debugger) Debug(){
d.DebugPrint(func(){})
return d
}

func (d *Debugger) DebugPrint( output func() ){
func (d *Debugger) Break( output func() ){
if !d.Enabled {
return
}

d.Lock()
<-d.lock

output()
if d.Enabled {
output()
d.HandleCommands()
}

d.HandleCommands()
d.Unlock()
d.lock <- 1
}

func (d *Debugger) HandleCommands(){
cmd <- d.commands
d.Handler(cmd, [])
}

func (d *Debugger) Lock(){
<- d.lock
handling: for {
select {
case ctrl := <-d.control:
switch ctrl {
case cBreak: break handling
}
case cmd := <-d.Commands:
tokens := strings.Split(cmd, " ")
action := d.Handler(d, tokens[0], tokens[1:len(tokens)])
action.Exec(d)
case <-d.Watch:
d.Watch <- 1
break handling
}
}
}

func (d *Debugger) Unlock(){
d.lock <- 1
func DefaultHandler(d *Debugger, cmd string, params []string ) Action {
switch cmd {
case "disable", "d": return Disable{}
case "skip", "s":
if len(params) > 0 {
timeout, err := strconv.Atoi(params[0])
if err == nil {
return Skip{timeout}
} else {
return Err{string(err.Error())}
}
} else {
return Err{"Requires skip count parameter."}
}
case "watch", "w": return Watch{}
case "": return Break{}
case "continue", "c": return Continue{}
case "quit", "q" : return Quit{}
}
return Nop{}
}
27 changes: 27 additions & 0 deletions src/debugger/shell.go
@@ -0,0 +1,27 @@
package debugger

import (
"bufio"
"os"
"strings"
)

func RunShell(d *Debugger){
r := bufio.NewReader(os.Stdin)

readLine := func () string {
ret, err := r.ReadString('\n')
if err != nil {
os.Exit(1)
}
return ret
}

go func(){
for {
cmd := readLine()
cmd = strings.TrimSpace(cmd)
d.Commands <- cmd
}
}()
}
32 changes: 32 additions & 0 deletions src/spxs/debugger.go
@@ -0,0 +1,32 @@
package main

import (
"fmt"
. "spexs/trie"
"debugger"
)

var dbg = debugger.New()

func AttachDebugger(s *AppSetup) {
debugger.RunShell(dbg)
f := s.Extender
s.Extender = func(p *Pattern, ref *Reference) Patterns {
tmp := f(p, ref)
result := NewPatterns()
dbg.Break(func(){
fmt.Fprintf(dbg.Logout, "extending: %v\n", ref.ReplaceGroups(p.String()))
for extended := range tmp {
result <- extended
fmt.Fprintf(dbg.Logout, " | %v\n", ref.ReplaceGroups(extended.String()))
if *verbose {
fmt.Fprintf(dbg.Logout, " E:%v O:%v\n", s.Extendable(extended, ref), s.Outputtable(extended, ref))
fmt.Fprintf(dbg.Logout, " ")
s.Printer(dbg.Logout, extended, ref)
}
}
close(result)
})
return result
}
}
14 changes: 4 additions & 10 deletions src/spxs/spxs.go
Expand Up @@ -5,7 +5,6 @@ import (
"fmt"
"runtime"
. "spexs/trie"
"time"

"log"
"os"
Expand All @@ -29,9 +28,10 @@ import (
var (
configs *string = flag.String("conf", "spxs.json", "configuration file(s), comma-delimited")
details *bool = flag.Bool("details", false, "detailed help")
interactiveDebug *bool = flag.Bool("debug", false, "attach step-by-step debugger")
verbose *bool = flag.Bool("verbose", false, "print extended debug info")

procs *int = flag.Int("procs", 4, "processors to use")
verbose *bool = flag.Bool("verbose", false, "print debug information")
cpuprofile *string = flag.String("cpuprofile", "", "write cpu profile to file")
)

Expand Down Expand Up @@ -106,14 +106,8 @@ func main() {
defer stopProfiler()
}

// debugging the input queue
if *verbose {
go func() {
for {
fmt.Printf("queue size: %v\n", setup.In.Len())
time.Sleep(1000 * 1000 * 100)
}
}()
if *interactiveDebug {
AttachDebugger(&setup)
}

if *procs <= 1 {
Expand Down
2 changes: 1 addition & 1 deletion test.sh
Expand Up @@ -4,4 +4,4 @@ export GOBIN=`pwd`/bin

go install spxs

time ./bin/spxs --procs=4 --conf=conf/spxs.json ref=data/dna.gen
time ./bin/spxs --debug --procs=4 --conf=conf/spxs.json ref=data/dna.gen

0 comments on commit 23d0825

Please sign in to comment.