Documentation
¶
Overview ¶
Package interp compiles and runs magusfile sources via the Buzz scripting backend. Owns the host-binding seam, REPL, and compiled-source cache.
Index ¶
- Constants
- Variables
- func AttachSessionObservers(ctx context.Context, sess *buzz.Session, mode string)
- func Available() bool
- func CtxFormTargetKeys(src string) map[string]bool
- func NewBuzzReplSession(ctx context.Context, autoloadDir string) (engine.Session, error)
- func NewBuzzWorkerFunc(src *Source) buzz.WorkerFunc
- func NewHostCallObserver(ctx context.Context) buzz.DirectObserver
- func NewPoolObserver(ctx context.Context) buzz.PoolObserver
- func PrettyPrint(w io.Writer, v engine.Value, opts PrettyOpts)
- func ProjectPathFromContext(ctx context.Context) (string, bool)
- func RegisterBuzzHostBindings(fn BuzzHostBindingsFn)
- func RegisterBuzzSpellImportCheck(fn func(handles []string) error)
- func RemovedAPICall(src string) (call, replacement string, ok bool)
- func RemovedAPINames() []string
- func Repl(ctx context.Context, sess engine.Session, opts ReplOptions) error
- func RunDir(ctx context.Context, dir, target string, extraArgs []string) (any, error)
- func TimeCall(ctx context.Context, mode string, fn func() (vm.Value, error)) (vm.Value, error)
- func TimeExec(ctx context.Context, mode string, fn func() error) error
- func WithCrossDispatch(ctx context.Context, c *CrossDispatch) context.Context
- func WithOverlay(ctx context.Context, files map[string]string) context.Context
- func WithProjectPath(ctx context.Context, path string) context.Context
- func WithSource(ctx context.Context, src *Source) context.Context
- type BuzzHostBindingsFn
- type CrossDispatch
- type PrettyOpts
- type PryContext
- type PryResume
- type ReplOptions
- type Source
- type Target
Constants ¶
const ( ModeMagusfile = "magusfile" ModeSpell = "spell" ModeRepl = "repl" )
Buzz execution modes, the "mode" attribute on magus.buzz.exec/compile.
const TargetContextGlobal = "__magus_target_context"
TargetContextGlobal is the session-global name under which the bindings layer stashes the shared magus.Context value (see bindings.registerAllBuzz). A target function receives it as its first argument; execBuzzSrc fetches it with GetGlobal and prepends it at dispatch. The double underscore keeps it out of the way of any magusfile identifier.
Variables ¶
var ErrNoMagusfile = errors.New("magusfile: not found (no magusfile.buzz or magusfiles/*.buzz in this project); run `magus init` to add one")
var ErrUnknownTarget = errors.New("magusfile: unknown target")
Functions ¶
func AttachSessionObservers ¶ added in v0.2.0
AttachSessionObservers wires the session-scoped compile observer and VM fault hook so sess's parse/check/compile phases, resolved imports, and faults feed the spine under mode. A no-op when telemetry is disabled, leaving sess unobserved.
func Available ¶
func Available() bool
Available reports whether the interp layer can run magusfiles: the Buzz engine is registered and Buzz host bindings are installed. Both are always present in a real magus binary (blank-imported from cmd/magus).
func CtxFormTargetKeys ¶ added in v0.3.0
CtxFormTargetKeys returns the normalized keys of the exported functions in src whose FIRST parameter is annotated `magus\Context` (types.ContextParamAnnotation) - the target contract. execBuzzSrc uses it to enforce that contract at load (an exported function missing the context is rejected with MGS1008) and to prepend the context at dispatch. It does NOT build the graph: the dependency graph is read statically by describe.Extract, which sees ctx-form declarations directly. Best-effort: a parse failure yields nil, matching the extractor's never-error contract.
func NewBuzzReplSession ¶
NewBuzzReplSession creates a Buzz session with host bindings installed, ready for the shared REPL. When autoloadDir is non-empty and a magusfile.buzz is found in or above it, its files are executed first so their top-level definitions are available at the prompt. The returned engine.Session also satisfies the optional REPL/debug interfaces.
func NewBuzzWorkerFunc ¶
func NewBuzzWorkerFunc(src *Source) buzz.WorkerFunc
NewBuzzWorkerFunc returns the buzz.WorkerFunc that creates a pre-warmed Buzz session for src. Safe to call from multiple goroutines because execBuzzSrc reads sources by absolute path and does not acquire chdirMu.
func NewHostCallObserver ¶ added in v0.2.0
func NewHostCallObserver(ctx context.Context) buzz.DirectObserver
NewHostCallObserver returns a DirectObserver that records magus.buzz.host.call for every wrapped native callable, or nil when telemetry is disabled so buzz.WrapDirect returns the callable unchanged and the VM's hot native-dispatch arm is untouched.
func NewPoolObserver ¶ added in v0.2.0
func NewPoolObserver(ctx context.Context) buzz.PoolObserver
NewPoolObserver returns a PoolObserver that reports Buzz session-pool lifecycle (reuse, warm, eviction, idle) to the spine, or nil when telemetry is disabled so the pool runs unobserved. Thread the result onto the dispatch ctx with buzz.WithPoolObserver.
func PrettyPrint ¶
func PrettyPrint(w io.Writer, v engine.Value, opts PrettyOpts)
PrettyPrint writes a human-readable rendering of v to w with cycle detection.
func ProjectPathFromContext ¶
ProjectPathFromContext returns the project path stored by WithProjectPath, and whether one was set.
func RegisterBuzzHostBindings ¶
func RegisterBuzzHostBindings(fn BuzzHostBindingsFn)
RegisterBuzzHostBindings stores the Buzz host-binding function. Called from bindings init().
func RegisterBuzzSpellImportCheck ¶
RegisterBuzzSpellImportCheck stores the validator for `magus/spell/*` imports. Called from bindings init(), the same seam as RegisterBuzzHostBindings.
func RemovedAPICall ¶ added in v0.4.0
RemovedAPICall reports the first removed magusfile API call in src, with the call that replaced it. ok is false when src uses none of them.
Two readings, because a stale magusfile fails in two different places. When src parses, the AST is authoritative and a mention inside a comment or string literal cannot fake a hit. When src does NOT parse, the removed shape may be the very reason (`magus.project.register(fun(p, cb) ...)` predates required parameter annotations, so it dies in the parser with a message about parameter "p"), and a textual scan is the only thing left; it is reached only for a file that is already failing, so at worst it re-explains a broken magusfile with the wrong migration.
func RemovedAPINames ¶ added in v0.4.0
func RemovedAPINames() []string
RemovedAPINames returns the dotted member path of every removed call, without the `magus.` root (e.g. "project.register"). The surface lock test uses it to assert the table never names something the namespace still binds.
func RunDir ¶
RunDir runs target for the project in dir. Returns ErrNoMagusfile or ErrUnknownTarget when not found.
Buzz is the only engine today, so FindAll yields a single source. The loop is the seam a second engine would extend: each source is fully executed (including top-level declarations such as magus.project) before its target registry is consulted, and an unknown target falls through to the next source.
func TimeCall ¶ added in v0.2.0
TimeCall is TimeExec for a value-returning call (Session.CallValue), the target and spell-handler dispatch boundary.
func TimeExec ¶ added in v0.2.0
TimeExec times fn as one Buzz execution under mode, recording exec duration, outcome, and the JIT-run delta when telemetry is active on ctx. With none it runs fn directly, adding no timing to the hot path.
func WithCrossDispatch ¶
func WithCrossDispatch(ctx context.Context, c *CrossDispatch) context.Context
WithCrossDispatch stores c in ctx; bindings retrieve it to run external deps.
func WithOverlay ¶ added in v0.4.0
WithOverlay supplies magusfile CONTENT for absolute paths, read instead of the file on disk. Paths not named here are read normally, and no overlay is the ordinary load.
It exists for the one caller that has to load a workspace whose magusfile it cannot read: `magus vcs resolve`, during a merge that left conflict markers in the magusfile itself. Everything that command does rests on the declarations - which target rebuilds which output - so a magusfile it cannot parse leaves it unable to settle even the conflicts it does own. The committed side of the merge is a complete, parseable copy of exactly those declarations, and reading it here is what lets the command do its half of the work while the hand-written conflict waits for a human.
An overlay, rather than swapping the file on disk and restoring it: a crash between the two would leave the user's conflict replaced by one side of it, and the merge state is not something a tool should be able to lose on the way to reporting an error.
func WithProjectPath ¶
WithProjectPath stores the workspace-relative path of the project whose magusfile is being parsed, so magus.project(fn) (the contextual form with no explicit path) can default to "this project".
Types ¶
type BuzzHostBindingsFn ¶
type BuzzHostBindingsFn func(ctx context.Context, sess *buzz.Session, targets map[string]vm.Callable, exports map[string]vm.Value, parseMode bool)
BuzzHostBindingsFn registers Go-backed host modules into a Buzz session. targets is the session's dispatchable target registry; exports maps each canonical target key to the exported function value itself, so ctx.needs can verify a passed function IS the exported target (nil when the session has no export discovery, e.g. the REPL). parseMode=true collects names only.
type CrossDispatch ¶
type CrossDispatch struct {
// contains filtered or unexported fields
}
CrossDispatch runs cross-project target dependencies (declared via a project import, then referenced as <alias>.<target>) at most once per run and detects cross-project cycles. One instance is installed in the run context and shared across every target, so two targets that both need the same remote target run it once; Dispatch is safe for concurrent use.
func CrossDispatchFromContext ¶
func CrossDispatchFromContext(ctx context.Context) *CrossDispatch
CrossDispatchFromContext returns the coordinator stored by WithCrossDispatch, or nil — e.g. in describe/parse, where external deps stay graph-only and must not run.
func NewCrossDispatch ¶
func NewCrossDispatch() *CrossDispatch
NewCrossDispatch returns an empty coordinator for one run.
func (*CrossDispatch) Dispatch ¶
func (c *CrossDispatch) Dispatch(ctx context.Context, dir, target string) error
Dispatch runs target in the project rooted at dir, at most once per run. A second caller for the same (dir, target) blocks on and shares the first run's result. A (dir, target) already on the current call stack is a cross-project cycle and errors instead of deadlocking.
The caller is responsible for yielding any concurrency slot it holds before calling Dispatch (the remote run needs slots of its own); see the binding's use of proc.RunChildSync.
type PrettyOpts ¶
type PrettyOpts struct {
MaxDepth int // recursion limit; default 4
Indent string // per-level indent; default " "
Color bool // ANSI color; REPL sets based on stream + NO_COLOR
}
PrettyOpts configures the pretty-printer.
type PryContext ¶
type PryContext struct {
File string // source file of the pry() call
Line int
Func string // enclosing function name when known
Frames []engine.Frame // call stack, innermost first
}
PryContext describes the call site and stack at a magus.pry() breakpoint.
type PryResume ¶
type PryResume int
PryResume tells the debugger how to proceed after a breakpoint.
func Pry ¶
func Pry(ctx context.Context, sess engine.Session, pctx PryContext, opts ReplOptions) (PryResume, error)
Pry runs the pry REPL on sess. On .step/.next/.finish the REPL exits and the caller re-enters Pry when the engine's one-shot step hook fires.
type ReplOptions ¶
type ReplOptions struct {
WorkDir string // working directory for the session; defaults to process cwd
Stdin io.Reader
Stdout io.Writer
Stderr io.Writer
Banner string // printed once before the first prompt
Locals map[string]engine.Value // injected as globals before the loop
// Candidates supplies completion candidates the interpreter cannot know:
// workspace target names, project paths, host module names. Optional.
//
// It is a callback rather than a slice because the workspace is the caller's to
// read, and reading it once at startup would go stale in a session long enough
// to matter - which is most of them, since a REPL is where you sit while editing
// the magusfile it is describing.
Candidates func() []string
}
ReplOptions configures a REPL session.
type Source ¶
type Source struct {
Dir string // absolute directory containing the magusfile
Files []string // absolute source paths in load order
Engine string // engine name ("buzz"); inferred from file extensions by Find
}
Source describes a located magusfile source.
func FindAll ¶
FindAll locates every magusfile source in dir grouped by engine, in priority order. Returns ErrNoMagusfile when nothing is found; errors when single-file and magusfiles/ forms coexist.
func SourceFromContext ¶
SourceFromContext retrieves the Source stored by WithSource, or nil.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package bindings registers the Go-backed modules (magus, std: os, platform, fs, vcs, env, crypto, json, log, http, archive) available to every magusfile script.
|
Package bindings registers the Go-backed modules (magus, std: os, platform, fs, vcs, env, crypto, json, log, http, archive) available to every magusfile script. |
|
gen
Package gen is the generated native-to-Buzz adapter layer.
|
Package gen is the generated native-to-Buzz adapter layer. |
|
Package engine defines the Engine and Session interfaces that all scripting engine implementations must satisfy, along with the engine registry.
|
Package engine defines the Engine and Session interfaces that all scripting engine implementations must satisfy, along with the engine registry. |
|
buzz
Package buzz adapts the standalone Buzz interpreter (magus/gopherbuzz) to magus's engine.Engine/engine.Session interfaces and registers it under the "buzz" key.
|
Package buzz adapts the standalone Buzz interpreter (magus/gopherbuzz) to magus's engine.Engine/engine.Session interfaces and registers it under the "buzz" key. |