Documentation
¶
Overview ¶
Package fasteval compiles expressions and renders raw string templates.
Its expression language covers arithmetic, comparisons, logic, collections, access, and function calls while preserving native Go numeric types. Compiled expressions and templates are immutable and safe for concurrent use.
Templates return raw text. Callers must encode values for HTML, SQL, shell commands, or any other destination before using rendered output there.
Index ¶
- func Eval(ctx context.Context, source string, variables map[string]any, ...) (any, error)
- func EvalAs[T any](ctx context.Context, source string, variables map[string]any, ...) (T, error)
- func EvalAsWith[T any](ctx context.Context, c *Compiler, source string, variables map[string]any, ...) (T, error)
- type Compiler
- type CompilerOption
- type Diagnostic
- type DiagnosticsError
- type ErrorCode
- type EvalError
- type EvalOption
- type Expression
- type Node
- type NodeKind
- type Program
- type ResolveFunc
- type Severity
- type Span
- type Template
- type TemplateOption
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Eval ¶
func Eval(ctx context.Context, source string, variables map[string]any, options ...EvalOption) (any, error)
Eval compiles source with the default compiler, then evaluates it.
Types ¶
type Compiler ¶
type Compiler struct {
// contains filtered or unexported fields
}
Compiler builds expressions and templates with an immutable function registry.
func NewCompiler ¶
func NewCompiler(options ...CompilerOption) (*Compiler, error)
NewCompiler returns an immutable compiler with every builtin enabled.
func (*Compiler) Compile ¶
func (c *Compiler) Compile(source string) (*Expression, error)
Compile builds an Expression from source with c's function registry.
func (*Compiler) CompileTemplate ¶
func (c *Compiler) CompileTemplate(source string, options ...TemplateOption) (*Template, error)
CompileTemplate builds a Template from source with c's function registry.
Example ¶
compiler, err := fasteval.NewCompiler(
fasteval.WithFunction("greet", func(name string) string {
return "Hello " + name
}),
)
if err != nil {
panic(err)
}
template, err := compiler.CompileTemplate("{{greet(name)}}")
if err != nil {
panic(err)
}
value, err := template.Render(context.Background(), map[string]any{testName: testAda})
if err != nil {
panic(err)
}
fmt.Println(value)
Output: Hello Ada
type CompilerOption ¶
type CompilerOption func(*compilerOptions) error
CompilerOption changes how a Compiler is built.
func WithFunction ¶
func WithFunction(name string, function any) CompilerOption
WithFunction adds one Go function to a compiler.
func WithFunctions ¶
func WithFunctions(functions map[string]any) CompilerOption
WithFunctions adds a map of named Go functions to a compiler.
type Diagnostic ¶
Diagnostic describes one compilation issue.
type DiagnosticsError ¶
type DiagnosticsError struct {
// contains filtered or unexported fields
}
DiagnosticsError contains one or more compilation diagnostics. Its accessors return copies instead of exposing mutable backing storage.
Example ¶
package main
import (
"errors"
"fmt"
"go.dw1.io/fasteval"
)
func main() {
_, err := fasteval.Compile("price +")
var diagnostics *fasteval.DiagnosticsError
if !errors.As(err, &diagnostics) {
panic(err)
}
diagnostic := diagnostics.At(0)
fmt.Println(diagnostics.Len(), diagnostic.Code, diagnostic.Severity)
}
Output: 1 syntax error
func (*DiagnosticsError) All ¶
func (d *DiagnosticsError) All() []Diagnostic
All returns a copy of every diagnostic in d.
func (*DiagnosticsError) At ¶
func (d *DiagnosticsError) At(index int) Diagnostic
At returns the diagnostic at index.
func (*DiagnosticsError) Error ¶
func (d *DiagnosticsError) Error() string
Error formats all diagnostics as a compact string.
func (*DiagnosticsError) Len ¶
func (d *DiagnosticsError) Len() int
Len returns the number of diagnostics in d.
type ErrorCode ¶
type ErrorCode string
ErrorCode classifies compile-time and evaluation failures. Its values are stable.
const ( // ErrSyntax reports malformed expression or template syntax. ErrSyntax ErrorCode = "syntax" // ErrUnknownVariable reports an unresolved variable name. ErrUnknownVariable ErrorCode = "unknown_variable" // ErrType reports an operation or conversion applied to an invalid type. ErrType ErrorCode = "type" // ErrOverflow reports checked integer overflow or underflow. ErrOverflow ErrorCode = "overflow" // ErrDivisionByZero reports integer division or remainder by zero. ErrDivisionByZero ErrorCode = "division_by_zero" // ErrAccess reports invalid field, method, map, or index access. ErrAccess ErrorCode = "access" // ErrFunction reports invalid function registration or invocation. ErrFunction ErrorCode = "function" // ErrPanic reports a recovered panic from caller-controlled code. ErrPanic ErrorCode = "panic" // ErrCanceled reports evaluation canceled through context.Context. ErrCanceled ErrorCode = "canceled" // ErrFormat reports a value that a template cannot render. ErrFormat ErrorCode = "format" )
type EvalError ¶
type EvalError struct {
// contains filtered or unexported fields
}
EvalError describes a failure during evaluation.
Example ¶
package main
import (
"context"
"errors"
"fmt"
"go.dw1.io/fasteval"
)
func main() {
_, err := fasteval.Eval(context.Background(), "missing", nil)
var evaluationError *fasteval.EvalError
if !errors.As(err, &evaluationError) {
panic(err)
}
fmt.Println(evaluationError.Code(), evaluationError.Operation(), evaluationError.Path())
}
Output: unknown_variable resolve variable missing
type EvalOption ¶
type EvalOption func(*evalOptions) error
EvalOption configures one evaluation call.
func WithResolver ¶
func WithResolver(resolve ResolveFunc) EvalOption
WithResolver uses resolve after a direct variables-map miss.
Example ¶
package main
import (
"context"
"fmt"
"go.dw1.io/fasteval"
)
func main() {
expression, err := fasteval.Compile("known + lazy")
if err != nil {
panic(err)
}
value, err := expression.Eval(
context.Background(),
map[string]any{"known": 40},
fasteval.WithResolver(func(_ context.Context, name string) (any, bool, error) {
if name == "lazy" {
return 2, true, nil
}
return nil, false, nil
}),
)
if err != nil {
panic(err)
}
fmt.Println(value)
}
Output: 42
type Expression ¶
type Expression struct {
// contains filtered or unexported fields
}
Expression is an immutable compiled expression with a dynamic result.
func Compile ¶
func Compile(source string) (*Expression, error)
Compile builds an Expression from source with the default builtin-only compiler.
Example ¶
package main
import (
"context"
"fmt"
"go.dw1.io/fasteval"
)
func main() {
expression, err := fasteval.Compile("price * quantity >= 100")
if err != nil {
panic(err)
}
value, err := expression.Eval(context.Background(), map[string]any{
"price": 25,
"quantity": 4,
})
if err != nil {
panic(err)
}
fmt.Println(value)
}
Output: true
func (*Expression) AST ¶
func (e *Expression) AST() *Node
AST returns the immutable root of the parsed source tree.
Example ¶
package main
import (
"fmt"
"go.dw1.io/fasteval"
)
func main() {
expression, err := fasteval.Compile("price * quantity")
if err != nil {
panic(err)
}
root := expression.AST()
fmt.Println(root.Kind() == fasteval.NodeBinary, root.Text(), len(root.Children()))
for _, child := range root.Children() {
fmt.Println(child.Kind() == fasteval.NodeIdentifier, child.Text())
}
}
Output: true * 2 true price true quantity
func (*Expression) Eval ¶
func (e *Expression) Eval(ctx context.Context, variables map[string]any, options ...EvalOption) (any, error)
Eval runs e with variables and evaluation options.
func (*Expression) Source ¶
func (e *Expression) Source() string
Source returns the expression text supplied at compile time.
type Node ¶
type Node struct {
// contains filtered or unexported fields
}
Node is an immutable node in a compiled expression AST.
type NodeKind ¶
type NodeKind uint8
NodeKind classifies a public AST node.
const ( // NodeInvalid is an unavailable node. NodeInvalid NodeKind = iota // NodeLiteral is a literal value. NodeLiteral // NodeIdentifier is a variable or function name. NodeIdentifier // NodeUnary is a prefix operation. NodeUnary // NodeBinary is a binary operation. NodeBinary // NodeConditional is a ternary expression. NodeConditional // NodeCall is a function or method call. NodeCall // NodeAccess is field or map-dot access. NodeAccess // NodeIndex is an index operation. NodeIndex // NodeList is a list literal. NodeList // NodeMap is a map literal. NodeMap )
type Program ¶
type Program[T any] struct { // contains filtered or unexported fields }
Program is an immutable compiled expression whose result is converted to T.
func CompileAs ¶
CompileAs compiles source and checks conversion to T during evaluation.
Example ¶
type result struct {
Name string `json:"name"`
Valid bool `json:"valid"`
}
program, err := fasteval.CompileAs[result]("{'name': name, 'valid': score >= 80}")
if err != nil {
panic(err)
}
value, err := program.Eval(context.Background(), map[string]any{testName: testAda, testScore: 90})
if err != nil {
panic(err)
}
fmt.Printf("%s: %t\n", value.Name, value.Valid)
Output: Ada: true
func CompileAsWith ¶
CompileAsWith compiles source as T with c.
type ResolveFunc ¶
ResolveFunc looks up a variable after a direct map miss. found distinguishes an explicit nil value from an unknown name.
type Template ¶
type Template struct {
// contains filtered or unexported fields
}
Template is an immutable compiled template safe for concurrent use.
func CompileTemplate ¶
func CompileTemplate(source string, options ...TemplateOption) (*Template, error)
CompileTemplate builds a Template from source with the default builtin-only compiler.
Example ¶
template, err := fasteval.CompileTemplate("Hello {{name}}: {{score >= 80 ? 'pass' : 'fail'}}")
if err != nil {
panic(err)
}
value, err := template.Render(context.Background(), map[string]any{testName: testAda, testScore: 90})
if err != nil {
panic(err)
}
fmt.Println(value)
Output: Hello Ada: pass
func (*Template) Execute ¶
func (t *Template) Execute( ctx context.Context, writer io.Writer, variables map[string]any, options ...EvalOption, ) (int64, error)
Execute evaluates t and writes raw output to writer. If a later expression or write fails, writer retains the bytes written before the error.
func (*Template) Render ¶
func (t *Template) Render(ctx context.Context, variables map[string]any, options ...EvalOption) (string, error)
Render evaluates t and returns raw output. On error, it also returns the text completed before the failure.
Example (PartialOutput) ¶
template, err := fasteval.CompileTemplate("Hello {{name}}! {{1 / zero}}")
if err != nil {
panic(err)
}
value, err := template.Render(context.Background(), map[string]any{
testName: testAda,
"zero": 0,
})
var evaluationError *fasteval.EvalError
if !errors.As(err, &evaluationError) {
panic(err)
}
fmt.Printf("%q %s\n", value, evaluationError.Code())
Output: "Hello Ada! " division_by_zero
type TemplateOption ¶
type TemplateOption func(*templateOptions) error
TemplateOption changes how a template is compiled.
func WithDelimiters ¶
func WithDelimiters(start, end string) TemplateOption
WithDelimiters replaces the default delimiters with a distinct, non-empty pair.
Source Files
¶
- access.go
- ast.go
- builtins.go
- builtins_access.go
- builtins_collection.go
- builtins_encoding.go
- builtins_helpers.go
- builtins_higher_order.go
- builtins_numeric.go
- builtins_sequence.go
- builtins_string.go
- builtins_time.go
- compiler.go
- convert.go
- doc.go
- equality.go
- errors.go
- eval.go
- function.go
- lexer.go
- numeric_arithmetic.go
- numeric_compare.go
- numeric_literal.go
- options.go
- parser.go
- template.go