Phase 3: Encode as a BehaviorTree
Here is documentation describing how we encode .mm
scripts as a BehaviorTree
.
NOTE: This is only used for bytecode rewriting!
What is a Behavior Tree?
The following pages are great resources describing behavior trees and how they can be used:
Why even do this?
That's a great question, I'm glad you asked!
The first implementation of this DSL required traversing lots of the AST inside the emitter rather than building something (e.g. a generator
) that generically traversed the AST and calling the emitter to do low-level instruction emission events.
Consider what the semantic implications of a probe definition.
A probe specifies locations in a program to insert some instrumentation code.
One probe could result in 0 to many matched locations.
This means, to emit a probe, the program must be traversed gradually, if a location is found, stop, check if the predicate tells us to emit the probe, if it does, we emit the probe's actions that that point.
If we think about this logic at a high level without the use of the behavior tree, there is a weird fuzzy layer between the generator
and emitter
.
Either the generator
needs to have some emitter
logic in it (traversing the program), or the emitter
needs to have some generator
logic in it (traversing the AST).
The BehaviorTree
decouples the two since the generator
logic is now in terms of the BehaviorTree
's control flow which encodes the decisions and actions to be taken while instrumenting the program rather than hardcoding those decisions and actions while traversing the AST!
This also makes adding new instrumentable event
s easier since the instrumentation logic can be encoded in the BehaviorTree
instead of hardcoding yet another conditional block to support the new functionality.
Visualization for Debugging
whamm vis-script --help
The whamm
CLI provides an easy way to generate a visualization of the BehaviorTree
to make it easier-to-debug the control flow of instrumentation.
Building the BehaviorTree
The builder_visitor.rs
file builds the BehaviorTree
from the script's AST.
The visit_whamm
function is the entrypoint for this action.
This follows the visitor software design pattern.
There are great resources online that teach about the visitor pattern if that is helpful for any readers.
While building the BehaviorTree
a simpler version of the script's AST is also built (see SimpleAST
in builder_visitor.rs
).
This new representation makes it easier to lookup relevant pieces of information that will be relevant to the logic performed in instr_generator.rs
.
Using the BehaviorTree
The instr_generator.rs
file actually uses the BehaviorTree
to follow the logic necessary to make decisions about emitting a probe into a program.
The run
function is the entrypoint for this action.
This follows the visitor software design pattern.
There are great resources online that teach about the visitor pattern if that is helpful for any readers.