eyeprolog 1.5.87 → 1.5.88

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.
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.5.87",
6
+ "version": "1.5.88",
7
7
  "description": "EyeProlog turns facts and rules into answers and proofs.",
8
8
  "type": "module",
9
9
  "main": "./index.js",
package/src/quads.js CHANGED
@@ -994,24 +994,39 @@ const FAILURE_LABELS = {
994
994
 
995
995
  // With several `|`-separated alternatives -- the norm for `sto`-annotated
996
996
  // queries -- a bare offending sub-term like `_B = [E|_B]` gives no sense of
997
- // which alternative it came from (issue #112's follow-up). Show that whole
998
- // alternative in place, and stand in for its siblings with `...` rather than
999
- // reproducing them (they were not the problem) or dropping them silently
1000
- // (a reader can no longer tell how many alternatives, or which one, this was).
1001
- // Returns null when the description has only one alternative to begin with:
1002
- // there is then nothing to elide, and the existing plain rendering already
1003
- // shows the whole thing.
997
+ // which alternative it came from. Show that whole alternative in place, laid
998
+ // out the same way the answer-description syntax itself lays out alternatives
999
+ // and leaves (a leading `|` per alternative after the first, a leading `;`
1000
+ // per leaf after an alternative's first), and stand in for sibling
1001
+ // alternatives with a bare `...` rather than reproducing them (they were not
1002
+ // the problem) or dropping them silently (a reader can no longer tell how
1003
+ // many alternatives, or which one, this was) -- see issue #112's follow-up
1004
+ // (https://github.com/eyereasoner/eyeprolog/issues/112#issuecomment-5645403025).
1005
+ // Comments are not retained past parsing, so unlike a hand-written answer
1006
+ // description this reconstruction never has any to show. Returns null when
1007
+ // the description has only one alternative to begin with: there is then
1008
+ // nothing to elide, and the existing plain rendering already shows the whole
1009
+ // thing.
1004
1010
  function formatAlternativeContext(program, description, alternative) {
1005
1011
  const parts = splitOperator(description, '|');
1006
1012
  if (parts.length <= 1 || !parts.includes(alternative)) return null;
1007
- return parts.map((part) => (part === alternative ? formatQuadTerm(program, part) : '...')).join(' | ');
1008
- }
1009
-
1010
- // A trailing `...` glued straight to a full stop reads as four dots; the
1011
- // quad answer-description syntax itself always writes a space before the
1012
- // period in that position (see `..., ad_infinitum` vs `... .`), so match it.
1013
- function terminate(text) {
1014
- return text.endsWith('...') ? `${text} .` : `${text}.`;
1013
+ const lines = [];
1014
+ parts.forEach((part, index) => {
1015
+ const prefix = index === 0 ? ' ' : '| ';
1016
+ if (part !== alternative) {
1017
+ lines.push(`${prefix}...`);
1018
+ return;
1019
+ }
1020
+ splitOperator(part, ';').forEach((leaf, leafIndex) => {
1021
+ lines.push(`${leafIndex === 0 ? prefix : '; '}${formatQuadTerm(program, leaf)}`);
1022
+ });
1023
+ });
1024
+ // A trailing `...` glued straight to a full stop reads as four dots; the
1025
+ // answer-description syntax itself always writes a space before the period
1026
+ // in that position (compare `..., ad_infinitum` with `... .`), so match it.
1027
+ const last = lines.length - 1;
1028
+ lines[last] = lines[last].endsWith('...') ? `${lines[last]} .` : `${lines[last]}.`;
1029
+ return lines.join('\n');
1015
1030
  }
1016
1031
 
1017
1032
  function formatFailure(program, quad, result, description = quad.answers[0]) {
@@ -1029,12 +1044,14 @@ function formatFailure(program, quad, result, description = quad.answers[0]) {
1029
1044
  const detail = result.kind === 'undecided'
1030
1045
  ? ` undecided: ${result.reason}.\n`
1031
1046
  // When the offending sub-term already *is* the whole alternative (an
1032
- // `expected:` line would just repeat the context line), the context line
1033
- // alone is the full, non-redundant report.
1047
+ // `expected:` line would just repeat the context lines), the context
1048
+ // alone is the full, non-redundant report. formatAlternativeContext
1049
+ // already lays out and terminates its own lines, so it needs no further
1050
+ // wrapping here (unlike the plain single-line `expected:` case below).
1034
1051
  : context != null && expected === result.alternative
1035
- ? ` ${terminate(context)}\n`
1052
+ ? `${context}\n`
1036
1053
  : context != null
1037
- ? ` ${terminate(context)}\n expected: ${formatQuadTerm(program, expected)}.\n`
1054
+ ? `${context}\n expected: ${formatQuadTerm(program, expected)}.\n`
1038
1055
  : ` expected: ${formatQuadTerm(program, expected)}.\n`;
1039
1056
  return `quads: ${reason} ${label}${source.filename}:${line}\n` +
1040
1057
  ` ?- ${formatQuadTerm(program, quad.query)}.\n` + detail;
@@ -2584,8 +2584,15 @@ c4 ?- call((!;1)).
2584
2584
  const result = publicApi.runQuads(Program.parseSources([{ text: source, filename: 'select-quad.pl' }]));
2585
2585
  assertEqual(result.total, 1, 'quad total');
2586
2586
  assertEqual(result.failed, 1, 'quad failed');
2587
+ // Laid out the same way the answer-description syntax itself lays
2588
+ // out alternatives (a leading `|`) and leaves (a leading `;`), per
2589
+ // Ulrich's own proposed shape in that follow-up comment.
2587
2590
  assertIncludes(result.stdout,
2588
- ' ... | sto, Xs = [E | Xs] ; Xs = [_A | _B], Ys = [E | Ys] ; ..., ad_infinitum | ... .\n',
2591
+ ' ...\n' +
2592
+ '| sto, Xs = [E | Xs]\n' +
2593
+ '; Xs = [_A | _B], Ys = [E | Ys]\n' +
2594
+ '; ..., ad_infinitum\n' +
2595
+ '| ... .\n',
2589
2596
  'sibling-elided alternative context');
2590
2597
  assertIncludes(result.stdout, ' expected: Ys = [E | Ys].\n', 'still-precise offending sub-term');
2591
2598
  },