AbstractClassicSolver
Base implementation of every :solve-classic it.unibo.tuprolog.solve.Solver/it.unibo.tuprolog.solve.MutableSolver (ClassicSolver and MutableClassicSolver, both internal, are the only two concrete subclasses; instances are normally obtained through ClassicSolverFactory, which is what Solver.prolog/Solver.classic resolve to).
What this class actually contributes over AbstractSolver is solveImpl: turning a goal into a Sequence of Solutions by driving the it.unibo.tuprolog.solve.classic.fsm.State finite-state machine described by the :solve-classic state-machine explanation page. Concretely, it builds the root ClassicExecutionContext for the query, wraps a fresh it.unibo.tuprolog.solve.classic.fsm.StateInit into a SolutionIterator (via the abstract solutionIterator hook, which lets subclasses choose a plain or hijackable iterator), and exposes that iterator as a lazy Sequence -- so pulling the next Solution from the sequence is exactly what drives the state machine one step further, rather than eagerly computing every solution up front. currentContext is kept in sync with the state machine's progress via updateCurrentContextAfterStateTransition, which every SolutionIterator created here is wired to call after each transition.
Running resolution as an explicit loop over it.unibo.tuprolog.solve.classic.fsm.State values, instead of host-language recursion, is what lets a resolution step be paused, resumed, or inspected without unwinding a JVM/JS call stack, and sidesteps host stack-depth limits for deeply recursive Prolog programs (the "call stack" here is the ClassicExecutionContext parent chain -- ordinary heap data).