eyeprolog 1.5.25 → 1.5.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -345,11 +345,8 @@ profile_prohibition(Request) :-
345
345
  cycle_request(Request),
346
346
  tnot(profile_permission(Request)).
347
347
 
348
- % For a ground WFS claim, true and false are successful positive and negative
349
- % probes. If neither probe succeeds, the WFS truth value is undefined.
350
- wfs_truth(Claim, true) :- call(Claim), \+ tnot(Claim).
351
- wfs_truth(Claim, false) :- tnot(Claim), \+ call(Claim).
352
- wfs_truth(Claim, undefined) :- \+ call(Claim), \+ tnot(Claim).
348
+ % The normal-profile wfs_truth/2 predicate reports the three-valued result of
349
+ % each ground claim without treating an undefined claim as ordinary success.
353
350
 
354
351
  % --- Curated questions -----------------------------------------------------
355
352
 
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.5.25",
6
+ "version": "1.5.26",
7
7
  "description": "EyeProlog turns facts and rules into answers and proofs.",
8
8
  "type": "module",
9
9
  "main": "./index.js",
package/src/cli.js CHANGED
@@ -28,6 +28,7 @@ export async function main(argv) {
28
28
  proofDetail: 'abstract',
29
29
  verifyProof: null,
30
30
  quads: false,
31
+ quiet: false,
31
32
  stats: false,
32
33
  isoStrict: false,
33
34
  portable: false,
@@ -60,6 +61,8 @@ export async function main(argv) {
60
61
  options.verifyProof = file;
61
62
  } else if (!endOptions && (arg === '--quads' || arg === '-q')) {
62
63
  options.quads = true;
64
+ } else if (!endOptions && arg === '--quiet') {
65
+ options.quiet = true;
63
66
  } else if (!endOptions && (arg === '--stats' || arg === '-s')) {
64
67
  options.stats = true;
65
68
  } else if (!endOptions && arg === '--iso-strict') {
@@ -116,7 +119,7 @@ export async function main(argv) {
116
119
  }
117
120
 
118
121
  if (options.isoStrict && options.files.length === 0 && options.goals.length === 0 &&
119
- options.verifyProof == null && !options.proof && !options.stats && !options.warnings) {
122
+ options.verifyProof == null && !options.proof && !options.quiet && !options.stats && !options.warnings) {
120
123
  const engine = await loadEngine();
121
124
  const { runRepl } = await import('./repl.js');
122
125
  const exitCode = await runRepl(engine, {
@@ -251,8 +254,8 @@ async function runForwardDefault(engine, program, options) {
251
254
  });
252
255
  try {
253
256
  const result = engine.executeForwardRules(program, solver, {
254
- onAnswer: (line) => process.stdout.write(line),
255
- onFuse: (line) => process.stdout.write(line),
257
+ onAnswer: (line) => { if (!options.quiet) process.stdout.write(line); },
258
+ onFuse: (line) => { if (!options.quiet) process.stdout.write(line); },
256
259
  onDiagnostic: (line) => process.stderr.write(line),
257
260
  });
258
261
  if (result.haltCode != null) process.exitCode = result.haltCode;
@@ -277,7 +280,7 @@ async function runDefault(engine, program, options) {
277
280
  try {
278
281
  const { haltCode } = engine.executeGoals(program, solver, goals, {
279
282
  onAnswer: (line, resolved) => {
280
- process.stdout.write(line);
283
+ if (!options.quiet) process.stdout.write(line);
281
284
  if (options.proof) writeExplanation(explanation, program, resolved, registry, options);
282
285
  },
283
286
  });
@@ -313,6 +316,7 @@ Options:
313
316
  --proof-detail mode Use abstract or expanded proof detail (implies --proof).
314
317
  --verify-proof file Verify why/2 proof certificates against the input program.
315
318
  -q, --quads Run embedded quad tests and fail if any do not hold.
319
+ --quiet Suppress answer terms while preserving Prolog output.
316
320
  -s, --stats Print solver and memory statistics to stderr after execution.
317
321
  --iso-strict Use ISO/IEC 13211-1 core + Corrigenda 1-3 only;
318
322
  reject EyeProlog language extensions.
package/src/program.js CHANGED
@@ -57,6 +57,10 @@ function collectMultiplicitySensitiveDependencies(goal, out = []) {
57
57
  collectMultiplicitySensitiveDependencies(goal.args[0], out);
58
58
  return out;
59
59
  }
60
+ if (goal.name === 'wfs_truth' && goal.arity === 2) {
61
+ collectMultiplicitySensitiveDependencies(goal.args[0], out);
62
+ return out;
63
+ }
60
64
  if (goal.name === 'forall' && goal.arity === 2) {
61
65
  collectMultiplicitySensitiveDependencies(goal.args[0], out);
62
66
  collectMultiplicitySensitiveDependencies(goal.args[1], out);
@@ -1134,6 +1138,10 @@ function collectAutoloadGoalDependencies(goal, out = []) {
1134
1138
  collectAutoloadGoalDependencies(goal.args[0], out);
1135
1139
  return out;
1136
1140
  }
1141
+ if (goal.name === 'wfs_truth' && goal.arity === 2) {
1142
+ collectAutoloadGoalDependencies(goal.args[0], out);
1143
+ return out;
1144
+ }
1137
1145
 
1138
1146
  out.push({ key: `${goal.name}/${goal.arity}`, name: goal.name, arity: goal.arity, module: goal.module });
1139
1147
 
@@ -1687,7 +1695,8 @@ function annotateGoalModule(term, module) {
1687
1695
  if (!term || (term.type !== ATOM && term.type !== COMPOUND)) return term;
1688
1696
  term.module = module;
1689
1697
  const callableArguments = (term.name === ',' || term.name === ';' || term.name === '->') ? term.args
1690
- : (['call', 'once', '\\+', 'not', 'catch', 'call_cleanup', 'setup_call_cleanup',
1698
+ : (term.name === 'wfs_truth' && term.arity === 2) ? [term.args[0]]
1699
+ : (['call', 'once', '\\+', 'not', 'tnot', 'catch', 'call_cleanup', 'setup_call_cleanup',
1691
1700
  'forall', 'findall', 'bagof', 'setof', 'countall', 'sumall',
1692
1701
  'aggregate_min', 'aggregate_max', 'maplist', 'phrase'].includes(term.name)
1693
1702
  ? term.args
package/src/solver.js CHANGED
@@ -919,7 +919,27 @@ export class Solver {
919
919
  }
920
920
 
921
921
  *solveTabledNegation(argument, env) {
922
- const invoked = copyResolved(argument, env);
922
+ const truth = this.groundGoalTruth(argument, env);
923
+ if (truth === 'true') return;
924
+ if (truth === 'undefined') {
925
+ this.stats.wfs_undefined_answers++;
926
+ return;
927
+ }
928
+ yield env;
929
+ }
930
+
931
+ groundGoalTruth(argument, env) {
932
+ let invoked = copyResolved(argument, env);
933
+ while (invoked.type === COMPOUND && invoked.name === ':' && invoked.arity === 2) {
934
+ const module = invoked.args[0];
935
+ if (module.type === VAR) throw new PrologError('instantiation_error');
936
+ if (module.type !== 'atom') throw new PrologError('type_error(atom)', module);
937
+ invoked = invoked.args[1];
938
+ if (invoked.type !== COMPOUND && invoked.type !== 'atom') {
939
+ throw new PrologError('type_error(callable)', invoked);
940
+ }
941
+ qualifyTerm(invoked, module.name);
942
+ }
923
943
  if (invoked.type === VAR) throw new PrologError('instantiation_error');
924
944
  if (invoked.type !== COMPOUND && invoked.type !== 'atom') {
925
945
  throw new PrologError('type_error(callable)', invoked);
@@ -928,25 +948,18 @@ export class Solver {
928
948
  const group = this.program.findGroup(invoked.name, invoked.arity, invoked.module ?? 'user');
929
949
  if (group?.wfsDatalog === true) {
930
950
  const model = this.wfsModelFor(group);
931
- const truth = truthOfGroundGoal(model, invoked);
932
- if (truth === 'true') return;
933
- if (truth === 'undefined') {
934
- this.stats.wfs_undefined_answers++;
935
- return;
936
- }
937
- yield env;
938
- return;
951
+ return truthOfGroundGoal(model, invoked);
939
952
  }
940
953
 
941
- // Outside an unstratified WFS component, a ground tabled negation has the
942
- // ordinary two-valued result after the positive goal is evaluated.
954
+ // Outside an unstratified WFS component, a ground goal has the ordinary
955
+ // two-valued result after the positive goal is evaluated.
943
956
  const child = this.cloneForInnerGoal(1);
944
957
  for (const _ of child.solve([invoked], env.clone(), 0)) {
945
958
  this.absorbStatsFrom(child);
946
- return;
959
+ return 'true';
947
960
  }
948
961
  this.absorbStatsFrom(child);
949
- yield env;
962
+ return 'false';
950
963
  }
951
964
 
952
965
  activeVariant(goal, env) {
@@ -310,6 +310,13 @@ function* tabledNegationBuiltin({ solver, goal, env }) {
310
310
  yield* solver.solveTabledNegation(goal.args[0], env);
311
311
  }
312
312
 
313
+ function* wfsTruthBuiltin({ solver, goal, env }) {
314
+ const truth = solver.groundGoalTruth(goal.args[0], env);
315
+ if (truth === 'undefined') solver.stats.wfs_undefined_answers++;
316
+ const next = env.clone();
317
+ if (unify(goal.args[1], atom(truth), next)) yield next;
318
+ }
319
+
313
320
  function runtimeStatistics(solver) {
314
321
  return { ...solver.stats, ...memoryStatistics() };
315
322
  }
@@ -361,6 +368,7 @@ export function createEyePrologRegistry() {
361
368
  registry.add('statistics', 0, statisticsBuiltin, { deterministic: true });
362
369
  registry.add('statistics', 2, statisticsValueBuiltin);
363
370
  registry.add('tnot', 1, tabledNegationBuiltin, { deterministic: true });
371
+ registry.add('wfs_truth', 2, wfsTruthBuiltin, { deterministic: true });
364
372
  attsHostBuiltins.register(registry);
365
373
  expansionBuiltins.register(registry);
366
374
  arithmeticHostBuiltins.register(registry);
@@ -119,7 +119,7 @@ families; `--iso-strict` is intended to remove their Part 1 interpretation.
119
119
  | 5.5.4 Types | The normal JavaScript API exposes an implementation-specific string term `stringTerm(Text)`. It is disjoint from the five Part 1 term types; normal term order places it after atoms and before compound terms, and normal `atomic/1` treats it as atomic. It has no Prolog source token syntax (double-quoted source still follows `double_quotes`), is non-callable for term-to-clause conversion, is not evaluable as an arithmetic expression, and writes as a double-quoted host string. | Strict mode rejects a programmatic string term at program/goal entry with `representation_error(term)`, so the additional type cannot enter the Part 1 execution domain. **defined** — `src/term.js`, `src/program.js`, `src/solver.js`; strict API-boundary regression. |
120
120
  | 5.5.5 Directives | `module/2`, `use_module/1-2`, `meta_predicate/1` and normal-profile library behavior | Rejected as implementation-specific Part 1 directives. |
121
121
  | 5.5.6 Side effects | Normal mode adds `statistics/0-2`, cleanup/library state, and optional proof/statistics host instrumentation. | The strict registry excludes Prolog-visible statistics/cleanup/library adapters; ordinary Part 1 I/O/database/flag/operator side effects remain. Host proof/statistics collection observes execution through the embedding API rather than adding a strict Prolog goal effect. **covered** — strict registry/execution regression. |
122
- | 5.5.7 Control constructs | `tnot/1` and normal-profile execution optimizations | `tnot/1` and the normal-profile explicit `table` declaration are absent. |
122
+ | 5.5.7 Control constructs | `tnot/1`, `wfs_truth/2`, and normal-profile execution optimizations | `tnot/1`, `wfs_truth/2`, and the normal-profile explicit `table` declaration are absent. |
123
123
  | 5.5.8 Flags | `occurs_check` | Absent in strict mode. |
124
124
  | 5.5.9 Built-in predicates | EyeProlog libraries, CLP(Z), statistics, Part 3 `phrase/2-3`, and bundled-library autoloaded predicates | Strict registry contains only the Part 1 + Corrigenda core registry. |
125
125
  | 5.5.10 Evaluable functors | Normal mode additionally accepts the EyeProlog evaluable atom `e`; the remaining arithmetic functors accepted by strict mode are the Part 1 + Corrigenda set. | Strict mode rejects `e/0` as non-evaluable and retains the Corrigendum arithmetic additions. **covered** — strict extension-boundary regression plus `src/iso-arithmetic.js`. |
@@ -40,7 +40,7 @@ certification claim.
40
40
  | 5.5.4 additional term types | covered | the normal JavaScript API's `stringTerm(Text)` is documented as an implementation-specific sixth term type, including disjointness, ordering, clause conversion, lack of source token syntax, expression behavior, and writing; strict program/goal entry rejects that type with `representation_error(term)` |
41
41
  | 5.5.5 additional directives | covered | normal module/library directives are documented implementation-specific features and are rejected by strict mode |
42
42
  | 5.5.6 additional side effects | covered | normal-profile `statistics/0-2`, cleanup/library state, proof/statistics host instrumentation, and other extension effects are documented outside the Part 1 core; strict registry tests exclude the Prolog-visible statistics/cleanup extensions. Host instrumentation is an embedding observation rather than an extra strict Prolog goal effect |
43
- | 5.5.7 additional control constructs | covered | `tnot/1` and implementation-specific execution optimizations are absent/disabled in strict mode; standard control constructs remain separately audited |
43
+ | 5.5.7 additional control constructs | covered | `tnot/1`, `wfs_truth/2`, and implementation-specific execution optimizations are absent/disabled in strict mode; standard control constructs remain separately audited |
44
44
  | 5.5.8 additional flags | covered | normal `occurs_check` extension is absent from strict mode; the Part 1 flag family is fully audited |
45
45
  | 5.5.9 additional built-in predicates and error forms | covered | strict registry excludes normal-profile library/native additions; `ISO-BUILTIN-MODE-ERROR-MATRIX.md` closes the complete 8.2-8.17 family row-by-row; simultaneous-error choices are documented per 7.12 rather than treated as a global table-order mandate |
46
46
  | 5.5.10 additional evaluable functors/types | covered | strict mode rejects the normal-profile evaluable `e` extension while retaining the full Part 1 + Corrigenda arithmetic set. `ISO-EVALUABLE-FUNCTOR-MATRIX.md` now closes the Clause 9 semantic/error audit and pins the 9.1.4.2 `resultF`, mixed-type `max/2`/`min/2`, and signed bitwise/shift choices. Post-N289 STC #75 remains separate from the published baseline |
@@ -31,9 +31,9 @@ Clause 9 evaluable functors. Public comparison material remains supporting revie
31
31
  evidence rather than a duplicated vendored corpus. Cases under `iso/`
32
32
  identify standards-derived behavior; other directories cover EyeProlog host
33
33
  contracts and extensions. EyeProlog-only execution features such as explicit
34
- tabling and `tnot/1` well-founded negation are outside the Part 1 strict-core
34
+ tabling, `tnot/1` well-founded negation, and `wfs_truth/2` inspection are outside the Part 1 strict-core
35
35
  claim. Their focused semantic coverage lives primarily in regression tests;
36
- `tnot/1` is absent from the strict ISO registry. The processor character set is documented as the Unicode scalar repertoire with
36
+ `tnot/1` and `wfs_truth/2` are absent from the strict ISO registry. The processor character set is documented as the Unicode scalar repertoire with
37
37
  scalar-value collation in both normal and strict profiles; `--iso-strict`
38
38
  therefore changes only implementation-specific language facilities, not this
39
39
  implementation-defined processor choice.
@@ -2404,6 +2404,7 @@ c4 ?- call((!;1)).
2404
2404
  assertIncludes(result.stdout, '-g, --goal goal', 'stdout');
2405
2405
  assertIncludes(result.stdout, '-p, --proof', 'stdout');
2406
2406
  assertIncludes(result.stdout, '-q, --quads', 'stdout');
2407
+ assertIncludes(result.stdout, '--quiet', 'stdout');
2407
2408
  assertIncludes(result.stdout, '-s, --stats', 'stdout');
2408
2409
  assertIncludes(result.stdout, '--portable', 'stdout');
2409
2410
  assertIncludes(result.stdout, '--no-autoload', 'stdout');
@@ -3821,6 +3822,19 @@ child.stdin.write(\`consult(${consultedAtom}).\\n\`);
3821
3822
  assertEqual(result.stderr, '', 'stderr');
3822
3823
  },
3823
3824
  },
3825
+ {
3826
+ name: '--quiet preserves goal side effects without printing answer terms',
3827
+ run: () => {
3828
+ const input = 'emit :- write(side_effect), nl.\n';
3829
+ const quiet = runCli(['--quiet', '--goal', 'emit', '-'], { input });
3830
+ assertEqual(quiet.status, 0, 'quiet exit status');
3831
+ assertEqual(quiet.stdout, 'side_effect\n', 'quiet stdout');
3832
+ assertEqual(quiet.stderr, '', 'quiet stderr');
3833
+
3834
+ const ordinary = runCli(['--goal', 'emit', '-'], { input });
3835
+ assertEqual(ordinary.stdout, 'side_effect\nemit.\n', 'ordinary answer output remains unchanged');
3836
+ },
3837
+ },
3824
3838
  {
3825
3839
  name: '-g requires a goal argument',
3826
3840
  run: () => {
@@ -6726,7 +6740,7 @@ answer(ok) :-
6726
6740
  assertEqual(Boolean(registry.get('is', 2)), true, 'ISO is/2 exists');
6727
6741
  assertEqual(Boolean(registry.get('append', 3)), false, 'append/3 is not ISO core');
6728
6742
  assertEqual(library.eyePrologLibrary, true, 'complete registry marker');
6729
- assertEqual(library.defs.size, 221, 'EyeProlog registry contains ISO definitions, cleanup controls, observability extensions, WFS tnot/1, and generic library adapters');
6743
+ assertEqual(library.defs.size, 222, 'EyeProlog registry contains ISO definitions, cleanup controls, observability extensions, WFS predicates, and generic library adapters');
6730
6744
  assertEqual(registry.get('eyeprolog__dynify', 1), null, 'Eyelet dynify adapter is absent from the ISO registry');
6731
6745
  assertEqual(Boolean(library.get('eyeprolog__dynify', 1)), true, 'Eyelet dynify adapter is an internal EyeProlog library primitive');
6732
6746
  assertEqual(registry.get('eyeprolog__eyelet_emit', 2), null, 'Eyelet event adapter is absent from the ISO registry');
@@ -6743,6 +6757,8 @@ answer(ok) :-
6743
6757
  assertEqual(Boolean(library.get('statistics', 2)), true, 'statistics/2 is an EyeProlog observability extension');
6744
6758
  assertEqual(registry.get('tnot', 1), null, 'tnot/1 is absent from the ISO registry');
6745
6759
  assertEqual(Boolean(library.get('tnot', 1)), true, 'tnot/1 is an EyeProlog WFS extension');
6760
+ assertEqual(registry.get('wfs_truth', 2), null, 'wfs_truth/2 is absent from the ISO registry');
6761
+ assertEqual(Boolean(library.get('wfs_truth', 2)), true, 'wfs_truth/2 is an EyeProlog WFS extension');
6746
6762
  assertEqual(registry.get('time', 1), null, 'time/1 is absent from the ISO registry');
6747
6763
  assertEqual(Boolean(library.get('time', 1)), true, 'time/1 is an EyeProlog timing extension');
6748
6764
  assertEqual(registry.get('dif', 2), null, 'dif/2 is absent from the strict ISO core registry');
@@ -7807,6 +7823,50 @@ undefined_case :- tnot(win(c)).
7807
7823
  assertEqual(run(source, { goal: 'undefined_case' }).stdout, '', 'tnot of an undefined WFS atom is not a successful answer');
7808
7824
  },
7809
7825
  },
7826
+ {
7827
+ name: 'wfs_truth exposes three-valued results without executing undefined goals',
7828
+ run: () => {
7829
+ const source = `
7830
+ :- use_module(library(tabling)).
7831
+ :- table(win/1).
7832
+ move(a, b).
7833
+ move(c, d).
7834
+ move(d, c).
7835
+ win(X) :- move(X, Y), tnot(win(Y)).
7836
+ `;
7837
+ assertEqual(run(source, { goal: 'wfs_truth(win(a), Truth)' }).stdout,
7838
+ 'wfs_truth(win(a), true).\n', 'true WFS atom');
7839
+ assertEqual(run(source, { goal: 'wfs_truth(win(b), Truth)' }).stdout,
7840
+ 'wfs_truth(win(b), false).\n', 'false WFS atom');
7841
+ const undefinedResult = run(source, { goal: 'wfs_truth(win(c), Truth)' });
7842
+ assertEqual(undefinedResult.stdout, 'wfs_truth(win(c), undefined).\n', 'undefined WFS atom');
7843
+ assertEqual(undefinedResult.stats.wfs_undefined_answers, 1, 'undefined truth inspection is counted');
7844
+ assertEqual(run(source, { goal: 'wfs_truth(win(c), true)' }).stdout, '', 'truth filter can reject undefined');
7845
+ let nongroundError = null;
7846
+ try {
7847
+ run(source, { goal: 'wfs_truth(win(X), Truth)' });
7848
+ } catch (error) {
7849
+ nongroundError = error;
7850
+ }
7851
+ assertEqual(nongroundError?.formal, 'instantiation_error', 'inspected goal must be ground');
7852
+
7853
+ const moduleSource = `
7854
+ :- module(cycle, [status/1]).
7855
+ :- use_module(library(tabling)).
7856
+ :- table(a/0).
7857
+ :- table(b/0).
7858
+ a :- tnot(b).
7859
+ b :- tnot(a).
7860
+ status(Truth) :- wfs_truth(a, Truth).
7861
+ `;
7862
+ assertEqual(run(moduleSource, { goal: 'cycle:status(Truth)' }).stdout,
7863
+ 'cycle:status(undefined).\n', 'lexical module qualification');
7864
+ assertEqual(run(moduleSource, { goal: 'wfs_truth(cycle:a, Truth)' }).stdout,
7865
+ 'wfs_truth(cycle:a, undefined).\n', 'explicit module qualification');
7866
+ assertEqual(run(moduleSource, { goal: 'tnot(cycle:a)' }).stdout, '',
7867
+ 'qualified tnot preserves undefined failure');
7868
+ },
7869
+ },
7810
7870
  {
7811
7871
  name: 'undefined WFS goals do not run continuations or print CLI answers',
7812
7872
  run: () => {
@@ -1147,6 +1147,16 @@ Here neither `win(a)` nor `win(b)` is unconditionally established; both belong
1147
1147
  to the undefined part of the well-founded model. EyeProlog retains that state
1148
1148
  internally but does not expose undefined atoms as successful query answers or
1149
1149
  run the remaining goals of a conjunction through them.
1150
+ Use `wfs_truth/2` when the truth state itself is data:
1151
+
1152
+ ```text
1153
+ ?- wfs_truth(win(a), Truth).
1154
+ Truth = undefined.
1155
+ ```
1156
+
1157
+ The inspected goal must be ground. The predicate reports `true`, `false`, or
1158
+ `undefined`; reporting `undefined` is a successful result of `wfs_truth/2`, not
1159
+ a successful execution of the inspected goal.
1150
1160
  Direct calls to `tnot/1` must be ground. In WFS rules, variables occurring in
1151
1161
  the head or a negated literal must be range-restricted by positive body
1152
1162
  literals. Ordinary `\+/1` is unchanged, and strict ISO mode does not provide
@@ -5951,8 +5961,9 @@ declaration; they never opt an undeclared predicate into tabling.
5951
5961
 
5952
5962
  Ordinary `\+/1` remains ISO-style negation as failure. The separate `tnot/1`
5953
5963
  extension explicitly requests well-founded evaluation for eligible finite,
5954
- range-restricted Datalog dependencies. Strict ISO mode exposes neither `table`
5955
- nor `tnot/1`.
5964
+ range-restricted Datalog dependencies. `wfs_truth/2` reports the three-valued
5965
+ state of a ground callable as `true`, `false`, or `undefined`. Strict ISO mode
5966
+ exposes none of `table`, `tnot/1`, or `wfs_truth/2`.
5956
5967
 
5957
5968
  #### Query execution
5958
5969
 
@@ -6359,9 +6370,9 @@ or observability. The ISO and library catalogs therefore cover **523 distinct pr
6359
6370
  re-exported by a compatibility module is counted once in this library surface:
6360
6371
  for example `call_cleanup/2` and `setup_call_cleanup/3` are exported by
6361
6372
  `library(iso_ext)`, while `time/1` and `statistics/2` are available from
6362
- `library(time)`. `statistics/0` and `tnot/1` remain normal-runtime extensions
6363
- outside the library catalog. These additions are absent from the strict ISO
6364
- registry.
6373
+ `library(time)`. `statistics/0`, `tnot/1`, and `wfs_truth/2` remain
6374
+ normal-runtime extensions outside the library catalog. These additions are
6375
+ absent from the strict ISO registry.
6365
6376
 
6366
6377
  The sources are `src/lib/aggregate.pl`, `src/lib/arithmetic.pl`,
6367
6378
  `src/lib/assoc.pl`, `src/lib/atts.pl`, `src/lib/between.pl`,
@@ -9375,6 +9386,8 @@ eyeprolog --goal 'ancestor(ada, Who)' examples/ancestor.pl
9375
9386
 
9376
9387
  Repeat `-g` or `--goal` to request several result relations in one run. EyeProlog prints
9377
9388
  their ground answers in the order the goals were supplied.
9389
+ Use `--quiet` for command-style goals: Prolog output such as `write/1` remains
9390
+ visible, while the resolved answer terms are suppressed.
9378
9391
 
9379
9392
  For a self-running example, place the host goal in an ordinary comment:
9380
9393
 
@@ -9396,6 +9409,7 @@ make the observed question explicit.
9396
9409
  | `--proof-detail abstract|expanded` | Select library abstraction for proof output; implies `--proof` |
9397
9410
  | `--verify-proof File` | Verify saved `why/2` proof certificates against the input program without proof search |
9398
9411
  | `-q`, `--quads` | Run embedded quad tests and fail if any do not hold |
9412
+ | `--quiet` | Suppress resolved answer terms while preserving Prolog output and diagnostics |
9399
9413
  | `--iso-strict` | Restrict parsing and execution to ISO/IEC 13211-1:1995 + Corrigenda 1–3; reject EyeProlog language extensions (including `table` and `:+`) and disable bundled-library autoloading |
9400
9414
  | `--portable` | Enforce the conservative EyeProlog/Trealla/Scryer interoperability profile |
9401
9415
  | `--no-autoload` | Disable bundled-library predicate autoloading |