66 lines
1.3 KiB
Go
66 lines
1.3 KiB
Go
package core
|
|
|
|
import (
|
|
"git.akyoto.dev/cli/q/src/build/ast"
|
|
"git.akyoto.dev/cli/q/src/build/config"
|
|
"git.akyoto.dev/cli/q/src/build/cpu"
|
|
"git.akyoto.dev/cli/q/src/build/token"
|
|
)
|
|
|
|
// Scope represents an independent code block.
|
|
type Scope struct {
|
|
variables map[string]*Variable
|
|
inLoop bool
|
|
cpu.State
|
|
}
|
|
|
|
// Scope returns the current scope.
|
|
func (s *state) Scope() *Scope {
|
|
return s.scopes[len(s.scopes)-1]
|
|
}
|
|
|
|
// pushScope pushes a new scope to the top of the stack.
|
|
func (f *Function) pushScope(body ast.AST) *Scope {
|
|
scope := &Scope{}
|
|
|
|
if len(f.scopes) > 0 {
|
|
lastScope := f.scopes[len(f.scopes)-1]
|
|
scope.State = lastScope.State
|
|
scope.variables = make(map[string]*Variable, len(lastScope.variables))
|
|
scope.inLoop = lastScope.inLoop
|
|
|
|
for k, v := range lastScope.variables {
|
|
count := ast.Count(body, token.Identifier, v.Name)
|
|
|
|
if count == 0 {
|
|
continue
|
|
}
|
|
|
|
scope.variables[k] = &Variable{
|
|
Name: v.Name,
|
|
Register: v.Register,
|
|
Alive: count,
|
|
}
|
|
}
|
|
} else {
|
|
scope.variables = map[string]*Variable{}
|
|
}
|
|
|
|
f.scopes = append(f.scopes, scope)
|
|
|
|
if config.Comments {
|
|
f.Comment("scope %d start", len(f.scopes))
|
|
}
|
|
|
|
return scope
|
|
}
|
|
|
|
// popScope removes the scope at the top of the stack.
|
|
func (f *Function) popScope() {
|
|
if config.Comments {
|
|
f.Comment("scope %d end", len(f.scopes))
|
|
}
|
|
|
|
f.scopes = f.scopes[:len(f.scopes)-1]
|
|
}
|