YAP 7.1.0
arith.yap
Go to the documentation of this file.
1/*************************************************************************
2* *
3* YAP Prolog *
4* *
5* Yap Prolog was developed at NCCUP - Universidade do Porto *
6* *
7* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
8* *
9**************************************************************************
10* *
11* File: arith.yap *
12* Last rev: *
13* mods: *
14* comments: arithmetical optimization *
15* *
16*************************************************************************/
17
18 % the default mode is on
19
20%% @file arith.yap
21
22:- compile_expressions/0expand_exprs/2plus/3succ/2'$c_built_in'/4system_module( '$_arith', [,
23 ,
24 ,
25 ], []).
26
27:- do_c_built_in/3do_c_built_metacall/3expand_expr/3expand_expr/5expand_expr/6private( [,
28 ,
29 ,
30 ,
31 ] ).
32
33:- '$do_error'/2use_system_module( '$_errors', []).
34
35:- '$clean_cuts'/2use_system_module( '$_modules', []).
36
37/** @defgroup CompilerAnalysis Internal Clause Rewriting
38 @ingroup YAPCompilerSettings
39
40 YAP supports several clause optimisation mechanisms, that
41 are designed to improve execution of arithmetic
42 and term construction built-ins. In other words, during the
43 compilation process a clause is rewritten twice:
44
45 1. first, perform user-defined goal_expansion as described
46 in the predicates goal_expansion/1 and goal_expansion/2.
47
48 2. Perform expansion of some built-ins like:
49
50 + pruning operators, like ->/2 and F>/2
51
52 + arithmetic, including early evaluation of constant expressions
53
54 + specialise versions for some built-ins, if we are aware of the
55 run-time execution mode
56
57 The user has some control over this process, through some
58 built-ins and through execution flsgs.
59
60*/
61
62%% @{
63
64/** @pred expand_exprs(- _O_,+ _N_)
65 Control term expansion during compilation.
66
67Enables low-level optimizations. It reports the current state by
68unifying _O_ with the previous state. It then puts YAP in state _N_
69(`on` or `off`)/ _On_ is equivalent to compile_expressions/0 and `off`
70is equivalent to do_not_compile_expressions/0.
71
72This predicate is useful when debugging, to ensure execution close to the original source.
73
74*/
75expand_exprs(Old,New) :-
76 yap_flag(optimise,BO),
77 (BO == true ->
78 Old = on ;
79 Old = off ),
80 (New == on ->
81 B = true ;
82 B = false ),
83 yap_flag(optimise,B).
84
85'$set_arith_expan'(on) :- prolog_flag(optimise,true).
86'$set_arith_expan'(off) :- prolog_flag(optimise,false).
87
88/** @pred compile_expressions
89
90After a call to this predicate, arithmetical expressions will be compiled.
91(see example below). This is the default behavior.
92*/
93prolog_flag :- set_prolog_flag(optimise, true).
94
95/** @pred do_not_compile_expressions
96
97
98After a call to this predicate, arithmetical expressions will not be compiled.
99
100```
101?- source, do_not_compile_expressions.
102yes
103?- [user].
104| p(X) :- X is 2 * (3 + 8).
105| :- end_of_file.
106?- compile_expressions.
107yes
108?- [user].
109| q(X) :- X is 2 * (3 + 8).
110| :- end_of_file.
111:- listing.
112
113p(A):-
114 A is 2 * (3 + 8).
115
116q(A):-
117 A is 22.
118```
119*/
120set_prolog_flag :-
121 set_prolog_flag(optimise, false).
122
123'$c_built_in'(IN, _M, (:- _H), IN) :-
124 '$c_built_in'.
125'$c_built_in'(IN, _M, (?- _H), IN) :-
126 '$c_built_in'.
127'$c_built_in'(IN, M, H, OUT) :-
128 prolog_flag(optimise,true), prolog_flag,
129 do_c_built_in(IN, M, H, OUT).
130'$c_built_in'(IN, _, _H, IN).
131
132
133do_c_built_in(G, M, H, OUT) :- var(G), var,
134 do_c_built_metacall(G, M, H, OUT).
135do_c_built_in(Mod:G, _, H, OUT) :-
136 '$yap_strip_module'(Mod:G, M1, G1),
137 var(G1), var,
138 do_c_built_metacall(G1, M1, H, OUT).
139do_c_built_in('$do_error'( Error, Goal), M, Head,OError) :-
140 do_c_built_in,
141 stream_property(loop_stream, file_name(F)),
142 stream_property(loop_stream, line_number(L)),
143 functor(Head,N,A),
144 OError = throw(error(Error,exception( [
145 prologPredFile=F,
146 prologPredName=N,
147 prologPredModule=M,
148 prologPredArity=A,
149 prologPredLine=L,
150 errorGoal=Goal
151 ])) ).
152do_c_built_in('$do_error'( Error, _), _M, _Head, (throw(Error))) :- do_c_built_in.
153do_c_built_in(X is Y, M, H, P) :-
154 primitive(X), primitive,
155 do_c_built_in(X =:= Y, M, H, P).
156do_c_built_in(X is Y, M, H, (P,A=X)) :-
157 nonvar(X), nonvar,
158 do_c_built_in(A is Y, M, H, P).
159do_c_built_in(X is Y, _, _, P) :-
160 nonvar(Y), % Don't rewrite variables
161 nonvar,
162 (
163 number(Y) ->
164 P = ( X = Y); % This case reduces to an unification
165 expand_expr(Y, P0, X0),
166 '$drop_is'(X0, X, P0, P)
167 ).
168do_c_built_in(phrase(NT,Xs), Mod, H, NTXsNil) :-
169 '$_arith':do_c_built_in(phrase(NT,Xs,[]), Mod, H, NTXsNil).
170do_c_built_in(phrase(NT,Xs0,Xs), Mod, _, NewGoal) :-
171 '$c_built_in_phrase'(NT, Xs0, Xs, Mod, NewGoal ).
172
173do_c_built_in(Comp0, _, _, R) :- % now, do it for comparisons
174 '$compop'(Comp0, Op, E, F),
175 '$compop',
176 '$compop'(Comp, Op, U, V),
177 expand_expr(E, P, U),
178 expand_expr(F, Q, V),
179 '$do_and'(P, Q, R0),
180 '$do_and'(R0, Comp, R).
181do_c_built_in(P, _M, _H, P).
182
183/*
184do_c_built_metacall(G1, Mod, _, '$execute_wo_mod'(G1,Mod)) :-
185 var(Mod), !.
186do_c_built_metacall(G1, Mod, _, '$execute_in_mod'(G1,Mod)) :-
187 atom(Mod), !.
188 */
189do_c_built_metacall(G1, Mod, _, (Mod:G1)) :- atom(Mod), nonvar(G1), nonvar.
190do_c_built_metacall(G1, Mod, _, call(Mod:G1)).
191
192'$do_and'(true, P, P) :- '$do_and'.
193'$do_and'(P, true, P) :- '$do_and'.
194'$do_and'(P, Q, (P,Q)).
195
196% V is the result of the simplification,
197% X the result of the initial expression
198% and the last argument is how we are writing this result
199'$drop_is'(V, V1, P0, G) :-
200 var(V),
201 var, % usual case
202 V = V1,
203 P0 = G.
204'$drop_is'(V, X, P0, P) :- % atoms
205 '$do_and'(P0, X is V, P).
206
207% Table of arithmetic comparisons
208'$compop'(X < Y, < , X, Y).
209'$compop'(X > Y, > , X, Y).
210'$compop'(X=< Y,=< , X, Y).
211'$compop'(X >=Y, >=, X, Y).
212'$compop'(X=:=Y,=:=, X, Y).
213'$compop'(X=\=Y,=\=, X, Y).
214
215'$composed_built_in'(V) :- var(V), var,
216 var.
217'$composed_built_in'((current_choice_point(_),NG,cut_by(_))) :- '$composed_built_in',
218 '$composed_built_in'(NG).
219'$composed_built_in'((_,_)).
220'$composed_built_in'((_;_)).
221'$composed_built_in'((_|_)).
222'$composed_built_in'((_->_)).
223'$composed_built_in'(_:G) :-
224 '$composed_built_in'(G).
225'$composed_built_in'(\+G) :-
226 '$composed_built_in'(G).
227'$composed_built_in'(not(G)) :-
228 '$composed_built_in'(G).
229
230% expanding an expression:
231% first argument is the expression not expanded,
232% second argument the expanded expression
233% third argument unifies with the result from the expression
234expand_expr(V, true, V) :-
235 var(V), var.
236expand_expr([T], E, V) :- expand_expr,
237 expand_expr(T, E, V).
238expand_expr(String, _E, V) :-
239 string( String ), string,
240 string_codes(String, [V]).
241expand_expr(A, true, A) :-
242 atomic(A), atomic.
243expand_expr(T, E, V) :-
244 T =.. [O, A], ,
245 expand_expr(A, Q, X),
246 expand_expr(O, X, V, Q, E).
247expand_expr(T, E, V) :-
248 T =.. [O, A, B], ,
249 expand_expr(A, Q, X),
250 expand_expr(B, R, Y),
251 expand_expr(O, X, Y, V, Q, S),
252 '$do_and'(R, S, E).
253
254% expanding an expression of the form:
255% O is Op(X),
256% after having expanded into Q
257% and giving as result P (the last argument)
258expand_expr(Op, X, O, Q, Q) :-
259 number(X),
260 catch(is( O, Op, X),_,fail), catch. % do not do error handling at compile time
261expand_expr(Op, X, O, Q, P) :-
262 '$unary_op_as_integer'(Op,IOp),
263 '$do_and'(Q, is( O, IOp, X), P).
264
265% expanding an expression of the form:
266% O is Op(X,Y),
267% after having expanded into Q
268% and giving as result P (the last argument)
269% included is some optimization for:
270% incrementing and decrementing,
271% the elementar arithmetic operations [+,-,*,//]
272expand_expr(Op, X, Y, O, Q, Q) :-
273 number(X), number(Y),
274 catch(is( O, Op, X, Y),_,fail), catch.
275expand_expr(+, X, Y, O, Q, P) :- expand_expr,
276 '$preprocess_args_for_commutative'(X, Y, X1, Y1, E),
277 '$do_and'(E, '$plus'(X1,Y1,O), F),
278 '$do_and'(Q, F, P).
279expand_expr(-, X, Y, O, Q, P) :-
280 var(X), number(Y),
281 Z is -Y, number,
282 expand_expr(+, Z, X, O, Q, P).
283expand_expr(-, X, Y, O, Q, P) :- expand_expr,
284 '$preprocess_args_for_non_commutative'(X, Y, X1, Y1, E),
285 '$do_and'(E, '$minus'(X1,Y1,O), F),
286 '$do_and'(Q, F, P).
287expand_expr(*, X, Y, O, Q, P) :- expand_expr,
288 '$preprocess_args_for_commutative'(X, Y, X1, Y1, E),
289 '$do_and'(E, '$times'(X1,Y1,O), F),
290 '$do_and'(Q, F, P).
291expand_expr(//, X, Y, O, Q, P) :-
292 nonvar(Y), Y == 0, nonvar,
293 '$binary_op_as_integer'(//,IOp),
294 '$do_and'(Q, is(O,IOp,X,Y), P).
295expand_expr(//, X, Y, O, Q, P) :- expand_expr,
296 '$preprocess_args_for_non_commutative'(X, Y, X1, Y1, E),
297 '$do_and'(E, '$div'(X1,Y1,O), F),
298 '$do_and'(Q, F, P).
299expand_expr(/\, X, Y, O, Q, P) :- expand_expr,
300 '$preprocess_args_for_commutative'(X, Y, X1, Y1, E),
301 '$do_and'(E, '$and'(X1,Y1,O), F),
302 '$do_and'(Q, F, P).
303expand_expr(\/, X, Y, O, Q, P) :- expand_expr,
304 '$preprocess_args_for_commutative'(X, Y, X1, Y1, E),
305 '$do_and'(E, '$or'(X1,Y1,O), F),
306 '$do_and'(Q, F, P).
307expand_expr(<<, X, Y, O, Q, P) :-
308 var(X), number(Y), Y < 0,
309 Z is -Y, number,
310 expand_expr(>>, X, Z, O, Q, P).
311expand_expr(<<, X, Y, O, Q, P) :- expand_expr,
312 '$preprocess_args_for_non_commutative'(X, Y, X1, Y1, E),
313 '$do_and'(E, '$sll'(X1,Y1,O), F),
314 '$do_and'(Q, F, P).
315expand_expr(>>, X, Y, O, Q, P) :-
316 var(X), number(Y), Y < 0,
317 Z is -Y, number,
318 expand_expr(<<, X, Z, O, Q, P).
319expand_expr(>>, X, Y, O, Q, P) :- expand_expr,
320 '$preprocess_args_for_non_commutative'(X, Y, X1, Y1, E),
321 '$do_and'(E, '$slr'(X1,Y1,O), F),
322 '$do_and'(Q, F, P).
323expand_expr(Op, X, Y, O, Q, P) :-
324 '$binary_op_as_integer'(Op,IOp),
325 '$do_and'(Q, is(O,IOp,X,Y), P).
326
327'$preprocess_args_for_commutative'(X, Y, X, Y, true) :-
328 var(X), var(Y), var.
329'$preprocess_args_for_commutative'(X, Y, X, Y, true) :-
330 var(X), integer(Y), \+ '$bignum'(Y), '$bignum'.
331'$preprocess_args_for_commutative'(X, Y, X, Z, Z = Y) :-
332 var(X), var.
333'$preprocess_args_for_commutative'(X, Y, Y, X, true) :-
334 integer(X), \+ '$bignum'(X), var(Y), var.
335'$preprocess_args_for_commutative'(X, Y, Z, X, Z = Y) :-
336 integer(X), \+ '$bignum'(X), '$bignum'.
337'$preprocess_args_for_commutative'(X, Y, Z, W, E) :-
338 '$do_and'(Z = X, Y = W, E).
339
340'$preprocess_args_for_non_commutative'(X, Y, X, Y, true) :-
341 var(X), var(Y), var.
342'$preprocess_args_for_non_commutative'(X, Y, X, Y, true) :-
343 var(X), integer(Y), \+ '$bignum'(Y), '$bignum'.
344'$preprocess_args_for_non_commutative'(X, Y, X, Z, Z = Y) :-
345 var(X), var.
346'$preprocess_args_for_non_commutative'(X, Y, X, Y, true) :-
347 integer(X), \+ '$bignum'(X), var(Y), var.
348'$preprocess_args_for_non_commutative'(X, Y, X, Z, Z = Y) :-
349 integer(X), \+ '$bignum'(X), '$bignum'.
350'$preprocess_args_for_non_commutative'(X, Y, Z, W, E) :-
351 '$do_and'(Z = X, Y = W, E).
352
353
354'$goal_expansion_allowed'(phrase(NT,_Xs0,_Xs), Mod) :-
356 atom(Mod).
357
358%% contains_illegal_dcgnt(+Term) is semidet.
359%
360% True if Term contains a non-terminal we cannot deal with using
361% goal-expansion. The test is too general approximation, but safe.
362
363'$contains_illegal_dcgnt'(NT) :-
364 functor(NT, _, A),
365 between(1, A, I),
366 arg(I, NT, AI),
367 nonvar(AI),
368 ( AI = ! ; AI = phrase(_,_,_) ), !.
369% write(contains_illegal_nt(NT)), % JW: we do not want to write
370% nl.
371
372'$harmless_dcgexception'(instantiation_error). % ex: phrase(([1],x:X,[3]),L)
373'$harmless_dcgexception'(type_error(callable,_)). % ex: phrase(27,L)
374
375
376:- set_prolog_flag(optimise,true).
377/**
378 @}
379*/
380
catch( : Goal,+ Exception,+ Action)
expand_exprs(- O,+ N)
must_be_callable( ?_Goal_ )
stream_property( Stream, Prop )
Definition: top.yap:2
system_module( + Mod)
throw(+ Ball)
yap_flag( ?Param, ?Value)
phrase(+ P, L, R)
set_prolog_flag(+ Flag,+ Value)
arg(+ N,+ T, A)
atom( T)
atomic(T)
functor( T, F, N)
integer( T)
nonvar( T)
number( T)
primitive( ?_T_)
var( T)
between(+ Low:int, + High:int, ? Value:int)
plus(? Int1:int, ? Int2:int, ? Int3:int)
succ(? Int1:int, ? Int2:int)