eyeprolog 1.5.65 → 1.5.67
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 +1 -1
- package/src/lib/error.pl +53 -33
- package/src/lib/si.pl +39 -21
- package/src/program.js +1 -1
- package/test/regression/cases-regression.mjs +100 -3
- package/the-art-of-eyeprolog.md +4 -2
package/package.json
CHANGED
package/src/lib/error.pl
CHANGED
|
@@ -17,10 +17,6 @@
|
|
|
17
17
|
|
|
18
18
|
:- meta_predicate(call_with_error_context(0, +)).
|
|
19
19
|
|
|
20
|
-
% The context is supplied once here rather than handed over manually at every
|
|
21
|
-
% raise site: the raise sites throw with [] and this wrapper prepends its
|
|
22
|
-
% element, so contexts stay proper lists and compose with any enclosing
|
|
23
|
-
% call_with_error_context/2 (issue #98).
|
|
24
20
|
% The context is named in exactly one place -- error__must_be_throw/1 -- so no
|
|
25
21
|
% raise site hands one over (issue #98). It is a throw helper rather than a
|
|
26
22
|
% call_with_error_context/2 wrapper because wrapping a Prolog goal in catch/3
|
|
@@ -57,9 +53,20 @@ error__must_be(ground, Term) :- !,
|
|
|
57
53
|
error__must_be(acyclic, Term) :- !,
|
|
58
54
|
( acyclic_term(Term) -> true ; type_error(acyclic_term, Term) ).
|
|
59
55
|
error__must_be(list, Term) :- !,
|
|
60
|
-
|
|
56
|
+
error__list(Term, Term, must_be/2, complete).
|
|
61
57
|
error__must_be(list(Type), Term) :- !,
|
|
58
|
+
error__list(Term, Term, must_be/2, complete),
|
|
62
59
|
error__proper_list_of(Term, Type).
|
|
60
|
+
error__must_be(character, Term) :- !,
|
|
61
|
+
( var(Term) -> error__must_be_throw(instantiation_error)
|
|
62
|
+
; atom(Term), atom_length(Term, 1) -> true
|
|
63
|
+
; error__must_be_throw(type_error(character, Term))
|
|
64
|
+
).
|
|
65
|
+
error__must_be(chars, Term) :- !,
|
|
66
|
+
error__list(Term, Term, must_be/2, partial),
|
|
67
|
+
error__partial_list_of(Term, character, must_be/2),
|
|
68
|
+
error__list(Term, Term, must_be/2, complete),
|
|
69
|
+
error__proper_list_of(Term, character).
|
|
63
70
|
error__must_be(pair, Term) :- !,
|
|
64
71
|
( var(Term) -> error__must_be_throw(instantiation_error)
|
|
65
72
|
; Term = _-_ -> true
|
|
@@ -73,12 +80,17 @@ error__must_be(Type, Term) :-
|
|
|
73
80
|
; error__must_be_throw(type_error(Type, Term))
|
|
74
81
|
).
|
|
75
82
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
).
|
|
83
|
+
% A list ends in []; a partial list ends in a variable (including a variable
|
|
84
|
+
% alone). Inspect before matching so validation never completes a partial list.
|
|
85
|
+
% Keep the original term as the culprit when a tail cannot become a list.
|
|
86
|
+
error__list(Term, _, Predicate, Mode) :- var(Term), !,
|
|
87
|
+
( Mode == partial -> true
|
|
88
|
+
; throw(error(instantiation_error, [predicate-Predicate])) ).
|
|
89
|
+
error__list([], _, _, _) :- !.
|
|
90
|
+
error__list([_|Tail], Original, Predicate, Mode) :- !,
|
|
91
|
+
error__list(Tail, Original, Predicate, Mode).
|
|
92
|
+
error__list(_, Original, Predicate, _) :-
|
|
93
|
+
throw(error(type_error(list, Original), [predicate-Predicate])).
|
|
82
94
|
|
|
83
95
|
error__proper_list_of([], _) :- !.
|
|
84
96
|
error__proper_list_of([Head|Tail], Type) :- !,
|
|
@@ -90,37 +102,46 @@ error__proper_list_of(Term, _) :-
|
|
|
90
102
|
).
|
|
91
103
|
|
|
92
104
|
can_be(Type, Term) :-
|
|
93
|
-
( var(Type) -> instantiation_error
|
|
105
|
+
( var(Type) -> error__can_be_throw(instantiation_error)
|
|
94
106
|
; var(Term) -> true
|
|
95
107
|
; error__can_be(Type, Term)
|
|
96
108
|
).
|
|
97
109
|
|
|
110
|
+
error__can_be_throw(Formal) :-
|
|
111
|
+
throw(error(Formal, [predicate-can_be/2])).
|
|
112
|
+
|
|
98
113
|
error__can_be(integer, Term) :- !,
|
|
99
|
-
( integer(Term) -> true ; type_error(integer, Term
|
|
114
|
+
( integer(Term) -> true ; error__can_be_throw(type_error(integer, Term)) ).
|
|
100
115
|
error__can_be(atom, Term) :- !,
|
|
101
|
-
( atom(Term) -> true ; type_error(atom, Term
|
|
116
|
+
( atom(Term) -> true ; error__can_be_throw(type_error(atom, Term)) ).
|
|
102
117
|
error__can_be(number, Term) :- !,
|
|
103
|
-
( number(Term) -> true ; type_error(number, Term
|
|
104
|
-
error__can_be(list, Term) :- !,
|
|
105
|
-
error__can_be(list(Type), Term) :- !,
|
|
118
|
+
( number(Term) -> true ; error__can_be_throw(type_error(number, Term)) ).
|
|
119
|
+
error__can_be(list, Term) :- !, error__list(Term, Term, can_be/2, partial).
|
|
120
|
+
error__can_be(list(Type), Term) :- !,
|
|
121
|
+
error__list(Term, Term, can_be/2, partial),
|
|
122
|
+
error__partial_list_of(Term, Type, can_be/2).
|
|
123
|
+
error__can_be(character, Term) :- !,
|
|
124
|
+
( atom(Term), atom_length(Term, 1) -> true
|
|
125
|
+
; error__can_be_throw(type_error(character, Term)) ).
|
|
126
|
+
error__can_be(chars, Term) :- !,
|
|
127
|
+
error__list(Term, Term, can_be/2, partial),
|
|
128
|
+
error__partial_list_of(Term, character, can_be/2).
|
|
106
129
|
error__can_be(not_less_than_zero, Term) :- !,
|
|
107
130
|
( integer(Term) ->
|
|
108
|
-
( Term >= 0 -> true ; domain_error(not_less_than_zero, Term
|
|
109
|
-
; type_error(integer, Term
|
|
131
|
+
( Term >= 0 -> true ; error__can_be_throw(domain_error(not_less_than_zero, Term)) )
|
|
132
|
+
; error__can_be_throw(type_error(integer, Term))
|
|
110
133
|
).
|
|
111
|
-
error__can_be(Type, Term) :-
|
|
112
|
-
|
|
113
|
-
error__partial_list(Term) :- var(Term), !.
|
|
114
|
-
error__partial_list([]) :- !.
|
|
115
|
-
error__partial_list([_|Tail]) :- !, error__partial_list(Tail).
|
|
116
|
-
error__partial_list(Term) :- type_error(list, Term, can_be/2).
|
|
134
|
+
error__can_be(Type, Term) :-
|
|
135
|
+
catch(error__must_be(Type, Term), error(Formal, _), error__can_be_throw(Formal)).
|
|
117
136
|
|
|
118
|
-
error__partial_list_of(Term, _) :- var(Term), !.
|
|
119
|
-
error__partial_list_of([], _) :- !.
|
|
120
|
-
error__partial_list_of([Head|Tail], Type) :-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
137
|
+
error__partial_list_of(Term, _, _) :- var(Term), !.
|
|
138
|
+
error__partial_list_of([], _, _) :- !.
|
|
139
|
+
error__partial_list_of([Head|Tail], Type, Predicate) :-
|
|
140
|
+
( var(Head) -> true
|
|
141
|
+
; Predicate == must_be/2 -> must_be(Type, Head)
|
|
142
|
+
; can_be(Type, Head)
|
|
143
|
+
),
|
|
144
|
+
error__partial_list_of(Tail, Type, Predicate).
|
|
124
145
|
|
|
125
146
|
instantiation_error :- throw(error(instantiation_error, [])).
|
|
126
147
|
instantiation_error(Context) :- throw(error(instantiation_error, Context)).
|
|
@@ -140,8 +161,7 @@ call_with_error_context(Goal, Pair) :-
|
|
|
140
161
|
error__require_pair(Pair),
|
|
141
162
|
catch(Goal,
|
|
142
163
|
error(Error, Context),
|
|
143
|
-
(
|
|
144
|
-
throw(error(Error, [Element|Context])) )).
|
|
164
|
+
throw(error(Error, [Pair|Context]))).
|
|
145
165
|
|
|
146
166
|
% The element must be a pair (issue #99). The test is inlined rather than
|
|
147
167
|
% delegated to must_be(pair, _) so that the wrapper stays independent of the
|
package/src/lib/si.pl
CHANGED
|
@@ -69,32 +69,50 @@ si__condition((A;B)) :- si__condition(A), si__condition(B).
|
|
|
69
69
|
% names, f(X,a) @< f(X,b) by the second arguments, and X == X gives (=), while
|
|
70
70
|
% f(a) vs f(Y) and X vs 1 are genuinely undecided.
|
|
71
71
|
compare_si(Order, A, B) :-
|
|
72
|
-
(
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
72
|
+
si__require_order(Order),
|
|
73
|
+
si__compare(Order, [A-B]).
|
|
74
|
+
|
|
75
|
+
si__require_order(Order) :- var(Order), !.
|
|
76
|
+
si__require_order(Order) :-
|
|
77
|
+
( atom(Order) ->
|
|
78
|
+
( (Order == (<) ; Order == (=) ; Order == (>)) -> true
|
|
79
|
+
; throw(error(domain_error(order, Order), [predicate-compare_si/3]))
|
|
80
|
+
)
|
|
81
|
+
; throw(error(type_error(atom, Order), [predicate-compare_si/3]))
|
|
77
82
|
).
|
|
78
83
|
|
|
79
|
-
%
|
|
80
|
-
|
|
81
|
-
|
|
84
|
+
% Keep pending argument pairs in a work list. Recursing inside an if-then-else
|
|
85
|
+
% condition retains a child Solver per list cell; testing whole-tail identity
|
|
86
|
+
% at each step also repeatedly scans the same suffix (issue #105).
|
|
87
|
+
si__compare(=, []).
|
|
88
|
+
si__compare(Order, [A-B|Pairs]) :-
|
|
89
|
+
si__compare_pair(A, B, Comparison, Pairs, Next),
|
|
90
|
+
si__compare_next(Comparison, Order, Next).
|
|
91
|
+
|
|
92
|
+
si__compare_next(=, Order, Pairs) :- si__compare(Order, Pairs).
|
|
93
|
+
si__compare_next(<, <, _).
|
|
94
|
+
si__compare_next(>, >, _).
|
|
95
|
+
|
|
96
|
+
si__compare_pair(A, B, =, Pairs, Pairs) :-
|
|
97
|
+
( var(A) ; var(B) ), !,
|
|
98
|
+
( A == B -> true
|
|
99
|
+
; throw(error(instantiation_error, [predicate-compare_si/3])) ).
|
|
100
|
+
si__compare_pair([A|As], [B|Bs], =, Pairs, [A-B,As-Bs|Pairs]) :- !.
|
|
101
|
+
si__compare_pair(A, B, Comparison, Pairs, Next) :-
|
|
82
102
|
compound(A), compound(B), !,
|
|
83
103
|
functor(A, NameA, ArityA),
|
|
84
104
|
functor(B, NameB, ArityB),
|
|
85
|
-
( ArityA =\= ArityB ->
|
|
86
|
-
; NameA \== NameB ->
|
|
105
|
+
( ArityA =\= ArityB -> compare(Comparison, ArityA, ArityB), Next = Pairs
|
|
106
|
+
; NameA \== NameB -> compare(Comparison, NameA, NameB), Next = Pairs
|
|
87
107
|
; A =.. [_|ArgsA],
|
|
88
108
|
B =.. [_|ArgsB],
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
% Otherwise both are non-variables and at least one is atomic, so either the
|
|
92
|
-
% type order or the values themselves settle it and no instantiation can
|
|
93
|
-
% change the outcome.
|
|
94
|
-
si__order_decided(_, _).
|
|
95
|
-
|
|
96
|
-
si__args_decided([A|As], [B|Bs]) :-
|
|
97
|
-
( A == B
|
|
98
|
-
-> si__args_decided(As, Bs)
|
|
99
|
-
; si__order_decided(A, B)
|
|
109
|
+
Comparison = (=),
|
|
110
|
+
si__prepend_pairs(ArgsA, ArgsB, Next, Pairs)
|
|
100
111
|
).
|
|
112
|
+
si__compare_pair(A, _, >, Pairs, Pairs) :- compound(A), !.
|
|
113
|
+
si__compare_pair(_, B, <, Pairs, Pairs) :- compound(B), !.
|
|
114
|
+
si__compare_pair(A, B, Comparison, Pairs, Pairs) :- compare(Comparison, A, B).
|
|
115
|
+
|
|
116
|
+
si__prepend_pairs([], [], Pairs, Pairs).
|
|
117
|
+
si__prepend_pairs([A|As], [B|Bs], [A-B|Pairs], Tail) :-
|
|
118
|
+
si__prepend_pairs(As, Bs, Pairs, Tail).
|
package/src/program.js
CHANGED
|
@@ -1219,7 +1219,7 @@ function collectAutoloadGoalDependencies(goal, out = []) {
|
|
|
1219
1219
|
collectAutoloadGoalDependencies(goal.args[2], out);
|
|
1220
1220
|
} else if ((goal.name === 'call_cleanup' || goal.name === 'setup_call_cleanup') && (goal.arity === 2 || goal.arity === 3)) {
|
|
1221
1221
|
for (const arg of goal.args) collectAutoloadGoalDependencies(arg, out);
|
|
1222
|
-
} else if (goal.name === 'call' && goal.arity === 1) {
|
|
1222
|
+
} else if ((goal.name === 'call' || goal.name === 'time') && goal.arity === 1) {
|
|
1223
1223
|
collectAutoloadGoalDependencies(goal.args[0], out);
|
|
1224
1224
|
}
|
|
1225
1225
|
return out;
|
|
@@ -28,6 +28,103 @@ import {
|
|
|
28
28
|
|
|
29
29
|
export function regressionCases() {
|
|
30
30
|
return [
|
|
31
|
+
{
|
|
32
|
+
name: 'timed compare_si/3 backtracks over growing prefixes without exhausting the host stack (issue #105)',
|
|
33
|
+
run: () => {
|
|
34
|
+
// Bound the reported generator so the regression exhausts every
|
|
35
|
+
// answer, including sizes beyond the original 256-cell failure.
|
|
36
|
+
const result = runCli(['-'], { input:
|
|
37
|
+
'%% goal: answer(I,R,S)\n' +
|
|
38
|
+
'answer(I,R,S) :- length(_,I), (I =< 9 -> true ; !, fail), ' +
|
|
39
|
+
'N is 2^I, length(P,N), append(P,[1],L1), append(P,[2],L2), ' +
|
|
40
|
+
'time(compare(R,L1,L2)), time(compare_si(S,L1,L2)).\n',
|
|
41
|
+
timeout: 20000,
|
|
42
|
+
});
|
|
43
|
+
assertEqual(result.status, 0, `exit status; error=${result.error}; stderr=${result.stderr}`);
|
|
44
|
+
for (let i = 0; i <= 9; i++) {
|
|
45
|
+
assertIncludes(result.stdout, `answer(${i}, <, <).`, 'comparison result');
|
|
46
|
+
}
|
|
47
|
+
assertNotIncludes(result.stderr + result.stdout, 'Maximum call stack', 'host stack');
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'compare_si/3 work list preserves argument priority and instantiation errors',
|
|
52
|
+
run: () => {
|
|
53
|
+
const goals = [
|
|
54
|
+
'compare_si(=,f(X,g(Y)),f(X,g(Y))),var(X),var(Y)',
|
|
55
|
+
'compare_si(<,f(g(X),a),f(g(X),b)),var(X)',
|
|
56
|
+
'compare_si(>,f(g(b),a),f(g(a),z))',
|
|
57
|
+
'compare_si(<,[a|X],[b|Y]),var(X),var(Y)',
|
|
58
|
+
'compare_si(>,f(X),a),var(X)',
|
|
59
|
+
'compare_si(<,a,f(X)),var(X)',
|
|
60
|
+
'\\+ compare_si(>,f(g(X),a),f(g(X),b))',
|
|
61
|
+
'catch((compare_si(_,f(g(X),a),f(g(Y),b)),fail),error(instantiation_error,[predicate-compare_si/3]),true),var(X),var(Y)',
|
|
62
|
+
];
|
|
63
|
+
for (const goal of goals) {
|
|
64
|
+
const result = runEyeProlog(`answer(ok) :- ${goal}.`, { goals: ['answer(X)'] });
|
|
65
|
+
assertIncludes(result.stdout, 'answer(ok)', goal);
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: 'compare_si/3 validates Order before term instantiation (issue #100)',
|
|
71
|
+
run: () => {
|
|
72
|
+
for (const terms of ['A,B', 'A,A', '1,2']) {
|
|
73
|
+
for (const [order, formal] of [['x', 'domain_error(order, x)'], ['1', 'type_error(atom, 1)']]) {
|
|
74
|
+
const result = runCli([], { input: `compare_si(${order},${terms}).\nhalt.\n` });
|
|
75
|
+
assertIncludes(result.stdout, `error(${formal}, [predicate-compare_si/3])`, 'order error');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: 'list and chars type checks preserve partial lists and report precise errors (issues #102 and #103)',
|
|
82
|
+
run: () => {
|
|
83
|
+
const goals = [
|
|
84
|
+
'catch(must_be(list,L),error(instantiation_error,[predicate-must_be/2]),true),var(L)',
|
|
85
|
+
'catch(must_be(list,[a|L]),error(instantiation_error,[predicate-must_be/2]),true),var(L)',
|
|
86
|
+
'catch(must_be(list(integer),L),error(instantiation_error,[predicate-must_be/2]),true),var(L)',
|
|
87
|
+
'catch(must_be(list(integer),[1|L]),error(instantiation_error,[predicate-must_be/2]),true),var(L)',
|
|
88
|
+
'must_be(list,[X]),var(X)',
|
|
89
|
+
'must_be(chars,[a,b])',
|
|
90
|
+
'catch(must_be(chars,[C]),error(instantiation_error,[predicate-must_be/2]),true),var(C)',
|
|
91
|
+
'catch(must_be(chars,[C,ab]),error(type_error(character,ab),[predicate-must_be/2]),true),var(C)',
|
|
92
|
+
'can_be(chars,[C|L]),var(C),var(L)',
|
|
93
|
+
'can_be(list(integer),[C|L]),var(C),var(L)',
|
|
94
|
+
'catch(can_be(chars,[C|1]),error(type_error(list,[D|1]),[predicate-can_be/2]),true),var(C),var(D)',
|
|
95
|
+
'catch(must_be(chars,[C|1]),error(type_error(list,[D|1]),[predicate-must_be/2]),true),var(C),var(D)',
|
|
96
|
+
'catch(can_be(chars,[ab|L]),error(type_error(character,ab),[predicate-can_be/2]),true),var(L)',
|
|
97
|
+
'catch(can_be(pair,a),error(type_error(pair,a),[predicate-can_be/2]),true)',
|
|
98
|
+
'catch(can_be(integer,a),error(type_error(integer,a),[predicate-can_be/2]),true)',
|
|
99
|
+
];
|
|
100
|
+
for (const goal of goals) {
|
|
101
|
+
const result = runCli(['-'], { input: `:- use_module(library(error)).\n%% goal: answer(X)\nanswer(ok) :- ${goal}.\n` });
|
|
102
|
+
assertEqual(result.status, 0, `${goal}: ${result.stderr}`);
|
|
103
|
+
assertIncludes(result.stdout, 'answer(ok)', goal);
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
name: 'call_with_error_context/2 preserves repeated variables in context pairs (issue #104)',
|
|
109
|
+
run: () => {
|
|
110
|
+
const result = runCli(['-'], { input: ':- use_module(library(error)).\n%% goal: answer(X)\n' +
|
|
111
|
+
'answer(ok) :- catch(call_with_error_context(throw(error(problem(X),[inner-X])),outer-f(Y,Y)),error(problem(A),[outer-f(B,C),inner-D]),true),B==C,A==D,var(Y).\n' });
|
|
112
|
+
assertEqual(result.status, 0, result.stderr);
|
|
113
|
+
assertIncludes(result.stdout, 'answer(ok)', 'shared error variables');
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: 'time/1 autoloads compare_si/3 on its first call (issue #105)',
|
|
118
|
+
run: () => {
|
|
119
|
+
const goal = 'length(P,8),append(P,[1],L1),append(P,[2],L2),time(compare(R,L1,L2)),time(compare_si(S,L1,L2))';
|
|
120
|
+
const repl = runCli([], { input: `${goal}.\n.\nhalt.\n` });
|
|
121
|
+
assertNotIncludes(repl.stdout, 'existence_error', 'first REPL call');
|
|
122
|
+
assertIncludes(repl.stdout, 'S = (<)', 'timed comparison');
|
|
123
|
+
const file = runCli(['-'], { input: `%% goal: answer(X)\nanswer(ok) :- ${goal},R==S.\n` });
|
|
124
|
+
assertEqual(file.status, 0, file.stderr);
|
|
125
|
+
assertIncludes(file.stdout, 'answer(ok)', 'file autoload');
|
|
126
|
+
},
|
|
127
|
+
},
|
|
31
128
|
{
|
|
32
129
|
name: 'dif/2 passes the WG17 finite-tree comparison cases (issue #68)',
|
|
33
130
|
run: () => {
|
|
@@ -4638,9 +4735,9 @@ answer(Result) :- countdown(2048, Result), Result = 2048.
|
|
|
4638
4735
|
},
|
|
4639
4736
|
},
|
|
4640
4737
|
{
|
|
4641
|
-
//
|
|
4642
|
-
//
|
|
4643
|
-
name: '
|
|
4738
|
+
// Throwing the error ball already freshens its variables; the wrapper
|
|
4739
|
+
// does not need a separate copy_term/2 call (issue #104).
|
|
4740
|
+
name: 'throw/1 freshens variables in the propagated context element',
|
|
4644
4741
|
run: () => {
|
|
4645
4742
|
const input = ':- use_module(library(error)).\n%% goal: answer(X)\n' +
|
|
4646
4743
|
'answer(ok) :- catch(call_with_error_context(atom_length(1.0,_), ctx-V), error(_,[ctx-W|_]), (V == W -> fail ; true)).\n';
|
package/the-art-of-eyeprolog.md
CHANGED
|
@@ -10794,8 +10794,10 @@ The host decides whether to reject, report, or inspect those answers.
|
|
|
10794
10794
|
definite program; equivalently, the fixed point obtained by repeatedly adding
|
|
10795
10795
|
supported ground consequences.
|
|
10796
10796
|
|
|
10797
|
-
**List.** Either `[]` or
|
|
10798
|
-
|
|
10797
|
+
**List.** Either `[]` or `[Head | Tail]` where `Tail` is a list. A list
|
|
10798
|
+
ends in `[]`. A partial list ends in a variable, for example `[X,Y|Xs]`;
|
|
10799
|
+
a variable alone is also a partial list. `[X,Y|non_list]` is an instance
|
|
10800
|
+
of a partial list that is not a list.
|
|
10799
10801
|
|
|
10800
10802
|
**Mode.** An intended direction of use described by which arguments are
|
|
10801
10803
|
supplied and which are produced.
|