eyeprolog 1.3.27 → 1.3.28

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.
Files changed (25) hide show
  1. package/conformance-report.md +2 -1
  2. package/package.json +1 -1
  3. package/src/iso.js +26 -4
  4. package/test/conformance/README.md +6 -2
  5. package/test/conformance/STC-DRAFT-STATUS.md +62 -0
  6. package/test/conformance/cases/stc/bagof_answer_order.pl +6 -0
  7. package/test/conformance/cases/stc/clause_variable_identity.pl +9 -0
  8. package/test/conformance/cases/stc/float_underflow_input.pl +10 -0
  9. package/test/conformance/cases/stc/integer_to_float_evaluable.pl +8 -0
  10. package/test/conformance/cases/stc/mixed_integer_float_comparison.pl +16 -0
  11. package/test/conformance/errors/stc/float_overflow_negative_literal.pl +3 -0
  12. package/test/conformance/errors/stc/float_overflow_negative_number_chars.pl +3 -0
  13. package/test/conformance/errors/stc/float_overflow_positive_literal.pl +3 -0
  14. package/test/conformance/errors/stc/float_overflow_positive_number_chars.pl +3 -0
  15. package/test/conformance/expected/stc/bagof_answer_order.pl +1 -0
  16. package/test/conformance/expected/stc/clause_variable_identity.pl +1 -0
  17. package/test/conformance/expected/stc/float_underflow_input.pl +1 -0
  18. package/test/conformance/expected/stc/integer_to_float_evaluable.pl +1 -0
  19. package/test/conformance/expected/stc/mixed_integer_float_comparison.pl +1 -0
  20. package/test/conformance/expected-errors/stc/float_overflow_negative_literal.txt +1 -0
  21. package/test/conformance/expected-errors/stc/float_overflow_negative_number_chars.txt +1 -0
  22. package/test/conformance/expected-errors/stc/float_overflow_positive_literal.txt +1 -0
  23. package/test/conformance/expected-errors/stc/float_overflow_positive_number_chars.txt +1 -0
  24. package/test/run-regression.mjs +23 -0
  25. package/the-art-of-eyeprolog.md +1 -1
@@ -18,9 +18,10 @@ This report summarizes the file-based conformance corpus under `test/conformance
18
18
  | proofs | 0 | 0 | 0 | 21 | 21 |
19
19
  | query | 8 | 2 | 0 | 0 | 10 |
20
20
  | rules | 13 | 3 | 0 | 0 | 16 |
21
+ | stc | 5 | 4 | 0 | 0 | 9 |
21
22
  | strings | 40 | 0 | 0 | 0 | 40 |
22
23
  | syntax | 12 | 23 | 0 | 0 | 35 |
23
24
  | terms | 26 | 3 | 0 | 0 | 29 |
24
25
  | unification | 18 | 0 | 0 | 0 | 18 |
25
26
  | variables | 16 | 7 | 0 | 0 | 23 |
26
- | **Total** | **484** | **267** | **19** | **21** | **791** |
27
+ | **Total** | **489** | **271** | **19** | **21** | **800** |
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.3.27",
6
+ "version": "1.3.28",
7
7
  "description": "EyeProlog turns facts and rules into answers and proofs.",
8
8
  "type": "module",
9
9
  "main": "./index.js",
package/src/iso.js CHANGED
@@ -2404,7 +2404,8 @@ function evaluateOperation(term, args) {
2404
2404
  if (name === '/' && y === 0) throw new PrologError('evaluation_error(zero_divisor)');
2405
2405
  let value;
2406
2406
  if (name === 'max' || name === 'min') {
2407
- const chooseLeft = name === 'max' ? x >= y : x <= y;
2407
+ const cmp = compareArithmeticValues(args[0], args[1]);
2408
+ const chooseLeft = name === 'max' ? cmp >= 0 : cmp <= 0;
2408
2409
  return chooseLeft ? args[0] : args[1];
2409
2410
  }
2410
2411
  if (name === 'atan2') {
@@ -2436,12 +2437,33 @@ function numericTerm(value) {
2436
2437
  export function evaluateArithmetic(term, env) {
2437
2438
  return evaluate(term, env);
2438
2439
  }
2440
+ function compareIntegerToFloat(integerValue, floatValue) {
2441
+ if (!Number.isFinite(floatValue)) throw new PrologError('evaluation_error(float_overflow)');
2442
+
2443
+ // Do not round an unbounded integer through JavaScript Number before a
2444
+ // mixed arithmetic comparison. Every integral IEEE-754 double can be
2445
+ // converted back to the exact integer value it represents; fractional
2446
+ // doubles necessarily have magnitude below 2^53, so their truncation is
2447
+ // also exact. This preserves mathematical ordering across the I/F boundary
2448
+ // (STC #50), e.g. 9007199254740993 > 9007199254740992.0.
2449
+ if (Number.isInteger(floatValue)) {
2450
+ const floatInteger = BigInt(floatValue);
2451
+ return integerValue < floatInteger ? -1 : integerValue > floatInteger ? 1 : 0;
2452
+ }
2453
+
2454
+ const truncated = BigInt(Math.trunc(floatValue));
2455
+ if (integerValue < truncated) return -1;
2456
+ if (integerValue > truncated) return 1;
2457
+ return floatValue > 0 ? -1 : 1;
2458
+ }
2459
+
2439
2460
  export function compareArithmeticValues(left, right) {
2440
2461
  const a = left.value;
2441
2462
  const b = right.value;
2442
- return left.integer && right.integer
2443
- ? (a < b ? -1 : a > b ? 1 : 0)
2444
- : (Number(a) < Number(b) ? -1 : Number(a) > Number(b) ? 1 : 0);
2463
+ if (left.integer && right.integer) return a < b ? -1 : a > b ? 1 : 0;
2464
+ if (left.integer) return compareIntegerToFloat(a, b);
2465
+ if (right.integer) return -compareIntegerToFloat(b, a);
2466
+ return a < b ? -1 : a > b ? 1 : 0;
2445
2467
  }
2446
2468
  function* isBuiltin({ goal, env }) {
2447
2469
  const result = arithmeticValueTerm(evaluateArithmetic(goal.args[1], env));
@@ -11,6 +11,9 @@ and proof output test the behavior of the JavaScript implementation.
11
11
  corrigenda, Part 2 modules, and Part 3 definite clause grammars to representative
12
12
  executable cases. [WG17-SYNTAX-STATUS.md](WG17-SYNTAX-STATUS.md) records the
13
13
  complete one-to-one trace for the vendored active upstream WG17 syntax cases.
14
+ [STC-DRAFT-STATUS.md](STC-DRAFT-STATUS.md) separately tracks executable
15
+ implementation questions from the post-N289 working draft; those cases are
16
+ review evidence, not normative ISO claims.
14
17
 
15
18
  “Conformance” here means conformance to EyeProlog's documented ISO compatibility
16
19
  profile and implementation extensions. The default registry covers the exact
@@ -131,8 +134,9 @@ Selected cases are adapted from the ISO and standard-core suites of Logtalk,
131
134
  Scryer Prolog, Trealla Prolog, and SWI-Prolog. Their upstream identifiers and licenses
132
135
  are recorded in [THIRD_PARTY.md](THIRD_PARTY.md).
133
136
 
134
- The corpus has 386 cases in `iso/` and 791 file-based conformance cases in
135
- total. The separate strict-reader WG17 matrix has 366 executable dispositions.
137
+ The corpus has 386 cases in `iso/` and 800 file-based conformance cases in
138
+ total. Of those, 9 cases in `stc/` are explicitly labelled working-draft
139
+ review evidence rather than normative ISO claims. The separate strict-reader WG17 matrix has 366 executable dispositions.
136
140
  The generated `conformance-report.md` is the authoritative source for current
137
141
  category totals. Together with regression, documentation-sync, API, example,
138
142
  and book-example checks, `npm test` is the release gate.
@@ -0,0 +1,62 @@
1
+ # WG17 STC draft review status
2
+
3
+ Source: [post-N289 draft for further technical corrigenda](https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc)
4
+
5
+ This file tracks implementation-relevant questions from the WG17 **working
6
+ draft**. It is deliberately separate from the ISO/IEC 13211-1 conformance
7
+ claim: an STC item is a proposal or defect report until WG17 adopts normative
8
+ wording.
9
+
10
+ The purpose of this ledger is practical. Where an STC item can be expressed as
11
+ an executable Prolog observation, EyeProlog keeps a standards-facing case under
12
+ `test/conformance/stc/` (or points to an existing strict/WG17 case) so discussion
13
+ of the draft can expose implementation problems before they become release
14
+ regressions.
15
+
16
+ ## Reviewed executable items
17
+
18
+ | STC item | Topic | EyeProlog evidence / finding |
19
+ | --- | --- | --- |
20
+ | [#37](https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#37) | `clause/2` variable identity | `stc/clause_variable_identity` verifies sharing between head and body is preserved. |
21
+ | [#39](https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#39) | negative-number syntax | Covered extensively by the upstream-first WG17 syntax matrix; unary-minus read-back discrepancies found by that matrix were fixed in v1.3.27. |
22
+ | [#40](https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#40) | inexact float representation | EyeProlog uses the host IEEE-754 binary64 value and requires written floats to read back to that same value. Input underflow is covered by `stc/float_underflow_input`. |
23
+ | [#42](https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#42) | integer-to-float conversion for float functions | `stc/integer_to_float_evaluable` verifies an integer expression is accepted by `sin/1` and produces a float. |
24
+ | [#44](https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#44) | `char_code/2` error classification | Existing strict conformance cases require `representation_error(character_code)` for an integer outside the character-code set. |
25
+ | [#49](https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#49) | `read_term/3` and EOF | Covered by strict reader/conformance tests and the interactive-read regressions. |
26
+ | [#50](https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#50) | mixed integer/float arithmetic comparison | **Found a bug during this audit.** EyeProlog rounded unbounded integers through JavaScript `Number`; `9007199254740993 > 9007199254740992.0` incorrectly failed. `stc/mixed_integer_float_comparison` now requires exact cross-type ordering and `max/2`/`min/2` use the same comparison. |
27
+ | [#55](https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#55) | integer rounding function | Existing flag conformance verifies `integer_rounding_function = toward_zero`. |
28
+ | [#58](https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#58) | `set_prolog_flag/2` instantiation error | Existing strict/error coverage requires an instantiation error when a required flag value is a variable. |
29
+ | [#67](https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#67) | `bagof/3` answer-order example | `stc/bagof_answer_order` verifies the proposed clarifying example produces `[2,1]`. |
30
+ | [#73](https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#73) | float-reading limits discussed from issue #54 | Positive/negative literal and `number_chars/2` overflow are kept as explicit draft cases; underflow is tested separately. See the note below. |
31
+
32
+ ## Float-reading note for #73
33
+
34
+ EyeProlog currently has a finite-double numeric profile. The draft-facing cases
35
+ record the behavior discussed in issue #54:
36
+
37
+ - a positive finite numeric token beyond the representable range raises
38
+ `representation_error(max_float)`;
39
+ - the corresponding negative overflow raises `representation_error(min_float)`;
40
+ - input underflow may round to `0.0`;
41
+ - overflow produced by arithmetic evaluation remains
42
+ `evaluation_error(float_overflow)`.
43
+
44
+ These `max_float` / `min_float` names are treated as a **provisional draft
45
+ extension**, not as a claim about the currently published ISO core standard.
46
+ The earlier WG17 float-update material also uses
47
+ `representation_error(float_overflow)` for unsupported infinity input, while a
48
+ separate reading-floats proposal discusses `max_float` for a finite value above
49
+ the implementation's largest finite float. Those cases should remain distinct
50
+ when WG17 settles the wording.
51
+
52
+ Relevant background:
53
+
54
+ - [WG17 float update](https://www.complang.tuwien.ac.at/ulrich/iso-prolog/core_update_float-2014-07-21)
55
+ - [Issue #54](https://github.com/eyereasoner/eyeprolog/issues/54)
56
+
57
+ ## Maintenance rule
58
+
59
+ When the STC draft changes, review executable changes before a release. Draft
60
+ expectations must never silently replace the normative ISO/WG17 expectations;
61
+ where the two differ, keep the draft test clearly labelled `stc/` until the
62
+ standardization status changes.
@@ -0,0 +1,6 @@
1
+ % STC #67: the clarifying bagof/3 example retains proof/answer order.
2
+ % https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#67
3
+ %% goal: bagof_answer_order
4
+
5
+ bagof_answer_order :-
6
+ bagof(X, (X = 2 ; X = 1), [2, 1]).
@@ -0,0 +1,9 @@
1
+ % STC #37: clause/2 must preserve sharing between variables in head and body.
2
+ % https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#37
3
+ %% goal: clause_variable_identity
4
+
5
+ a(X) :- b(X).
6
+
7
+ clause_variable_identity :-
8
+ clause(a(A), b(B)),
9
+ A == B.
@@ -0,0 +1,10 @@
1
+ % Float-reading draft review associated with STC #73 / issue #54. EyeProlog's
2
+ % finite-double profile permits input underflow to round to zero.
3
+ % https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#73
4
+ %% goal: float_underflow_input
5
+
6
+ float_underflow_input :-
7
+ number_chars(Positive, "1.0e-99999"),
8
+ Positive =:= 0.0,
9
+ number_chars(Negative, "-1.0e-99999"),
10
+ Negative =:= 0.0.
@@ -0,0 +1,8 @@
1
+ % STC #42: float evaluable functors such as sin/1 accept integer expressions
2
+ % through the specified integer-to-float conversion.
3
+ % https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#42
4
+ %% goal: integer_to_float_evaluable
5
+
6
+ integer_to_float_evaluable :-
7
+ X is sin(1),
8
+ float(X).
@@ -0,0 +1,16 @@
1
+ % STC #50: mixed arithmetic comparisons must not become incorrect by rounding
2
+ % an integer through the float representation before comparing it.
3
+ % https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#50
4
+ %% goal: mixed_integer_float_comparison
5
+
6
+ mixed_integer_float_comparison :-
7
+ 9007199254740993 > 9007199254740992.0,
8
+ 9007199254740992.0 < 9007199254740993,
9
+ 9007199254740993 =\= 9007199254740992.0,
10
+ -9007199254740993 < -9007199254740992.0,
11
+ Max is max(9007199254740993, 9007199254740992.0),
12
+ integer(Max),
13
+ Max =:= 9007199254740993,
14
+ Min is min(9007199254740993, 9007199254740992.0),
15
+ float(Min),
16
+ Min =:= 9007199254740992.0.
@@ -0,0 +1,3 @@
1
+ % Draft float-reading limit review associated with STC #73 / issue #54.
2
+ % https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#73
3
+ answer(-1.0e99999).
@@ -0,0 +1,3 @@
1
+ % Draft float-reading limit review associated with STC #73 / issue #54.
2
+ % https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#73
3
+ %% goal: number_chars(_, "-1.0e99999")
@@ -0,0 +1,3 @@
1
+ % Draft float-reading limit review associated with STC #73 / issue #54.
2
+ % https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#73
3
+ answer(1.0e99999).
@@ -0,0 +1,3 @@
1
+ % Draft float-reading limit review associated with STC #73 / issue #54.
2
+ % https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#73
3
+ %% goal: number_chars(_, "1.0e99999")
@@ -0,0 +1 @@
1
+ bagof_answer_order.
@@ -0,0 +1 @@
1
+ clause_variable_identity.
@@ -0,0 +1 @@
1
+ float_underflow_input.
@@ -0,0 +1 @@
1
+ integer_to_float_evaluable.
@@ -0,0 +1 @@
1
+ mixed_integer_float_comparison.
@@ -0,0 +1 @@
1
+ error(representation_error(min_float))
@@ -0,0 +1 @@
1
+ error(representation_error(min_float))
@@ -0,0 +1 @@
1
+ error(representation_error(max_float))
@@ -0,0 +1 @@
1
+ error(representation_error(max_float))
@@ -849,6 +849,29 @@ c4 ?- call((!;1)).
849
849
  assertEqual(hostTermError?.formal, 'evaluation_error(float_overflow)', 'host-created non-finite term');
850
850
  },
851
851
  },
852
+ {
853
+ name: 'mixed integer/float arithmetic comparison preserves exact order (STC #50)',
854
+ run: () => {
855
+ const hugeInteger = `1${'0'.repeat(309)}`;
856
+ const program = `
857
+ check :-
858
+ 9007199254740993 > 9007199254740992.0,
859
+ 9007199254740992.0 < 9007199254740993,
860
+ 9007199254740993 =\\= 9007199254740992.0,
861
+ -9007199254740993 < -9007199254740992.0,
862
+ ${hugeInteger} > 1.0e308,
863
+ -${hugeInteger} < -1.0e308,
864
+ Max is max(9007199254740993, 9007199254740992.0),
865
+ integer(Max),
866
+ Max =:= 9007199254740993,
867
+ Min is min(9007199254740993, 9007199254740992.0),
868
+ float(Min),
869
+ Min =:= 9007199254740992.0.
870
+ `;
871
+ const result = runEyeProlog(program, { goal: 'check' });
872
+ assertEqual(result.stdout, 'check.\n', 'mixed integer/float ordering');
873
+ },
874
+ },
852
875
  {
853
876
  name: 'readers keep a full stop inside a character-code constant (WG17 #367)',
854
877
  run: () => {
@@ -7414,7 +7414,7 @@ upstream syntax cases. Reviewed cases can pin exact strict-reader outcomes, whil
7414
7414
  newly upgraded cases execute directly against the upstream Codex expectation.
7415
7415
 
7416
7416
  The complete suite must pass before release. The file-based conformance corpus
7417
- contains 791 cases, including 386 focused ISO
7417
+ contains 800 cases, including 386 focused ISO
7418
7418
  cases derived from the success, failure, mode, and error behavior in
7419
7419
  ISO/IEC 13211-1 clauses 7 and 8, Part 2 modules, and Part 3 grammar rules.
7420
7420
  Separate exact-output suites check 210 normal