Adds e to congruence table.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Returns true if e is of the form @Eq Prop a b
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Re-entrant internalization #
internalizeImpl creates the ENode of an application before visiting its arguments, because
registerParent and the congruence table need the node of the parent. Until the argument loop
finishes, the application is in progress: alreadyInternalized holds for it, but some of its
arguments may have no ENode yet.
We say u is a strict ancestor of t if u is an in-progress application and t is one of
its proper subterms. The in-progress applications are exactly the strict ancestors of the term
currently being internalized.
Invariant. While t is being internalized, solver code must not call internalize on a term
that is, or contains, a strict ancestor of t.
Why it matters. The alreadyInternalized branch of internalizeImpl treats its argument as
complete: it does not visit the arguments again, and it hands the term to the solver hooks so that
they can register it under a new parent. If the term is a strict ancestor, the hooks see a term
with missing arguments. The ring solver, for example, reifies it and asks for a variable for an
argument that has no ENode. The branch is also what keeps the descent finite: without it,
re-internalizing an ancestor would visit the current term again.
How it is maintained. The solver hooks run synchronously at the end of a term's
internalization, so they run while the strict ancestors of that term are in progress. They are the
only solver code that runs in this position. The newEq/newDiseq callbacks triggered by
SolverExtension.markTerm are queued (ToProcessElement.solverEq), and so are the propagators
(ToProcessElement.propagateUp); both run from processToDo, when no application is in progress.
A hook therefore only has to avoid internalizing a term that contains one of its own strict
ancestors. A hook that must state a fact about such a term queues it with pushNewFactCore; the
term is internalized when the fact is processed.
Checking. When isDebugEnabled holds, GoalState.internalizing holds the in-progress
applications, and the alreadyInternalized branch throws an internal error if it reaches one of
them.