From 26214366e37a04b26d1267bc6da440cc86939ff2 Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Tue, 23 Jul 2024 22:14:23 +0200 Subject: [PATCH] Simplified code --- src/build/core/Compare.go | 6 +++--- src/build/core/CompileCall.go | 9 +++++---- src/build/core/CompileDefinition.go | 3 +-- src/build/core/Execute.go | 4 ++-- src/build/core/ExpressionToRegister.go | 5 ++--- src/build/core/Function.go | 4 ++-- src/build/core/NewFunction.go | 4 ++-- src/build/core/TokenToRegister.go | 2 +- src/build/{z => register}/AddLabel.go | 4 ++-- src/build/register/Call.go | 7 +++++++ src/build/{z => register}/Comment.go | 4 ++-- src/build/register/FreeRegister.go | 8 ++++++++ src/build/{z => register}/Jump.go | 4 ++-- src/build/{z/Compiler.go => register/Machine.go} | 6 +++--- src/build/{z => register}/MemoryNumber.go | 4 ++-- src/build/register/NewRegister.go | 10 ++++++++++ src/build/{z => register}/Register.go | 6 +++--- src/build/register/RegisterIsUsed.go | 8 ++++++++ src/build/{z => register}/RegisterLabel.go | 8 ++++---- src/build/{z => register}/RegisterNumber.go | 8 ++++---- src/build/{z => register}/RegisterRegister.go | 8 ++++---- src/build/{z => register}/Return.go | 4 ++-- src/build/{z => register}/SaveRegister.go | 9 ++++----- src/build/register/Syscall.go | 7 +++++++ src/build/register/UseRegister.go | 8 ++++++++ src/build/{z => register}/isDestructive.go | 2 +- src/build/{z => register}/postInstruction.go | 4 ++-- src/build/z/Call.go | 7 ------- src/build/z/Syscall.go | 7 ------- tests/programs/branch.q | 4 ++++ 30 files changed, 105 insertions(+), 69 deletions(-) rename src/build/{z => register}/AddLabel.go (63%) create mode 100644 src/build/register/Call.go rename src/build/{z => register}/Comment.go (54%) create mode 100644 src/build/register/FreeRegister.go rename src/build/{z => register}/Jump.go (57%) rename src/build/{z/Compiler.go => register/Machine.go} (72%) rename src/build/{z => register}/MemoryNumber.go (54%) create mode 100644 src/build/register/NewRegister.go rename src/build/{z => register}/Register.go (62%) create mode 100644 src/build/register/RegisterIsUsed.go rename src/build/{z => register}/RegisterLabel.go (52%) rename src/build/{z => register}/RegisterNumber.go (54%) rename src/build/{z => register}/RegisterRegister.go (58%) rename src/build/{z => register}/Return.go (50%) rename src/build/{z => register}/SaveRegister.go (69%) create mode 100644 src/build/register/Syscall.go create mode 100644 src/build/register/UseRegister.go rename src/build/{z => register}/isDestructive.go (92%) rename src/build/{z => register}/postInstruction.go (74%) delete mode 100644 src/build/z/Call.go delete mode 100644 src/build/z/Syscall.go diff --git a/src/build/core/Compare.go b/src/build/core/Compare.go index 7eb92f7..0ccfe3c 100644 --- a/src/build/core/Compare.go +++ b/src/build/core/Compare.go @@ -31,16 +31,16 @@ func (f *Function) Compare(comparison *expression.Expression) error { return err } - return f.Execute(comparison.Token, f.CPU.Output[0], right) + return f.ExecuteLeaf(comparison.Token, f.CPU.Output[0], right.Token) } - tmp := f.CurrentScope().MustFindFree(f.CPU.General) + tmp := f.NewRegister() err := f.ExpressionToRegister(left, tmp) if err != nil { return err } - defer f.CurrentScope().Free(tmp) + defer f.FreeRegister(tmp) return f.Execute(comparison.Token, tmp, right) } diff --git a/src/build/core/CompileCall.go b/src/build/core/CompileCall.go index 358d4f8..1441ee9 100644 --- a/src/build/core/CompileCall.go +++ b/src/build/core/CompileCall.go @@ -11,8 +11,8 @@ import ( // Registers that are in use must be saved if they are modified by the function. // After the function call, they must be restored in reverse order. func (f *Function) CompileCall(root *expression.Expression) error { - funcNameRoot := root.Children[0] funcName := "" + funcNameRoot := root.Children[0] if funcNameRoot.IsLeaf() { funcName = funcNameRoot.Token.Text(f.File.Bytes) @@ -47,7 +47,7 @@ func (f *Function) CompileCall(root *expression.Expression) error { // Push for _, register := range f.CPU.General { - if f.CurrentScope().IsUsed(register) { + if f.RegisterIsUsed(register) { f.Register(asm.PUSH, register) } } @@ -59,19 +59,20 @@ func (f *Function) CompileCall(root *expression.Expression) error { f.Call(funcName) } + // Free parameter registers for _, register := range registers { if register == f.CPU.Output[0] && root.Parent != nil { continue } - f.CurrentScope().Free(register) + f.FreeRegister(register) } // Pop for i := len(f.CPU.General) - 1; i >= 0; i-- { register := f.CPU.General[i] - if f.CurrentScope().IsUsed(register) { + if f.RegisterIsUsed(register) { f.Register(asm.POP, register) } } diff --git a/src/build/core/CompileDefinition.go b/src/build/core/CompileDefinition.go index 71745b5..6e1943f 100644 --- a/src/build/core/CompileDefinition.go +++ b/src/build/core/CompileDefinition.go @@ -21,8 +21,7 @@ func (f *Function) CompileDefinition(node *ast.Define) error { return errors.New(&errors.UnusedVariable{Name: name}, f.File, node.Name.Position) } - register := f.CurrentScope().MustFindFree(f.CPU.General) - f.CurrentScope().Reserve(register) + register := f.NewRegister() err := f.ExpressionToRegister(node.Value, register) f.AddVariable(&scope.Variable{ diff --git a/src/build/core/Execute.go b/src/build/core/Execute.go index 09f2dec..76a54bf 100644 --- a/src/build/core/Execute.go +++ b/src/build/core/Execute.go @@ -23,8 +23,8 @@ func (f *Function) Execute(operation token.Token, register cpu.Register, value * return f.ExecuteRegisterRegister(operation, register, f.CPU.Output[0]) } - tmp := f.CurrentScope().MustFindFree(f.CPU.General) - defer f.CurrentScope().Free(tmp) + tmp := f.NewRegister() + defer f.FreeRegister(tmp) err := f.ExpressionToRegister(value, tmp) diff --git a/src/build/core/ExpressionToRegister.go b/src/build/core/ExpressionToRegister.go index c900c7b..212b7ed 100644 --- a/src/build/core/ExpressionToRegister.go +++ b/src/build/core/ExpressionToRegister.go @@ -33,10 +33,9 @@ func (f *Function) ExpressionToRegister(node *expression.Expression, register cp final := register if f.UsesRegister(right, register) { - register = f.CurrentScope().MustFindFree(f.CPU.General) + register = f.NewRegister() } - f.CurrentScope().Reserve(register) err := f.ExpressionToRegister(left, register) if err != nil { @@ -47,7 +46,7 @@ func (f *Function) ExpressionToRegister(node *expression.Expression, register cp if register != final { f.RegisterRegister(asm.MOVE, final, register) - f.CurrentScope().Free(register) + f.FreeRegister(register) } return err diff --git a/src/build/core/Function.go b/src/build/core/Function.go index 65b9252..f926956 100644 --- a/src/build/core/Function.go +++ b/src/build/core/Function.go @@ -2,13 +2,13 @@ package core import ( "git.akyoto.dev/cli/q/src/build/fs" + "git.akyoto.dev/cli/q/src/build/register" "git.akyoto.dev/cli/q/src/build/token" - "git.akyoto.dev/cli/q/src/build/z" ) // Function represents the smallest unit of code. type Function struct { - z.Compiler + register.Machine Name string File *fs.File Body []token.Token diff --git a/src/build/core/NewFunction.go b/src/build/core/NewFunction.go index f73aedb..d4bc8f3 100644 --- a/src/build/core/NewFunction.go +++ b/src/build/core/NewFunction.go @@ -5,9 +5,9 @@ import ( "git.akyoto.dev/cli/q/src/build/asm" "git.akyoto.dev/cli/q/src/build/cpu" "git.akyoto.dev/cli/q/src/build/fs" + "git.akyoto.dev/cli/q/src/build/register" "git.akyoto.dev/cli/q/src/build/scope" "git.akyoto.dev/cli/q/src/build/token" - "git.akyoto.dev/cli/q/src/build/z" ) // NewFunction creates a new function. @@ -16,7 +16,7 @@ func NewFunction(name string, file *fs.File, body []token.Token) *Function { Name: name, File: file, Body: body, - Compiler: z.Compiler{ + Machine: register.Machine{ Assembler: asm.Assembler{ Instructions: make([]asm.Instruction, 0, 8), }, diff --git a/src/build/core/TokenToRegister.go b/src/build/core/TokenToRegister.go index cbdd1c9..50e2b77 100644 --- a/src/build/core/TokenToRegister.go +++ b/src/build/core/TokenToRegister.go @@ -21,8 +21,8 @@ func (f *Function) TokenToRegister(t token.Token, register cpu.Register) error { return errors.New(&errors.UnknownIdentifier{Name: name}, f.File, t.Position) } - f.UseVariable(variable) f.RegisterRegister(asm.MOVE, register, variable.Register) + f.UseVariable(variable) return nil case token.Number, token.Rune: diff --git a/src/build/z/AddLabel.go b/src/build/register/AddLabel.go similarity index 63% rename from src/build/z/AddLabel.go rename to src/build/register/AddLabel.go index ccc18a8..3189ee0 100644 --- a/src/build/z/AddLabel.go +++ b/src/build/register/AddLabel.go @@ -1,8 +1,8 @@ -package z +package register import "git.akyoto.dev/cli/q/src/build/asm" -func (f *Compiler) AddLabel(label string) { +func (f *Machine) AddLabel(label string) { f.Assembler.Label(asm.LABEL, label) f.postInstruction() } diff --git a/src/build/register/Call.go b/src/build/register/Call.go new file mode 100644 index 0000000..6008dbd --- /dev/null +++ b/src/build/register/Call.go @@ -0,0 +1,7 @@ +package register + +func (f *Machine) Call(label string) { + f.Assembler.Call(label) + f.UseRegister(f.CPU.Output[0]) + f.postInstruction() +} diff --git a/src/build/z/Comment.go b/src/build/register/Comment.go similarity index 54% rename from src/build/z/Comment.go rename to src/build/register/Comment.go index d795f3b..ca86f0f 100644 --- a/src/build/z/Comment.go +++ b/src/build/register/Comment.go @@ -1,8 +1,8 @@ -package z +package register import "fmt" -func (f *Compiler) Comment(format string, args ...any) { +func (f *Machine) Comment(format string, args ...any) { f.Assembler.Comment(fmt.Sprintf(format, args...)) f.postInstruction() } diff --git a/src/build/register/FreeRegister.go b/src/build/register/FreeRegister.go new file mode 100644 index 0000000..5c459b7 --- /dev/null +++ b/src/build/register/FreeRegister.go @@ -0,0 +1,8 @@ +package register + +import "git.akyoto.dev/cli/q/src/build/cpu" + +// FreeRegister frees a register. +func (f *Machine) FreeRegister(register cpu.Register) { + f.CurrentScope().Free(register) +} diff --git a/src/build/z/Jump.go b/src/build/register/Jump.go similarity index 57% rename from src/build/z/Jump.go rename to src/build/register/Jump.go index 5938ed5..ff77d01 100644 --- a/src/build/z/Jump.go +++ b/src/build/register/Jump.go @@ -1,8 +1,8 @@ -package z +package register import "git.akyoto.dev/cli/q/src/build/asm" -func (f *Compiler) Jump(mnemonic asm.Mnemonic, label string) { +func (f *Machine) Jump(mnemonic asm.Mnemonic, label string) { f.Assembler.Label(mnemonic, label) f.postInstruction() } diff --git a/src/build/z/Compiler.go b/src/build/register/Machine.go similarity index 72% rename from src/build/z/Compiler.go rename to src/build/register/Machine.go index b93e895..50a22b7 100644 --- a/src/build/z/Compiler.go +++ b/src/build/register/Machine.go @@ -1,4 +1,4 @@ -package z +package register import ( "git.akyoto.dev/cli/q/src/build/asm" @@ -6,8 +6,8 @@ import ( "git.akyoto.dev/cli/q/src/build/scope" ) -// Compiler is a register usage aware assembler. -type Compiler struct { +// Machine is a register usage aware assembler. +type Machine struct { scope.Stack Assembler asm.Assembler CPU cpu.CPU diff --git a/src/build/z/MemoryNumber.go b/src/build/register/MemoryNumber.go similarity index 54% rename from src/build/z/MemoryNumber.go rename to src/build/register/MemoryNumber.go index 55ab175..6e99fda 100644 --- a/src/build/z/MemoryNumber.go +++ b/src/build/register/MemoryNumber.go @@ -1,8 +1,8 @@ -package z +package register import "git.akyoto.dev/cli/q/src/build/asm" -func (f *Compiler) MemoryNumber(mnemonic asm.Mnemonic, a asm.Memory, b int) { +func (f *Machine) MemoryNumber(mnemonic asm.Mnemonic, a asm.Memory, b int) { f.Assembler.MemoryNumber(mnemonic, a, b) f.postInstruction() } diff --git a/src/build/register/NewRegister.go b/src/build/register/NewRegister.go new file mode 100644 index 0000000..fb2300c --- /dev/null +++ b/src/build/register/NewRegister.go @@ -0,0 +1,10 @@ +package register + +import "git.akyoto.dev/cli/q/src/build/cpu" + +// NewRegister reserves a register. +func (f *Machine) NewRegister() cpu.Register { + register := f.CurrentScope().MustFindFree(f.CPU.General) + f.CurrentScope().Reserve(register) + return register +} diff --git a/src/build/z/Register.go b/src/build/register/Register.go similarity index 62% rename from src/build/z/Register.go rename to src/build/register/Register.go index 6244121..89f0ca1 100644 --- a/src/build/z/Register.go +++ b/src/build/register/Register.go @@ -1,15 +1,15 @@ -package z +package register import ( "git.akyoto.dev/cli/q/src/build/asm" "git.akyoto.dev/cli/q/src/build/cpu" ) -func (f *Compiler) Register(mnemonic asm.Mnemonic, a cpu.Register) { +func (f *Machine) Register(mnemonic asm.Mnemonic, a cpu.Register) { f.Assembler.Register(mnemonic, a) if mnemonic == asm.POP { - f.CurrentScope().Use(a) + f.UseRegister(a) } f.postInstruction() diff --git a/src/build/register/RegisterIsUsed.go b/src/build/register/RegisterIsUsed.go new file mode 100644 index 0000000..0ba6d0e --- /dev/null +++ b/src/build/register/RegisterIsUsed.go @@ -0,0 +1,8 @@ +package register + +import "git.akyoto.dev/cli/q/src/build/cpu" + +// RegisterIsUsed reserves a register. +func (f *Machine) RegisterIsUsed(register cpu.Register) bool { + return f.CurrentScope().IsUsed(register) +} diff --git a/src/build/z/RegisterLabel.go b/src/build/register/RegisterLabel.go similarity index 52% rename from src/build/z/RegisterLabel.go rename to src/build/register/RegisterLabel.go index 6047d05..7778e5a 100644 --- a/src/build/z/RegisterLabel.go +++ b/src/build/register/RegisterLabel.go @@ -1,19 +1,19 @@ -package z +package register import ( "git.akyoto.dev/cli/q/src/build/asm" "git.akyoto.dev/cli/q/src/build/cpu" ) -func (f *Compiler) RegisterLabel(mnemonic asm.Mnemonic, register cpu.Register, label string) { - if f.CurrentScope().IsUsed(register) && isDestructive(mnemonic) { +func (f *Machine) RegisterLabel(mnemonic asm.Mnemonic, register cpu.Register, label string) { + if f.RegisterIsUsed(register) && isDestructive(mnemonic) { f.SaveRegister(register) } f.Assembler.RegisterLabel(mnemonic, register, label) if mnemonic == asm.MOVE { - f.CurrentScope().Use(register) + f.UseRegister(register) } f.postInstruction() diff --git a/src/build/z/RegisterNumber.go b/src/build/register/RegisterNumber.go similarity index 54% rename from src/build/z/RegisterNumber.go rename to src/build/register/RegisterNumber.go index 14f84ae..ce9a41f 100644 --- a/src/build/z/RegisterNumber.go +++ b/src/build/register/RegisterNumber.go @@ -1,19 +1,19 @@ -package z +package register import ( "git.akyoto.dev/cli/q/src/build/asm" "git.akyoto.dev/cli/q/src/build/cpu" ) -func (f *Compiler) RegisterNumber(mnemonic asm.Mnemonic, a cpu.Register, b int) { - if f.CurrentScope().IsUsed(a) && isDestructive(mnemonic) { +func (f *Machine) RegisterNumber(mnemonic asm.Mnemonic, a cpu.Register, b int) { + if f.RegisterIsUsed(a) && isDestructive(mnemonic) { f.SaveRegister(a) } f.Assembler.RegisterNumber(mnemonic, a, b) if mnemonic == asm.MOVE { - f.CurrentScope().Use(a) + f.UseRegister(a) } f.postInstruction() diff --git a/src/build/z/RegisterRegister.go b/src/build/register/RegisterRegister.go similarity index 58% rename from src/build/z/RegisterRegister.go rename to src/build/register/RegisterRegister.go index 7370955..a969ca5 100644 --- a/src/build/z/RegisterRegister.go +++ b/src/build/register/RegisterRegister.go @@ -1,23 +1,23 @@ -package z +package register import ( "git.akyoto.dev/cli/q/src/build/asm" "git.akyoto.dev/cli/q/src/build/cpu" ) -func (f *Compiler) RegisterRegister(mnemonic asm.Mnemonic, a cpu.Register, b cpu.Register) { +func (f *Machine) RegisterRegister(mnemonic asm.Mnemonic, a cpu.Register, b cpu.Register) { if mnemonic == asm.MOVE && a == b { return } - if f.CurrentScope().IsUsed(a) && isDestructive(mnemonic) { + if f.RegisterIsUsed(a) && isDestructive(mnemonic) { f.SaveRegister(a) } f.Assembler.RegisterRegister(mnemonic, a, b) if mnemonic == asm.MOVE { - f.CurrentScope().Use(a) + f.UseRegister(a) } f.postInstruction() diff --git a/src/build/z/Return.go b/src/build/register/Return.go similarity index 50% rename from src/build/z/Return.go rename to src/build/register/Return.go index 596584b..b9e09b7 100644 --- a/src/build/z/Return.go +++ b/src/build/register/Return.go @@ -1,6 +1,6 @@ -package z +package register -func (f *Compiler) Return() { +func (f *Machine) Return() { f.Assembler.Return() f.postInstruction() } diff --git a/src/build/z/SaveRegister.go b/src/build/register/SaveRegister.go similarity index 69% rename from src/build/z/SaveRegister.go rename to src/build/register/SaveRegister.go index dacacf5..1c20818 100644 --- a/src/build/z/SaveRegister.go +++ b/src/build/register/SaveRegister.go @@ -1,4 +1,4 @@ -package z +package register import ( "git.akyoto.dev/cli/q/src/build/asm" @@ -6,8 +6,8 @@ import ( ) // SaveRegister attempts to move a variable occupying this register to another register. -func (f *Compiler) SaveRegister(register cpu.Register) { - if !f.CurrentScope().IsUsed(register) { +func (f *Machine) SaveRegister(register cpu.Register) { + if !f.RegisterIsUsed(register) { return } @@ -23,8 +23,7 @@ func (f *Compiler) SaveRegister(register cpu.Register) { return } - newRegister := f.CurrentScope().MustFindFree(f.CPU.General) - f.CurrentScope().Reserve(newRegister) + newRegister := f.NewRegister() f.RegisterRegister(asm.MOVE, newRegister, register) variable.Register = newRegister } diff --git a/src/build/register/Syscall.go b/src/build/register/Syscall.go new file mode 100644 index 0000000..ace09d7 --- /dev/null +++ b/src/build/register/Syscall.go @@ -0,0 +1,7 @@ +package register + +func (f *Machine) Syscall() { + f.Assembler.Syscall() + f.UseRegister(f.CPU.Output[0]) + f.postInstruction() +} diff --git a/src/build/register/UseRegister.go b/src/build/register/UseRegister.go new file mode 100644 index 0000000..ce45d81 --- /dev/null +++ b/src/build/register/UseRegister.go @@ -0,0 +1,8 @@ +package register + +import "git.akyoto.dev/cli/q/src/build/cpu" + +// Use marks a register to be currently in use. +func (f *Machine) UseRegister(register cpu.Register) { + f.CurrentScope().Use(register) +} diff --git a/src/build/z/isDestructive.go b/src/build/register/isDestructive.go similarity index 92% rename from src/build/z/isDestructive.go rename to src/build/register/isDestructive.go index 2165fcb..086ceca 100644 --- a/src/build/z/isDestructive.go +++ b/src/build/register/isDestructive.go @@ -1,4 +1,4 @@ -package z +package register import "git.akyoto.dev/cli/q/src/build/asm" diff --git a/src/build/z/postInstruction.go b/src/build/register/postInstruction.go similarity index 74% rename from src/build/z/postInstruction.go rename to src/build/register/postInstruction.go index a9166e4..d3e2b5d 100644 --- a/src/build/z/postInstruction.go +++ b/src/build/register/postInstruction.go @@ -1,8 +1,8 @@ -package z +package register import "git.akyoto.dev/cli/q/src/build/config" -func (f *Compiler) postInstruction() { +func (f *Machine) postInstruction() { if !config.Assembler { return } diff --git a/src/build/z/Call.go b/src/build/z/Call.go deleted file mode 100644 index f1284bb..0000000 --- a/src/build/z/Call.go +++ /dev/null @@ -1,7 +0,0 @@ -package z - -func (f *Compiler) Call(label string) { - f.Assembler.Call(label) - f.CurrentScope().Use(f.CPU.Output[0]) - f.postInstruction() -} diff --git a/src/build/z/Syscall.go b/src/build/z/Syscall.go deleted file mode 100644 index dfd2199..0000000 --- a/src/build/z/Syscall.go +++ /dev/null @@ -1,7 +0,0 @@ -package z - -func (f *Compiler) Syscall() { - f.Assembler.Syscall() - f.CurrentScope().Use(f.CPU.Output[0]) - f.postInstruction() -} diff --git a/tests/programs/branch.q b/tests/programs/branch.q index aaa393f..9e6f514 100644 --- a/tests/programs/branch.q +++ b/tests/programs/branch.q @@ -63,6 +63,10 @@ main() { sys.exit(1) } + if inc(x) == dec(x) { + sys.exit(1) + } + if x == 0 { sys.exit(0) }