Skip to content

interp: add stmt, subshell, builtin, func-call, and var-lookup handlers#1331

Open
saracen wants to merge 1 commit into
mvdan:masterfrom
saracen:interp-handler-chains
Open

interp: add stmt, subshell, builtin, func-call, and var-lookup handlers#1331
saracen wants to merge 1 commit into
mvdan:masterfrom
saracen:interp-handler-chains

Conversation

@saracen
Copy link
Copy Markdown

@saracen saracen commented May 4, 2026

ExecHandlers already lets external code wrap external command execution. Apply the same middleware-chain pattern to five more dispatch points so the interpreter can be extended from outside without patching its internals.

StmtHandlers fires around every syntax.Stmt before dispatch. SubshellHandlers fires around each subshell creation site, with a SubshellKind to distinguish background, paren, cmd subst, proc subst, and pipeline. BuiltinHandler registers a name-keyed override for a builtin; BuiltinHandlers wraps all builtin dispatch with middleware. FuncCallHandlers wraps the body of a declared shell function. LookupVarHandlers wraps lookupVar on top of the runner's own special-variable and environment resolution, so middlewares can add or override variables without losing the existing behaviour.

Each chain follows ExecHandlers' shape: middlewares are chained first-to-last, the bottom of the chain is the runner's own behaviour, and a middleware may short-circuit by not calling next. Chain bottoms recover the active runner from ctx, so the chains are built once in Reset and inherited by subshell copies the same way execHandler is.

Also add RunStmts, a top-level helper for dispatching stmts on the runner attached to ctx, useful for handlers that need to execute shell code in the runner's current scope (e.g. a trap body from a Go-side signal handler).

ExecHandlers already lets external code wrap external command
execution. Apply the same middleware-chain pattern to five more
dispatch points so the interpreter can be extended from outside
without patching its internals.

StmtHandlers fires around every syntax.Stmt before dispatch.
SubshellHandlers fires around each subshell creation site, with a
SubshellKind to distinguish background, paren, cmd subst, proc subst,
and pipeline. BuiltinHandler registers a name-keyed override for a
builtin; BuiltinHandlers wraps all builtin dispatch with middleware.
FuncCallHandlers wraps the body of a declared shell function.
LookupVarHandlers wraps lookupVar on top of the runner's own
special-variable and environment resolution, so middlewares can add
or override variables without losing the existing behaviour.

Each chain follows ExecHandlers' shape: middlewares are chained
first-to-last, the bottom of the chain is the runner's own behaviour,
and a middleware may short-circuit by not calling next. Chain bottoms
recover the active runner from ctx, so the chains are built once in
Reset and inherited by subshell copies the same way execHandler is.

Also add RunStmts, a top-level helper for dispatching stmts on the
runner attached to ctx, useful for handlers that need to execute shell
code in the runner's current scope (e.g. a trap body from a Go-side
signal handler).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant