133 lines
3.6 KiB
Go
133 lines
3.6 KiB
Go
package analyzer
|
|
|
|
import "git.tebibyte.media/fspl/fspl/entity"
|
|
|
|
// scopeContextManager is a stack of scopeContexts allowing multiple stacks of
|
|
// scopes to be managed at the same time in case the analysis of one scoped
|
|
// entity causes the analysis of another.
|
|
type scopeContextManager []scopeContext
|
|
|
|
func (this *scopeContextManager) pushScopeContext (declaration entity.TopLevel) {
|
|
*this = append(*this, scopeContext { declaration: declaration })
|
|
}
|
|
|
|
func (this *scopeContextManager) popScopeContext () {
|
|
this.assertPopulated()
|
|
*this = (*this)[:len(*this) - 1]
|
|
}
|
|
|
|
func (this *scopeContextManager) pushLoop (loop entity.Breakable) {
|
|
this.assertPopulated()
|
|
(*this)[len(*this) - 1].pushLoop(loop)
|
|
}
|
|
|
|
func (this *scopeContextManager) popLoop () {
|
|
this.assertPopulated()
|
|
(*this)[len(*this) - 1].popLoop()
|
|
}
|
|
|
|
func (this *scopeContextManager) topLoop () (entity.Breakable, bool) {
|
|
this.assertPopulated()
|
|
return (*this)[len(*this) - 1].topLoop()
|
|
}
|
|
|
|
func (this *scopeContextManager) topDeclaration () (entity.TopLevel, bool) {
|
|
if len(*this) < 1 { return nil, false }
|
|
return (*this)[len(*this) - 1].declaration, true
|
|
}
|
|
|
|
func (this *scopeContextManager) pushScope (scope entity.Scoped) {
|
|
this.assertPopulated()
|
|
(*this)[len(*this) - 1].pushScope(scope)
|
|
}
|
|
|
|
func (this *scopeContextManager) popScope () {
|
|
this.assertPopulated()
|
|
(*this)[len(*this) - 1].popScope()
|
|
}
|
|
|
|
func (this *scopeContextManager) topScope () (entity.Scoped, bool) {
|
|
this.assertPopulated()
|
|
return (*this)[len(*this) - 1].topScope()
|
|
}
|
|
|
|
func (this *scopeContextManager) variable (name string) *entity.Declaration {
|
|
this.assertPopulated()
|
|
return (*this)[len(*this) - 1].variable(name)
|
|
}
|
|
|
|
func (this *scopeContextManager) addVariable (declaration *entity.Declaration) {
|
|
this.assertPopulated()
|
|
(*this)[len(*this) - 1].addVariable(declaration)
|
|
}
|
|
|
|
func (this *scopeContextManager) assertPopulated () {
|
|
if len(*this) < 1 {
|
|
panic("scopeContextManager must have at least 1 scope context")
|
|
}
|
|
}
|
|
|
|
// scopeContext is a stack of scopes and loops used when analyzing scoped
|
|
// entities.
|
|
type scopeContext struct {
|
|
scopes []entity.Scoped
|
|
loops []entity.Breakable
|
|
declaration entity.TopLevel
|
|
}
|
|
|
|
func (this *scopeContext) pushLoop (loop entity.Breakable) {
|
|
this.loops = append(this.loops, loop)
|
|
}
|
|
|
|
func (this *scopeContext) popLoop () {
|
|
this.assertLoopPopulated()
|
|
this.loops = this.loops[:len(this.loops) - 1]
|
|
}
|
|
|
|
func (this *scopeContext) topLoop () (entity.Breakable, bool) {
|
|
if len(this.loops) < 1 { return nil, false }
|
|
return this.loops[len(this.loops) - 1], true
|
|
}
|
|
|
|
func (this *scopeContext) pushScope (scope entity.Scoped) {
|
|
this.scopes = append(this.scopes, scope)
|
|
}
|
|
|
|
func (this *scopeContext) popScope () {
|
|
this.assertScopePopulated()
|
|
this.scopes = this.scopes[:len(this.scopes) - 1]
|
|
}
|
|
|
|
func (this *scopeContext) topScope () (entity.Scoped, bool) {
|
|
if len(this.scopes) < 1 { return nil, false }
|
|
return this.scopes[len(this.scopes) - 1], true
|
|
}
|
|
|
|
func (this *scopeContext) variable (name string) *entity.Declaration {
|
|
this.assertScopePopulated()
|
|
for index := len(this.scopes) - 1; index >= 0; index -- {
|
|
variable := this.scopes[index].Variable(name)
|
|
if variable != nil {
|
|
return variable
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (this *scopeContext) addVariable (declaration *entity.Declaration) {
|
|
this.assertScopePopulated()
|
|
this.scopes[len(this.scopes) - 1].AddVariable(declaration)
|
|
}
|
|
|
|
func (this *scopeContext) assertScopePopulated () {
|
|
if len(this.scopes) < 1 {
|
|
panic("scopeContext must have at least 1 scope")
|
|
}
|
|
}
|
|
|
|
func (this *scopeContext) assertLoopPopulated () {
|
|
if len(this.scopes) < 1 {
|
|
panic("scopeContext must have at least 1 loop")
|
|
}
|
|
}
|