syntax

package
v1.17.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 17, 2026 License: Apache-2.0 Imports: 6 Imported by: 0

Documentation

Overview

Package syntax implements Scheme syntax representation with hygiene support.

The package wraps Scheme values with source location and scope information:

Syntax Types

All syntax types implement SyntaxValue, which provides:

  • [SyntaxValue.SourceContext]: source location, scopes, and origin
  • [SyntaxValue.Unwrap]: shallow unwrap to underlying value
  • [SyntaxValue.UnwrapAll]: deep recursive unwrap

Hygiene

The package implements Flatt's "sets of scopes" model for macro hygiene:

  • Scope: unique identifier with optional rebinding flag
  • [SourceContext.Scopes]: scope set attached to syntax objects
  • ScopesMatch: binding/reference scope subset check

Source Tracking

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func EqualTo

func EqualTo(a, b SyntaxValue) bool

EqualTo compares two syntax values for equality, handling nil and pointer identity.

func FormatOriginChain

func FormatOriginChain(origin *OriginInfo, maxDepth int) string

FormatOriginChain renders a macro expansion chain as a string. maxDepth limits how many expansions to show (0 = unlimited).

func IsSyntaxEmptyList

func IsSyntaxEmptyList(v SyntaxValue) bool

IsSyntaxEmptyList returns true if the value is the syntax empty list.

Delegates to values.IsEmptyList — after the empty-list duality merge, the syntax empty list is the same singleton as values.EmptyList, and values.IsEmptyList works on any Tuple. This restores symmetric equality (previously the strict pointer-type assertion produced #f for `(equal? (syntax ()) '())`, contrary to Chez).

func IsSyntaxList

func IsSyntaxList(v SyntaxValue) bool

IsSyntaxList returns true if the value is a proper syntax list.

func IsSyntaxVoid

func IsSyntaxVoid(v SyntaxValue) bool

IsSyntaxVoid returns true if the value is nil or void.

func ScopesCompatible added in v1.10.7

func ScopesCompatible(bindingScopes, useScopes []*Scope) bool

ScopesCompatible checks whether a binding's scopes can match a reference's. A binding with no scopes matches any reference.

func ScopesMatch

func ScopesMatch(useScopes, bindingScopes []*Scope) bool

ScopesMatch checks if two sets of scopes are compatible for binding resolution. See values.ScopesMatch for the full hygiene-model documentation.

func SyntaxWalk added in v1.5.0

func SyntaxWalk(ctx context.Context, o SyntaxValue, fn func(SyntaxValue) error) error

SyntaxWalk iterates over a syntax tuple, calling fn for each element. It is a convenience wrapper around SyntaxForEach for callers that only need the element value (ignoring the index and hasNext arguments).

func UnwrapAllShared

func UnwrapAllShared(sv SyntaxValue, cache map[SyntaxValue]values.Value) values.Value

UnwrapAllShared recursively unwraps a syntax value while preserving object identity. This is essential for datum labels (R7RS §2.4) where #n# must refer to the exact same object as #n=. The cache parameter tracks already-unwrapped syntax values to ensure the same SyntaxValue always unwraps to the same values.Value. This also handles circular structures by pre-registering placeholders before recursing.

Types

type FormArityError added in v1.17.0

type FormArityError struct {
	Name string
	// Min and Max are the element-count bounds (keyword included); Max < 0
	// means unbounded. Got is the actual element count.
	Min, Max, Got int
}

FormArityError reports that a form is a proper list of the wrong length. It is the one FormParts failure that carries structured data — the bounds and the actual count — because callers re-render it in their own vocabulary: compilation reports keyword-inclusive "element" counts (FormParts counts the form keyword at index 0), while the validator restates them as keyword- exclusive "argument" counts. Structural failures (not a list, improper list) carry no such data and are returned as plain ErrInvalidSyntax wraps, not as this type. FormArityError Unwraps to werr.ErrInvalidSyntax so callers keep matching with errors.Is regardless of the failure mode.

func (*FormArityError) Error added in v1.17.0

func (e *FormArityError) Error() string

func (*FormArityError) Unwrap added in v1.17.0

func (*FormArityError) Unwrap() error

Unwrap reports ErrInvalidSyntax so an arity failure matches with errors.Is(err, werr.ErrInvalidSyntax), like the structural failures.

type OriginInfo

type OriginInfo = values.OriginInfo

OriginInfo tracks macro expansion chains. Defined in package values alongside SourceContext.

type ResolvedRef added in v1.5.0

type ResolvedRef interface {
	values.Value
}

ResolvedRef is the type for a pre-resolved binding stored on a SyntaxSymbol. The concrete type is always *environment.GlobalIndex; this interface exists solely to break the circular import between internal/syntax and environment.

type Scope

type Scope = values.Scope

Scope is the macro-hygiene identity marker. Defined in package values alongside SourceContext (the empty-list duality merge).

func FlipScopeInSet

func FlipScopeInSet(scopes []*Scope, target *Scope) []*Scope

FlipScopeInSet toggles the presence of a scope in a set. This is the core operation for syntax-local-introduce.

func NewRebindingScope

func NewRebindingScope() *Scope

NewRebindingScope creates a new scope that can potentially rebind auxiliary syntax.

func NewRebindingScopeWithLabel added in v1.6.0

func NewRebindingScopeWithLabel(label string) *Scope

NewRebindingScopeWithLabel creates a new rebinding scope with a label.

func NewScope

func NewScope() *Scope

NewScope creates a new scope with unique identity for hygiene tracking.

func NewScopeWithLabel added in v1.6.0

func NewScopeWithLabel(label string) *Scope

NewScopeWithLabel creates a new scope with a human-readable label for debugging.

type SourceContext

type SourceContext = values.SourceContext

SourceContext is the source-location-and-hygiene metadata type. It is defined in package values so that values.emptyListType can implement values.SyntaxValue directly (the empty-list duality merge — see values/syntax_value.go and the comment in values/source_context.go).

func NewSourceContext

func NewSourceContext(text, file string, start, end SourceIndexes) *SourceContext

NewSourceContext constructs a SourceContext.

func NewZeroValueSourceContext

func NewZeroValueSourceContext() *SourceContext

NewZeroValueSourceContext constructs an empty SourceContext.

type SourceIndexes

type SourceIndexes = values.SourceIndexes

SourceIndexes is the source-position type. It is defined in package values so that values.emptyListType can implement values.SyntaxValue directly (the empty-list duality merge — see values/syntax_value.go).

func NewSourceIndexes

func NewSourceIndexes(index, column, line int) SourceIndexes

NewSourceIndexes constructs a SourceIndexes at the given position.

type SyntaxComment

type SyntaxComment struct {
	Text string
	// contains filtered or unexported fields
}

SyntaxComment represents a source comment (line or block) with source location.

func NewSyntaxComment

func NewSyntaxComment(text string, sctx *SourceContext) *SyntaxComment

NewSyntaxComment creates a new syntax comment with the given text and source context.

func (*SyntaxComment) AddScope

func (p *SyntaxComment) AddScope(scope *Scope) SyntaxValue

AddScope returns the comment unchanged (comments don't participate in hygiene).

func (*SyntaxComment) EqualTo

func (p *SyntaxComment) EqualTo(v values.Value) bool

EqualTo returns true if the comments have the same text.

func (*SyntaxComment) IsVoid

func (p *SyntaxComment) IsVoid() bool

IsVoid returns true if the comment is nil.

func (*SyntaxComment) SchemeString

func (p *SyntaxComment) SchemeString() string

SchemeString returns the comment text.

func (*SyntaxComment) Unwrap

func (p *SyntaxComment) Unwrap() values.Value

func (*SyntaxComment) UnwrapAll

func (p *SyntaxComment) UnwrapAll() values.Value

UnwrapAll returns the comment text as a string value.

type SyntaxDatumComment

type SyntaxDatumComment struct {
	Label string
	Value SyntaxValue
	// contains filtered or unexported fields
}

SyntaxDatumComment represents a datum comment (#;datum).

func NewSyntaxDatumComment

func NewSyntaxDatumComment(label string, value SyntaxValue, sctx *SourceContext) *SyntaxDatumComment

NewSyntaxDatumComment creates a new datum comment.

func (*SyntaxDatumComment) AddScope

func (p *SyntaxDatumComment) AddScope(_ *Scope) SyntaxValue

AddScope returns the comment unchanged (comments don't participate in hygiene).

func (*SyntaxDatumComment) EqualTo

func (p *SyntaxDatumComment) EqualTo(v values.Value) bool

EqualTo compares datum comments by label and value.

func (*SyntaxDatumComment) IsVoid

func (p *SyntaxDatumComment) IsVoid() bool

IsVoid returns true if the comment is nil.

func (*SyntaxDatumComment) SchemeString

func (p *SyntaxDatumComment) SchemeString() string

SchemeString returns a string representation of the datum comment.

func (*SyntaxDatumComment) Unwrap

func (p *SyntaxDatumComment) Unwrap() values.Value

func (*SyntaxDatumComment) UnwrapAll

func (p *SyntaxDatumComment) UnwrapAll() values.Value

UnwrapAll recursively unwraps the commented value.

type SyntaxDatumLabel

type SyntaxDatumLabel struct {
	Label int
	// contains filtered or unexported fields
}

SyntaxDatumLabel represents a datum label reference (#n#).

func NewSyntaxDatumLabel

func NewSyntaxDatumLabel(label int, sctx *SourceContext) *SyntaxDatumLabel

NewSyntaxDatumLabel creates a new datum label reference with the given number.

func (*SyntaxDatumLabel) AddScope

func (p *SyntaxDatumLabel) AddScope(_ *Scope) SyntaxValue

AddScope returns the label unchanged (labels don't participate in hygiene).

func (*SyntaxDatumLabel) EqualTo

func (p *SyntaxDatumLabel) EqualTo(v values.Value) bool

EqualTo returns true if the labels have the same number.

func (*SyntaxDatumLabel) IsVoid

func (p *SyntaxDatumLabel) IsVoid() bool

IsVoid returns true if the label is nil.

func (*SyntaxDatumLabel) SchemeString

func (p *SyntaxDatumLabel) SchemeString() string

SchemeString returns the label number as a string.

func (*SyntaxDatumLabel) Unwrap

func (p *SyntaxDatumLabel) Unwrap() values.Value

func (*SyntaxDatumLabel) UnwrapAll

func (p *SyntaxDatumLabel) UnwrapAll() values.Value

UnwrapAll returns the label number as an integer value.

type SyntaxDatumLabelAssignment

type SyntaxDatumLabelAssignment struct {
	Label int
	Value values.Value
	// contains filtered or unexported fields
}

SyntaxDatumLabelAssignment represents a datum label assignment (#n=datum).

func NewSyntaxDatumLabelAssignment

func NewSyntaxDatumLabelAssignment(label int, value values.Value, sctx *SourceContext) *SyntaxDatumLabelAssignment

NewSyntaxDatumLabelAssignment creates a new datum label assignment.

func (*SyntaxDatumLabelAssignment) AddScope

AddScope returns the assignment unchanged (labels don't participate in hygiene).

func (*SyntaxDatumLabelAssignment) EqualTo

EqualTo returns true if both assignments are the same object.

func (*SyntaxDatumLabelAssignment) IsVoid

func (p *SyntaxDatumLabelAssignment) IsVoid() bool

IsVoid returns true if the assignment is nil.

func (*SyntaxDatumLabelAssignment) SchemeString

func (p *SyntaxDatumLabelAssignment) SchemeString() string

SchemeString returns the Scheme representation of the label.

func (*SyntaxDatumLabelAssignment) Unwrap

func (*SyntaxDatumLabelAssignment) UnwrapAll

func (p *SyntaxDatumLabelAssignment) UnwrapAll() values.Value

UnwrapAll recursively unwraps the assigned value.

type SyntaxDirective

type SyntaxDirective struct {
	Name string
	// contains filtered or unexported fields
}

SyntaxDirective represents a reader directive (#!fold-case, etc.).

func NewSyntaxDirective

func NewSyntaxDirective(name string, sctx *SourceContext) *SyntaxDirective

NewSyntaxDirective creates a new reader directive with the given name.

func (*SyntaxDirective) AddScope

func (p *SyntaxDirective) AddScope(_ *Scope) SyntaxValue

AddScope returns the directive unchanged (directives don't participate in hygiene).

func (*SyntaxDirective) EqualTo

func (p *SyntaxDirective) EqualTo(v values.Value) bool

EqualTo returns true if both directives have the same name.

func (*SyntaxDirective) IsVoid

func (p *SyntaxDirective) IsVoid() bool

IsVoid returns true if the directive is nil.

func (*SyntaxDirective) SchemeString

func (p *SyntaxDirective) SchemeString() string

SchemeString returns the directive name.

func (*SyntaxDirective) Unwrap

func (p *SyntaxDirective) Unwrap() values.Value

func (*SyntaxDirective) UnwrapAll

func (p *SyntaxDirective) UnwrapAll() values.Value

UnwrapAll returns the directive name as a string value.

type SyntaxForEachFunc

type SyntaxForEachFunc = values.SyntaxForEachFunc

SyntaxForEachFunc is the callback type for iterating over syntax tuples.

type SyntaxObject

type SyntaxObject struct {
	// contains filtered or unexported fields
}

SyntaxObject wraps a non-compound Scheme value with source context.

func NewSyntaxObject

func NewSyntaxObject(v values.Value, sctx *SourceContext) *SyntaxObject

NewSyntaxObject creates a new SyntaxObject wrapping the given value and source context. It panics if the value is already a syntax value to prevent double-wrapping.

func (*SyntaxObject) Datum

func (p *SyntaxObject) Datum() values.Value

Datum returns the underlying datum of the syntax object.

func (*SyntaxObject) EqualTo

func (p *SyntaxObject) EqualTo(v values.Value) bool

EqualTo performs pointer comparison only, matching Chez Scheme/Racket behavior. Two syntax objects are equal? only if they are the same object. For value comparison of syntax objects, use bound-identifier=? or free-identifier=?.

func (*SyntaxObject) IsVoid

func (p *SyntaxObject) IsVoid() bool

IsVoid returns true if the syntax object is nil.

func (*SyntaxObject) SchemeString

func (p *SyntaxObject) SchemeString() string

SchemeString returns the Scheme representation of the syntax object.

func (*SyntaxObject) Unwrap

func (p *SyntaxObject) Unwrap() values.Value

func (*SyntaxObject) UnwrapAll

func (p *SyntaxObject) UnwrapAll() values.Value

UnwrapAll recursively unwraps all syntax wrappers and returns the underlying value.

type SyntaxPair

type SyntaxPair struct {
	Values [2]SyntaxValue
	// contains filtered or unexported fields
}

SyntaxPair wraps a Scheme pair (cons cell) with source context.

func NewSyntaxCons

func NewSyntaxCons(v0, v1 SyntaxValue, sctx *SourceContext) *SyntaxPair

NewSyntaxCons creates a new syntax pair (cons cell).

func (*SyntaxPair) AddScope

func (p *SyntaxPair) AddScope(scope *Scope) SyntaxValue

AddScope recursively propagates a scope to all nested symbols.

This implements scope propagation for Flatt's "sets of scopes" hygiene. When a macro expands, the intro scope must be added to all identifiers (symbols) in the expansion. This method walks the pair structure and calls AddScope on each element, ultimately reaching the symbols.

Only symbols store scopes for hygiene resolution. Pairs just propagate.

func (*SyntaxPair) Append

func (p *SyntaxPair) Append(vs values.Value) values.Value

Append appends a value to the end of the list.

func (*SyntaxPair) AsSyntaxVector

func (p *SyntaxPair) AsSyntaxVector() *SyntaxVector

AsSyntaxVector converts the list to a syntax vector.

func (*SyntaxPair) AsVector

func (p *SyntaxPair) AsVector() *values.Vector

AsVector converts the SyntaxPair (assumed to be a proper list) into a Vector of unwrapped values.

func (*SyntaxPair) Car

func (p *SyntaxPair) Car() values.Value

Car returns the car of the pair.

func (*SyntaxPair) Cdr

func (p *SyntaxPair) Cdr() values.Value

Cdr returns the cdr of the pair.

func (*SyntaxPair) EqualTo

func (p *SyntaxPair) EqualTo(o values.Value) bool

EqualTo performs pointer comparison only, matching Chez Scheme/Racket behavior. Two syntax objects are equal? only if they are the same object. For value comparison of syntax objects, use bound-identifier=? or free-identifier=?.

func (*SyntaxPair) ForEach

func (p *SyntaxPair) ForEach(ctx context.Context, fn values.ForEachFunc) (values.Value, error)

ForEach iterates over the elements of the list.

func (*SyntaxPair) IsEmptyList

func (*SyntaxPair) IsEmptyList() bool

IsEmptyList returns false. A *SyntaxPair is never the empty list; SyntaxEmptyList (an alias for the values.EmptyList singleton) is the only representation of the empty list at the syntax phase.

func (*SyntaxPair) IsList

func (p *SyntaxPair) IsList() bool

IsList returns true if the pair forms a proper list.

func (*SyntaxPair) IsPair

func (p *SyntaxPair) IsPair() bool

IsPair returns true; SyntaxPair is always a pair.

func (*SyntaxPair) IsVoid

func (p *SyntaxPair) IsVoid() bool

IsVoid returns true if the pair is nil.

func (*SyntaxPair) Length

func (p *SyntaxPair) Length() int

Len returns the length of the list.

func (*SyntaxPair) SchemeString

func (p *SyntaxPair) SchemeString() string

SchemeString returns a string representation of the syntax pair.

func (*SyntaxPair) SetCar

func (p *SyntaxPair) SetCar(v values.Value)

SetCar sets the car of the pair.

func (*SyntaxPair) SetCdr

func (p *SyntaxPair) SetCdr(v values.Value)

SetCdr sets the cdr of the pair.

func (*SyntaxPair) SetSyntaxCar

func (p *SyntaxPair) SetSyntaxCar(v SyntaxValue)

SetSyntaxCar sets the car of the pair to a syntax value.

func (*SyntaxPair) SetSyntaxCdr

func (p *SyntaxPair) SetSyntaxCdr(v SyntaxValue)

SetSyntaxCdr sets the cdr of the pair to a syntax value.

func (*SyntaxPair) SyntaxAppend

func (p *SyntaxPair) SyntaxAppend(vs SyntaxValue) SyntaxValue

SyntaxAppend appends a syntax value to the end of the list.

func (*SyntaxPair) SyntaxCar

func (p *SyntaxPair) SyntaxCar() SyntaxValue

SyntaxCar returns the car as a syntax value.

func (*SyntaxPair) SyntaxCdr

func (p *SyntaxPair) SyntaxCdr() SyntaxValue

SyntaxCdr returns the cdr as a syntax value.

func (*SyntaxPair) SyntaxForEach

func (p *SyntaxPair) SyntaxForEach(ctx context.Context, fn SyntaxForEachFunc) (SyntaxValue, error)

SyntaxForEach iterates over the syntax elements of the list.

func (*SyntaxPair) Unwrap

func (p *SyntaxPair) Unwrap() values.Value

Unwrap returns a regular Scheme pair without recursively unwrapping.

func (*SyntaxPair) UnwrapAll

func (p *SyntaxPair) UnwrapAll() values.Value

UnwrapAll recursively unwraps the pair and returns a regular Scheme pair.

type SyntaxSymbol

type SyntaxSymbol struct {
	Sym *values.Symbol

	// ResolvedBinding holds a pre-resolved binding for free identifiers in macro templates.
	// This is set during macro expansion for identifiers that should resolve to bindings
	// in the macro's definition environment rather than the use-site environment.
	// Type: *environment.GlobalIndex (satisfies ResolvedRef via values.Value).
	// nil for normal symbols; only set for free identifiers from macros.
	ResolvedBinding ResolvedRef
	// contains filtered or unexported fields
}

SyntaxSymbol wraps a Scheme symbol with source context and hygiene scopes.

func NewSyntaxSymbol

func NewSyntaxSymbol(key string, sctx *SourceContext) *SyntaxSymbol

NewSyntaxSymbol creates a new syntax symbol from a key string.

func NewSyntaxSymbolForSymbol

func NewSyntaxSymbolForSymbol(sym *values.Symbol, sctx *SourceContext) *SyntaxSymbol

NewSyntaxSymbolForSymbol creates a new syntax symbol from an existing symbol.

func NewSyntaxSymbolForSyntaxSymbol

func NewSyntaxSymbolForSyntaxSymbol(sym *SyntaxSymbol, sctx *SourceContext) *SyntaxSymbol

NewSyntaxSymbolForSyntaxSymbol creates a new syntax symbol with a different source context.

func (*SyntaxSymbol) AddScope

func (p *SyntaxSymbol) AddScope(scope *Scope) SyntaxValue

AddScope returns a new SyntaxSymbol with an additional scope. This is the core operation for implementing hygiene in Flatt's "sets of scopes" model. When a macro expands, an "intro scope" is added to all identifiers in the expansion. This scope distinguishes macro-introduced identifiers from user-provided ones.

The method returns a NEW SyntaxSymbol (syntax objects are immutable) with the scope added to its SourceContext. The SyntaxValue return type supports recursive scope propagation through nested syntax structures.

Example: When swap! macro introduces "tmp", that "tmp" gets the macro's intro scope. A user's "tmp" at the call site doesn't have this scope, so they're distinguished during variable resolution (see ScopesMatch in scope_utils.go).

func (*SyntaxSymbol) Datum

func (p *SyntaxSymbol) Datum() *values.Symbol

Datum returns the underlying symbol.

func (*SyntaxSymbol) EqualTo

func (p *SyntaxSymbol) EqualTo(o values.Value) bool

EqualTo performs pointer comparison only, matching Chez Scheme/Racket behavior. Two syntax objects are equal? only if they are the same object. For value comparison of syntax objects, use bound-identifier=? or free-identifier=?.

func (*SyntaxSymbol) IsVoid

func (p *SyntaxSymbol) IsVoid() bool

IsVoid returns true if the syntax symbol is nil.

func (*SyntaxSymbol) Key added in v1.17.0

func (p *SyntaxSymbol) Key() string

Key returns the underlying symbol's name. For void symbols it returns "".

func (*SyntaxSymbol) SchemeString

func (p *SyntaxSymbol) SchemeString() string

SchemeString returns a string representation of the syntax symbol.

func (*SyntaxSymbol) Scopes

func (p *SyntaxSymbol) Scopes() []*Scope

Scopes returns the scopes of this syntax symbol. Always returns a non-nil slice (empty when the symbol has no scopes). This guarantees that callers passing Scopes() to environment.GetBinding trigger scope checking rather than the "match any" nil-scopes path.

func (*SyntaxSymbol) Unwrap

func (p *SyntaxSymbol) Unwrap() values.Value

func (*SyntaxSymbol) UnwrapAll

func (p *SyntaxSymbol) UnwrapAll() values.Value

UnwrapAll returns the underlying symbol value.

func (*SyntaxSymbol) WithResolvedBinding

func (p *SyntaxSymbol) WithResolvedBinding(binding ResolvedRef) *SyntaxSymbol

WithResolvedBinding returns a new SyntaxSymbol with the given pre-resolved binding. This is used during macro expansion to tag free identifiers with their definition-site bindings, enabling proper resolution across library boundaries.

type SyntaxTuple

type SyntaxTuple = values.SyntaxTuple

SyntaxTuple is the interface for syntax lists (pairs and vectors). Defined in package values so that values.emptyListType can satisfy it.

var (

	// SyntaxEmptyList is the empty list singleton at the syntax phase.
	// It is the same singleton as values.EmptyList — the empty list has no
	// symbols, scopes, or source-attachable hygiene content, so the
	// value-level singleton serves both phases (matching Chez's
	// `(equal? (syntax ()) '()) → #t`).
	SyntaxEmptyList SyntaxTuple = values.SyntaxEmptyList
)

type SyntaxValue

type SyntaxValue = values.SyntaxValue

SyntaxValue is the interface for all syntax objects. Defined in package values so that values.emptyListType can satisfy it directly (the empty-list duality merge — see values/syntax_value.go).

var SyntaxVoid SyntaxValue = syntaxVoidType{}

SyntaxVoid is the singleton syntax void value.

func AddScopeToSyntax

func AddScopeToSyntax(stx SyntaxValue, scope *Scope) SyntaxValue

AddScopeToSyntax adds a scope to a syntax object. Returns a new syntax object with the scope added. This is used by syntax-local-identifier-as-binding to mark identifiers as binding sites. Only symbols and pairs receive scopes; self-evaluating literals (SyntaxObject) are returned unchanged.

func FlipScope

func FlipScope(stx SyntaxValue, scope *Scope) SyntaxValue

FlipScope toggles the presence of a scope on a syntax object. Returns a new syntax object with the scope flipped. This is used by syntax-local-introduce to make introduced identifiers behave as if they came from the macro use site.

func FormParts added in v1.17.0

func FormParts(form SyntaxValue, name string, minLen, maxLen int) ([]SyntaxValue, error)

FormParts destructures a fixed-shape syntax form into its positional elements, validating that the form is a proper list of acceptable length.

It replaces the recurring hand-rolled "assert *SyntaxPair, take car, assert cdr, ..." chains used by special-form compilers and expanders. name is the form name used in error messages. minLen and maxLen bound the number of elements (set maxLen to -1 for an unbounded upper limit; set minLen == maxLen for an exact count). All elements are counted — callers that keep the form keyword at element 0 should include it in the bounds.

On success it returns the elements in source order. On a structural failure (not a list, improper list) it returns a nil slice and an ErrInvalidSyntax wrap naming the form. On an arity mismatch it returns a nil slice and a *FormArityError carrying the bounds and actual count; callers add source context. Both error forms match errors.Is(err, werr.ErrInvalidSyntax).

Call sites cluster into three consumption paths (grep FormParts / formSingleArg / formPrologue for the authoritative list):

  • Directly, from fixed-arity special-form compilers and expanders in machine/compilation: define-syntax (both the top-level CompileDefineSyntax and the body-path compileDefineSyntaxFromSyntax), er-macro-transformer, and the (rename internal external) export specs (compile path and library-summary index).
  • Via formSingleArg, the arity-1 convenience wrapper, for single-argument forms: syntax, quasisyntax, and the (description <string>) forms.
  • Via internal/validate.formPrologue, which shifts these keyword-inclusive element bounds to keyword-exclusive "argument" bounds and restates a *FormArityError in "argument" vocabulary; it backs the core-form validators (if, lambda, set!, quote, begin, dynamic-wind, apply, ...).

func SyntaxForEach

func SyntaxForEach(ctx context.Context, o SyntaxValue, fn func(ctx context.Context, i int, hasNext bool, v SyntaxValue) error) (SyntaxValue, error)

SyntaxForEach iterates over a syntax tuple, calling fn for each element.

func SyntaxList

func SyntaxList(sc *SourceContext, os ...SyntaxValue) SyntaxValue

SyntaxList constructs a syntax list from the given elements. The sc parameter provides a fallback source context for the list container. Each intermediate pair uses the source context of its car element when available, preserving per-element source location information for better error reporting.

type SyntaxVector

type SyntaxVector = values.SyntaxVector

SyntaxVector wraps a Scheme vector with source context. Defined in package values (the empty-list duality merge — see values/syntax_vector.go). Methods that need to traverse concrete syntax types defined in this package (AddScope, UnwrapAll) dispatch via hooks registered at init time below.

func NewSyntaxVector

func NewSyntaxVector(sc *SourceContext, vs ...SyntaxValue) *SyntaxVector

NewSyntaxVector creates a new syntax vector with the given source context and elements.

Directories

Path Synopsis
Package syntaxtest provides test helpers for the syntax package.
Package syntaxtest provides test helpers for the syntax package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL