evaluator

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Aug 23, 2026 License: MIT Imports: 27 Imported by: 0

Documentation

Overview

Package evaluator contains the pure, per-call JSONata evaluator.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DecodeJSON

func DecodeJSON(data []byte) (any, error)

func DecodeJSONWithOptions

func DecodeJSONWithOptions(data []byte, options Options) (any, error)

DecodeJSONWithOptions decodes JSON under the same synchronous runtime controls used by evaluation. Checks run before decoder reads, so a canceled context or exhausted budget stops parsing before the full value is built.

func Eval

func Eval(n syntax.Node, input any) (any, error)

func EvalBindings

func EvalBindings(n syntax.Node, input any, bindings map[string]any) (any, error)

EvalBindings evaluates with an isolated binding map. Both "name" and "$name" keys are accepted because fixtures and compatibility callers use both forms.

func EvalBindingsWithOptions

func EvalBindingsWithOptions(n syntax.Node, input any, bindings map[string]any, options Options) (any, error)

func EvalBytesWithOptions

func EvalBytesWithOptions(n syntax.Node, data []byte, options Options) (any, error)

EvalBytesWithOptions decodes and evaluates with one runtime. Decoded input is already evaluator-owned, so it bypasses the public-input normalization copy while bindings and evaluation continue to share the same budget.

func EvalNoInputBindingsWithOptions

func EvalNoInputBindingsWithOptions(n syntax.Node, bindings map[string]any, options Options) (any, error)

func EvalNoInputWithOptions

func EvalNoInputWithOptions(n syntax.Node, options Options) (any, error)

EvalNoInputWithOptions evaluates with the JSONata empty input sequence. This is distinct from EvalWithOptions with nil, which represents JSON null.

func EvalStaticComparison

func EvalStaticComparison(plan *StaticComparisonPlan, input any) (any, bool)

EvalStaticComparison returns ok=false whenever normalisation or JSONata sequence semantics could affect the answer. In that case the caller must evaluate the original syntax tree.

func EvalStaticComparisonBytes

func EvalStaticComparisonBytes(plan *StaticComparisonPlan, data []byte) (result []byte, ok bool)

EvalStaticComparisonBytes evaluates the narrow scalar comparison plan on a raw JSON document. Missing, null, container, invalid, and ambiguous values all fall back to the complete evaluator so its sequence and error rules remain authoritative.

func EvalStaticContains

func EvalStaticContains(plan *StaticContainsPlan, input any) (bool, bool)

EvalStaticContains evaluates a decoded input only after validating the complete value graph. Missing, null, containers, non-strings, cycles, unsupported values, non-finite numbers, and over-budget inputs all fall back to the complete evaluator, preserving its public diagnostics.

func EvalStaticContainsBytes

func EvalStaticContainsBytes(plan *StaticContainsPlan, data []byte) (bool, bool)

EvalStaticContainsBytes evaluates a static contains plan over a validated JSON document. The scanner validates the full document, not just the selected path, before attempting the regex shortcut.

func EvalStaticDescendantSum

func EvalStaticDescendantSum(plan *StaticDescendantSumPlan, input any) (any, bool)

EvalStaticDescendantSum evaluates a plan only when every observable value is unambiguous for the ordinary evaluator. Missing fields on descendants are ignored, as they are by the descendant path; no matching numeric field causes fallback so the public undefined result remains available. A matching array, object, nonnumeric value, nonfinite value, or overflow also causes fallback.

func EvalStaticDescendantSumBytes

func EvalStaticDescendantSumBytes(plan *StaticDescendantSumPlan, data []byte) ([]byte, bool)

EvalStaticDescendantSumBytes evaluates a decoded-input descendant sum plan over a validated JSON document.

func EvalStaticExtensionArithmetic

func EvalStaticExtensionArithmetic(plan *StaticExtensionArithmeticPlan, input any, registry map[string]any) (result any, ok bool, err error)

EvalStaticExtensionArithmetic evaluates the plan against an ordinary decoded Go JSON value. ok=false requests the complete evaluator. An error means the fast plan has reached an observable runtime error and must be returned rather than silently changing its semantics.

func EvalStaticFilterProject

func EvalStaticFilterProject(plan *StaticFilterProjectPlan, input any) (any, bool)

EvalStaticFilterProject preserves JSONata's singleton collapse: a single projected match is scalar, while multiple matches are returned as an array at the public boundary. Empty or ambiguous matches use the normal evaluator.

func EvalStaticFilterProjectBytes

func EvalStaticFilterProjectBytes(plan *StaticFilterProjectPlan, data []byte) ([]byte, bool)

EvalStaticFilterProjectBytes evaluates a decoded-input static plan after validating and decoding the complete JSON document. The raw scalar plans have a more direct representation and remain separate from this bridge.

func EvalStaticMap

func EvalStaticMap(plan *StaticMapPlan, input any) (any, bool)

EvalStaticMap returns ok=false whenever JSONata's sequence, undefined, coercion, or diagnostic semantics may be observable. The original AST must be evaluated in those cases.

func EvalStaticMapBytes

func EvalStaticMapBytes(plan *StaticMapPlan, data []byte) ([]byte, bool)

EvalStaticMapBytes evaluates a decoded-input map plan over a validated JSON document.

func EvalStaticPath

func EvalStaticPath(plan *StaticPathPlan, input any) (result any, ok bool)

EvalStaticPath evaluates a plan only when the input shape makes the result unambiguously scalar. A false ok value tells the caller to use the complete evaluator, preserving projections, undefined handling, and ownership rules.

func EvalStaticPathBytes

func EvalStaticPathBytes(plan *StaticPathPlan, data []byte) (result []byte, ok bool)

EvalStaticPathBytes evaluates a static scalar path directly from a JSON document. It returns ok=false for any input whose result cannot be proven to have the same semantics as the normal decoder. Callers must then use the complete evaluator. The scanner validates the complete document, including members unrelated to the selected path.

func EvalStaticSum

func EvalStaticSum(plan *StaticSumPlan, input any) (any, bool)

EvalStaticSum returns ok=false for an empty/missing sequence or whenever a full evaluation may observe a different error or sequence result. This is deliberate: the public fast-path interface cannot represent ErrUndefined, so ambiguous cases must use the original evaluator.

func EvalStaticSumBytes

func EvalStaticSumBytes(plan *StaticSumPlan, data []byte) ([]byte, bool)

EvalStaticSumBytes evaluates a decoded-input sum plan over a validated JSON document.

func EvalStaticTransform

func EvalStaticTransform(plan *StaticTransformPlan, input any) (any, bool)

EvalStaticTransform returns ok=false for any input whose normalization, clone, sequence, diagnostic, or resource semantics could differ. The caller then evaluates the original syntax tree.

func EvalWithOptions

func EvalWithOptions(n syntax.Node, input any, options Options) (any, error)

func IsUndefined

func IsUndefined(err error) bool

IsUndefined reports whether an evaluation returned the empty-sequence sentinel. Callers should use this helper instead of comparing error text.

func NewReflectedExtension

func NewReflectedExtension(name string, spec ReflectedExtension) (binding any, err error)

NewReflectedExtension validates and constructs an evaluator binding.

func NormalizeExtensionBinding

func NormalizeExtensionBinding(input any) any

NormalizeExtensionBinding converts public extension values to evaluator values while preserving callable values.

func NormalizeExtensionBindingSafe

func NormalizeExtensionBindingSafe(input any, maxDepth int, check func() error) (any, error)

NormalizeExtensionBindingSafe converts a public extension value while bounding cycles and nesting. Registrations supply a finite check callback; evaluations use the active runtime through normalizeExtensionValue.

Types

type ExtensionArgCountError

type ExtensionArgCountError struct {
	Func     string
	Expected int
	Received int
}

ExtensionArgCountError describes a reflected extension arity mismatch.

func (*ExtensionArgCountError) Error

func (e *ExtensionArgCountError) Error() string

type ExtensionArgTypeError

type ExtensionArgTypeError struct {
	Func  string
	Which int
}

ExtensionArgTypeError describes a reflected extension argument mismatch.

func (*ExtensionArgTypeError) Error

func (e *ExtensionArgTypeError) Error() string

type Options

type Options struct {
	Context           context.Context
	Bindings          map[string]any
	Timeout           time.Duration
	Deadline          time.Time
	MaxCallDepth      int
	MaxOperations     int64
	MaxSequenceLength int
	Timestamp         time.Time
}

Options controls one evaluation without changing the compatibility wrappers. Bindings are copied into the evaluation root and are never retained by the compiled expression. A zero or negative MaxCallDepth or MaxOperations uses the safe runtime default; a positive value sets an explicit limit. A positive MaxSequenceLength enables the JSONata v2.2 sequence guardrail; zero or negative disables it. Timeout values at or below zero are ignored, while a non-zero Deadline is enforced.

type ReflectedExtension

type ReflectedExtension struct {
	Func               any
	UndefinedHandler   jtypes.ArgHandler
	EvalContextHandler jtypes.ArgHandler
}

ReflectedExtension is the evaluator-facing description of a Go extension. The public jsonata.Extension type is converted to this form at registration.

type StaticComparisonPlan

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

StaticComparisonPlan describes a scalar field comparison whose operands do not depend on the evaluation environment. The plan is immutable after construction and is safe to share between concurrent evaluations.

func BuildStaticComparisonPlan

func BuildStaticComparisonPlan(n syntax.Node) *StaticComparisonPlan

BuildStaticComparisonPlan recognizes only equality and inequality between a static field path and a scalar literal. All other comparisons use the full evaluator because their coercion and sequence rules are broader.

func (*StaticComparisonPlan) RegistryConflict

func (p *StaticComparisonPlan) RegistryConflict(registry map[string]any) bool

RegistryConflict reports whether a registered name can change the meaning of a field in this plan. Unrelated extensions do not invalidate it.

type StaticContainsPlan

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

StaticContainsPlan describes the only regex shortcut that is safe to use without evaluating the complete expression tree: a field-only path and a parsed regex literal. The regex product is immutable and is shared by all evaluations of the compiled expression.

func BuildStaticContainsPlan

func BuildStaticContainsPlan(n syntax.Node) *StaticContainsPlan

BuildStaticContainsPlan recognises $contains(static.path, /literal/). Function values, string patterns, dynamic paths, and non-literal patterns remain on the normal evaluator path because their coercion and binding rules are observable.

func (*StaticContainsPlan) RegistryConflict

func (p *StaticContainsPlan) RegistryConflict(registry map[string]any) bool

RegistryConflict also covers an override of $contains itself. A registry entry for an unrelated function or field cannot affect this plan.

type StaticDescendantSumPlan

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

StaticDescendantSumPlan describes the narrow decoded-input form $sum(static.path.**.field). It intentionally does not cover bytes input: duplicate JSON object members and source ordering must remain governed by the normal decoder and evaluator.

func BuildStaticDescendantSumPlan

func BuildStaticDescendantSumPlan(n syntax.Node) *StaticDescendantSumPlan

BuildStaticDescendantSumPlan recognises the AST shape of a built-in sum over a recursive descendant path. The plan contains no source text and is immutable after construction.

func (*StaticDescendantSumPlan) RegistryConflict

func (p *StaticDescendantSumPlan) RegistryConflict(registry map[string]any) bool

RegistryConflict reports whether a registered name can alter either the built-in reduction, the static path, or the descendant field lookup.

type StaticExtensionArithmeticPlan

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

StaticExtensionArithmeticPlan describes a narrow arithmetic expression in which both operands are calls to registered functions with scalar input paths. The plan contains AST-derived data only; it does not inspect source text or benchmark case names.

func BuildStaticExtensionArithmeticPlan

func BuildStaticExtensionArithmeticPlan(n syntax.Node) *StaticExtensionArithmeticPlan

BuildStaticExtensionArithmeticPlan recognises expressions such as `$double(value) + $double(offset)`. Calls with dynamic arguments, partial application, or non-named procedures remain on the evaluator path.

func (*StaticExtensionArithmeticPlan) RegistryConflict

func (p *StaticExtensionArithmeticPlan) RegistryConflict(registry map[string]any) bool

RegistryConflict reports only bindings that can shadow one of the input paths. The extension itself is intentionally not treated as a conflict: the current copy-on-write registry snapshot supplies the callable at evaluation time, so re-registration remains visible after compilation.

func (*StaticExtensionArithmeticPlan) RegistryReady

func (p *StaticExtensionArithmeticPlan) RegistryReady(registry map[string]any) bool

RegistryReady reports whether both procedures resolve to callables in the supplied registry snapshot. Builtins and non-callable overrides deliberately fall back to the full evaluator so its name lookup and diagnostics remain authoritative.

type StaticFilterProjectPlan

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

StaticFilterProjectPlan describes the common JSONata shape `items[field = literal].projection`. It deliberately excludes path flattening, dynamic bindings, and all non-scalar intermediate values.

func BuildStaticFilterProjectPlan

func BuildStaticFilterProjectPlan(n syntax.Node) *StaticFilterProjectPlan

BuildStaticFilterProjectPlan recognizes one static equality predicate and a static scalar projection. The AST shape is the selector followed by a path step, which is the parser representation of the documented form.

func (*StaticFilterProjectPlan) RegistryConflict

func (p *StaticFilterProjectPlan) RegistryConflict(registry map[string]any) bool

type StaticMapPlan

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

StaticMapPlan describes the narrow AST shape $map(items, function($item){$item.price * $item.quantity}). It is immutable and is used only for ordinary decoded JSON input.

func BuildStaticMapPlan

func BuildStaticMapPlan(n syntax.Node) *StaticMapPlan

BuildStaticMapPlan recognizes one-parameter callbacks whose body is exactly a product of two explicit paths rooted at that callback parameter.

func (*StaticMapPlan) RegistryConflict

func (p *StaticMapPlan) RegistryConflict(registry map[string]any) bool

type StaticPathPlan

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

StaticPathPlan is an immutable description of a root field path. It is deliberately narrow: expressions with any dynamic path semantics are not represented and must use the normal evaluator.

func BuildStaticPathPlan

func BuildStaticPathPlan(n syntax.Node) *StaticPathPlan

BuildStaticPathPlan recognizes only a root/context path made from field names. The returned plan owns a copy of all path data and is safe for concurrent use.

func (*StaticPathPlan) RegistryConflict

func (p *StaticPathPlan) RegistryConflict(registry map[string]any) bool

RegistryConflict reports whether a binding can shadow one of the path fields. Unrelated extensions and variables do not affect a static field path and therefore do not disable the plan.

type StaticSumPlan

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

StaticSumPlan describes a narrow, immutable reduction over ordinary decoded JSON input. It is intentionally kept separate from the general evaluator: the plan is used only when every value that could affect the result is scalar, finite, and represented by the same JSON-compatible Go types that the normal evaluator accepts.

func BuildStaticSumPlan

func BuildStaticSumPlan(n syntax.Node) *StaticSumPlan

BuildStaticSumPlan recognises only calls to the built-in $sum with a static path, or a static collection selector followed by a scalar path/product. No source-text matching is used: all decisions are made from the parsed AST.

func (*StaticSumPlan) RegistryConflict

func (p *StaticSumPlan) RegistryConflict(registry map[string]any) bool

type StaticTransformPlan

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

StaticTransformPlan describes one deliberately narrow decoded-input transform. It is immutable after compilation and safe to share between concurrent evaluations. Any input or expression shape outside this subset is evaluated by the normal transform implementation.

func BuildStaticTransformPlan

func BuildStaticTransformPlan(n syntax.Node) *StaticTransformPlan

BuildStaticTransformPlan recognizes the frozen medium-transform shape:

$ ~> |collection.path[field = scalar]|{literal, total: left * right}, ["key"]|

The operation must be rooted at the input focus and every name must be a plain field path. In particular, no source-string or benchmark identifier is used to select this plan.

func (*StaticTransformPlan) RegistryConflict

func (p *StaticTransformPlan) RegistryConflict(registry map[string]any) bool

RegistryConflict disables the plan when a registered name can shadow a field lookup or the transform's clone binding. Builtins unrelated to these names cannot alter this plan's meaning.

Jump to

Keyboard shortcuts

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