expr

package
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: May 7, 2026 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package expr is a small compile-once / evaluate-many expression engine over decimal.Decimal values.

Compile turns a textual expression into a Program (an RPN bytecode produced by a shunting-yard parser); Program.Eval then runs that program against a decimal.Context and a Vars binding. The split lets callers pay the parsing cost once and reuse the compiled program in hot loops.

Supported syntax:

  • Numeric literals (decimal point optional, no scientific notation)
  • Identifiers as variable names (look up via the Vars argument)
  • Binary operators: + - * / ^
  • Unary +/-, parentheses for grouping

The ^ operator is right-associative and binds tighter than * and /; 2^3^2 evaluates to 2^(3^2) = 512, and -2^2 evaluates to -(2^2) = -4.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalidExpr is returned when parsing fails.
	//
	// Common triggers: empty input, unbalanced parentheses, misplaced
	// operators, malformed numeric literals, and unfinished expressions
	// (e.g. a trailing operator with no operand).
	ErrInvalidExpr = errors.New("invalid expression")

	// ErrUnknownVar is returned by Eval when the program references a
	// variable name that the supplied Vars cannot resolve.
	//
	// The actual error wraps the variable name in "%w: name", so use
	// errors.Is to compare against this sentinel.
	ErrUnknownVar = errors.New("unknown variable")
)

Functions

This section is empty.

Types

type MapVars

type MapVars map[string]decimal.Decimal

MapVars is a Vars implementation backed by an ordinary map. It is the fastest way to plug a fixed set of bindings into a Program.

func (MapVars) Get

func (m MapVars) Get(name string) (decimal.Decimal, bool)

Get satisfies Vars by looking name up in the underlying map. Missing keys produce (zero Decimal, false).

type Program

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

Program is a compiled expression ready to be evaluated.

Internally it holds an RPN bytecode plus its constant pool and the list of variable names referenced by the source. A Program is safe to reuse and to share across goroutines as long as no one mutates it (which the public API does not allow). Compile to obtain one.

func Compile

func Compile(input string) (*Program, error)

Compile parses input and produces a Program ready for repeated Eval.

The grammar is the one documented on the package: numeric literals, identifier variables, parentheses, unary +/-, and the binary operators +, -, *, /, ^. Whitespace is ignored. ^ is right-associative and binds tighter than * and /.

On success the returned *Program is independent from the input string and safe to reuse. On failure Compile returns nil and ErrInvalidExpr.

func (*Program) Eval

func (p *Program) Eval(ctx decimal.Context, vars Vars) (decimal.Decimal, error)

Eval runs the program against ctx and the provided Vars binding, returning the resulting decimal value.

All arithmetic is performed through the decimal package, so every intermediate result is normalized to ctx.Scale and ctx.Mode just as if the caller had used Add / Sub / Mul / Div / Pow directly.

Possible errors:

  • ErrInvalidExpr if the program is nil or its bytecode is malformed. A well-formed Compile output should never trigger this at Eval time.
  • ErrUnknownVar if vars cannot resolve a referenced name. The wrapped error includes the offending name.
  • decimal.ErrDivisionByZero on division by zero.
  • decimal.ErrInvalidPow from "^" with a negative base and a non-integer exponent.
  • decimal.ErrNonPositiveLog surfaced through "^" when computing ln(base) for non-positive base under a fractional exponent.

A nil Vars is acceptable as long as the program references no variables.

func (*Program) String

func (p *Program) String() string

String returns a short diagnostic summary of the compiled program — the number of bytecode ops, constants, and referenced variable names. It is meant for logging and debugging, not for serialization.

type Vars

type Vars interface {
	// Get looks up a single variable by name. It returns the value and
	// true on hit, or the zero Decimal and false on miss.
	Get(name string) (decimal.Decimal, bool)
}

Vars resolves variable names to decimal values during Eval.

Implementations should return ok = false when the name is unknown so Eval can surface ErrUnknownVar with the offending name attached.

Jump to

Keyboard shortcuts

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