Simplified variable usage
This commit is contained in:
parent
504111734f
commit
c027208369
@ -20,7 +20,7 @@ func (f *Function) Compare(comparison *expression.Expression) error {
|
|||||||
return errors.New(&errors.UnknownIdentifier{Name: name}, f.File, left.Token.Position)
|
return errors.New(&errors.UnknownIdentifier{Name: name}, f.File, left.Token.Position)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer f.useVariable(variable)
|
defer f.UseVariable(variable)
|
||||||
return f.Execute(comparison.Token, variable.Register, right)
|
return f.Execute(comparison.Token, variable.Register, right)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ func (f *Function) CompileAssign(node *ast.Assign) error {
|
|||||||
return errors.New(&errors.UnknownIdentifier{Name: name}, f.File, left.Token.Position)
|
return errors.New(&errors.UnknownIdentifier{Name: name}, f.File, left.Token.Position)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer f.useVariable(variable)
|
defer f.UseVariable(variable)
|
||||||
return f.Execute(operator, variable.Register, right)
|
return f.Execute(operator, variable.Register, right)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ func (f *Function) CompileAssign(node *ast.Assign) error {
|
|||||||
return errors.New(&errors.UnknownIdentifier{Name: name}, f.File, left.Children[0].Token.Position)
|
return errors.New(&errors.UnknownIdentifier{Name: name}, f.File, left.Children[0].Token.Position)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer f.useVariable(variable)
|
defer f.UseVariable(variable)
|
||||||
|
|
||||||
index := left.Children[1]
|
index := left.Children[1]
|
||||||
offset, _, err := f.Number(index.Token)
|
offset, _, err := f.Number(index.Token)
|
||||||
|
@ -17,7 +17,7 @@ func (f *Function) ExecuteLeaf(operation token.Token, register cpu.Register, ope
|
|||||||
return errors.New(&errors.UnknownIdentifier{Name: name}, f.File, operand.Position)
|
return errors.New(&errors.UnknownIdentifier{Name: name}, f.File, operand.Position)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer f.useVariable(variable)
|
defer f.UseVariable(variable)
|
||||||
return f.ExecuteRegisterRegister(operation, register, variable.Register)
|
return f.ExecuteRegisterRegister(operation, register, variable.Register)
|
||||||
|
|
||||||
case token.Number, token.Rune:
|
case token.Number, token.Rune:
|
||||||
|
@ -21,7 +21,7 @@ func (f *Function) TokenToRegister(t token.Token, register cpu.Register) error {
|
|||||||
return errors.New(&errors.UnknownIdentifier{Name: name}, f.File, t.Position)
|
return errors.New(&errors.UnknownIdentifier{Name: name}, f.File, t.Position)
|
||||||
}
|
}
|
||||||
|
|
||||||
f.useVariable(variable)
|
f.UseVariable(variable)
|
||||||
f.RegisterRegister(asm.MOVE, register, variable.Register)
|
f.RegisterRegister(asm.MOVE, register, variable.Register)
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
package core
|
|
||||||
|
|
||||||
import (
|
|
||||||
"git.akyoto.dev/cli/q/src/build/config"
|
|
||||||
"git.akyoto.dev/cli/q/src/build/scope"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (f *Function) useVariable(variable *scope.Variable) {
|
|
||||||
for i, scope := range f.Scopes {
|
|
||||||
if scope.InLoop && variable.Scope != scope {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
local := scope.VariableByName(variable.Name)
|
|
||||||
|
|
||||||
if local == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
local.Alive--
|
|
||||||
|
|
||||||
if local.Alive < 0 {
|
|
||||||
panic("incorrect number of variable use calls")
|
|
||||||
}
|
|
||||||
|
|
||||||
if local.Alive == 0 {
|
|
||||||
if config.Comments {
|
|
||||||
f.Comment("%s (%s) died in scope %d", local.Name, local.Register, i)
|
|
||||||
}
|
|
||||||
|
|
||||||
scope.Free(local.Register)
|
|
||||||
} else if config.Comments {
|
|
||||||
f.Comment("%s (%s) used in scope %d", local.Name, local.Register, i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,13 +7,14 @@ import (
|
|||||||
// Scope represents an independent code block.
|
// Scope represents an independent code block.
|
||||||
type Scope struct {
|
type Scope struct {
|
||||||
Variables []*Variable
|
Variables []*Variable
|
||||||
|
Depth uint8
|
||||||
InLoop bool
|
InLoop bool
|
||||||
cpu.State
|
cpu.State
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddVariable adds a new variable to the current scope.
|
// AddVariable adds a new variable to the current scope.
|
||||||
func (s *Scope) AddVariable(variable *Variable) {
|
func (s *Scope) AddVariable(variable *Variable) {
|
||||||
variable.Scope = s
|
variable.Depth = s.Depth
|
||||||
s.Variables = append(s.Variables, variable)
|
s.Variables = append(s.Variables, variable)
|
||||||
s.Use(variable.Register)
|
s.Use(variable.Register)
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ func (stack *Stack) PushScope(body ast.AST, buffer []byte) *Scope {
|
|||||||
Name: v.Name,
|
Name: v.Name,
|
||||||
Register: v.Register,
|
Register: v.Register,
|
||||||
Alive: count,
|
Alive: count,
|
||||||
|
Depth: uint8(len(stack.Scopes)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -47,3 +48,24 @@ func (stack *Stack) PushScope(body ast.AST, buffer []byte) *Scope {
|
|||||||
stack.Scopes = append(stack.Scopes, s)
|
stack.Scopes = append(stack.Scopes, s)
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UseVariable reduces the lifetime of the variable in all scopes.
|
||||||
|
func (stack *Stack) UseVariable(variable *Variable) {
|
||||||
|
for depth, scope := range stack.Scopes {
|
||||||
|
if scope.InLoop && variable.Depth != uint8(depth) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
local := scope.VariableByName(variable.Name)
|
||||||
|
|
||||||
|
if local == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
local.Use()
|
||||||
|
|
||||||
|
if !local.IsAlive() {
|
||||||
|
scope.Free(local.Register)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -6,8 +6,22 @@ import (
|
|||||||
|
|
||||||
// Variable represents a named register.
|
// Variable represents a named register.
|
||||||
type Variable struct {
|
type Variable struct {
|
||||||
Scope *Scope
|
|
||||||
Name string
|
Name string
|
||||||
Register cpu.Register
|
|
||||||
Alive int
|
Alive int
|
||||||
|
Depth uint8
|
||||||
|
Register cpu.Register
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsAlive returns true if the variable is still alive.
|
||||||
|
func (v *Variable) IsAlive() bool {
|
||||||
|
return v.Alive > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use reduces the lifetime counter by one.
|
||||||
|
func (v *Variable) Use() {
|
||||||
|
v.Alive--
|
||||||
|
|
||||||
|
if v.Alive < 0 {
|
||||||
|
panic("incorrect number of variable use calls")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user