diff --git a/src/build/core/AddVariable.go b/src/build/core/AddVariable.go index 8b36a56..b04ed1f 100644 --- a/src/build/core/AddVariable.go +++ b/src/build/core/AddVariable.go @@ -11,13 +11,5 @@ func (f *Function) AddVariable(variable *scope.Variable) { f.Comment("%s = %s (%d uses)", variable.Name, variable.Register, variable.Alive) } - s := f.CurrentScope() - variable.Scope = s - - if s.Variables == nil { - s.Variables = map[string]*scope.Variable{} - } - - s.Variables[variable.Name] = variable - s.Use(variable.Register) + f.CurrentScope().AddVariable(variable) } diff --git a/src/build/core/VariableByName.go b/src/build/core/VariableByName.go index a7b9ff7..8cce143 100644 --- a/src/build/core/VariableByName.go +++ b/src/build/core/VariableByName.go @@ -4,5 +4,5 @@ import "git.akyoto.dev/cli/q/src/build/scope" // VariableByName returns the variable with the given name or `nil` if it doesn't exist. func (f *Function) VariableByName(name string) *scope.Variable { - return f.CurrentScope().Variables[name] + return f.CurrentScope().VariableByName(name) } diff --git a/src/build/core/useVariable.go b/src/build/core/useVariable.go index 8109f20..35c058a 100644 --- a/src/build/core/useVariable.go +++ b/src/build/core/useVariable.go @@ -11,7 +11,7 @@ func (f *Function) useVariable(variable *scope.Variable) { continue } - local := scope.Variables[variable.Name] + local := scope.VariableByName(variable.Name) if local == nil { continue diff --git a/src/build/scope/Scope.go b/src/build/scope/Scope.go index 793bb27..da9a1a3 100644 --- a/src/build/scope/Scope.go +++ b/src/build/scope/Scope.go @@ -6,7 +6,25 @@ import ( // Scope represents an independent code block. type Scope struct { - Variables map[string]*Variable + Variables []*Variable InLoop bool cpu.State } + +// AddVariable adds a new variable to the current scope. +func (s *Scope) AddVariable(variable *Variable) { + variable.Scope = s + s.Variables = append(s.Variables, variable) + s.Use(variable.Register) +} + +// VariableByName returns the variable with the given name or `nil` if it doesn't exist. +func (s *Scope) VariableByName(name string) *Variable { + for _, v := range s.Variables { + if v.Name == name { + return v + } + } + + return nil +} diff --git a/src/build/scope/Stack.go b/src/build/scope/Stack.go index 1760f6b..2258cdd 100644 --- a/src/build/scope/Stack.go +++ b/src/build/scope/Stack.go @@ -26,24 +26,22 @@ func (stack *Stack) PushScope(body ast.AST, buffer []byte) *Scope { if len(stack.Scopes) > 0 { lastScope := stack.Scopes[len(stack.Scopes)-1] s.State = lastScope.State - s.Variables = make(map[string]*Variable, len(lastScope.Variables)) + s.Variables = make([]*Variable, 0, len(lastScope.Variables)) s.InLoop = lastScope.InLoop - for k, v := range lastScope.Variables { + for _, v := range lastScope.Variables { count := ast.Count(body, buffer, token.Identifier, v.Name) if count == 0 { continue } - s.Variables[k] = &Variable{ + s.Variables = append(s.Variables, &Variable{ Name: v.Name, Register: v.Register, Alive: count, - } + }) } - } else { - s.Variables = map[string]*Variable{} } stack.Scopes = append(stack.Scopes, s)