The shared runtime and generated-code cache stamp.
FEEL's semantics live in the runtime: arithmetic with decimal128 rounding, the three-valued logic, comparison across temporal types, filters, the built-in functions. The interpreter calls it directly, and the code that the BEAM backend generates calls nothing else. That makes it the contract between the compiler and the code it produces.
Generated code
abi/0 is a cache-generation stamp used in generated module names. It changes
when compiler/runtime changes make existing generated code unsuitable for reuse.
Only code generated by the current compiler is supported. Regenerate prepared
expressions on upgrade; persisting generated .beam files is not supported.
There is no multi-version runtime or compatibility negotiation.
The runtime functions
The runtime is a set of modules under Feel.Runtime, one per area of the
specification. They are pure functions on FEEL values (Feel.Value), each citing
the tables of DMN 1.6 it implements. A function that can fail returns an
Feel.Runtime.Env.outcome/0 and the caller settles it with Feel.Runtime.Env,
so the operations themselves touch no state.
| Module | Area |
|---|---|
Feel.Runtime.Env | mode, dialect, extensions, clock, limits, and the diagnostics of one run |
Feel.Runtime.Bindings | the values an expression reads by name |
Feel.Runtime.Kind | the kind of a value, which the tables dispatch on |
Feel.Runtime.Number | decimal128 arithmetic, rounding, scale checks |
Feel.Runtime.Number.Power | **, ln and exp, correctly rounded to 34 digits |
Feel.Runtime.Logic | three-valued and, or, not (Tables 51-52) |
Feel.Runtime.Compare | equality and ordering (Tables 50, 53-55) |
Feel.Runtime.Arithmetic | + - * / ** and negation (Tables 57-61, 63) |
Feel.Runtime.Temporal | date, time, and duration arithmetic and comparison (Tables 54, 55, 58) |
Feel.Runtime.Path | e.name and e...name: entries and properties (Tables 65-68, 71) |
Feel.Runtime.Filter | filters and indexes (Table 69) |
Feel.Runtime.TypeCheck | instance of (Table 62) |
Feel.Runtime.Invoke | function values and calls, parameter conversion (Table 64) |
Feel.Runtime.Iteration | for, some and every: the loops, partial, the domains (Table 50, 10.3.2.14) |
Feel.Runtime.Partial | the results of a for so far, for a body that only indexes partial (D-86) |
Feel.Runtime.Interpret | the interpreter's walk, for generated code that began a guarded fast path and cannot finish it (D-164) |
Feel.Runtime.UnaryTests | what it means for a value to satisfy unary tests, and in |
Feel.Runtime.RangeLiteral | the value of a range literal such as [1..10) or (< 10) |
Feel.Runtime.RangeText | reading the text of a range, for range(from) |
Feel.Runtime.TemporalText | reading the text of a time and a date and time, as the extensions spell it (D-81) |
Feel.Runtime.Regex | the regular expressions of XPath, for matches, replace and split |
Feel.Runtime.AllowedValues, BindingTypes, ResultType | the run-time half of what a scope declares: allowed values, types of the names, type of the result |
A module says in its own documentation what it leaves out. A case that the specification
defines and that is not written raises RuntimeError; a call of a built-in function that is not
written is caught earlier, as an :analysis error of Feel.prepare/2.
The built-in functions are in the modules under Feel.Builtin, one per area of
section 10.3.4 (see Feel.Builtin.areas/0). Generated code calls them as well, so
they are part of that runtime contract too.
Summary
Functions
@spec abi() :: pos_integer()
Returns the current generated-code cache stamp. It is part of the name of every generated module, so changing it when the runtime functions that generated code calls change in arity or meaning keeps the code of the old runtime from being reused.
iex> Feel.Runtime.abi()
1