app.engine.dsl_interpreter module¶
Walker-based interpreter for the strategy DSL.
This is the sandbox. It walks the JSON AST node-by-node, dispatching on
node["type"] through a fixed handler table - no getattr, no
eval, no exec. Anything not in the handler table is rejected as
DslValidationError (the validator should have caught it; the runtime
check is defence in depth).
Hard guarantees:
No code path exposes Python attribute lookup to AST-supplied strings.
Field access is a frozen-dict lookup; the resolved values were precomputed by
ExecutionContext.build_for_ast.Node count and recursion depth are bounded - the validator already rejects programs that would exceed them; the runtime guards exist so that future dynamic expansion (e.g. macros) still can’t blow out.
await asyncio.sleep(0)everyyield_everyvisits gives the event loop a chance to actually cancel the coroutine whenasyncio.wait_forfires. Without it a CPU-bound walk would run to completion and only then see the timeout - which is whatRestrictedPython-style sandboxes generally get wrong.
Execution semantics mirror app/engine/default.py:
Rules are evaluated in order.
The first
assign_pointsreached in a matched rule sets the result and halts the program (early-return).set_callback_datastatements before the assignment accumulate into a dict; statements after the assignment never run.If no rule matches, the program’s
defaultsection runs (if any); otherwise the result is(0, None, {}).