eyeprolog 1.5.61 → 1.5.62

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.61",
6
+ "version": "1.5.62",
7
7
  "description": "EyeProlog turns facts and rules into answers and proofs.",
8
8
  "type": "module",
9
9
  "main": "./index.js",
package/src/lib/error.pl CHANGED
@@ -21,34 +21,39 @@
21
21
  % raise site: the raise sites throw with [] and this wrapper prepends its
22
22
  % element, so contexts stay proper lists and compose with any enclosing
23
23
  % call_with_error_context/2 (issue #98).
24
+ % The context is named in exactly one place -- error__must_be_throw/1 -- so no
25
+ % raise site hands one over (issue #98). It is a throw helper rather than a
26
+ % call_with_error_context/2 wrapper because wrapping a Prolog goal in catch/3
27
+ % costs a child Solver on every call, and must_be/2 succeeds almost always.
24
28
  must_be(Type, Term) :-
25
- call_with_error_context(
26
- ( var(Type) -> instantiation_error
27
- ; error__must_be(Type, Term)
28
- ),
29
- predicate-must_be/2).
29
+ ( var(Type) -> error__must_be_throw(instantiation_error)
30
+ ; error__must_be(Type, Term)
31
+ ).
32
+
33
+ error__must_be_throw(Formal) :-
34
+ throw(error(Formal, [predicate-must_be/2])).
30
35
 
31
36
  error__must_be(integer, Term) :- !,
32
- ( var(Term) -> instantiation_error
37
+ ( var(Term) -> error__must_be_throw(instantiation_error)
33
38
  ; integer(Term) -> true
34
- ; type_error(integer, Term)
39
+ ; error__must_be_throw(type_error(integer, Term))
35
40
  ).
36
41
  error__must_be(atom, Term) :- !,
37
- ( var(Term) -> instantiation_error
42
+ ( var(Term) -> error__must_be_throw(instantiation_error)
38
43
  ; atom(Term) -> true
39
- ; type_error(atom, Term)
44
+ ; error__must_be_throw(type_error(atom, Term))
40
45
  ).
41
46
  error__must_be(number, Term) :- !,
42
- ( var(Term) -> instantiation_error
47
+ ( var(Term) -> error__must_be_throw(instantiation_error)
43
48
  ; number(Term) -> true
44
- ; type_error(number, Term)
49
+ ; error__must_be_throw(type_error(number, Term))
45
50
  ).
46
51
  error__must_be(var, Term) :- !,
47
52
  ( var(Term) -> true
48
53
  ; throw(error(uninstantiation_error(Term), []))
49
54
  ).
50
55
  error__must_be(ground, Term) :- !,
51
- ( ground(Term) -> true ; instantiation_error ).
56
+ ( ground(Term) -> true ; error__must_be_throw(instantiation_error) ).
52
57
  error__must_be(acyclic, Term) :- !,
53
58
  ( acyclic_term(Term) -> true ; type_error(acyclic_term, Term) ).
54
59
  error__must_be(list, Term) :- !,
@@ -56,23 +61,23 @@ error__must_be(list, Term) :- !,
56
61
  error__must_be(list(Type), Term) :- !,
57
62
  error__proper_list_of(Term, Type).
58
63
  error__must_be(pair, Term) :- !,
59
- ( var(Term) -> instantiation_error
64
+ ( var(Term) -> error__must_be_throw(instantiation_error)
60
65
  ; Term = _-_ -> true
61
- ; type_error(pair, Term)
66
+ ; error__must_be_throw(type_error(pair, Term))
62
67
  ).
63
68
  error__must_be(not_less_than_zero, Term) :- !,
64
69
  must_be(integer, Term),
65
70
  ( Term >= 0 -> true ; domain_error(not_less_than_zero, Term) ).
66
71
  error__must_be(Type, Term) :-
67
- ( var(Term) -> instantiation_error
68
- ; type_error(Type, Term)
72
+ ( var(Term) -> error__must_be_throw(instantiation_error)
73
+ ; error__must_be_throw(type_error(Type, Term))
69
74
  ).
70
75
 
71
76
  error__proper_list([]) :- !.
72
77
  error__proper_list([_|Tail]) :- !, error__proper_list(Tail).
73
78
  error__proper_list(Term) :-
74
- ( var(Term) -> instantiation_error
75
- ; type_error(list, Term)
79
+ ( var(Term) -> error__must_be_throw(instantiation_error)
80
+ ; error__must_be_throw(type_error(list, Term))
76
81
  ).
77
82
 
78
83
  error__proper_list_of([], _) :- !.
@@ -80,7 +85,7 @@ error__proper_list_of([Head|Tail], Type) :- !,
80
85
  must_be(Type, Head),
81
86
  error__proper_list_of(Tail, Type).
82
87
  error__proper_list_of(Term, _) :-
83
- ( var(Term) -> instantiation_error
88
+ ( var(Term) -> error__must_be_throw(instantiation_error)
84
89
  ; type_error(list, Term)
85
90
  ).
86
91
 
package/src/lib/random.pl CHANGED
@@ -10,7 +10,7 @@
10
10
  :- module(random, [maybe/0, maybe/1, maybe/2, random/1, random/3, random_integer/3, set_random/1]).
11
11
 
12
12
  :- use_module(library(iso_ext), [bb_get/2, bb_put/2]).
13
- :- use_module(library(error), [call_with_error_context/2, instantiation_error/0, type_error/2]).
13
+
14
14
 
15
15
  maybe :-
16
16
  random_integer(0, 2, 0).
@@ -31,7 +31,7 @@ random(Value) :-
31
31
  % Context declared once per predicate instead of at each raise site, so the
32
32
  % raise sites throw with [] and contexts stay proper composable lists.
33
33
  random_integer(Lower, Upper, R) :-
34
- call_with_error_context(random__check_integer_range(Lower, Upper), predicate-random_integer/3),
34
+ random__check_integer_range(Lower, Upper),
35
35
  Lower < Upper,
36
36
  random__current_seed(Seed0),
37
37
  random(Seed0, _, Seed),
@@ -39,28 +39,31 @@ random_integer(Lower, Upper, R) :-
39
39
  R is Lower + Seed mod (Upper - Lower).
40
40
 
41
41
  set_random(Seed) :-
42
- call_with_error_context(random__set_seed(Seed), predicate-set_random/1).
42
+ random__set_seed(Seed).
43
+
44
+ random__throw(Formal, Predicate) :-
45
+ throw(error(Formal, [predicate-Predicate])).
43
46
 
44
47
  random__check_integer_range(Lower, Upper) :-
45
- ( var(Lower) -> instantiation_error
46
- ; var(Upper) -> instantiation_error
48
+ ( var(Lower) -> random__throw(instantiation_error, random_integer/3)
49
+ ; var(Upper) -> random__throw(instantiation_error, random_integer/3)
47
50
  ; integer(Lower) -> true
48
- ; type_error(integer, Lower)
51
+ ; random__throw(type_error(integer, Lower), random_integer/3)
49
52
  ),
50
53
  ( integer(Upper) -> true
51
- ; type_error(integer, Upper)
54
+ ; random__throw(type_error(integer, Upper), random_integer/3)
52
55
  ).
53
56
 
54
57
  random__set_seed(Seed) :-
55
- ( var(Seed) -> instantiation_error
58
+ ( var(Seed) -> random__throw(instantiation_error, set_random/1)
56
59
  ; Seed = seed(S) ->
57
- ( var(S) -> instantiation_error
60
+ ( var(S) -> random__throw(instantiation_error, set_random/1)
58
61
  ; integer(S) ->
59
62
  random__random_normalize_seed(S, Normalized),
60
63
  bb_put('$random_seed', Normalized)
61
- ; type_error(integer, S)
64
+ ; random__throw(type_error(integer, S), set_random/1)
62
65
  )
63
- ; type_error(random_state, Seed)
66
+ ; random__throw(type_error(random_state, Seed), set_random/1)
64
67
  ).
65
68
 
66
69
  random__current_seed(Seed) :- bb_get('$random_seed', Seed), !.
@@ -4510,6 +4510,24 @@ answer(Result) :- countdown(2048, Result), Result = 2048.
4510
4510
  assertIncludes(repl.stdout, 'throw(foo)', 'non-error ball keeps the wrapper');
4511
4511
  },
4512
4512
  },
4513
+ {
4514
+ // must_be/2 is called constantly by library code, so its context must be
4515
+ // supplied without a catch/3 frame: wrapping a Prolog goal in catch/3
4516
+ // costs a child Solver per call and made the suite ~35% slower.
4517
+ name: 'must_be/2 does not pay for a catch frame on success',
4518
+ run: () => {
4519
+ const input = '%% goal: answer(X)\n' +
4520
+ 'loop(0) :- !.\nloop(N) :- must_be(integer, N), M is N - 1, loop(M).\n' +
4521
+ 'answer(ok) :- loop(20000).\n';
4522
+ const started = Date.now();
4523
+ const result = runCli(['-'], { input });
4524
+ const elapsed = Date.now() - started;
4525
+ assertEqual(result.status, 0, `exit status; stderr=${result.stderr}`);
4526
+ assertIncludes(result.stdout, 'answer(ok)', 'loop completes');
4527
+ // Generous bound: the catch/3 wrapper made this roughly 2x slower.
4528
+ if (elapsed >= 20000) throw new Error(`20k must_be/2 calls took ${elapsed}ms`);
4529
+ },
4530
+ },
4513
4531
  {
4514
4532
  // Issue #99: the context element must be a pair, as in Scryer and
4515
4533
  // Trealla, and predicate contexts use the predicate-F/A convention.