Documentation
¶
Overview ¶
Package macros extends the compiler with a @macro engine.
A @macro directive stores a declaration; OnPreprocess turns each declaration into a PrimaryExtension dispatching on TokAtPrompt; and every expansion re-enters the parser with the caller's arguments substituted into the body.
Typical use:
@macro greet(name) { runtime.const @{ value: $name } }
@greet("World") // expands to: runtime.const @{ value: "World" }
Without this bundle, @name is "unexpected token @name".
Index ¶
Constants ¶
const DeclarationKey = "macros"
DeclarationKey is the meta slot where @macro declarations land before OnPreprocess converts them to a PrimaryExtension.
const ID = "macros"
Variables ¶
var DefaultBuiltinMacros = []Declaration{ { Name: "check_required", Params: []string{"field"}, Body: `assert(.$field != nil && .$field != "", "field '" + "$field" + "' is required")`, }, { Name: "check_choice", Params: []string{"field", "choices"}, Body: `assert(.$field in $choices, "field '" + "$field" + "' must be one of " + string($choices))`, }, { Name: "check_range", Params: []string{"field", "min", "max"}, Body: `assert(.$field >= $min && .$field <= $max, "field '" + "$field" + "' must be between " + string($min) + " and " + string($max))`, }, }
DefaultBuiltinMacros provides standard reusable validation and guard macros. In expr-lang, membership testing uses the 'in' operator rather than contains().
var Directive = core.Directive{
Name: "macro",
Example: "@macro greet(name) {\n runtime.const @{ value: $name }\n}",
Handler: handleDirective,
}
Directive parses `@macro name(p1, p2) { body }` into a Declaration appended to meta[DeclarationKey]. Duplicate names are a compile error, not a silent override.
Every declaration is also checked against two static limits at declaration time — body size and recursion — so a bad macro is rejected before any invocation. Expansion depth is bounded at parse time by macroPrimary, not here: it depends on invocation order, not on the declaration order.
Functions ¶
Types ¶
type Declaration ¶
Declaration is the parsed form of `@macro name(params) { body }`.
DefLine and BodyLine are 1-based file lines. DefLine is the line of the @macro directive itself. BodyLine is the line where body content begins — the same line for an inline body like `@macro x { ... }`, or the line after the opening brace for a multi-line body. They are used to remap parse errors from inside the expanded body back to the correct file position so diagnostics are clickable.
type Expansion ¶ added in v0.14.0
type Expansion struct {
Macro string
DefLine int
InvokeLine int
Where string // "top-level" or "pipeline <name>"
Body string
Err error
}
Expansion is one recorded macro invocation and its substituted body. DefLine and InvokeLine are 1-based. For an expansion that occurred at the top level, InvokeLine is file-relative. For an expansion inside a pipeline body, InvokeLine is body-relative and Where names the pipeline.
type Trace ¶ added in v0.14.0
type Trace struct {
// contains filtered or unexported fields
}
Trace records every macro expansion that occurs during one parse. Install it into the parser's context before Parse; if no trace is installed, expansion runs without recording anything.
func (*Trace) Expansions ¶ added in v0.14.0
Expansions returns a copy of the recorded expansions, in the order they completed.