OnExec
Line coverage - fires before each bytecode instruction
starlark-go-x is our enhanced fork of Google’s official starlark-go interpreter. It adds instrumentation hooks that enable coverage collection, profiling, and debugging without modifying user code.
The official starlark-go interpreter doesn’t expose hooks for:
These hooks are essential for building coverage tools like skycov and skytest --coverage.
OnExec
Line coverage - fires before each bytecode instruction
OnBranch
Branch coverage - fires after each conditional jump
OnFunctionEnter/Exit
Function coverage - fires on function entry and return
OnIteration
Loop coverage - fires on each for-loop iteration decision
Add to your go.mod:
// Replace upstream starlark-go with our forkreplace go.starlark.net => github.com/albertocavalcante/starlark-go-x v0.0.0-trunkOr use a local path during development:
replace go.starlark.net => ../starlark-go-x/trunkimport "go.starlark.net/starlark"
thread := &starlark.Thread{ Name: "my-thread",
// Line coverage OnExec: func(fn *starlark.Function, pc uint32) { pos := fn.PositionAt(pc) fmt.Printf("Executing %s:%d\n", pos.Filename(), pos.Line) },
// Branch coverage OnBranch: func(fn *starlark.Function, pc uint32, taken bool) { pos := fn.PositionAt(pc) fmt.Printf("Branch at %s:%d -> %v\n", pos.Filename(), pos.Line, taken) },}
// Execute Starlark code with instrumentationstarlark.ExecFile(thread, "example.star", src, nil)| Branch | Purpose | Status |
|---|---|---|
main | Tracks upstream google/starlark-go | Read-only |
trunk | All features combined | Use this |
coverage-hooks | OnExec hook only | Merged to trunk |
branch-coverage | +OnBranch | Merged to trunk |
function-coverage | +OnFunctionEnter/Exit | Merged to trunk |
loop-coverage | +OnIteration | Merged to trunk |
type-hints | Type annotation parsing | Merged to trunk |
| Metric | Hook | Description |
|---|---|---|
| Line Coverage | OnExec | Tracks which source lines execute |
| Branch Coverage | OnBranch | Tracks if/else and short-circuit outcomes |
| Function Coverage | OnFunctionEnter | Tracks which functions are called |
| Loop Coverage | OnIteration | Tracks for-loop iteration counts |
| Construct | Bytecode | Hook |
|---|---|---|
if/elif/else | CJMP | OnBranch |
for x in items | ITERJMP | OnIteration |
a and b | CJMP | OnBranch |
a or b | CJMP | OnBranch |
x if cond else y | CJMP | OnBranch |
[x for x in items] | ITERJMP | OnIteration |
def f(): ... calls | CALL | OnFunctionEnter/Exit |
We intend to propose these changes to google/starlark-go:
OnExec hook (most impactful, enables line coverage)OnBranch hook (branch coverage)OnFunctionEnter/Exit hooks (function coverage, profiling)OnIteration hook (loop coverage)Each hook is designed to have zero overhead when not used (nil check at call site).