Documentation
¶
Overview ¶
Package feel implements the FEEL expression language: the lexer, parser, AST, type system, type checker and the compiler that lowers expressions into reusable Go closures (CompiledExpr).
The compiler follows the two-phase principle: expensive work happens once at compile time, while the resulting closure evaluates with minimal allocation on the hot path. Numbers are decimal (never float64); see ADR-0007.
The lexer (token.go, lexer.go) and the parser (ast.go, parser.go) are implemented; the type system, compiler and built-ins follow in WP-05ff.
Example ¶
Compile a FEEL expression once, then evaluate it against different inputs.
package main
import (
"fmt"
"github.com/pblumer/feel"
"github.com/pblumer/feel/value"
)
func main() {
// Declare the variables the expression may reference.
env := feel.NewEnv("Season", "Guest Count")
// Parse + type-check + compile into a reusable Go closure.
expr, err := feel.CompileString(
`if Season = "Winter" and Guest Count > 8 then "Spareribs" else "Salad"`,
env,
)
if err != nil {
panic(err)
}
// Evaluate: bind values by name and run the closure.
out, err := expr(env.NewScope(map[string]value.Value{
"Season": value.Str("Winter"),
"Guest Count": value.NumberFromInt64(10),
}))
if err != nil {
panic(err)
}
fmt.Println(out)
}
Output: Spareribs
Index ¶
- Constants
- Variables
- func CoerceArg(v value.Value, t *Type) (value.Value, bool)
- func CoerceToType(v value.Value, t *Type) value.Value
- func ConformsToType(v value.Value, t *Type) bool
- func ConstValue(src string) (value.Value, bool)
- func Matches(test CompiledExpr, s *Scope) (bool, error)
- func NullExpr(s *Scope) (value.Value, error)
- type Arg
- type AtLit
- type BetweenExpr
- type BinaryExpr
- type BoolLit
- type CallExpr
- type CmpTest
- type CompileError
- type CompiledExpr
- func BoxedFilter(coll CompiledExpr, matchSrc string, env *Env, funcs map[string]*Func) (CompiledExpr, error)
- func CallFunc(f *Func, args []CompiledExpr) CompiledExpr
- func CallValue(callee CompiledExpr, args []CompiledExpr) CompiledExpr
- func Compile(expr Expr, env *Env) (CompiledExpr, error)
- func CompileString(src string, env *Env) (CompiledExpr, error)
- func CompileStringRefs(src string, env *Env) (CompiledExpr, []string, error)
- func CompileStringWith(src string, env *Env, funcs map[string]*Func) (CompiledExpr, error)
- func CompileUnaryTest(src string, env *Env) (CompiledExpr, error)
- func CompileUnaryTestWith(src string, env *Env, funcs map[string]*Func) (CompiledExpr, error)
- func CompileWith(expr Expr, env *Env, funcs map[string]*Func) (CompiledExpr, error)
- func ForOne(coll, body CompiledExpr) CompiledExpr
- func FuncValue(params []string, body CompiledExpr) CompiledExpr
- func IfThenElse(cond, then, els CompiledExpr) CompiledExpr
- func QuantifyOne(some bool, coll, pred CompiledExpr) CompiledExpr
- type ContextEntry
- type ContextLit
- type Env
- func (e *Env) Append(name string) *Env
- func (e *Env) Derive(extra ...string) *Env
- func (e *Env) Has(name string) bool
- func (e *Env) Names() []string
- func (e *Env) NewScope(values map[string]value.Value) *Scope
- func (e *Env) NewScopeShared(values map[string]value.Value, st *EvalState) *Scope
- func (e *Env) NewScopeWithLimits(values map[string]value.Value, lim Limits) *Scope
- func (e *Env) WithTypes(types map[string]*Type) *Env
- type EvalState
- type Expr
- type FilterExpr
- type ForExpr
- type Func
- type FunctionDefExpr
- type IfExpr
- type InExpr
- type InstanceOfExpr
- type IntervalLit
- type Iterator
- type Kind
- type Lexer
- type LimitError
- type Limits
- type ListLit
- type NameRef
- type NameSet
- type NullLit
- type NumberLit
- type Param
- type ParseError
- type PathExpr
- type Position
- type QuantifiedExpr
- type Scope
- type StringLit
- type Token
- type Type
- type TypeEnv
- type TypeError
- type UnaryExpr
Examples ¶
Constants ¶
const DefaultMaxCallDepth = 256
DefaultMaxCallDepth bounds nested user-function (BKM / function literal) calls, turning unbounded recursion into a runtime error instead of a stack overflow (ADR-0008).
const DefaultMaxParseDepth = 10_000
DefaultMaxParseDepth bounds the syntactic nesting the parser will descend into, turning pathologically deep input (e.g. millions of prefix `-` or nested `(`/`[`) into a *ParseError instead of a fatal stack overflow that would crash the whole process (audit finding K1, ADR-0008). It sits far above any realistic DMN model, whose FEEL nesting is in the low tens.
const InputVar = "?"
InputVar is the name of the implicit input value inside a decision-table unary test. In FEEL a cell like "< 18" means "? < 18", where ? is the value being tested. The decision-table compiler (WP-09) binds this variable per input column.
Variables ¶
var ( TNumber = &Type{Kind: value.KindNumber} TString = &Type{Kind: value.KindString} TBoolean = &Type{Kind: value.KindBool} TDate = &Type{Kind: value.KindDate} TTime = &Type{Kind: value.KindTime} TDateTime = &Type{Kind: value.KindDateTime} TDaysTimeDuration = &Type{Kind: value.KindDaysTimeDuration} TYearsMonthsDuration = &Type{Kind: value.KindYearsMonthsDuration} TNull = &Type{Kind: value.KindNull} )
Built-in scalar type singletons. nil is used directly for Any.
Functions ¶
func CoerceArg ¶
CoerceArg coerces a call argument to a formal parameter's declared type. Unlike CoerceToType it distinguishes a genuine non-conformance (ok=false) from a valid coercion, so an invocation can evaluate to null as a whole — the function is "not invoked" — rather than binding a silently-nulled argument (DMN §10.4, TCK 0082/0085). A null argument conforms to every type.
func CoerceToType ¶
CoerceToType applies FEEL's item-definition coercion of a value to a declared type (DMN §10.3.2.9.4): a conforming value is kept; a singleton list whose sole element conforms is unwrapped to that element; anything else becomes null. A nil *Type (Any) imposes nothing.
func ConformsToType ¶
ConformsToType reports whether v is a member of the FEEL type t. null is a member of every type; a nil *Type is Any and accepts anything; lists and contexts are checked element- and field-wise against any declared element or field types (DMN §10.3.2.9.4).
func ConstValue ¶
ConstValue returns the value of src when it is a single constant literal — a number, string, boolean, null or @-temporal — and false otherwise. It lets a caller evaluate a constant cell (e.g. a decision-table output) without a scope, for example to test it against an allowed-values constraint (WP-31).
Types ¶
type AtLit ¶
type AtLit struct {
Value string
// contains filtered or unexported fields
}
AtLit is a temporal literal such as @"2024-01-01"; Value holds the content.
type BetweenExpr ¶
type BetweenExpr struct {
X, Low, High Expr
// contains filtered or unexported fields
}
BetweenExpr is `X between Low and High`.
func (*BetweenExpr) String ¶
func (n *BetweenExpr) String() string
type BinaryExpr ¶
BinaryExpr is an infix operation (arithmetic, boolean or comparison).
func (*BinaryExpr) String ¶
func (n *BinaryExpr) String() string
type BoolLit ¶
type BoolLit struct {
Value bool
// contains filtered or unexported fields
}
BoolLit is a true/false literal.
type CmpTest ¶
CmpTest is an operator-prefixed positive unary test on the right-hand side of `in`, e.g. the `<= 10` in `x in <= 10` or the explicit `= 10` in `x in = 10`. It compares the in-value against Y with Op (one of < <= > >= = !=). It only occurs inside InExpr.Tests.
type CompileError ¶
CompileError is a compile-time failure (unknown variable, unsupported construct, malformed literal) with its source position.
func (*CompileError) Error ¶
func (e *CompileError) Error() string
type CompiledExpr ¶
CompiledExpr is a compiled FEEL expression: a pure Go closure that evaluates against a Scope. It performs no AST walk or reflection in the hot path (ADR-0004) and is immutable, so it may be evaluated concurrently.
func BoxedFilter ¶
func BoxedFilter(coll CompiledExpr, matchSrc string, env *Env, funcs map[string]*Func) (CompiledExpr, error)
BoxedFilter compiles a boxed filter: coll is the already-compiled collection and matchSrc the FEEL predicate text, compiled against env extended with the implicit element variable item (its context keys resolve directly, e.g. `age > 18`). A numeric predicate selects by index (WP-26).
func CallFunc ¶
func CallFunc(f *Func, args []CompiledExpr) CompiledExpr
CallFunc returns a CompiledExpr that calls the statically known function f with the given compiled arguments (already arranged in f's parameter order), under the recursion-depth limit. It is the entry point boxed invocations use to call a business knowledge model.
func CallValue ¶
func CallValue(callee CompiledExpr, args []CompiledExpr) CompiledExpr
CallValue returns a CompiledExpr that evaluates callee to a function value and calls it with the compiled positional arguments. A callee that is not a function yields null.
func Compile ¶
func Compile(expr Expr, env *Env) (CompiledExpr, error)
Compile lowers an AST into a CompiledExpr, resolving variable names to slots via env. It returns the first CompileError encountered, if any.
func CompileString ¶
func CompileString(src string, env *Env) (CompiledExpr, error)
CompileString parses and compiles src in one step. It supplies the built-in registry as the parser's name oracle so multi-word builtin names whose fragments include keywords (e.g. "index of") assemble correctly.
func CompileStringRefs ¶
func CompileStringRefs(src string, env *Env) (CompiledExpr, []string, error)
CompileStringRefs is CompileString that also returns which of env's variable names the expression references (its free variables drawn from env). It lets a caller learn an expression's dependencies without a separate AST walk — used by package dmn's CompiledExpression to report references (full-FEEL flow mappings). The returned names are sorted and unique.
func CompileStringWith ¶
CompileStringWith is CompileString with user-defined functions in scope. The parser's name oracle covers both the built-ins and the function names, so a multi-word function name (e.g. a BKM named "Rate Table") assembles correctly.
func CompileUnaryTest ¶
func CompileUnaryTest(src string, env *Env) (CompiledExpr, error)
CompileUnaryTest compiles a decision-table input-entry cell into a boolean CompiledExpr over env. env must define InputVar ("?"); a cell may also refer to other decision variables (e.g. "< limit"). An empty cell or "-" always matches.
func CompileUnaryTestWith ¶
CompileUnaryTestWith is CompileUnaryTest with user-defined functions (BKMs) in scope, so a cell that calls one (e.g. "> discount(?)") resolves it as a known function rather than an unknown name. A nil map behaves like CompileUnaryTest.
func CompileWith ¶
CompileWith is Compile with a set of user-defined functions (BKMs, boxed function definitions) in scope, resolved by name when an expression calls or references them (WP-23/WP-24). A nil map behaves like Compile.
func ForOne ¶
func ForOne(coll, body CompiledExpr) CompiledExpr
ForOne builds a boxed `for` over a single iterator: coll yields the domain (list/range/single value, per the iteration rules) and body — compiled against an env with the iterator variable appended as its trailing slot — runs for each element, collecting the results into a list (WP-26).
func FuncValue ¶
func FuncValue(params []string, body CompiledExpr) CompiledExpr
FuncValue returns a CompiledExpr that yields a first-class function value capturing the scope it is evaluated in (closure over enclosing variables). The body must have been compiled against an Env whose trailing slots are params, in order; calling the value binds the arguments to those slots (missing → null, surplus ignored) and runs the body under the recursion-depth limit.
func IfThenElse ¶
func IfThenElse(cond, then, els CompiledExpr) CompiledExpr
IfThenElse builds a FEEL conditional: then runs on the boolean true; a genuine non-boolean condition (e.g. a string) makes the whole conditional null (DMN 10.3.2.5, TCK 1150); false and null take the else branch (the common null-safe form). It is the shared runtime of the literal `if` and the boxed <conditional> (WP-26).
func QuantifyOne ¶
func QuantifyOne(some bool, coll, pred CompiledExpr) CompiledExpr
QuantifyOne builds a boxed `some` (some=true) or `every` (some=false) over a single iterator, applying FEEL's three-valued semantics: some is true on any satisfied element, every false on any unsatisfied one, with unknowns otherwise yielding null (WP-26). pred is compiled against an env with the iterator variable appended as its trailing slot.
type ContextEntry ¶
ContextEntry is a single key/value pair of a context literal.
type ContextLit ¶
type ContextLit struct {
Entries []ContextEntry
// contains filtered or unexported fields
}
ContextLit is a context literal { k: v, ... } with ordered entries.
func (*ContextLit) String ¶
func (n *ContextLit) String() string
type Env ¶
type Env struct {
// contains filtered or unexported fields
}
Env is the compile-time symbol table mapping variable names to slot indices. It defines the slot layout that a matching Scope must follow.
func (*Env) Append ¶
Append returns a new Env with name bound to a fresh trailing slot, shadowing any existing binding of the same name. Unlike Derive it always allocates a new slot, so it pairs with Scope.Extend to introduce iteration and filter variables that may shadow an outer variable of the same name.
func (*Env) Derive ¶
Derive returns a new Env with extra names appended after the existing slots. It is used to add the implicit unary-test input "?" to a decision env without disturbing the existing slot indices.
func (*Env) Has ¶
Has reports whether name is a bound variable. It lets an Env act as a parser NameSet oracle so a variable whose name embeds a keyword or a hyphen (e.g. "Date-Time") assembles as one name instead of a subtraction (WP-41.15).
func (*Env) NewScope ¶
NewScope builds a runtime Scope from named input values, placing each into its env slot. Names absent from values (or with a nil value) become null. This is the single map→slots boundary; everything past it is index-based.
func (*Env) NewScopeShared ¶
NewScopeShared builds a runtime Scope like NewScopeWithLimits but carries the caller-supplied execution state st instead of allocating a fresh one, so all scopes of a single evaluation share one state (and one allocation).
func (*Env) NewScopeWithLimits ¶
NewScopeWithLimits is NewScope with explicit resource limits enforced for the evaluation rooted at the returned scope (ADR-0008, WP-34).
type EvalState ¶
type EvalState = evalState
EvalState is the mutable per-evaluation execution state (the resource counters). It is exported as an alias so a graph evaluator can build one with NewEvalState and share it across every decision's scope via NewScopeShared, allocating it once per evaluation instead of once per decision and bounding the budgets over the whole evaluation (which is what "per-evaluation limits" means).
func NewEvalState ¶
NewEvalState builds shared per-evaluation execution state enforcing lim.
type Expr ¶
Expr is a node in the FEEL abstract syntax tree. Every node carries its source position for diagnostics and renders to a compact S-expression via String, which is the basis for the parser's table tests.
type FilterExpr ¶
FilterExpr is `X[Filter]`.
func (*FilterExpr) String ¶
func (n *FilterExpr) String() string
type Func ¶
type Func struct {
Name string
Params []string
Body CompiledExpr
// ParamTypes, when non-nil for a slot, is the formal parameter's declared type:
// an argument that does not conform (after singleton-list unwrapping) makes the
// whole invocation null (the function is "not invoked"). Shorter than Params or
// nil entries mean an unconstrained (Any) parameter.
ParamTypes []*Type
// ResultType, when set, coerces the body's result to the declared return type
// (DMN §10.3.2.9.4): a non-conforming result — or a singleton list around a
// conforming element — is coerced, otherwise null.
ResultType *Type
// Native, when set, is called instead of Body with the positional argument
// values (already padded to len(Params) with null). It lets a higher layer
// supply a callable whose behaviour is not a compiled FEEL body — e.g. package
// dmn registering a decision service as an invocable function (DMN §10.4).
Native func(args []value.Value) (value.Value, error)
}
Func is a user-defined FEEL function: a business knowledge model's encapsulated logic, or a function(...) literal compiled as a named callable.
Body is compiled against an Env whose trailing slots are the formal Params (in order); calling the function runs Body in a scope whose those slots hold the argument values. Body is assigned after compilation so a function may reference itself (recursion) or sibling functions (mutual recursion) by name.
type FunctionDefExpr ¶
type FunctionDefExpr struct {
Params []Param
External bool
Body Expr
// contains filtered or unexported fields
}
FunctionDefExpr is `function(params) body` or `function(params) external body`.
func (*FunctionDefExpr) String ¶
func (n *FunctionDefExpr) String() string
type IfExpr ¶
type IfExpr struct {
Cond, Then, Else Expr
// contains filtered or unexported fields
}
IfExpr is `if Cond then Then else Else` (else is mandatory in FEEL).
type InstanceOfExpr ¶
InstanceOfExpr is `X instance of Type`.
func (*InstanceOfExpr) String ¶
func (n *InstanceOfExpr) String() string
type IntervalLit ¶
type IntervalLit struct {
LowClosed bool
Low Expr
High Expr
HighClosed bool
// contains filtered or unexported fields
}
IntervalLit is a range literal whose endpoints may be open or closed, e.g. [1..10], (1..10], ]1..10[.
func (*IntervalLit) String ¶
func (n *IntervalLit) String() string
type Kind ¶
type Kind int
Kind enumerates the lexical token categories produced by the lexer.
Per docs/30-feel-spec.md §2 the lexer does not assemble multi-word FEEL names: it emits one Name token per identifier fragment (and distinct tokens for keywords), leaving longest-match name assembly to the parser (WP-04).
const ( EOF Kind = iota // Error marks an invalid lexeme. Its Value carries a human-readable message // and its Text the offending source. The lexer always makes progress after // an Error so tokenisation terminates on any input. Error // Literals and identifiers. Number // 42, 3.14, .5, 1.2e10 String // "abc", with escapes resolved into Value At // @"2024-01-01" temporal literal; Value holds the quoted content Name // an identifier fragment // Keywords. And Or Not If Then Else For In Return Some Every Satisfies Between Instance Of Function External True False Null // Operators. Plus // + Minus // - Star // * Slash // / Pow // ** Eq // = Neq // != Lt // < Lte // <= Gt // > Gte // >= // Punctuation. LParen // ( RParen // ) LBracket // [ RBracket // ] LBrace // { RBrace // } Comma // , Colon // : Dot // . DotDot // .. )
Token kinds.
type Lexer ¶
type Lexer struct {
// contains filtered or unexported fields
}
Lexer turns FEEL source into a stream of tokens. It never panics: malformed input yields Error tokens and the lexer always advances, so Tokenize terminates on any input (docs/30-feel-spec.md §2, WP-03 acceptance criterion).
type LimitError ¶
type LimitError struct {
Limit string // which limit: "call depth", "iterations", "list size"
Max int
}
LimitError reports that an evaluation exceeded a configured resource limit (ADR-0008). The execution-edge classifier maps it to a distinct code so a limit breach is distinguishable from other runtime failures.
func (*LimitError) Error ¶
func (e *LimitError) Error() string
type Limits ¶
type Limits struct {
MaxCallDepth int // nested user-function (BKM / function literal) calls
MaxIterations int // total iteration steps across all comprehensions
MaxListSize int // element count of any single produced list
}
Limits configures the per-evaluation resource bounds. A zero field means that dimension is unbounded; DefaultLimits supplies safe non-zero defaults.
func DefaultLimits ¶
func DefaultLimits() Limits
DefaultLimits returns the resource limits applied when none are configured. They are generous enough not to affect normal models yet bound hostile input (deep recursion, runaway comprehensions, huge lists).
type ListLit ¶
type ListLit struct {
Elements []Expr
// contains filtered or unexported fields
}
ListLit is a list literal [e1, e2, ...].
type NameRef ¶
NameRef is a (possibly multi-word) name reference. Parts holds the original fragments; Name is them joined by single spaces.
type NameSet ¶
type NameSet interface {
// Has reports whether name (fragments joined by single spaces) is known.
Has(name string) bool
}
NameSet is an optional oracle of known names. When supplied to the parser it enables longest-match assembly of multi-word names, including names that contain keywords (e.g. the builtin "date and time"). Without it, the parser greedily merges consecutive plain name fragments, which covers all names that do not embed a keyword (see ADR / docs/30-feel-spec.md §2).
type NullLit ¶
type NullLit struct {
// contains filtered or unexported fields
}
NullLit is the null literal.
type NumberLit ¶
type NumberLit struct {
Text string
// contains filtered or unexported fields
}
NumberLit is a numeric literal. The source text is kept verbatim; decimal parsing happens in WP-05.
type ParseError ¶
ParseError is a syntax error with its source position.
func (*ParseError) Error ¶
func (e *ParseError) Error() string
type QuantifiedExpr ¶
type QuantifiedExpr struct {
Quant string // "some" or "every"
Iterators []Iterator
Satisfies Expr
// contains filtered or unexported fields
}
QuantifiedExpr is `some|every it1, ... satisfies Satisfies`.
func (*QuantifiedExpr) String ¶
func (n *QuantifiedExpr) String() string
type Scope ¶
type Scope struct {
// contains filtered or unexported fields
}
Scope holds a compiled expression's variables as a flat slot array. Compiled variable accesses are resolved to slot indices at compile time (ADR-0004, architecture §5.2), so evaluation is an array index rather than a map lookup. A Scope is read-only during evaluation and therefore safe to share across goroutines.
A Scope may carry an opaque trace sink (WithTrace). The execution core treats it as an untyped value and never inspects it; a consumer that wants an explanation attaches its own recorder and type-asserts it back where it records (e.g. the decision-table evaluator). The default scope carries no sink (nil), so non-traced evaluation stays allocation-free.
func (*Scope) BindInput ¶
BindInput rebinds the implicit-input slot of a scope returned by WithInput to v. It overwrites the trailing slot in place; use only on a WithInput scope.
func (*Scope) Extend ¶
Extend returns a new Scope with extra values appended after the existing slots, matching an Env produced by Derive. The receiver is left unchanged, so a base scope can be extended repeatedly with different values.
func (*Scope) WithInput ¶
WithInput returns a scope with one extra trailing slot holding a decision-table unary test's implicit input ("?"), which the unary-test env (Env.Derive with InputVar) places last. The slot starts null; BindInput rebinds it. The scope is freshly allocated and confined to a single evaluation, so a decision table reuses one such scope across all input columns — rebinding the slot per column via BindInput — instead of allocating a scope per column. Rebinding in place is safe precisely because the scope is not shared: it is created here and only the evaluating goroutine reads it, synchronously, between rebinds.
type StringLit ¶
type StringLit struct {
Value string
// contains filtered or unexported fields
}
StringLit is a string literal with escapes already resolved into Value.
type Token ¶
type Token struct {
Kind Kind
// Text is the exact source lexeme (raw, including quotes for strings).
Text string
// Value holds decoded content for String and At tokens (escapes resolved),
// or the error message for Error tokens. It is empty otherwise.
Value string
Line int
Col int
}
Token is a single lexical token with its source position (1-based line and column, measured in runes).
type Type ¶
type Type struct {
Kind value.Kind
Elem *Type // element type for a list (nil = unknown element)
Fields map[string]*Type // field types for a context (nil = open/unknown)
}
Type is a FEEL type used by the static type checker (WP-30) and the `instance of` operator. A nil *Type means Any — an unknown or unconstrained type that the checker never flags and that conforms to (and from) every type.
Concrete scalar types are the package singletons (TNumber, TString, …). A List carries its element type in Elem (nil = list of Any); a Context carries its known field types in Fields.
func BuiltinType ¶
BuiltinType resolves a FEEL built-in type name (optionally namespace-prefixed, e.g. "feel:number", and ignoring any generic parameter) to its Type. The second result is false for a name that is not a built-in type (Any, or a user-defined item-definition type the caller must resolve itself).
type TypeEnv ¶
type TypeEnv struct {
// contains filtered or unexported fields
}
TypeEnv maps variable names to their declared types for static checking. A name that is absent (or mapped to nil) is Any and is never flagged.
type TypeError ¶
TypeError is a static type-check finding with its source position (within the expression text).
func Typecheck ¶
Typecheck statically infers types over expr against env and returns the provable type mismatches it finds. It is deliberately conservative: an operand whose type is unknown (Any) is never flagged, so a well-typed model and a model the checker cannot reason about both produce no findings — only a definite, statically-provable clash is reported. Evaluation still follows FEEL's null semantics regardless; these findings are advisory.
func TypecheckString ¶
TypecheckString parses src (using the same name oracle as compilation, so multi-word built-in and function names assemble) and type-checks it against env. A source that does not parse yields no findings — the compile path reports the syntax error separately.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package builtins is the registry of FEEL built-in functions.
|
Package builtins is the registry of FEEL built-in functions. |
|
Package value is the FEEL/DMN runtime value model: the Value interface and its concrete kinds (null, boolean, number, string, the temporal types, list, context, range and function), together with equality, ordering and arithmetic that follow FEEL semantics — most importantly decimal numbers (never float64, ADR-0007) and pervasive null propagation.
|
Package value is the FEEL/DMN runtime value model: the Value interface and its concrete kinds (null, boolean, number, string, the temporal types, list, context, range and function), together with equality, ordering and arithmetic that follow FEEL semantics — most importantly decimal numbers (never float64, ADR-0007) and pervasive null propagation. |