Dmn.Compiler.Checks (dmn v0.1.0)

Copy Markdown View Source

What the types of FEEL can say of a decision table before it runs (Feel.Rules).

The input entries of a table are unary tests, and the input of a column has the type the analysis gives its expression, so a rule is a set of inputs and the questions about a table are about sets: does a pair of rules share an input, is a rule never reached, does the table take every input. Each answer of Feel.Rules is proved, refuted with an input that shows it, or unknown, and only what is shown is said:

CodeSeverityWhen
:overlapping_ruleswarningtwo rules of a UNIQUE table that an input matches both of (the table is null with an error for it)
:dead_rulewarninga rule of a FIRST table that the rules before it take every input of
:incomplete_tableinfoa table with no default output that an input matches no rule of (the table is null for it)
:table_not_checkedinfoa check ran out of time or memory, raised, or found mismatched model/prepared table dimensions

The input that shows it is in the details as input, by the name input 1, input 2, … of the column. The questions are asked of a table of at most 200 rules and 4,000 cells (rules times inputs), since the pairs of rules are the square of the first and each cell is prepared for each question; a table of more is not asked. Size skips and tables with no inputs produce a :table_not_checked diagnostic. Individual proof questions can still be unknown; absence of a warning is not a proof.

The time is not bounded by the size of a table (100 rules of ranges and not(…) with 4 inputs took 38 s), so the questions about a table are asked in a process that is ended at a deadline (Feel.Worker), and there is a deadline for all the tables of a compile (table_check_timeout and checks_timeout of Dmn.Limits). A table that passed one is an info (:table_not_checked), and says nothing of its rules.

The columns, rules and policy are those of the model; the types come from the prepared expression, in which a decision table is a node whose span is the glue of the table (Dmn.Compiler.Source), and whose place in the model is its path. Prepared wildcard entries use the column's effective inputValues; explicit entries use their own tests. Source preparation retains the unit's named type definitions, including aliases and qualified names, even when analysis has resolved or folded away an instance of reference. Proofs exclude null from column types, matching the table's null-input behavior. A bound containing only null falls back to non-null Any. Questions concern these abstract column domains, not reachability through upstream decisions or concrete host bindings. A test that depends on model/local bindings, filter fields, dynamic lookup, extension calls or indirect calls is passed as :unknown: possible inputs are the whole column and certain inputs are empty. Resolved builtin aliases retain their binding provenance. Independent cells and rules can still prove facts; model functions are not invoked for proof construction (DD-43). Effective-source and column preparation run inside the same deadline/memory guard as the queries, after the size checks. Reported witnesses are not universally revalidated against original entries.

Summary

Types

How long the questions may take: table milliseconds for each table, until deadline (in System.monotonic_time(:millisecond)) for all of them, within max_memory bytes.

Functions

The diagnostics for the decision tables of an expression. tables are the tables the compiler made nodes of, by their path. types must contain the named type definitions from the scope used to prepare the expression.

Types

budget()

@type budget() :: %{
  table: pos_integer(),
  deadline: integer(),
  max_memory: pos_integer()
}

How long the questions may take: table milliseconds for each table, until deadline (in System.monotonic_time(:millisecond)) for all of them, within max_memory bytes.

Functions

tables(expression, tables, source, owner, budget, types \\ %{})

@spec tables(
  Feel.Expression.t(),
  %{optional([term()]) => Dmn.Model.DecisionTable.t()},
  Dmn.Compiler.Source.finished(),
  String.t(),
  budget(),
  %{optional(String.t()) => Feel.Type.t()}
) :: [Dmn.Diagnostic.t()]

The diagnostics for the decision tables of an expression. tables are the tables the compiler made nodes of, by their path. types must contain the named type definitions from the scope used to prepare the expression.