Rete.Engine.State (Rete v0.1.0)

Copy Markdown View Source

Everything that changes while rules fire, as one value threaded through the loop.

Internal. A node is a function of state that returns the state plus the work it produced. The loop does the walking, which keeps propagation flat and leaves one place where listener events are emitted. See docs/design/engine.md §1.

:listeners is [{module, state}] rather than a map, so listeners see events in attachment order and one module can be attached twice with different state.

Summary

Types

A unit of pending propagation.

t()

Functions

Takes the next unit of work, or :empty.

Appends propagation work.

A state over a network, with empty memory and nothing pending.

Types

op()

@type op() ::
  {:left | :left_retract, term(), [Rete.Token.t()]}
  | {:right | :right_retract, term(), [Rete.Element.t()]}
  | {:retract_facts, term(), [term()]}
  | {:event, Rete.Listener.event()}

A unit of pending propagation.

:left carries tokens from a parent, :right carries elements from an alpha.

The last two are work a node produces but cannot carry out where it happens. A retraction has to re-enter the alpha network, and telling a listener is not a node's business.

t()

@type t() :: %Rete.Engine.State{
  agenda: Rete.Agenda.t(),
  fired: non_neg_integer(),
  listeners: [{module(), term()}],
  memory: Rete.Memory.t(),
  network: Rete.Network.t(),
  order: %{required(term()) => non_neg_integer()},
  queue: :queue.queue(op())
}

Functions

dequeue(state)

@spec dequeue(t()) :: {:ok, op(), t()} | :empty

Takes the next unit of work, or :empty.

enqueue(state, ops)

@spec enqueue(t(), [op()]) :: t()

Appends propagation work.

new(network)

@spec new(Rete.Network.t()) :: t()

A state over a network, with empty memory and nothing pending.

:order is the compile position of each production, so two activations of equal salience fire in the order the rules were written.