eyeprolog 1.3.32 → 1.3.33

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.
@@ -11,7 +11,7 @@ This report summarizes the file-based conformance corpus under `test/conformance
11
11
  | builtins | 11 | 0 | 0 | 0 | 11 |
12
12
  | context | 11 | 0 | 0 | 0 | 11 |
13
13
  | control | 15 | 0 | 0 | 0 | 15 |
14
- | iso | 168 | 218 | 0 | 0 | 386 |
14
+ | iso | 169 | 217 | 0 | 0 | 386 |
15
15
  | lists | 52 | 3 | 0 | 0 | 55 |
16
16
  | modules | 2 | 0 | 0 | 0 | 2 |
17
17
  | negation | 8 | 0 | 19 | 0 | 27 |
@@ -24,4 +24,4 @@ This report summarizes the file-based conformance corpus under `test/conformance
24
24
  | terms | 26 | 3 | 0 | 0 | 29 |
25
25
  | unification | 18 | 0 | 0 | 0 | 18 |
26
26
  | variables | 16 | 7 | 0 | 0 | 23 |
27
- | **Total** | **489** | **271** | **19** | **21** | **800** |
27
+ | **Total** | **490** | **270** | **19** | **21** | **800** |
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.3.32",
6
+ "version": "1.3.33",
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
@@ -2360,7 +2360,6 @@ function evaluateOperation(term, args) {
2360
2360
  const value = fn(a);
2361
2361
  if (Number.isNaN(value) || (name === 'log' && a === 0)) throw new PrologError('evaluation_error(undefined)');
2362
2362
  if (!Number.isFinite(value)) throw new PrologError('evaluation_error(float_overflow)');
2363
- if (value === 0 && a !== 0 && name === 'exp') throw new PrologError('evaluation_error(underflow)');
2364
2363
  return { integer: false, value };
2365
2364
  }
2366
2365
  if (arity !== 2) throw new PrologError('type_error(evaluable)', compound('/', [atom(name), numberTerm(arity)]));
@@ -2420,12 +2419,6 @@ function evaluateOperation(term, args) {
2420
2419
  else throw new PrologError('type_error(evaluable)', compound('/', [atom(name), numberTerm(arity)]));
2421
2420
  if (Number.isNaN(value)) throw new PrologError('evaluation_error(undefined)');
2422
2421
  if (!Number.isFinite(value)) throw new PrologError('evaluation_error(float_overflow)');
2423
- const underflow = value === 0 && (
2424
- (name === '*' && x !== 0 && y !== 0) ||
2425
- (name === '/' && x !== 0) ||
2426
- ((name === '**' || name === '^') && x !== 0)
2427
- );
2428
- if (underflow) throw new PrologError('evaluation_error(underflow)');
2429
2422
  return { integer: false, value };
2430
2423
  }
2431
2424
  export function arithmeticValueTerm(value) {
@@ -73,7 +73,7 @@ Status values are:
73
73
  | 8.17.3 | Other effects of `halt/0` | Terminates EyeProlog execution and returns host/process status `0`; it produces no Prolog solution. | **defined** — `HaltSignal`, `haltBuiltin()`, CLI/runner handling. |
74
74
  | 8.17.4 | Meaning/effects of `halt(Status)` | Integer `Status` is converted to the host process/runner halt code; it produces no Prolog solution. | **defined** — `haltBuiltin()`, `src/execute.js`, `src/cli.js`. |
75
75
  | 9.1.4.1 | Floating-point rounding function `rndF` | Floating values and operations use ECMAScript `Number` (IEEE-754 binary64) and the host's specified binary64 arithmetic/conversions. | **defined** — `src/iso.js`, `src/number-value.js`. |
76
- | 9.1.4.2 | Floating-point result function, including tiny non-zero arithmetic results | For arithmetic operation results that underflow to zero from non-zero operands, EyeProlog chooses the exceptional value `underflow`, exposed as `evaluation_error(underflow)`. Float token/`number_chars/2` input is a separate conversion path and finite input underflow rounds to `0.0`. | **defined** — `evaluateOperation()` and parser/number conversion; executable issue-56 regression below. |
76
+ | 9.1.4.2 | Floating-point result function, including tiny non-zero arithmetic results | EyeProlog chooses `round(x)` rather than the exceptional value `underflow`. ECMAScript binary64 arithmetic therefore preserves a representable subnormal result and rounds a still-smaller result to `0.0`, consistently with float-token and `number_chars/2` input. | **defined** — `evaluateOperation()` and parser/number conversion; executable issue-56 regression below. |
77
77
  | 9.1.4.3 | Approximate-addition function | ECMAScript binary64 addition is used; subtraction is implemented through the corresponding host operation and all finite results remain binary64 values. | **defined** — `evaluateOperation()` in `src/iso.js`. |
78
78
  | 9.4 | Representation of negative integers for bitwise operations | BigInt's unbounded signed binary semantics are used, equivalent to an infinite two's-complement sign extension for bitwise operations. | **defined** — `src/iso.js` BigInt bitwise operators. |
79
79
  | 9.4.1 | Right shift of negative integers and unusual shift counts | `>>` is arithmetic/sign-propagating. A negative count reverses direction according to JavaScript BigInt shift semantics; there is no finite integer bit-size ceiling in the Prolog model. | **defined** — `a >> b` in `src/iso.js`. |
@@ -83,22 +83,18 @@ Status values are:
83
83
  | 9.4.5 | Bitwise complement | BigInt complement, i.e. `~N = -N-1`. | **defined** — `~a`. |
84
84
  | Cor.2 9.4.6 | `xor/2` with negative operands | BigInt infinite-two's-complement semantics. | **defined** — `a ^ b`. |
85
85
 
86
- ### Why issue #56's two float results differ
87
-
88
- The arithmetic expression and the float token go through different specified
89
- layers. Clause 9.1.4 defines arithmetic operations in terms of the
90
- implementation-defined floating rounding/result functions, and EyeProlog's
91
- chosen `resultF` policy reports underflow for a non-zero arithmetic result that
92
- falls below the normal range and rounds to zero. By contrast, reading the token
93
- `0.1e-999` is an input conversion; the 1995 text does not precisely define the
94
- rounding of an inexact float token, a gap also called out in the later
95
- [WG17/STC item #40](https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#40).
96
- EyeProlog's documented input policy is therefore to accept finite token
97
- underflow as `0.0` while arithmetic underflow remains an evaluation error.
98
-
99
- The regression suite contains an issue-56 case that checks both observations,
100
- and the existing `stc/float_underflow_input` conformance case covers the related
101
- input-conversion policy.
86
+ ### Issue #56: one underflow policy
87
+
88
+ Clause 9.1.4.2 permits the processor to choose `round(x)` or the exceptional
89
+ value `underflow` for a tiny non-zero arithmetic result. EyeProlog chooses
90
+ `round(x)`. Because its floating-point profile is ECMAScript IEEE-754 binary64,
91
+ representable subnormal values remain non-zero and smaller results round to
92
+ `0.0`. Float-token and `number_chars/2` input use the same finite-double
93
+ rounding policy, so the same mathematical magnitude is no longer accepted as
94
+ `0.0` on input while rejected as an arithmetic result.
95
+
96
+ The regression suite checks both arithmetic and token input, and the existing
97
+ `stc/float_underflow_input` conformance case covers the related input conversion.
102
98
 
103
99
  ## Implementation-specific features required to be documented by 5.4
104
100
 
@@ -33,8 +33,8 @@ clause-by-clause in [ISO-IMPLEMENTATION-DEFINED.md](ISO-IMPLEMENTATION-DEFINED.m
33
33
  with *The Art of EyeProlog* remaining the implementation reference. In
34
34
  particular, the index records the unbounded integer model, `double_quotes=chars`,
35
35
  `//` rounding toward zero, the ECMAScript binary64 float policy (including the
36
- 9.1.4.2 arithmetic-underflow choice), stream/character decisions, and the
37
- normal-profile extension boundary.
36
+ 9.1.4.2 choice to round tiny arithmetic results rather than raise underflow),
37
+ stream/character decisions, and the normal-profile extension boundary.
38
38
 
39
39
  This is an executable conformance matrix, not a certification issued by an
40
40
  independent standards body. Release gating runs the ISO cases and the dedicated
@@ -37,7 +37,8 @@ record the behavior discussed in issue #54:
37
37
  - a positive finite numeric token beyond the representable range raises
38
38
  `representation_error(max_float)`;
39
39
  - the corresponding negative overflow raises `representation_error(min_float)`;
40
- - input underflow may round to `0.0`;
40
+ - float input and arithmetic underflow use the same binary64 rounding policy;
41
+ values smaller than the representable range round to `0.0`;
41
42
  - overflow produced by arithmetic evaluation remains
42
43
  `evaluation_error(float_overflow)`.
43
44
 
@@ -0,0 +1,7 @@
1
+ %% goal: arithmetic_underflow_rounds
2
+
3
+ arithmetic_underflow_rounds :-
4
+ A is 0.1*10** -999,
5
+ B is exp(-1000.0),
6
+ A =:= 0.0,
7
+ B =:= 0.0.
@@ -0,0 +1 @@
1
+ arithmetic_underflow_rounds.
@@ -740,10 +740,10 @@ c4 ?- call((!;1)).
740
740
  },
741
741
  },
742
742
  {
743
- name: 'arithmetic underflow choice differs from float-token input underflow (issue #56)',
743
+ name: 'arithmetic and float-token underflow both round to zero (issue #56)',
744
744
  run: () => {
745
- const result = run('', { goal: 'catch((N is 0.1*10** -999), error(evaluation_error(underflow), _), N = underflow)' });
746
- assertEqual(result.stdout, 'catch(underflow is 0.1 * 10 ** -999, error(evaluation_error(underflow), eyeprolog), underflow = underflow).\n', 'operation underflow');
745
+ assertEqual(run('', { goal: 'N is 0.1*10** -999' }).stdout, '0.0 is 0.1 * 10 ** -999.\n', 'operation underflow');
746
+ assertEqual(run('', { goal: 'N is exp(-1000.0)' }).stdout, '0.0 is exp(-1000.0).\n', 'function underflow');
747
747
  assertEqual(run('', { goal: 'N = 0.1e-999' }).stdout, '0.0 = 0.0.\n', 'float-token input underflow');
748
748
  },
749
749
  },
@@ -3431,7 +3431,7 @@ function documentationSyncCases() {
3431
3431
  '8.17.3', '8.17.4', '9.1.3.1', '9.1.4.1', '9.1.4.2', '9.1.4.3', '9.4',
3432
3432
  '9.4.1', '9.4.2', '9.4.3', '9.4.4', '9.4.5', 'Cor.2 9.4.6',
3433
3433
  ]) assertIncludes(text, `| ${clause} |`, `ISO 5.4 clause ${clause}`);
3434
- assertIncludes(text, 'Why issue #56', 'issue #56 explanation');
3434
+ assertIncludes(text, 'Issue #56: one underflow policy', 'issue #56 explanation');
3435
3435
  assertIncludes(text, 'Implementation-specific features required to be documented by 5.4', '5.5 extension inventory');
3436
3436
  },
3437
3437
  },
@@ -1,3 +0,0 @@
1
- %% goal: trigger
2
-
3
- trigger :- _ is exp(-1000.0).
@@ -1 +0,0 @@
1
- error(evaluation_error(underflow))