Rete.Compiler (Rete v0.2.0)

Copy Markdown View Source

Turns ruleset modules into a Rete.Network.

Internal. The DSL front end already ran at compile time inside each defrule. What is left at build time is the part that depends on the whole set of rules:

Rete.Compiler.Negation   rewrite compound negations into helper productions
disambiguate_codes/1     qualify an expression code two modules disagree on
Rete.Compiler.BetaGraph  build the beta nodes, sharing them where possible
Rete.Network             group conditions into alpha nodes, index the taxonomy

Node sharing is why this cannot happen per rule. Whether two conditions collapse onto one node depends on what every other rule already put in the graph.

Cross-module expression codes. A code is equal exactly when two expressions behave the same — with one hole. An unqualified call hashes as the bare name. So two modules that each define ok?/1 differently produce the same code for {:bar, amt} when ok?(amt). The compiler qualifies a code more than one module contributed as <code>@<module>, before building anything from it. Sharing within a module is untouched. Sharing across modules is only an optimisation, and getting it wrong is silent corruption. See docs/design/ir.md §5.

Summary

Functions

Builds a network from ruleset modules.

Builds a network from productions directly, bypassing module aggregation.

Qualifies every expression code that more than one module contributed.

The beta graph of a network, for inspection.

Functions

build(modules, opts \\ [])

@spec build(
  [module()],
  keyword()
) :: Rete.Network.t()

Builds a network from ruleset modules.

Options go to Rete.Taxonomy.new/2. :fact_type_fn is the one that matters, and it defaults to struct, tagged tuple and tagged map.

Rete.Compiler.build([MyRuleset])
Rete.Compiler.build([MyRuleset, OtherRuleset], fact_type_fn: &MyApp.type/1)

build_productions(productions, taxo_data \\ [], opts \\ [])

@spec build_productions([Rete.IR.Production.t()], [tuple()], keyword()) ::
  Rete.Network.t()

Builds a network from productions directly, bypassing module aggregation.

Useful for testing a set of productions without a ruleset module per case.

disambiguate_codes(productions)

@spec disambiguate_codes([Rete.IR.Production.t()]) :: [Rete.IR.Production.t()]

Qualifies every expression code that more than one module contributed.

If only one module produces an expression's code, this leaves it alone. So nothing changes for a single-module network. See the module doc for why a shared code cannot be trusted across modules.

This is exposed so a test can check the disambiguation, without building a network.

graph(network)

The beta graph of a network, for inspection.