formula

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Nov 9, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package formula holds the formula language: lexer, parser, function catalog, binder, bytecode, the Go virtual machine and the SQL generator with its SQLite and DuckDB dialects. One compiler, three targets; the browser VM of Phase 7 executes the same bytecode.

Parse turns text into a tree, Bind turns the tree into a Program by the static typing rules of ADR-0019, VM.Run executes a Program over the values of its slots, and GenerateSQL turns a Program into a value and an error expression for a Dialect. The grammar and semantics are fixed by ADR-0019, the query functions by ADR-0020, and the suite under conformance/ is the specification. Composite values and the query functions are not implemented yet.

Index

Constants

View Source
const (
	ErrDivByZero        = "div_by_zero"
	ErrNotANumber       = "not_a_number"
	ErrBadText          = "bad_text"
	ErrOutOfRange       = "out_of_range"
	ErrLengthMismatch   = "length_mismatch"
	ErrTooManyElements  = "too_many_elements"
	ErrQueryFailed      = "query_failed"
	ErrOverflow         = "overflow"
	ErrInexact          = "inexact"
	ErrCurrencyMismatch = "currency_mismatch"
)

Error codes (ADR-0019, ADR-0020, ADR-0022, ADR-0024).

View Source
const CurrencySuffix = "_currency"

CurrencySuffix is appended to a money variable's name for the column that holds its currency.

View Source
const DefaultMaxText = 1 << 16

DefaultMaxText is the text limit of a new database: 65,536 code points, room for a long note, and small enough that a vector of 2,048 of them on the analytical engine stays under a gigabyte.

View Source
const DivScaleStep = 4

DivScaleStep is how many digits a division adds to the dividend's scale, the rule MySQL uses: 1.00 / 3 is 0.333333 at scale six.

View Source
const MaxScale = 18

MaxScale is the most digits after the point an exact value may carry. Eighteen leaves one digit before the point at the top of the range and keeps every power of ten in an int64.

View Source
const MinMaxText = 64

MinMaxText is the smallest text limit a database may set: every rendering of a number or a date fits in it.

Variables

View Source
var ErrorCodes = map[string]bool{
	"div_by_zero": true, "not_a_number": true, "bad_text": true, "out_of_range": true,
	"length_mismatch": true, "too_many_elements": true,
	"unknown_source": true, "unknown_column": true, "query_failed": true,
	"overflow": true, "inexact": true, "currency_mismatch": true,
}

ErrorCodes is the closed list of evaluation error codes (ADR-0019, ADR-0020, ADR-0022, ADR-0024). A case may only expect one of these.

View Source
var RoundMethods = []string{"half_up", "half_even", "down", "up", "floor", "ceiling"}

RoundMethods lists the names ROUND and DECIMAL accept, in catalog order.

Functions

func Classes

func Classes() map[Class]string

Classes returns the evaluation classes with their descriptions.

func Equal

func Equal(a, b Value) bool

Equal reports whether two values are the same value of the same kind. An exact value compares by mantissa and scale, so 0.3 and 0.30 differ. It is the identity used by tests, not the = operator of the language.

func IsKeyword added in v0.2.0

func IsKeyword(name string) bool

IsKeyword reports whether a name, in any case, is a keyword of the language and so can never name a variable, a field, a column or a table (ADR-0019).

func NearlyEqual

func NearlyEqual(a, b Value, rel float64) bool

NearlyEqual compares two values exactly, except numbers, which may differ by the relative tolerance: the allowance of ADR-0019 for floating-point aggregates across targets.

func ParseCaseDate

func ParseCaseDate(s string) (int64, error)

ParseCaseDate reads an instant as the suite writes it: YYYY-MM-DD or YYYY-MM-DD HH:MM:SS, UTC, as seconds since the epoch.

func ParseCaseDay added in v0.2.0

func ParseCaseDay(s string) (int64, error)

ParseCaseDay reads a calendar day as the suite writes it, YYYY-MM-DD, as days since 1970-01-01.

func ParseExact added in v0.2.0

func ParseExact(s string, t Type) (Value, *EvalError)

ParseExact reads an exact number written as text, "12.30" for a decimal or "12.30 PLN" for a money (ADR-0022), as a value of the type, brought to the type's scale. A digit the scale would drop is the error inexact, a mantissa past int64 is overflow, and anything else is bad_text.

func Render added in v0.2.0

func Render(v Value) string

Render renders a value as the TEXT function does: a decimal with every place, a money with its currency, a date as YYYY-MM-DD, a datetime as YYYY-MM-DD HH:MM:SS, a blank as the empty text (ADR-0019, ADR-0022).

func Rescale added in v0.2.0

func Rescale(v Value, scale int) (Value, *EvalError)

Rescale brings an exact value to another scale: up is exact, down is the error inexact when a dropped digit is not zero. A blank stays blank; a value that is not exact is returned as it is.

func SetupSources added in v0.2.0

func SetupSources(db *sql.DB, d Dialect, rows map[*Source][][]Value) error

SetupSources creates the tables of the sources in a database, named as the sources are, and fills them: the conformance and property runners' half of LOOKUP on the SQL dialects. Rows are row-major in column order; a money column is its amount and its currency column.

func Sexpr

func Sexpr(n Node) string

Sexpr renders a node as an S-expression with every operation parenthesised, which makes precedence and associativity visible: -x ^ 2 is (^ (neg x) 2). It is the form the parser tests and the conformance tooling use; it is not the formula language.

Types

type Array

type Array struct {
	Elem  Kind
	Nums  []float64
	Strs  []string
	Nulls []bool
}

Array is an array<scalar>, stored column-wise: numbers, dates and booleans in Nums, text, refs and json in Strs, with Nulls marking blank elements. Composite operations arrive with a later change.

type Binary

type Binary struct {
	Op    TokenKind
	Const bool
	L, R  Node
	P     int
}

Binary is an infix operation. Op is one of the arithmetic, text, comparison and logical operator kinds. Const marks a +, - or * of two constant expressions, which the binder folds.

func (*Binary) Pos

func (n *Binary) Pos() int

Pos implements Node.

type BindOptions

type BindOptions struct {
	Mode Mode
	// Sources are the explicit tables LOOKUP may read (ADR-0016); nil
	// means none, and every LOOKUP is an unknown source.
	Sources Sources
}

BindOptions configures a bind.

type BindingSuite

type BindingSuite struct {
	Suite       string                       `json:"suite"`
	Description string                       `json:"description,omitempty"`
	Variables   map[string]string            `json:"variables,omitempty"`
	Schemas     map[string]map[string]string `json:"schemas,omitempty"`
	// Sources declares the tables LOOKUP may read, as in an evaluation
	// suite; their rows are not needed to bind.
	Sources map[string]*SuiteSource `json:"sources,omitempty"`
	// Mode is "any" (the default), "auto" (ADR-0015) or "pure" (ADR-0018).
	Mode   string       `json:"mode,omitempty"`
	Accept []string     `json:"accept"`
	Reject []RejectCase `json:"reject"`
	File   string       `json:"-"`
}

BindingSuite is one file of definition-time cases for the binder: formulas that must bind and formulas it must refuse, in a mode.

func LoadBindingSuites

func LoadBindingSuites(dir string) ([]*BindingSuite, error)

LoadBindingSuites loads every binding suite from dir, sorted by file name.

func (*BindingSuite) BindMode added in v0.2.0

func (s *BindingSuite) BindMode() Mode

BindMode is the binding mode the suite names.

func (*BindingSuite) Scope added in v0.2.0

func (s *BindingSuite) Scope() (*Scope, error)

Scope builds the scope of the suite's variables, in name order.

func (*BindingSuite) SourceSet added in v0.2.0

func (s *BindingSuite) SourceSet() (*SourceSet, error)

SourceSet resolves the suite's sources.

type BlankLit

type BlankLit struct {
	P int
}

BlankLit is the BLANK literal.

func (*BlankLit) Pos

func (n *BlankLit) Pos() int

Pos implements Node.

type BoolLit

type BoolLit struct {
	Value bool
	P     int
}

BoolLit is TRUE or FALSE.

func (*BoolLit) Pos

func (n *BoolLit) Pos() int

Pos implements Node.

type Call

type Call struct {
	Name string
	Args []Node
	P    int
}

Call is a function call by canonical name. IF, AND, OR and NOT never appear here: the parser turns them into If, Binary and Unary nodes.

func (*Call) Pos

func (n *Call) Pos() int

Pos implements Node.

type Case

type Case struct {
	Name    string `json:"name,omitempty"`
	Formula string `json:"formula"`
	// Inputs are values for declared variables; an absent variable is blank.
	// Dates are written as YYYY-MM-DD or YYYY-MM-DD HH:MM:SS.
	Inputs map[string]json.RawMessage `json:"inputs,omitempty"`
	// Context sets the context functions: user, groups, now (a date),
	// state and id.
	Context *CaseContext `json:"context,omitempty"`
	// Type is the static type the formula must have, when the case pins it.
	// A date result must declare it so that Expected can be written as text.
	Type string `json:"type,omitempty"`
	// Expected is the value, in the same notation as Inputs. Exactly one of
	// Expected and Error is set; Expected may be null for a blank result.
	Expected json.RawMessage `json:"expected,omitempty"`
	// Error is the error code the evaluation must stop with.
	Error string `json:"error,omitempty"`
}

Case is one evaluation case: a formula, its inputs and context, and the value or the error it must produce on every target.

type CaseContext

type CaseContext struct {
	User   string   `json:"user,omitempty"`
	Groups []string `json:"groups,omitempty"`
	Now    string   `json:"now,omitempty"`
	State  string   `json:"state,omitempty"`
	ID     string   `json:"id,omitempty"`
}

CaseContext is the context a case runs in.

func (*CaseContext) Context

func (c *CaseContext) Context() (*Context, error)

Context converts the case context to a VM context; nil for none.

type Class

type Class string

Class is the evaluation class of a function (ADR-0015, ADR-0016). It decides where a formula using the function may appear.

const (
	ClassPure    Class = "pure"
	ClassContext Class = "context"
	ClassLookup  Class = "lookup"
	ClassQuery   Class = "query"
)

The four evaluation classes.

type Column

type Column struct {
	Name  string
	Kind  Kind
	Scale int8
}

Column is one column of a rows type.

type Context

type Context struct {
	// User is the id of the user the formula runs for; empty for a system
	// recompute.
	User string
	// Groups are the groups the user belongs to.
	Groups []string
	// Now is the current time in seconds since the epoch, UTC. Zero means
	// the wall clock.
	Now int64
	// State is the state of the document the formula runs over, for
	// STATE(); empty for a class without states and in a preview of a
	// stateless application (ADR-0040).
	State string
	// ID is the id of the document the formula runs over, for ID(); empty
	// when there is no document.
	ID string
}

Context is what the context functions see (ADR-0015).

type DecConst added in v0.2.0

type DecConst struct {
	Mant  int64
	Scale int8
}

DecConst is an exact constant: a mantissa at a scale (ADR-0022).

type Dialect

type Dialect interface {
	Name() string
	NumberLit(f float64) string
	// IntLit spells an integer literal as the engine's 64-bit integer.
	IntLit(m int64) string
	TextLit(s string) string
	True() string
	False() string
	// Load references a column holding a variable of the kind, cast to the
	// SQL type the dialect computes with.
	Load(column string, k Kind) string
	// Num, Cond and Text read an expression as a number, a condition or
	// text with the blank rules of ADR-0005: a blank is 0, FALSE or "".
	Num(e SQLExpr) string
	Cond(e SQLExpr) string
	Text(e SQLExpr) string
	// Mant reads an exact expression's mantissa as a non-null integer in
	// the type the dialect does exact arithmetic in: a blank is 0, a bool
	// 1 or 0. RawMant reads it with a blank kept NULL, for the functions
	// that skip blanks.
	Mant(e SQLExpr) string
	RawMant(e SQLExpr) string
	// Narrow brings an exact arithmetic result back to a 64-bit integer,
	// NULL when it does not fit, and OverflowErr is the matching check.
	Narrow(val string) string
	OverflowErr(val string) string
	// NotFinite is the condition that a numeric value is not a finite
	// number, the overflow check of ADR-0019.
	NotFinite(val string) string
	// Pow spells x to the power y as the VM computes it.
	Pow(x, y string) string
	// Render applies the TEXT rule of ADR-0019 to a scalar.
	Render(e SQLExpr) string
	// Call translates a builtin by canonical name. Args are translated
	// already; the dialect reads their kinds.
	Call(name string, args []SQLExpr, params *Params) (SQLExpr, error)
	// Param references a context parameter by name.
	Param(name string) string
	// ColumnType is the SQL type of a column that stores values of the
	// kind, as the engine's tables declare it.
	ColumnType(k Kind) string
	// ContextArgs binds the context parameters for database/sql, in the
	// form the dialect's SQL expects.
	ContextArgs(ctx *Context) []any
	// Setup lists statements to run on a connection before the generated
	// SQL can be used: the DuckDB macros, nothing for SQLite.
	Setup() []string
	// Limits are the size limits the generated SQL enforces (ADR-0021).
	Limits() Limits
	// WithLimits returns the dialect under other limits.
	WithLimits(l Limits) Dialect
}

Dialect spells one SQL engine.

type DuckDB

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

DuckDB is the dialect for DuckDB through github.com/duckdb/duckdb-go.

func NewDuckDB

func NewDuckDB() DuckDB

NewDuckDB makes the DuckDB dialect under the default limits.

func (DuckDB) Call

func (d DuckDB) Call(name string, args []SQLExpr, params *Params) (SQLExpr, error)

Call implements Dialect.

func (DuckDB) ColumnType added in v0.2.0

func (DuckDB) ColumnType(k Kind) string

ColumnType implements Dialect: DOUBLE for a number and for the days and seconds of dates, BIGINT for a mantissa, BOOLEAN, VARCHAR.

func (DuckDB) Cond

func (c DuckDB) Cond(e SQLExpr) string

Cond reads an expression as a condition: a blank is FALSE.

func (DuckDB) ContextArgs

func (DuckDB) ContextArgs(ctx *Context) []any

ContextArgs implements Dialect: groups bind as a list of text.

func (DuckDB) False

func (DuckDB) False() string

False implements Dialect.

func (DuckDB) IntLit added in v0.2.0

func (DuckDB) IntLit(m int64) string

IntLit implements Dialect.

func (DuckDB) Limits

func (d DuckDB) Limits() Limits

Limits implements Dialect.

func (DuckDB) Load

func (DuckDB) Load(column string, k Kind) string

Load implements Dialect.

func (DuckDB) Mant added in v0.2.0

func (c DuckDB) Mant(e SQLExpr) string

Mant reads an exact expression's mantissa as a non-null integer in the arithmetic type: a blank is 0, a bool 1 or 0.

func (DuckDB) Name

func (DuckDB) Name() string

Name implements Dialect.

func (DuckDB) Narrow added in v0.2.0

func (DuckDB) Narrow(val string) string

Narrow implements Dialect.

func (DuckDB) NotFinite

func (DuckDB) NotFinite(val string) string

NotFinite implements Dialect: DuckDB keeps NaN and the infinities.

func (DuckDB) Num

func (c DuckDB) Num(e SQLExpr) string

Num reads an expression as a number: a blank is 0, a bool is 1 or 0.

func (DuckDB) NumberLit

func (DuckDB) NumberLit(f float64) string

NumberLit implements Dialect. Every literal is a DOUBLE.

func (DuckDB) OverflowErr added in v0.2.0

func (DuckDB) OverflowErr(val string) string

OverflowErr implements Dialect: a NULL is a blank, not an overflow.

func (DuckDB) Param

func (DuckDB) Param(name string) string

Param implements Dialect.

func (DuckDB) Pow

func (DuckDB) Pow(x, y string) string

Pow implements Dialect: DuckDB's pow is the C library's, which the VM's double-double power matches.

func (DuckDB) RawMant added in v0.2.0

func (c DuckDB) RawMant(e SQLExpr) string

RawMant reads an exact expression's mantissa in the arithmetic type with a blank kept NULL.

func (DuckDB) Render

func (d DuckDB) Render(e SQLExpr) string

Render implements Dialect: the TEXT rule of ADR-0019 and ADR-0022.

func (DuckDB) Setup

func (DuckDB) Setup() []string

Setup implements Dialect: the macro definitions.

func (DuckDB) Text

func (c DuckDB) Text(e SQLExpr) string

Text reads an expression as text: a blank is the empty text.

func (DuckDB) TextLit

func (DuckDB) TextLit(s string) string

TextLit implements Dialect.

func (DuckDB) True

func (DuckDB) True() string

True implements Dialect.

func (DuckDB) WithLimits

func (d DuckDB) WithLimits(l Limits) Dialect

WithLimits implements Dialect.

type Error

type Error struct {
	// Pos is the byte offset of the error in the formula.
	Pos int
	// Col is the 1-based column in characters, for people.
	Col int
	Msg string
}

Error is a lexical or syntax error at a position in a formula.

func (*Error) Error

func (e *Error) Error() string

type EvalError

type EvalError struct {
	Code string
	Pos  int
	Msg  string
}

EvalError is an evaluation error: a code from the closed list, the byte offset of the failing operation in the source when known, and a message.

func (*EvalError) Error

func (e *EvalError) Error() string

type Field added in v0.2.0

type Field struct {
	Name string
	Type Type
}

Field is one field of an object type, or one column of rows.

type Function

type Function struct {
	Name     string   `json:"name"`
	Aliases  []string `json:"aliases,omitempty"`
	Class    Class    `json:"class"`
	Category string   `json:"category"`
	Params   []Param  `json:"params"`
	Returns  string   `json:"returns"`
	Summary  string   `json:"summary"`
}

Function is one catalog entry.

func Functions

func Functions() []*Function

Functions returns every catalog entry in catalog order.

func LookupFunction

func LookupFunction(name string) *Function

LookupFunction returns the catalog entry for a function name or alias, case-insensitively, or nil when there is none.

func (*Function) MaxArgs

func (fn *Function) MaxArgs() int

MaxArgs is the most arguments a call may pass, or -1 when unbounded.

func (*Function) MinArgs

func (fn *Function) MinArgs() int

MinArgs is the fewest arguments a call may pass.

func (*Function) Signature

func (fn *Function) Signature(name string) string

Signature renders the function under the given name as the editor shows it: ROUND(number[, digits]), MIN(value[, value, ...]).

type Ident

type Ident struct {
	Name string
	P    int
}

Ident is a variable, or inside LOOKUP and QUERY a source column.

func (*Ident) Pos

func (n *Ident) Pos() int

Pos implements Node.

type If

type If struct {
	Cond, Then, Else Node
	P                int
}

If is IF(c, a, b) or IF c THEN a ELSE b.

func (*If) Pos

func (n *If) Pos() int

Pos implements Node.

type Instr

type Instr struct {
	Op  Op
	Arg int32
}

Instr is one instruction.

type Kind

type Kind uint8

Kind is the kind of a value, static or at run time (ADR-0013, ADR-0022, ADR-0023).

const (
	KindNull Kind = iota
	KindBool
	KindNumber   // float64, Excel arithmetic (ADR-0004)
	KindDecimal  // an exact number: an int64 mantissa at a scale (ADR-0022)
	KindMoney    // a decimal with a currency (ADR-0022)
	KindText     // UTF-8 text
	KindDate     // a calendar day: days since 1970-01-01 (ADR-0023)
	KindDateTime // an instant: seconds since 1970-01-01 00:00:00 UTC
	KindRef      // a document reference in its Class:id form
	KindJSON     // opaque JSON text
	KindArray
	KindRows
	KindObject // one record of a named schema; static only, never a run-time value (ADR-0031)
)

The kinds. KindNull is the blank: the static type of the BLANK literal and the run-time kind of a missing value. The scalar kinds come first so that IsScalar is one comparison.

func (Kind) IsDateLike added in v0.2.0

func (k Kind) IsDateLike() bool

IsDateLike reports whether the kind is a calendar day or an instant.

func (Kind) IsExact added in v0.2.0

func (k Kind) IsExact() bool

IsExact reports whether the kind is an exact number: decimal or money.

func (Kind) IsScalar

func (k Kind) IsScalar() bool

IsScalar reports whether the kind is a scalar, blank included.

func (Kind) String

func (k Kind) String() string

type Limits

type Limits struct {
	// MaxText is the longest text a formula may produce or a document may
	// store, in code points. A longer result is the error out_of_range,
	// decided before the text is built.
	MaxText int
}

Limits are the size limits a database evaluates under (ADR-0021). They are a property of the database, chosen when it is created and kept with its metadata, so that a formula gives the same result wherever the database is opened and a commit recomputes as it was committed. A server's resource budgets, memory, threads and timeouts, are not limits: they decide whether a recompute runs, never what it returns.

func DefaultLimits

func DefaultLimits() Limits

DefaultLimits are the limits of a new database.

type Member

type Member struct {
	Base string
	Path []string
	P    int
}

Member is base.name, or a longer path base.a.b: one column of a rows variable as an array, or a field of an object variable, nested through object fields (ADR-0031).

func (*Member) Pos

func (n *Member) Pos() int

Pos implements Node.

type MemoryExecutor added in v0.2.0

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

MemoryExecutor is a QueryExecutor over rows held in memory: the in-memory executor of ADR-0020 that the conformance suite runs against, which tests and the formula tool use. It evaluates the condition on every row with a VM of its own, so it is exact and slow; the store has its index and its statements.

func NewMemoryExecutor added in v0.2.0

func NewMemoryExecutor() *MemoryExecutor

NewMemoryExecutor makes an executor with no tables.

func (*MemoryExecutor) AddTable added in v0.2.0

func (m *MemoryExecutor) AddTable(src *Source, rows [][]Value)

AddTable adds or replaces a table: rows are row-major in the source's column order and are sorted into the source's key order.

func (*MemoryExecutor) Lookup added in v0.2.0

func (m *MemoryExecutor) Lookup(q *QuerySlot, args []Value, ctx *Context) (Value, *EvalError)

Lookup implements QueryExecutor.

type Mode

type Mode uint8

Mode says where a formula will run, which decides the function classes it may use (ADR-0015).

const (
	// ModeAny allows every class: defaults, triggered formulas, guards,
	// rules, access rules and layouts.
	ModeAny Mode = iota
	// ModeAuto allows pure functions and LOOKUP only: the stored value of
	// an auto variable must be a function of the document itself.
	ModeAuto
	// ModePure allows pure functions only: a class title (ADR-0018) and a
	// schema's presentation formulas (ADR-0032) are computed from the
	// document's own values and nothing else.
	ModePure
)

The modes.

func (Mode) String

func (m Mode) String() string

type Node

type Node interface {
	// Pos is the byte offset of the node in the formula: the operator for
	// operators, the start otherwise.
	Pos() int
}

Node is a node of a parsed formula. The parser produces it; the binder turns it into bytecode. Function names in a Call are canonical upper-case catalog names; variable names are kept as written and resolved case-insensitively by the binder.

func Parse

func Parse(src string) (Node, error)

Parse turns a formula into a syntax tree. It checks the grammar of ADR-0019 and every call against the catalog: the function must exist and the number of arguments must fit. Names, types and function classes are the binder's job.

Precedence from highest to lowest: postfix %, unary -, ^ (right- associative), * / \, + -, &, comparisons, NOT, AND, OR. IF c THEN a ELSE b is an expression whose ELSE branch extends as far right as it can.

type NumberLit

type NumberLit struct {
	Value float64
	P     int32
	Len   int32
}

NumberLit is a number literal: its value, its byte offset and its length in the source, from which the binder reads the spelling exactly when the literal meets an exact operand (ADR-0022).

func (*NumberLit) Pos

func (n *NumberLit) Pos() int

Pos implements Node.

func (*NumberLit) Text added in v0.2.0

func (n *NumberLit) Text(src string) string

Text is the literal's spelling in the source it was parsed from.

type Op

type Op uint8

Op is an opcode. The numbering is part of the format: append only.

const (
	OpNop       Op = iota
	OpConstNum     // push Nums[arg]
	OpConstText    // push Texts[arg]
	OpTrue         // push TRUE
	OpFalse        // push FALSE
	OpBlank        // push BLANK
	OpLoad         // push the variable in slot arg
	OpNeg          // -x
	OpPercent      // x%
	OpNot          // NOT x
	OpAdd
	OpSub
	OpMul
	OpDiv       // / and \ : by zero is an error (ADR-0024)
	OpDivStrict // kept for the numbering: the same as div
	OpPow
	OpConcat
	OpEq
	OpNe
	OpLt
	OpLe
	OpGt
	OpGe
	OpJump        // pc = arg
	OpJumpIfFalse // pop; when FALSE or blank, pc = arg
	OpAndJump     // when the top is FALSE or blank, replace it by FALSE and pc = arg; else pop
	OpOrJump      // when the top is TRUE, pc = arg; else pop
	OpToBool      // replace a blank top by FALSE
	OpCall        // call builtin arg>>8 with arg&0xff arguments from the stack
	OpLookup      // reserved: LOOKUP through query slot arg (ADR-0020)
	OpQuery       // reserved: QUERY through query slot arg (ADR-0020)
	OpReturn      // the top is the result
	OpConstDec    // push Decs[arg] (ADR-0022)
	OpDecNeg      // -x on an exact value; arg is the result's scale and money flag
	OpDecPercent  // x% on an exact value; arg as dec.neg
	OpDecAdd      // exact +; arg as dec.neg
	OpDecSub      // exact -; arg as dec.neg
	OpDecMul      // exact *; arg as dec.neg
	OpDecDiv      // exact /; arg as dec.neg
	OpDecScale    // bring the exact top to the static scale and kind; arg as dec.neg
	OpTry         // on an error before the matching end.try, restore the stack and pc = arg (IFERROR)
	OpEndTry      // leave the innermost try
)

The opcodes. Arg is the operand of the instruction.

func (Op) String

func (o Op) String() string

type Param

type Param struct {
	Name string `json:"name"`
	// Type names the argument's static type, or a shape such as "numbers"
	// (a number or an array of numbers), "source" or "condition" for the
	// query functions.
	Type string `json:"type"`
	// Optional: this argument and every one after it may be left out.
	Optional bool `json:"optional,omitempty"`
	// Repeat: the argument may be given any number of times.
	Repeat bool `json:"repeat,omitempty"`
}

Param is one argument of a function.

type Params

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

Params records the context parameters a statement uses.

func NewParams added in v0.2.0

func NewParams(d Dialect) *Params

NewParams makes an empty parameter list for a dialect, for callers that generate fragments with LookupSQL.

func (*Params) Names added in v0.2.0

func (p *Params) Names() []string

Names lists the parameters recorded so far.

func (*Params) Use

func (p *Params) Use(name string) string

Use records a parameter and returns its reference in the dialect.

type Program

type Program struct {
	Nums    []float64
	Decs    []DecConst
	Texts   []string
	Slots   []Slot
	Code    []Instr
	Pos     []int32 // byte offset in the source per instruction, for messages
	Result  Type
	Classes []Class // function classes used, in catalog order
	Queries []QuerySlot
	// MaxStack is the stack depth the program needs.
	MaxStack int
}

Program is a compiled formula.

func Bind

func Bind(src string, scope *Scope, opts BindOptions) (*Program, error)

Bind parses and binds a formula against a scope.

func BindNode

func BindNode(src string, n Node, scope *Scope, opts BindOptions) (*Program, error)

BindNode binds a parsed formula. src is the source the tree came from, for positions in messages.

func Decode

func Decode(data []byte) (*Program, error)

Decode reads a program in the binary format.

func (*Program) Calls

func (p *Program) Calls(name string) bool

Calls reports whether the program calls the named builtin.

func (*Program) ClaimExact added in v0.2.0

func (p *Program) ClaimExact(t Type) bool

ClaimExact makes a program that is one number constant into the exact constant of the type, when the number is exactly a value at the type's scale: a default of "0" for a decimal(2) variable is 0.00, as a literal meeting an exact operand is read exactly (ADR-0022). It reports whether it did; a program that is not a lone constant, a type that is not a decimal, or a number that does not fit the scale leave the program as it is.

func (*Program) Encode

func (p *Program) Encode() []byte

Encode serializes the program in the binary format.

func (*Program) HasOp

func (p *Program) HasOp(op Op) bool

HasOp reports whether the program contains the opcode.

func (*Program) MarshalJSON

func (p *Program) MarshalJSON() ([]byte, error)

MarshalJSON renders the debug form: one line per instruction with the opcode name, the operand, and what the operand refers to.

type QueryExecutor added in v0.2.0

type QueryExecutor interface {
	// Lookup returns the slot's column of the first row of its source, in
	// the source's key order, on which the condition holds for the
	// arguments, or blank when no row does. A row on which the condition
	// stops with an error does not match. ctx is the context the formula
	// runs in, for a condition that reads it.
	Lookup(q *QuerySlot, args []Value, ctx *Context) (Value, *EvalError)
}

QueryExecutor answers the query functions of a program at run time (ADR-0020). The VM hands it the compiled slot and the values of the document variables the condition reads; nothing crosses the boundary per row.

type QuerySlot

type QuerySlot struct {
	Source string
	Column string
	// Type is the column's type, which is the type of the lookup.
	Type Type
	// Order lists the source's key columns: "first row" is first in this
	// order.
	Order []string
	// Args are the slots of the enclosing program whose values the
	// condition reads as THIS.name, and ArgNames those variables' names,
	// so that a slot "THIS.<name>" of Cond or Key maps to Args[i].
	Args     []int32
	ArgNames []string
	// Cond is the condition; a row matches when it is TRUE, and a row on
	// which it stops with an error does not match.
	Cond *Program
	// Key is the compared expression of an equality condition, nil for
	// any other shape, and IndexColumn the column it is compared with.
	Key         *Program
	IndexColumn string
}

QuerySlot is a compiled LOOKUP call (ADR-0020): the source and the column it returns; the condition as a program of its own over the source's columns, named by column, and the document variables it reads as THIS.name, named "THIS.<variable>"; the slots of the enclosing program those variables live in; and, when the condition is one equality of a column with an expression of the document alone, that expression as a program, so that an index on the column can serve the lookup (ADR-0036). QUERY arrives with Phase 4.

func (*QuerySlot) ArgIndex added in v0.2.0

func (q *QuerySlot) ArgIndex(slotName string) int

ArgIndex returns the position in Args of a "THIS.<name>" slot of Cond or Key, or -1 when the slot is a column.

type RegisteredFunc

type RegisteredFunc struct {
	// Name is the SQL function name.
	Name string
	// NArgs is the argument count, the limit included when Limited, or -1
	// for variadic.
	NArgs int
	// Kinds gives the kind expected at each position; the last repeats. A
	// KindDecimal position receives a raw mantissa, scale 0.
	Kinds []Kind
	// Fn is the implementation, the VM's own.
	Fn func(vm *VM, args []Value) (Value, *EvalError)
	// Limited: the last argument is the text limit, and Fn reads it from
	// the VM it is called with.
	Limited bool
}

RegisteredFunc describes an engine function a SQL dialect calls back into Go (ADR-0019).

func SQLiteFunctions

func SQLiteFunctions() []RegisteredFunc

SQLiteFunctions lists the engine functions the SQLite dialect expects to be registered, as fado_<name> and fado_<name>_err: the builtins named in sqliteRegistered under their own arguments, then the exact-arithmetic helpers. The sqlitefn package registers them from this list.

func (RegisteredFunc) Kind

func (f RegisteredFunc) Kind(i int) Kind

Kind returns the kind expected at argument position i.

type RejectCase

type RejectCase struct {
	Formula string `json:"formula"`
	Reason  string `json:"reason,omitempty"`
}

RejectCase is a formula that must be refused, with the reason for people.

type Rows

type Rows struct {
	Cols []Column
	Data []Array
	N    int
}

Rows is a rows<schema> value: one Array per column.

type SQL

type SQL struct {
	// Value is the value expression.
	Value string
	// Error is the error expression, or "" when the formula cannot fail.
	Error string
	// Currency is the currency expression of a money result, "" otherwise.
	Currency string
	// Kind is the kind of the value expression.
	Kind Kind
	// Scale is the scale of an exact value expression.
	Scale int8
	// Params lists the context parameters the expressions reference, by
	// name: now (seconds since the epoch, always bound, never NULL), user
	// (the user id or NULL) and groups (the user's groups or NULL, in the
	// form the dialect's ContextArgs binds).
	Params []string
}

SQL is a generated statement fragment.

func GenerateSQL

func GenerateSQL(p *Program, d Dialect, column func(Slot) string) (SQL, error)

GenerateSQL translates a program for a dialect. column gives the column expression that holds each slot's value; for a money slot it is asked again for the currency column, a text slot named with CurrencySuffix. A program with a lookup refers to the source by its quoted name; a caller whose tables are named otherwise uses GenerateSQLWith. Column expressions must be qualified when the program has a lookup, since they are referenced inside its subquery.

func GenerateSQLBound added in v0.3.0

func GenerateSQLBound(p *Program, d Dialect, b SQLBinding) (SQL, error)

GenerateSQLBound is GenerateSQL with every binding given.

func GenerateSQLWith added in v0.2.0

func GenerateSQLWith(p *Program, d Dialect, column func(Slot) string, table func(source string) string) (SQL, error)

GenerateSQLWith is GenerateSQL with the table expression of each source a LOOKUP reads given by table.

func (SQL) CurrencyOrNull added in v0.2.0

func (s SQL) CurrencyOrNull() string

CurrencyOrNull returns the currency expression, or NULL when there is none.

func (SQL) ErrorOrNull

func (s SQL) ErrorOrNull() string

ErrorOrNull returns the error expression, or NULL when there is none.

type SQLBinding added in v0.3.0

type SQLBinding struct {
	// Column gives the column expression that holds each slot's value; for
	// a money slot it is asked again for the currency column, a text slot
	// named with CurrencySuffix. Column expressions must be qualified when
	// the program has a lookup, since they are referenced inside its
	// subquery.
	Column func(Slot) string
	// Table gives the table expression of each source a LOOKUP reads; nil
	// refers to the source by its quoted name.
	Table func(source string) string
	// Row gives the column that holds a system value of the document row
	// the statement runs over, asked for "state" and "id", which STATE()
	// and ID() read (ADR-0040); nil binds them to parameters, as USER().
	Row func(name string) string
}

SQLBinding says how a program's references are spelled in a statement.

type SQLExpr

type SQLExpr struct {
	// Val is the value expression: the mantissa for an exact kind.
	Val string
	// Err is the error expression, or "" when the expression cannot fail.
	Err string
	// Cur is the currency expression of a money value, NULL for a blank.
	Cur string
	// Kind is the static kind of Val.
	Kind Kind
	// Scale is the scale of an exact Val.
	Scale int8
	// Sure reports that Val is never NULL, so no COALESCE is needed.
	Sure bool
	// IsConst and Const carry a number literal, which a dialect reads for
	// an argument that must be written in the formula, such as places.
	IsConst bool
	Const   float64
}

SQLExpr is one translated expression with its static kind.

func LookupSQL added in v0.2.0

func LookupSQL(q *QuerySlot, d Dialect, arg func(i int, currency bool) string, table func(string) string, params *Params) (SQLExpr, error)

LookupSQL translates one lookup slot into a correlated scalar subquery (ADR-0020): the column of the first row of the source, in key order, on which the condition holds, NULL when none does. A row on which the condition would stop with an error does not match. arg gives the expression of the i-th THIS argument, and of its currency column when currency is set; table the expression of the source. The store's statement path and the generator's lookup instruction share it.

type SQLResult

type SQLResult struct {
	// Query is the statement that ran, for messages.
	Query string
	// Value is the value column as a Value of the program's result kind.
	Value Value
	// Code is the error column, or "" when NULL.
	Code string
}

SQLResult is what RunSQL got back from the engine.

func RunSQL

func RunSQL(db *sql.DB, d Dialect, prog *Program, vars []Value, ctx *Context) (SQLResult, error)

RunSQL executes one program through database/sql on a dialect: it generates the SQL, binds vars, one value per program slot in slot order, as named parameters over a one-row subselect, a money slot as its amount and its currency column, binds the context, and reads the value, the error and the currency columns. It is the shared half of every SQL conformance and property runner; comparing with the VM is the runner's job.

func RunSQLCase

func RunSQLCase(db *sql.DB, d Dialect, prog *Program, c *Case) (SQLResult, error)

RunSQLCase executes one evaluation case: the case inputs become the program's variables, an absent input is blank, and the case context is the context.

type SQLite

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

SQLite is the dialect for SQLite through modernc.org/sqlite.

func NewSQLite

func NewSQLite() SQLite

NewSQLite makes the SQLite dialect under the default limits.

func (SQLite) Call

func (d SQLite) Call(name string, args []SQLExpr, params *Params) (SQLExpr, error)

Call implements Dialect.

func (SQLite) ColumnType added in v0.2.0

func (SQLite) ColumnType(k Kind) string

ColumnType implements Dialect: SQLite's storage classes, a date as INTEGER days and a datetime as INTEGER seconds (ADR-0023), an exact value as its INTEGER mantissa (ADR-0022), a bool as 0 or 1.

func (SQLite) Cond

func (c SQLite) Cond(e SQLExpr) string

Cond reads an expression as a condition: a blank is FALSE.

func (SQLite) ContextArgs

func (SQLite) ContextArgs(ctx *Context) []any

ContextArgs implements Dialect: now is always bound, user is text or NULL, groups is the text groupsArg makes or NULL.

func (SQLite) ContextArgsFor added in v0.3.0

func (d SQLite) ContextArgsFor(ctx *Context, names []string, dst []any) []any

ContextArgsFor appends to dst the context parameters a statement uses, by name as SQL.Params lists them, bound as ContextArgs binds them. A statement that reads no context binds nothing, which keeps a lookup inside a commit free of the cost of parameters it never reads.

func (SQLite) False

func (SQLite) False() string

False implements Dialect.

func (SQLite) IntLit added in v0.2.0

func (SQLite) IntLit(m int64) string

IntLit implements Dialect.

func (SQLite) Limits

func (d SQLite) Limits() Limits

Limits implements Dialect.

func (SQLite) Load

func (SQLite) Load(column string, k Kind) string

Load implements Dialect.

func (SQLite) Mant added in v0.2.0

func (c SQLite) Mant(e SQLExpr) string

Mant reads an exact expression's mantissa as a non-null integer in the arithmetic type: a blank is 0, a bool 1 or 0.

func (SQLite) Name

func (SQLite) Name() string

Name implements Dialect.

func (SQLite) Narrow added in v0.2.0

func (SQLite) Narrow(val string) string

Narrow implements Dialect: an integer result is already 64-bit.

func (SQLite) NotFinite

func (SQLite) NotFinite(val string) string

NotFinite implements Dialect. SQLite yields NULL for NaN and keeps infinities, so both are checked.

func (SQLite) Num

func (c SQLite) Num(e SQLExpr) string

Num reads an expression as a number: a blank is 0, a bool is 1 or 0.

func (SQLite) NumberLit

func (SQLite) NumberLit(f float64) string

NumberLit implements Dialect. The literal always reads as REAL.

func (SQLite) OverflowErr added in v0.2.0

func (SQLite) OverflowErr(val string) string

OverflowErr implements Dialect: an integer operation that overflows turns REAL in SQLite; a NULL is a blank, not an overflow.

func (SQLite) Param

func (SQLite) Param(name string) string

Param implements Dialect.

func (SQLite) Pow

func (SQLite) Pow(x, y string) string

Pow implements Dialect: the engine's own power function, not SQLite's.

func (SQLite) RawMant added in v0.2.0

func (c SQLite) RawMant(e SQLExpr) string

RawMant reads an exact expression's mantissa in the arithmetic type with a blank kept NULL.

func (SQLite) Render

func (d SQLite) Render(e SQLExpr) string

Render implements Dialect: the TEXT rule of ADR-0019 and ADR-0022.

func (SQLite) Setup

func (SQLite) Setup() []string

Setup implements Dialect: the engine functions come from the sqlitefn package's registration, not from statements.

func (SQLite) Text

func (c SQLite) Text(e SQLExpr) string

Text reads an expression as text: a blank is the empty text.

func (SQLite) TextLit

func (SQLite) TextLit(s string) string

TextLit implements Dialect.

func (SQLite) True

func (SQLite) True() string

True implements Dialect: SQLite has no bool type, so 1 and 0.

func (SQLite) WithLimits

func (d SQLite) WithLimits(l Limits) Dialect

WithLimits implements Dialect.

type Scope

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

Scope is the set of variables a formula may read. Names resolve case-insensitively (ADR-0013).

func NewScope

func NewScope(vars ...Variable) (*Scope, error)

NewScope makes a scope. A name declared twice, in any case, is an error.

func ScopeOf

func ScopeOf(vars map[string]string, schemas map[string]map[string]string) (*Scope, error)

ScopeOf builds the scope of a suite's variables, in name order, with object<Name> types resolved against the schemas.

func (*Scope) Lookup

func (s *Scope) Lookup(name string) (Variable, bool)

Lookup finds a variable by name, case-insensitively.

type Slot

type Slot struct {
	Name string
	Type Type
}

Slot is one variable the program reads. The engine supplies values in slot order.

type Source added in v0.2.0

type Source struct {
	Name    string
	Columns []Field
	// Key lists the columns that order the source. LOOKUP returns the
	// first matching row in this order (ADR-0020).
	Key []string
	// Binding is sqlite, duckdb or external (ADR-0016); "" is the
	// store's default.
	Binding string
}

Source is an explicit table a LOOKUP or QUERY may read (ADR-0016, ADR-0020): its columns with their scalar types, the columns whose order is its key order, and the binding that says where its rows live.

func (*Source) Column added in v0.2.0

func (s *Source) Column(name string) (Field, bool)

Column finds a column by name, case-insensitively.

func (*Source) ColumnNames added in v0.2.0

func (s *Source) ColumnNames() []string

ColumnNames lists the columns in order.

type SourceSet added in v0.2.0

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

SourceSet is a Sources over a list, resolved case-insensitively. A nil SourceSet has no sources.

func NewSourceSet added in v0.2.0

func NewSourceSet(srcs ...*Source) *SourceSet

NewSourceSet makes a set of the sources.

func (*SourceSet) Add added in v0.2.0

func (s *SourceSet) Add(src *Source)

Add adds or replaces a source.

func (*SourceSet) Names added in v0.2.0

func (s *SourceSet) Names() []string

Names lists the sources in the order they were added.

func (*SourceSet) Source added in v0.2.0

func (s *SourceSet) Source(name string) (*Source, bool)

Source implements Sources.

type Sources added in v0.2.0

type Sources interface {
	Source(name string) (*Source, bool)
}

Sources resolves the sources a formula may read, by name.

type Suite

type Suite struct {
	// Suite is the short name, unique across files.
	Suite       string `json:"suite"`
	Description string `json:"description,omitempty"`
	// Variables declares the input variables the cases may set, by type:
	// bool, number, text, date, ref, json, array<scalar>, rows, or
	// object<Name> for a schema of Schemas.
	Variables map[string]string `json:"variables,omitempty"`
	// Schemas declares object schemas by name: field name to type, where
	// a type may be object<Name> of another schema (ADR-0031). A case sets
	// an object's leaf by its path, "shipping.city".
	Schemas map[string]map[string]string `json:"schemas,omitempty"`
	// Sources declares the explicit tables LOOKUP may read (ADR-0020),
	// with their rows.
	Sources map[string]*SuiteSource `json:"sources,omitempty"`
	// Limits sets the size limits the cases evaluate under (ADR-0021);
	// absent, the defaults. A suite at a small limit reaches the boundary
	// with short texts.
	Limits *SuiteLimits `json:"limits,omitempty"`
	Cases  []Case       `json:"cases"`
	// File is where the suite was loaded from, for messages.
	File string `json:"-"`
}

Suite is one file of evaluation cases.

func LoadSuites

func LoadSuites(dir string) ([]*Suite, error)

LoadSuites loads every evaluation suite from dir, sorted by file name.

func (*Suite) EvalLimits

func (s *Suite) EvalLimits() Limits

EvalLimits are the limits the suite's cases evaluate under.

func (*Suite) Executor added in v0.2.0

func (s *Suite) Executor() (*MemoryExecutor, error)

Executor makes the in-memory executor over the suite's sources.

func (*Suite) Scope added in v0.2.0

func (s *Suite) Scope() (*Scope, error)

Scope builds the scope of the suite's variables, in name order.

func (*Suite) SourceRows added in v0.2.0

func (s *Suite) SourceRows() (map[*Source][][]Value, error)

SourceRows parses the rows of every source, row-major in column order.

func (*Suite) SourceSet added in v0.2.0

func (s *Suite) SourceSet() (*SourceSet, error)

SourceSet resolves the suite's sources.

type SuiteLimits

type SuiteLimits struct {
	MaxText int `json:"max_text"`
}

SuiteLimits is the limits field of a suite.

type SuiteSource added in v0.2.0

type SuiteSource struct {
	Columns map[string]string            `json:"columns"`
	Key     []string                     `json:"key"`
	Rows    []map[string]json.RawMessage `json:"rows,omitempty"`
}

SuiteSource declares one table a suite's LOOKUP cases read: its columns by scalar type, its key columns, and its rows as objects in the input notation, an absent column blank. Columns are in name order.

type SyntaxSuite

type SyntaxSuite struct {
	Suite       string            `json:"suite"`
	Description string            `json:"description,omitempty"`
	Variables   map[string]string `json:"variables,omitempty"`
	Accept      []string          `json:"accept"`
	Reject      []RejectCase      `json:"reject"`
	File        string            `json:"-"`
}

SyntaxSuite is one file of definition-time cases: formulas the parser must accept and formulas it must reject.

func LoadSyntaxSuites

func LoadSyntaxSuites(dir string) ([]*SyntaxSuite, error)

LoadSyntaxSuites loads every syntax suite from dir, sorted by file name.

type TextLit

type TextLit struct {
	Value string
	P     int
}

TextLit is a text literal.

func (*TextLit) Pos

func (n *TextLit) Pos() int

Pos implements Node.

type ThisRef

type ThisRef struct {
	Name string
	P    int
}

ThisRef is THIS.name: the document's variable inside LOOKUP and QUERY.

func (*ThisRef) Pos

func (n *ThisRef) Pos() int

Pos implements Node.

type Token

type Token struct {
	Kind TokenKind
	// Text is the name as written for a name, the unescaped value for a
	// text literal, and the source text otherwise.
	Text string
	// Num is the value of a number literal.
	Num float64
	// Pos is the byte offset of the token in the formula.
	Pos int
}

Token is one lexical token with its position in the formula.

func Lex

func Lex(src string) ([]Token, error)

Lex splits a formula into tokens. The last token is always TokEOF. The grammar is ADR-0019's: numbers, double-quoted text with "" for a quote, names, case-insensitive keywords, and the operator set + - * / \ ^ % & = <> < <= > >= with parentheses, commas and dots.

type TokenKind

type TokenKind uint8

TokenKind is the kind of a lexical token.

const (
	TokEOF TokenKind = iota
	TokNumber
	TokText
	TokIdent

	TokAnd
	TokOr
	TokNot
	TokIf
	TokThen
	TokElse
	TokTrue
	TokFalse
	TokBlank
	TokThis

	TokLParen
	TokRParen
	TokComma
	TokDot
	TokPlus
	TokMinus
	TokStar
	TokSlash
	TokBackslash
	TokCaret
	TokPercent
	TokAmp
	TokEq
	TokNe
	TokLt
	TokLe
	TokGt
	TokGe
)

Token kinds. Keywords are case-insensitive and reserved (ADR-0019).

func (TokenKind) String

func (k TokenKind) String() string

type Type

type Type struct {
	Kind Kind
	// Scale is the number of digits after the point of a decimal or money
	// type, 0 to MaxScale. For an array it is the element's scale.
	Scale int8
	// Elem is the element kind of an array.
	Elem Kind
	// contains filtered or unexported fields
}

Type is a static type: a scalar kind with its scale when it is exact, an array of a scalar kind, rows with a schema, or an object of a named schema. The struct is two words: what only composites and objects carry lives behind a pointer, since the binder passes types by value on every expression.

func ArrayOf

func ArrayOf(elem Kind) Type

ArrayOf makes the type of an array of a scalar kind.

func DecimalType added in v0.2.0

func DecimalType(scale int) Type

DecimalType makes an exact decimal type at the scale.

func MoneyType added in v0.2.0

func MoneyType(scale int) Type

MoneyType makes a money type at the scale.

func ObjectType added in v0.2.0

func ObjectType(schema string, fields []Field) Type

ObjectType makes the type of an object of a named schema.

func ParseType

func ParseType(s string) (Type, error)

ParseType reads a type as written in class definitions and in the conformance suite: a scalar name, `int`, `decimal(s)`, `money(s)`, `array<scalar>`, or `rows`. `decimal` alone is `decimal(2)` and `money` alone is `money(2)`. It also reads "blank", the static type of a formula that is BLANK, so that every type String writes decodes again; a variable is never declared blank, which is the declaring side's check.

func RowsType added in v0.2.0

func RowsType(schema string, fields []Field) Type

RowsType makes a rows type with the given columns, of a named schema when schema is not empty.

func Scalar

func Scalar(k Kind) Type

Scalar makes the type of a scalar kind. A decimal or money kind gets scale 0; DecimalType and MoneyType take a scale.

func (Type) Cols

func (t Type) Cols() []Column

Cols are the columns of a rows type as the VM holds them; nil when unknown.

func (Type) Equal

func (t Type) Equal(o Type) bool

Equal reports whether two types are the same. Exact types compare by scale too; rows compare by schema; objects by schema name and fields.

func (Type) Field added in v0.2.0

func (t Type) Field(name string) (Field, bool)

Field finds a field by name, case-insensitively.

func (Type) FieldNames added in v0.2.0

func (t Type) FieldNames() []string

FieldNames lists the field names of an object type, for messages.

func (Type) Fields added in v0.2.0

func (t Type) Fields() []Field

Fields are the fields of an object type or the columns of rows, in declared order; nil for anything else.

func (Type) IsExact added in v0.2.0

func (t Type) IsExact() bool

IsExact reports whether the type is a decimal or money scalar.

func (Type) IsScalar

func (t Type) IsScalar() bool

IsScalar reports whether the type is a scalar, blank included.

func (Type) Schema added in v0.2.0

func (t Type) Schema() string

Schema is the schema name of an object, or of rows of a named schema, and "" otherwise.

func (Type) String

func (t Type) String() string

type Unary

type Unary struct {
	Op    TokenKind
	Const bool
	X     Node
	P     int
}

Unary is -x, NOT x, or the postfix x%. Op is TokMinus, TokNot or TokPercent. Const marks a minus or a percent of a constant expression, which the binder folds.

func (*Unary) Pos

func (n *Unary) Pos() int

Pos implements Node.

type VM

type VM struct {
	// Limits are the size limits of the database the programs belong to
	// (ADR-0021). NewVM sets the defaults; set others before Run.
	Limits Limits
	// Executor answers LOOKUP (ADR-0020). A program with a lookup and no
	// executor stops with query_failed.
	Executor QueryExecutor
	// contains filtered or unexported fields
}

VM executes programs. A VM is not safe for concurrent use; make one per goroutine. Its stack is reused across runs.

func NewVM

func NewVM() *VM

NewVM makes a VM with the default limits.

func (*VM) Run

func (vm *VM) Run(p *Program, vars []Value, ctx *Context) (Value, error)

Run executes the program. vars holds one value per program slot, in slot order. ctx may be nil when the program uses no context function.

type Value

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

Value is a run-time value. Scalars live in the struct and never allocate: bool, number, date and datetime in num, text, ref and json in str, and an exact number's mantissa in the bits of num with its scale beside it, so that the struct stays four words wide (ADR-0022). Composites (ADR-0013) will hang off pointers added with the composites change; the scalar layout does not move. The zero Value is blank.

func Blank

func Blank() Value

Blank is the blank value.

func Bool

func Bool(b bool) Value

Bool makes a bool value.

func Date

func Date(days int64) Value

Date makes a date value from days since 1970-01-01.

func DateTime added in v0.2.0

func DateTime(secs int64) Value

DateTime makes a datetime value from seconds since the epoch, UTC.

func Day added in v0.2.0

func Day(year int, month int, day int) Value

Day makes a date value from a calendar day of the proleptic Gregorian calendar, as DATE(year, month, day) does; the month and the day normalise as time.Date normalises them.

func Decimal added in v0.2.0

func Decimal(mant int64, scale int) Value

Decimal makes an exact value from a mantissa at a scale: Decimal(1230, 2) is 12.30.

func ExactFromFloat added in v0.2.0

func ExactFromFloat(f float64, t Type) (Value, bool)

ExactFromFloat makes a decimal of the type from a float64 that is exactly a value at the type's scale, as a bare literal meeting an exact variable is read (ADR-0022): 0 and 12.3 fit a decimal(2), 0.125 does not. It reports whether the float fit.

func JSON

func JSON(s string) Value

JSON makes a json value from its text.

func Money added in v0.2.0

func Money(mant int64, scale int, currency string) Value

Money makes a money value from a mantissa, a scale and a currency code.

func Number

func Number(f float64) Value

Number makes a number value.

func ParseCaseValue

func ParseCaseValue(raw json.RawMessage, t Type) (Value, error)

ParseCaseValue reads a case value written in the suite notation as a value of the given type. An exact value is written as a JSON number or as text, read exactly and brought to the type's scale, which must not drop a digit; a money value is text such as "12.30 PLN".

func Ref

func Ref(s string) Value

Ref makes a ref value from its Class:id form.

func Text

func Text(s string) Value

Text makes a text value.

func ValueFromDriver

func ValueFromDriver(v any, k Kind) Value

ValueFromDriver converts a value as a database driver delivers it (nil, int64, float64, string or []byte) to a Value of the expected kind. KindNull means "whatever it is": numbers become numbers and text text. KindDecimal reads a raw mantissa at scale 0; ValueOfType reads a typed value with its scale and currency.

func ValueOfType added in v0.2.0

func ValueOfType(v any, t Type, cur any) Value

ValueOfType converts a driver value to a Value of a static type: an exact value gets the type's scale, a money value its currency from cur, and is blank when the currency is.

func (Value) Currency added in v0.2.0

func (v Value) Currency() string

Currency returns the currency code of a money value, "" otherwise.

func (Value) Days added in v0.2.0

func (v Value) Days() int64

Days returns the days of a date value.

func (Value) DriverValue

func (v Value) DriverValue() any

DriverValue converts a Value to what a database driver takes: nil, float64, int64 or string. A date is REAL days, a datetime REAL seconds, a bool 0 or 1, an exact value its mantissa; a money's currency is bound apart, from Currency.

func (Value) IsBlank

func (v Value) IsBlank() bool

IsBlank reports whether the value is blank.

func (Value) Kind

func (v Value) Kind() Kind

Kind is the run-time kind of the value.

func (Value) Mant added in v0.2.0

func (v Value) Mant() int64

Mant returns the mantissa of a decimal or money value, and 0 for a blank.

func (Value) Num

func (v Value) Num() float64

Num returns the number of a number, the 1 or 0 of a bool, the days of a date, the seconds of a datetime, and 0 for a blank: the zero of ADR-0005. It is meaningless for a decimal or a money; use Mant.

func (Value) Scale added in v0.2.0

func (v Value) Scale() int

Scale returns the scale of a decimal or money value.

func (Value) Secs

func (v Value) Secs() int64

Secs returns the seconds of a datetime value.

func (Value) Str

func (v Value) Str() string

Str returns the text of a text, ref or json value, the currency of a money, and "" for a blank.

func (Value) String

func (v Value) String() string

String renders the value for messages and tests, as the TEXT function does, with blank shown as BLANK and text quoted.

func (Value) Truth

func (v Value) Truth() bool

Truth returns the value as a condition: TRUE is true, FALSE and blank are false.

type Variable

type Variable struct {
	Name string
	Type Type
}

Variable is one name a formula may read.

Directories

Path Synopsis
Package fuzz generates random, well-typed formulas with inputs and runs each one on the Go VM and on a SQL dialect, reporting any divergence.
Package fuzz generates random, well-typed formulas with inputs and runs each one on the Go VM and on a SQL dialect, reporting any divergence.
Package sqlitefn registers the formula engine's Go functions into the pure-Go SQLite driver, so that the SQLite dialect of the SQL generator agrees with the Go VM by construction (ADR-0019).
Package sqlitefn registers the formula engine's Go functions into the pure-Go SQLite driver, so that the SQLite dialect of the SQL generator agrees with the Go VM by construction (ADR-0019).

Jump to

Keyboard shortcuts

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