mirror of
https://github.com/taigrr/gopher-os
synced 2025-01-18 04:43:13 -08:00
65 lines
1.9 KiB
Go
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
|
|
}
|