1
0
mirror of https://github.com/taigrr/gopher-os synced 2025-01-18 04:43:13 -08:00
2017-12-29 15:58:56 +00:00

65 lines
1.9 KiB
Go

package entity
// Visitor is a function invoked by the VM for each AML tree entity that matches
// a particular type. The return value controls whether the children of this
// entity should also be visited.
type Visitor func(depth int, obj Entity) (keepRecursing bool)
// Type defines the type of entity that visitors should inspect.
type Type uint8
// The list of supported Type values. TypeAny works as a wildcard
// allowing the visitor to inspect all entities in the AML tree.
const (
TypeAny Type = iota
TypeDevice
TypeProcessor
TypePowerResource
TypeThermalZone
TypeMethod
TypeMutex
TypeEvent
TypeField
TypeIndexField
TypeBankField
)
// Visit descends a scope hierarchy and invokes visitorFn for each entity
// that matches entType.
func Visit(depth int, ent Entity, entType Type, visitorFn Visitor) bool {
op := ent.Opcode()
switch {
case (entType == TypeAny) ||
(entType == TypeDevice && op == OpDevice) ||
(entType == TypeProcessor && op == OpProcessor) ||
(entType == TypePowerResource && op == OpPowerRes) ||
(entType == TypeThermalZone && op == OpThermalZone) ||
(entType == TypeMethod && op == OpMethod) ||
(entType == TypeMutex && op == OpMutex) ||
(entType == TypeEvent && op == OpEvent) ||
(entType == TypeField && op == OpField) ||
(entType == TypeIndexField && op == OpIndexField) ||
(entType == TypeBankField && op == OpBankField):
// If the visitor returned false we should not visit the children
if !visitorFn(depth, ent) {
return false
}
// Visit any args that are also entities
for _, arg := range ent.Args() {
if argEnt, isEnt := arg.(Entity); isEnt && !Visit(depth+1, argEnt, entType, visitorFn) {
return false
}
}
}
// If the entity defines a scope we need to visit the child entities.
if container, isContainer := ent.(Container); isContainer {
for _, child := range container.Children() {
_ = Visit(depth+1, child, entType, visitorFn)
}
}
return true
}