diff --git a/src/build/Debug.go b/src/build/Debug.go new file mode 100644 index 0000000..5f95db4 --- /dev/null +++ b/src/build/Debug.go @@ -0,0 +1,22 @@ +package build + +import "git.akyoto.dev/cli/q/src/build/token" + +type debug struct { + pos int + instruction token.List +} + +func (f *Function) debugLine(instructionIndex int) token.List { + for _, record := range f.debug { + if record.pos == instructionIndex { + return record.instruction + } + + if record.pos > instructionIndex { + return nil + } + } + + return nil +} diff --git a/src/build/Function.go b/src/build/Function.go index 819479a..4bd2a94 100644 --- a/src/build/Function.go +++ b/src/build/Function.go @@ -6,6 +6,7 @@ import ( "git.akyoto.dev/cli/q/src/build/arch/x64" "git.akyoto.dev/cli/q/src/build/asm" + "git.akyoto.dev/cli/q/src/build/config" "git.akyoto.dev/cli/q/src/build/cpu" "git.akyoto.dev/cli/q/src/build/expression" "git.akyoto.dev/cli/q/src/build/fs" @@ -24,6 +25,7 @@ type Function struct { CPU cpu.CPU Error error count struct{ loop int } + debug []debug } // Compile turns a function into machine code. @@ -59,6 +61,14 @@ func (f *Function) CompileTokens(body token.List) error { if start != -1 { instruction := body[start:i] + + if config.Verbose { + f.debug = append(f.debug, debug{ + pos: len(f.Assembler.Instructions), + instruction: instruction, + }) + } + err := f.CompileInstruction(instruction) if err != nil { @@ -182,11 +192,6 @@ func (f *Function) ExpressionsToRegisters(expressions []*expression.Expression, return nil } -func (f *Function) Log(messages ...any) { - fmt.Printf("[%s] ", f.Name) - fmt.Println(messages...) -} - // TokenToRegister moves a token into a register. // It only works with identifiers, numbers and strings. func (f *Function) TokenToRegister(t token.Token, register cpu.Register) error { @@ -227,27 +232,33 @@ func (f *Function) TokenToRegister(t token.Token, register cpu.Register) error { // PrintAsm shows the assembly instructions. func (f *Function) PrintAsm() { - ansi.Dim.Println("╭────────────────────────────────────────────────╮") + ansi.Dim.Println("╭──────────────────────────────────────╮") + + for i, x := range f.Assembler.Instructions { + instruction := f.debugLine(i) + + if instruction != nil { + ansi.Dim.Println("├──────────────────────────────────────┤") + } - for _, x := range f.Assembler.Instructions { ansi.Dim.Print("│ ") if x.Mnemonic == asm.LABEL { - ansi.Yellow.Printf("%-46s", x.Data.String()+":") + ansi.Yellow.Printf("%-36s", x.Data.String()+":") } else { ansi.Green.Printf("%-8s", x.Mnemonic.String()) if x.Data != nil { - fmt.Printf("%-38s", x.Data.String()) + fmt.Printf("%-28s", x.Data.String()) } else { - fmt.Printf("%-38s", "") + fmt.Printf("%-28s", "") } } ansi.Dim.Print(" │\n") } - ansi.Dim.Println("╰────────────────────────────────────────────────╯") + ansi.Dim.Println("╰──────────────────────────────────────╯") } // String returns the function name.