From d454572870e00953c4550ef1dbd7effcc3959fe5 Mon Sep 17 00:00:00 2001 From: Chuck Smith Date: Sat, 16 Mar 2024 20:02:57 -0400 Subject: [PATCH] debug --- main.go | 32 +++++++++++++++++++++++++++++--- repl/repl.go | 2 ++ vm/vm.go | 15 +++++++++++++++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/main.go b/main.go index 8469d5b..b6ae08b 100644 --- a/main.go +++ b/main.go @@ -3,15 +3,17 @@ package main import ( "flag" "fmt" - "io/ioutil" + "io" "log" "monkey/compiler" "monkey/lexer" + "monkey/object" "monkey/parser" "monkey/repl" "os" "os/user" "path" + "strings" ) var ( @@ -37,6 +39,22 @@ func init() { flag.StringVar(&engine, "e", "vm", "engine to use (eval or vm)") } +// Indent indents a block of text with an indent string +func Indent(text, indent string) string { + if text[len(text)-1:] == "\n" { + result := "" + for _, j := range strings.Split(text[:len(text)-1], "\n") { + result += indent + j + "\n" + } + return result + } + result := "" + for _, j := range strings.Split(strings.TrimRight(text, "\n"), "\n") { + result += indent + j + "\n" + } + return result[:len(result)-1] +} + func main() { flag.Parse() @@ -59,7 +77,7 @@ func main() { f, err := os.Open(args[0]) defer f.Close() - b, err := ioutil.ReadAll(f) + b, err := io.ReadAll(f) if err != nil { log.Fatal(err) } @@ -79,7 +97,15 @@ func main() { } code := c.Bytecode() - fmt.Printf("%s\n", code.Instructions) + fmt.Printf("Main:\n%s\n", code.Instructions) + + fmt.Print("Constants:\n") + for i, constant := range code.Constants { + fmt.Printf("%04d %s\n", i, constant.Inspect()) + if fn, ok := constant.(*object.CompiledFunction); ok { + fmt.Printf("%s\n", Indent(fn.Instructions.String(), " ")) + } + } } else { opts := &repl.Options{ Debug: debug, diff --git a/repl/repl.go b/repl/repl.go index 02ee005..3e86796 100644 --- a/repl/repl.go +++ b/repl/repl.go @@ -126,6 +126,7 @@ func (r *REPL) Exec(f io.Reader) (state *VMState) { state.constants = code.Constants machine := vm.NewWithGlobalState(code, state.globals) + machine.Debug = r.opts.Debug err = machine.Run() if err != nil { fmt.Fprintf(os.Stderr, "Woops! Executing bytecode failed:\n %s\n", err) @@ -206,6 +207,7 @@ func (r *REPL) StartExecLoop(in io.Reader, out io.Writer, state *VMState) { state.constants = code.Constants machine := vm.NewWithGlobalState(code, state.globals) + machine.Debug = r.opts.Debug err = machine.Run() if err != nil { fmt.Fprintf(os.Stderr, "Woops! Executing bytecode failed:\n %s\n", err) diff --git a/vm/vm.go b/vm/vm.go index 869ed00..f39349e 100644 --- a/vm/vm.go +++ b/vm/vm.go @@ -2,9 +2,11 @@ package vm import ( "fmt" + "log" "monkey/code" "monkey/compiler" "monkey/object" + "strings" ) const StackSize = 2048 @@ -16,6 +18,8 @@ var True = &object.Boolean{Value: true} var False = &object.Boolean{Value: false} type VM struct { + Debug bool + constants []object.Object stack []object.Object @@ -77,6 +81,17 @@ func (vm *VM) Run() error { var ins code.Instructions var op code.Opcode + if vm.Debug { + log.Printf( + "%-20s %-20s\n", + strings.Split(ins[ip:].String(), "\n")[0], + fmt.Sprintf( + "[ip=%02d fp=%02d, sp=%02d]", + ip, vm.sp, vm.framesIndex-1, + ), + ) + } + for vm.currentFrame().ip < len(vm.currentFrame().Instructions())-1 { vm.currentFrame().ip++