Implemented definitions

This commit is contained in:
Eduard Urbach 2024-06-30 12:28:43 +02:00
parent 247b82b529
commit 7e5d45f17d
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
6 changed files with 70 additions and 14 deletions

View File

@ -190,6 +190,16 @@ func (f *Function) TokenToRegister(t token.Token, register cpu.Register) error {
switch t.Kind { switch t.Kind {
case token.Identifier: case token.Identifier:
name := t.Text() name := t.Text()
constant, exists := f.definitions[name]
if exists {
if config.Verbose {
f.Logf("constant %s = %s", constant.Name, constant.Value)
}
return f.ExpressionToRegister(constant.Value, register)
}
variable, exists := f.variables[name] variable, exists := f.variables[name]
if !exists { if !exists {

View File

@ -133,6 +133,18 @@ func (f *Function) Wait() {
// identifierExists returns true if the identifier has been defined. // identifierExists returns true if the identifier has been defined.
func (f *Function) identifierExists(name string) bool { func (f *Function) identifierExists(name string) bool {
_, exists := f.variables[name] _, exists := f.variables[name]
if exists {
return true
}
_, exists = f.definitions[name]
if exists {
return true
}
_, exists = f.functions[name]
return exists return exists
} }

View File

@ -2,11 +2,18 @@ package build
import ( import (
"git.akyoto.dev/cli/q/src/build/cpu" "git.akyoto.dev/cli/q/src/build/cpu"
"git.akyoto.dev/cli/q/src/build/expression"
) )
// Variable represents a variable in a function. // Variable represents a named register.
type Variable struct { type Variable struct {
Name string Name string
Register cpu.Register Register cpu.Register
Alive int Alive int
} }
// Definitions are single use expressions that don't reside in a register yet.
type Definition struct {
Name string
Value *expression.Expression
}

View File

@ -25,27 +25,34 @@ func (f *Function) CompileVariableDefinition(expr *expression.Expression) error
return errors.New(&errors.UnusedVariable{Name: name}, f.File, expr.Children[0].Token.Position) return errors.New(&errors.UnusedVariable{Name: name}, f.File, expr.Children[0].Token.Position)
} }
reg, exists := f.cpu.FindFree(f.cpu.General) value := expr.Children[1]
if !exists { err := value.EachLeaf(func(leaf *expression.Expression) error {
panic("no free registers") if leaf.Token.Kind == token.Identifier && !f.identifierExists(leaf.Token.Text()) {
return errors.New(&errors.UnknownIdentifier{Name: leaf.Token.Text()}, f.File, leaf.Token.Position)
} }
err := f.ExpressionToRegister(expr.Children[1], reg) return nil
})
if err != nil { if err != nil {
return err return err
} }
f.addVariable(&Variable{ if uses == 1 {
expr.RemoveChild(value)
f.definitions[name] = &Definition{
Name: name, Name: name,
Register: reg, Value: value,
Alive: uses, }
})
return nil return nil
} }
return f.storeVariableInRegister(name, value, uses)
}
func (f *Function) addVariable(variable *Variable) { func (f *Function) addVariable(variable *Variable) {
if config.Verbose { if config.Verbose {
f.Logf("%s occupies %s (alive: %d)", variable.Name, variable.Register, variable.Alive) f.Logf("%s occupies %s (alive: %d)", variable.Name, variable.Register, variable.Alive)
@ -75,6 +82,24 @@ func (f *Function) useVariable(variable *Variable) {
} }
} }
func (f *Function) storeVariableInRegister(name string, value *expression.Expression, uses int) error {
reg, exists := f.cpu.FindFree(f.cpu.General)
if !exists {
panic("no free registers")
}
err := f.ExpressionToRegister(value, reg)
f.addVariable(&Variable{
Name: name,
Register: reg,
Alive: uses,
})
return err
}
func countIdentifier(tokens token.List, name string) int { func countIdentifier(tokens token.List, name string) int {
count := 0 count := 0

View File

@ -16,6 +16,7 @@ type compiler struct {
cpu cpu.CPU cpu cpu.CPU
debug []debug debug []debug
err error err error
definitions map[string]*Definition
variables map[string]*Variable variables map[string]*Variable
functions map[string]*Function functions map[string]*Function
sideEffects int sideEffects int

View File

@ -250,6 +250,7 @@ func scanFile(path string, functions chan<- *Function) error {
Syscall: x64.SyscallRegisters, Syscall: x64.SyscallRegisters,
Return: x64.ReturnValueRegisters, Return: x64.ReturnValueRegisters,
}, },
definitions: map[string]*Definition{},
variables: map[string]*Variable{}, variables: map[string]*Variable{},
finished: make(chan struct{}), finished: make(chan struct{}),
}, },