Simplified code

This commit is contained in:
Eduard Urbach 2024-07-23 22:14:23 +02:00
parent 69245caf62
commit 26214366e3
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
30 changed files with 105 additions and 69 deletions

View File

@ -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)
}

View File

@ -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)
}
}

View File

@ -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{

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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),
},

View File

@ -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:

View File

@ -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()
}

View File

@ -0,0 +1,7 @@
package register
func (f *Machine) Call(label string) {
f.Assembler.Call(label)
f.UseRegister(f.CPU.Output[0])
f.postInstruction()
}

View File

@ -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()
}

View File

@ -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)
}

View File

@ -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()
}

View File

@ -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

View File

@ -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()
}

View File

@ -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
}

View File

@ -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()

View File

@ -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)
}

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -1,6 +1,6 @@
package z
package register
func (f *Compiler) Return() {
func (f *Machine) Return() {
f.Assembler.Return()
f.postInstruction()
}

View File

@ -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
}

View File

@ -0,0 +1,7 @@
package register
func (f *Machine) Syscall() {
f.Assembler.Syscall()
f.UseRegister(f.CPU.Output[0])
f.postInstruction()
}

View File

@ -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)
}

View File

@ -1,4 +1,4 @@
package z
package register
import "git.akyoto.dev/cli/q/src/build/asm"

View File

@ -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
}

View File

@ -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()
}

View File

@ -1,7 +0,0 @@
package z
func (f *Compiler) Syscall() {
f.Assembler.Syscall()
f.CurrentScope().Use(f.CPU.Output[0])
f.postInstruction()
}

View File

@ -63,6 +63,10 @@ main() {
sys.exit(1)
}
if inc(x) == dec(x) {
sys.exit(1)
}
if x == 0 {
sys.exit(0)
}