with one click
debug-solve
// Debug solver failures or unexpected results in yopl. Use when `solve` produces no solutions, the wrong solutions, or unexpected variable bindings.
// Debug solver failures or unexpected results in yopl. Use when `solve` produces no solutions, the wrong solutions, or unexpected variable bindings.
Use the yopl Prolog-style logic engine in a JavaScript/TypeScript project. Use when adding rule-based search, pattern matching with extraction, constraint solving, type inference, planning, or expert-system style logic to a project that depends on `yopl`.
Write or update tests for a module or feature in yopl. Use when asked to write tests, add coverage, or verify functionality.
| name | debug-solve |
| description | Debug solver failures or unexpected results in yopl. Use when `solve` produces no solutions, the wrong solutions, or unexpected variable bindings. |
Debug why a yopl query failed, produced no answers, or yielded unexpected bindings.
Identify the failing query
solve(rules, name, args, callback) (or the gen / async / asyncGen variant).Understand the prove/backtrack flow
src/solve.js — prove function. Key stages per frame:
POP command → env.pop() (undo bindings on backtrack)frame.ruleList rules for the current goalenv.push(), generate fresh variables, call the rule bodyunify(terms[0].args, frame.args, env) — head unificationenv.pop() and try the next rulesrc/solvers/ reuse the same core, just changing how solutions are delivered.Check the rule shape
[{args: [...]}, ...subgoals].{name: 'foo/1', args: [...]} (call another rule) or a function env => boolean (inline guard).'name/arity' — arity must match the call site length.Add debug logging temporarily
src/solve.js, log at decision points: which rule is being tried, the head unification result, the next subgoal pushed.console.log('try', frame.name, 'rule', frame.index, 'args', frame.args);assemble(v, env) from deep6/traverse/assemble.js.Common failure modes
foo/2 but called with one arg — silently no match.X.get(env) before X is bound. Gate guards with X.isBound(env) && ....env.pop() paths: if you patched the solver, every push must have a matching pop on every backtrack path.await the solver or to consume the async iterator.Reproduce in isolation
tests/test-*.js file.Fix and verify
npm test.npm test — run the full suite.npm run debug — run under the Node inspector for breakpoint debugging.assemble(v, env) — materialise a variable's bound value (deep) for inspection.env.getAllValues() — inspect the full binding map.