34
35:- module(typeprops,
36 [ list/1, list/2, tlist/2, nlist/1, nlist/2, goal/2, nnegint/1, flt/1,
37 gndstr/1, posflt/1, num/1, nnegnum/1, posnum/1, atm/1, gnd/1, any/1,
38 int/1, nnegflt/1, str/1, term/1, char/1, atmel/1, keypair/1, pair/1,
39 struct/1, constant/1, operator_specifier/1, character_code/1, rat/1,
40 mod_qual/1, mod_qual/2, keylist/1, predname/1, sequence/2, linear/1,
41 negint/1, posint/1, dict/1, atmstr/1, opts/1, metaopts/2, goal/1,
42 arithexpression/1
43 ]). 44
45:- use_module(library(apply)). 46:- use_module(library(arithmetic)). 47:- use_module(library(occurs)). 48:- use_module(library(neck)). 49:- use_module(library(assertions)). 50:- use_module(library(metaprops)). 51:- use_module(library(static_strip_module)). 52:- init_expansors. 53
54%! int(Int)
55%
56% The type of integers
57
58:- type int/1.
59
60int(X) :-
61 nonvar(X),
62 !,
63 integer(X).
64int(X) :-
65 checkprop_goal(
66 ( between(0, inf, N),
67 give_sign(N, X)
68 )).
69
70:- type posint/1.
71
72posint(X) :-
73 nonvar(X),
74 !,
75 integer(X),
76 X > 0.
77posint(X) :-
78 checkprop_goal(curr_posint(X)).
79
80curr_posint(N) :- between(1, inf, N).
81
82:- type negint/1.
83
84negint(X) :-
85 nonvar(X),
86 !,
87 integer(X),
88 X < 0.
89negint(X) :-
90 checkprop_goal(
91 ( curr_posint(N),
92 X is -N
93 )).
94
95give_sign(0, 0) :- !.
96give_sign(P, P).
97give_sign(P, N) :- N is -P.
98
99:- type nnegint/1.
105nnegint(X) :-
106 nonvar(X),
107 !,
108 integer(X),
109 X >= 0.
110nnegint(N) :-
111 checkprop_goal(between(0, inf, N)).
112
113:- type flt/1.
119flt(X) :-
120 nonvar(X),
121 !,
122 float(X).
123flt(F) :-
124 checkprop_goal(
125 ( nnegfltgen(Q),
126 give_sign(Q, F)
127 )).
128
129:- type nnegflt/1.
130
131nnegflt(X) :-
132 nonvar(X),
133 !,
134 float(X),
135 X >= 0.
136nnegflt(Q) :-
137 checkprop_goal(nnegfltgen(Q)).
138
139nnegfltgen(Q) :-
140 nnegint(X),
141 intfrac1(X, Q).
142
143intfrac1(X, Q) :-
144 ( Q is 1.0*X
145 ; frac(X, Q)
146 ).
147
148:- type posflt/1.
149
150posflt(X) :-
151 nonvar(X),
152 !,
153 float(X),
154 X > 0.
155posflt(Q) :-
156 checkprop_goal(
157 ( curr_posint(X),
158 intfrac1(X, Q)
159 )).
160
161:- type rat/1.
162
163rat(X) :-
164 rational(X),
165 !.
166rat(X) :-
167 checkprop_goal(
168 ( int(A),
169 int(B),
170 X is A rdiv B
171 )).
172
173:- type num/1.
179num(X) :-
180 nonvar(X),
181 !,
182 number(X).
183num(F) :-
184 checkprop_goal(
185 ( nnegnumgen(Q),
186 give_sign(Q, F)
187 )).
188
189:- type nnegnum/1.
190
191nnegnum(X) :-
192 nonvar(X),
193 !,
194 number(X),
195 X >= 0.
196nnegnum(Q) :-
197 checkprop_goal(nnegnumgen(Q)).
198
199nnegnumgen(Q) :-
200 nnegint(X),
201 intfrac2(X, Q).
202
203:- type posnum/1.
204
205posnum(X) :-
206 nonvar(X), !,
207 number(X),
208 X > 0.
209posnum(Q) :-
210 checkprop_goal(
211 ( curr_posint(X),
212 intfrac2(X, Q)
213 )).
214
215intfrac2(X, Q) :-
216 ( Q is X
217 ; Q is 1.0*X
218 ; frac(X, R),
219 ( Q is R
220 ; Q is 1.0*R
221 )
222 ).
223
224frac(X, Q) :-
225 between(2, X, Y),
226 1 =:= gcd(X, Y),
227 ( Q is X rdiv Y
228 ; Q is Y rdiv X
229 ).
230
231:- type atm/1.
237atm(T) :-
238 nonvar(T),
239 !,
240 atom(T).
241atm(A) :-
242 checkprop_goal(
243 ( list(character_code, L),
244 atom_codes(A, L)
245 )).
246
247:- type atmel/1.
253atmel([]).
254atmel(A) :- atm(A).
255
256:- type str/1.
262str(T) :-
263 nonvar(T),
264 !,
265 string(T).
266str(S) :-
267 checkprop_goal(
268 ( list(character_code, L),
269 string_codes(S, L)
270 )).
271
272%! character_code(I)
273%
274% An integer which is a character code
275
276:- type character_code/1.
277
278character_code(I) :-
279 between(0, 255, I),
280 neck.
281
282:- type atmstr/1.
288atmstr(T) :-
289 nonvar(T),
290 !,
291 once(( atom(A)
292 ; string(A)
293 )).
294atmstr(S) :-
295 checkprop_goal(
296 ( list(character_code, L),
297 ( string_codes(S, L)
298 ; atom_codes(S, L)
299 )
300 )).
301
302
303%! constant(C)
304%
305% An atomic term (an atom, string or a number)
306
307:- type constant/1.
308
309constant([]).
310constant(T) :- atm(T).
311constant(T) :- num(T).
312constant(T) :- str(T).
313
314:- type predname/1.
320predname(P/A) :-
321 atm(P),
322 nnegint(A).
323
324:- type term/1.
330term(_).
331
332:- type list/1.
338list([]).
339list([_|L]) :- list(L).
340
341%! list(:Type, List:list)
342%
343% List is a list of Type
344
345:- type list(1, list).
346:- meta_predicate list(1, ?). 347
348list(Type, List) :- list_(List, Type).
349
350:- type list_/2.
351list_([], _).
352list_([E|L], T) :-
353 type(T, E),
354 list_(L, T).
355
356:- type pair/1.
357pair(_-_).
358
359:- type keypair/1.
360keypair(_-_).
361
362:- type keylist/1.
363keylist(KL) :- list(keypair, KL).
364
365%! tlist(T, L)
366%
367% L is a list or a value of T's
368
369:- type tlist/2.
370:- meta_predicate tlist(1, ?). 371
372tlist(T, L) :- list(T, L).
373tlist(T, E) :- type(T, E).
374
375%! nlist(T, NL)
376%
377% A nested list of T's
378
379:- type nlist/2.
380:- meta_predicate nlist(1, ?). 381
382nlist(T, X) :- type(T, X).
383nlist(T, L) :- list(nlist(T), L).
384
385%! nlist(NL)
386%
387% A nested list
388
389:- type nlist/1.
390:- meta_predicate nlist(1, ?). 391
392nlist(T) :- term(T).
393nlist(L) :- list(nlist, L).
394
395/* Note: this definition could lead to il-formed lists, like [a|b], that is why
396 * we prefer the definition above
397
398nlist(Type, NList) :- nlist_(NList, Type).
399
400nlist_([], _).
401nlist_([X|Xs], T) :-
402 nlist_(X, T),
403 nlist_(Xs, T).
404nlist_(X, T) :-
405 type(T, X).
406*/
407
408:- type char/1.
409char(A) :- atm(A). % size(A)=1
410
411:- type any/1.
412any(_).
413
414:- type linear/1.
419linear(T) :-
420 term_variables(T, Vars),
421 maplist(occurrs_one(T), Vars).
422
423occurrs_one(T, Var) :- occurrences_of_var(Var, T, 1).
424
425%! sequence(:T, S)
426%
427% S is a sequence of T's
428
429:- type sequence/2.
430
431:- meta_predicate sequence(1, ?). 432
433sequence(T, S) :- sequence_(T, S).
434
435sequence_(E, T) :- type(E, T).
436sequence_((E, S), T) :-
437 type(E, T),
438 sequence_(S, T).
439
440:- type struct/1 # "A compound term".
441
443struct([_|_]):- !.
444struct(T) :- functor(T, _, A), A>0. % compound(T).
445
446:- type gnd/1 # "A ground term".
447
449gnd([]) :- !.
450gnd(T) :-
451 term_variables(T, Vars),
452 list(gnd, Vars).
453
454:- type arithexpression/1.
455
456%! arithexpression(Expr)
457
458% An arithmetic expression
459
460:- type gndstr/1.
461
462gndstr(A) :- gnd(A), struct(A).
463
464arithexpression(X) :- number(X), !. 465arithexpression(X) :- num(X).
466arithexpression(X) :-
467 callable(X),
468 curr_arithmetic_function(X),
469 X =.. [_|Args],
470 list(arithexpression, Args).
471
472curr_arithmetic_function(X) :- current_arithmetic_function(X).
473curr_arithmetic_function(X) :- arithmetic:evaluable(X, _Module).
474
475% BUG: if the trace has all the ports active, we can not use ';'/2 in goal/2
476% and some variables becomes uninstantiated. That is an SWI-Prolog bug but I
477% don't have time to isolate it --EMM
478
479%! goal(:P)
480%
481% P is a defined predicate
482
483:- true prop goal/1.
484:- meta_predicate goal(0). 485goal(Pred) :- goal(0, Pred).
486 % current_predicate(_, M:G).
487
488%! goal(N, :P)
489%
490% P is a defined predicate with N extra arguments
491
492:- true prop goal/2.
493:- meta_predicate goal(+, :). 494goal(N, Pred) :-
495 nnegint(N),
496 goal_2(Pred, N).
497
498goal_2(M:Pred, N) :-
499 var(Pred),
500 !,
501 checkprop_goal(
502 ( ( var(M)
503 ->current_module(CM),
504 current_predicate(CM:F/A),
505 M=CM
506 ; current_module(M),
507 current_predicate(M:F/A)
508 ),
509 A >= N,
510 A1 is A - N,
511 functor(Pred, F, A1)
512 )).
513goal_2(M:Pred, N) :-
514 callable(Pred),
515 functor(Pred, F, A1),
516 A is A1 + N,
517 ( var(M)
518 ->checkprop_goal(
519 ( current_module(CM),
520 current_predicate(CM:F/A),
521 M=CM
522 ))
523 ; current_module(M),
524 current_predicate(M:F/A)
525 ).
526
527:- true prop mod_qual/1.
528:- meta_predicate mod_qual(:). 529mod_qual(M:V) :-
530 static_strip_module(V, M, _, CM),
531 current_module(CM).
532
533:- true prop mod_qual/2.
534:- meta_predicate mod_qual(1, :). 535mod_qual(T, M:V) :-
536 static_strip_module(V, M, C, CM),
537 current_module(CM),
538 with_cv_module(type(T, C), CM).
539
540:- type operator_specifier/1.
541
542operator_specifier(fy).
543operator_specifier(fx).
544operator_specifier(yfx).
545operator_specifier(xfy).
546operator_specifier(xfx).
547operator_specifier(yf).
548operator_specifier(xf).
549
550% Note: options as defined by the type opts/1 are a subset of the supported
551% options, since it can only handle atomic/unique keys related to single values
552
553:- type opt/1.
554
555opt(A=B) :-
556 atm(A),
557 term(B).
558opt(A-B) :-
559 atm(A),
560 term(B).
561opt(AB) :-
562 nonvar(AB),
563 !,
564 AB =.. [_, _].
565
566:- type opt_eq/1.
567
568opt_eq(A=B) :-
569 atm(A),
570 term(B).
571
572opt_eq(Opt, Opts, [Opt|Opts]) :-
573 opt_eq(Opt),
574 \+ member(Opt, Opts).
575
576:- type dict/1.
577
578dict(D) :-
579 nonvar(D),
580 !,
581 is_dict(D).
582dict(D) :-
583 atm(T),
584 foldl(opt_eq, _, [], O),
585 dict_create(D, T, O).
586
587:- type opts/1.
588
589opts(L) :- list(opt, L).
590opts(D) :- dict(D).
591
592:- type metaopts(1, :opts).
593:- meta_predicate metaopts(1, :). 594
595metaopts(IsMeta, MOpts) :-
596 goal(1, IsMeta),
597 mod_qual(opts, MOpts)