From c027208369c5403df2c07fe31adf78cc0d3bc63c Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Mon, 22 Jul 2024 19:10:14 +0200 Subject: [PATCH] Simplified variable usage --- src/build/core/Compare.go | 2 +- src/build/core/CompileAssign.go | 4 ++-- src/build/core/ExecuteLeaf.go | 2 +- src/build/core/TokenToRegister.go | 2 +- src/build/core/useVariable.go | 36 ------------------------------- src/build/scope/Scope.go | 3 ++- src/build/scope/Stack.go | 22 +++++++++++++++++++ src/build/scope/Variable.go | 18 ++++++++++++++-- 8 files changed, 45 insertions(+), 44 deletions(-) delete mode 100644 src/build/core/useVariable.go diff --git a/src/build/core/Compare.go b/src/build/core/Compare.go index 6cd0b5d..4351c4a 100644 --- a/src/build/core/Compare.go +++ b/src/build/core/Compare.go @@ -20,7 +20,7 @@ func (f *Function) Compare(comparison *expression.Expression) error { 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) } diff --git a/src/build/core/CompileAssign.go b/src/build/core/CompileAssign.go index 767a2df..b811ab3 100644 --- a/src/build/core/CompileAssign.go +++ b/src/build/core/CompileAssign.go @@ -21,7 +21,7 @@ func (f *Function) CompileAssign(node *ast.Assign) error { 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) } @@ -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) } - defer f.useVariable(variable) + defer f.UseVariable(variable) index := left.Children[1] offset, _, err := f.Number(index.Token) diff --git a/src/build/core/ExecuteLeaf.go b/src/build/core/ExecuteLeaf.go index 8dbda36..6dd7645 100644 --- a/src/build/core/ExecuteLeaf.go +++ b/src/build/core/ExecuteLeaf.go @@ -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) } - defer f.useVariable(variable) + defer f.UseVariable(variable) return f.ExecuteRegisterRegister(operation, register, variable.Register) case token.Number, token.Rune: diff --git a/src/build/core/TokenToRegister.go b/src/build/core/TokenToRegister.go index 36af04f..cbdd1c9 100644 --- a/src/build/core/TokenToRegister.go +++ b/src/build/core/TokenToRegister.go @@ -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) } - f.useVariable(variable) + f.UseVariable(variable) f.RegisterRegister(asm.MOVE, register, variable.Register) return nil diff --git a/src/build/core/useVariable.go b/src/build/core/useVariable.go deleted file mode 100644 index 35c058a..0000000 --- a/src/build/core/useVariable.go +++ /dev/null @@ -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) - } - } -} diff --git a/src/build/scope/Scope.go b/src/build/scope/Scope.go index da9a1a3..42021e6 100644 --- a/src/build/scope/Scope.go +++ b/src/build/scope/Scope.go @@ -7,13 +7,14 @@ import ( // Scope represents an independent code block. type Scope struct { Variables []*Variable + Depth uint8 InLoop bool cpu.State } // AddVariable adds a new variable to the current scope. func (s *Scope) AddVariable(variable *Variable) { - variable.Scope = s + variable.Depth = s.Depth s.Variables = append(s.Variables, variable) s.Use(variable.Register) } diff --git a/src/build/scope/Stack.go b/src/build/scope/Stack.go index 2258cdd..32acf1f 100644 --- a/src/build/scope/Stack.go +++ b/src/build/scope/Stack.go @@ -40,6 +40,7 @@ func (stack *Stack) PushScope(body ast.AST, buffer []byte) *Scope { Name: v.Name, Register: v.Register, 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) 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) + } + } +} diff --git a/src/build/scope/Variable.go b/src/build/scope/Variable.go index 940d595..e1a54c3 100644 --- a/src/build/scope/Variable.go +++ b/src/build/scope/Variable.go @@ -6,8 +6,22 @@ import ( // Variable represents a named register. type Variable struct { - Scope *Scope Name string - Register cpu.Register 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") + } }