Simplified code
This commit is contained in:
parent
69245caf62
commit
26214366e3
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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{
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
},
|
||||
|
@ -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:
|
||||
|
@ -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()
|
||||
}
|
7
src/build/register/Call.go
Normal file
7
src/build/register/Call.go
Normal 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()
|
||||
}
|
@ -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()
|
||||
}
|
8
src/build/register/FreeRegister.go
Normal file
8
src/build/register/FreeRegister.go
Normal 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)
|
||||
}
|
@ -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()
|
||||
}
|
@ -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
|
@ -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()
|
||||
}
|
10
src/build/register/NewRegister.go
Normal file
10
src/build/register/NewRegister.go
Normal 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
|
||||
}
|
@ -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()
|
8
src/build/register/RegisterIsUsed.go
Normal file
8
src/build/register/RegisterIsUsed.go
Normal 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)
|
||||
}
|
@ -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()
|
@ -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()
|
@ -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()
|
@ -1,6 +1,6 @@
|
||||
package z
|
||||
package register
|
||||
|
||||
func (f *Compiler) Return() {
|
||||
func (f *Machine) Return() {
|
||||
f.Assembler.Return()
|
||||
f.postInstruction()
|
||||
}
|
@ -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
|
||||
}
|
7
src/build/register/Syscall.go
Normal file
7
src/build/register/Syscall.go
Normal file
@ -0,0 +1,7 @@
|
||||
package register
|
||||
|
||||
func (f *Machine) Syscall() {
|
||||
f.Assembler.Syscall()
|
||||
f.UseRegister(f.CPU.Output[0])
|
||||
f.postInstruction()
|
||||
}
|
8
src/build/register/UseRegister.go
Normal file
8
src/build/register/UseRegister.go
Normal 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)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package z
|
||||
package register
|
||||
|
||||
import "git.akyoto.dev/cli/q/src/build/asm"
|
||||
|
@ -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
|
||||
}
|
@ -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()
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
package z
|
||||
|
||||
func (f *Compiler) Syscall() {
|
||||
f.Assembler.Syscall()
|
||||
f.CurrentScope().Use(f.CPU.Output[0])
|
||||
f.postInstruction()
|
||||
}
|
@ -63,6 +63,10 @@ main() {
|
||||
sys.exit(1)
|
||||
}
|
||||
|
||||
if inc(x) == dec(x) {
|
||||
sys.exit(1)
|
||||
}
|
||||
|
||||
if x == 0 {
|
||||
sys.exit(0)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user