3 Part of CHR (Constraint Handling Rules)
6 E-mail: Tom.Schrijvers@cs.kuleuven.be
7 WWW: http://www.swi-prolog.org
8 Copyright (C): 2003-2004, K.U. Leuven
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 As a special exception, if you link this library with other files,
25 compiled with a Free Software compiler, to produce an executable, this
26 library does not by itself cause the resulting executable to be covered
27 by the GNU General Public License. This exception does not however
28 invalidate any other reasons why the executable file might be covered by
29 the GNU General Public License.
32 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34 %% ____ _ _ ____ ____ _ _
35 %% / ___| | | | _ \ / ___|___ _ __ ___ _ __ (_) | ___ _ __
36 %% | | | |_| | |_) | | | / _ \| '_ ` _ \| '_ \| | |/ _ \ '__|
37 %% | |___| _ | _ < | |__| (_) | | | | | | |_) | | | __/ |
38 %% \____|_| |_|_| \_\ \____\___/|_| |_| |_| .__/|_|_|\___|_|
41 %% hProlog CHR compiler:
43 %% * by Tom Schrijvers, K.U. Leuven, Tom.Schrijvers@cs.kuleuven.be
45 %% * based on the SICStus CHR compilation by Christian Holzbaur
47 %% First working version: 6 June 2003
49 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
55 %% * add mode checking to debug mode
56 %% * add groundness info to a.i.-based observation analysis
57 %% * proper fd/index analysis
58 %% * re-add generation checking
59 %% * untangle CHR-level and target source-level generation & optimization
61 %% AGGRESSIVE OPTIMISATION IDEAS
63 %% * analyze history usage to determine whether/when
64 %% cheaper suspension is possible:
65 %% don't use history when all partners are passive and self never triggers
66 %% * store constraint unconditionally for unconditional propagation rule,
67 %% if first, i.e. without checking history and set trigger cont to next occ
68 %% * get rid of suspension passing for never triggered constraints,
69 %% up to allocation occurrence
70 %% * get rid of call indirection for never triggered constraints
71 %% up to first allocation occurrence.
72 %% * get rid of unnecessary indirection if last active occurrence
73 %% before unconditional removal is head2, e.g.
76 %% * Eliminate last clause of never stored constraint, if its body
80 %% * Specialize lookup operations and indexes for functional dependencies.
84 %% * map A \ B <=> true | true rules
85 %% onto efficient code that empties the constraint stores of B
86 %% in O(1) time for ground constraints where A and B do not share
88 %% * ground matching seems to be not optimized for compound terms
89 %% in case of simpagation_head2 and propagation occurrences
90 %% * analysis for storage delaying (see primes for case)
91 %% * internal constraints declaration + analyses?
92 %% * Do not store in global variable store if not necessary
93 %% NOTE: affects show_store/1
94 %% * var_assoc multi-level store: variable - ground
95 %% * Do not maintain/check unnecessary propagation history
96 %% for reasons of anti-monotony
97 %% * Strengthen storage analysis for propagation rules
98 %% reason about bodies of rules only containing constraints
99 %% -> fixpoint with observation analysis
100 %% * instantiation declarations
101 %% COMPOUND (bound to nonvar)
102 %% avoid nonvar tests
104 %% * make difference between cheap guards for reordering
105 %% and non-binding guards for lock removal
106 %% * fd -> once/[] transformation for propagation
107 %% * cheap guards interleaved with head retrieval + faster
108 %% via-retrieval + non-empty checking for propagation rules
109 %% redo for simpagation_head2 prelude
110 %% * intelligent backtracking for simplification/simpagation rule
111 %% generator_1(X),'_$savecp'(CP_1),
118 %% ('_$cutto'(CP_1), fail)
122 %% or recently developped cascading-supported approach
123 %% * intelligent backtracking for propagation rule
124 %% use additional boolean argument for each possible smart backtracking
125 %% when boolean at end of list true -> no smart backtracking
126 %% false -> smart backtracking
127 %% only works for rules with at least 3 constraints in the head
128 %% * (set semantics + functional dependency) declaration + resolution
130 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
131 :- module(chr_translate,
132 [ chr_translate/2 % +Decls, -TranslatedDecls
133 , chr_translate_line_info/3 % +DeclsWithLines, -TranslatedDecls
136 :- use_module(library(lists),[member/2, append/3,reverse/2,permutation/2,last/2]).
137 :- use_module(library(ordsets)).
138 :- use_module(library(aggregate)).
139 :- use_module(library(apply_macros)).
140 :- use_module(library(occurs)).
141 :- use_module(library(assoc)).
144 % imports and operators {{{
145 :- use_module(hprolog).
146 :- use_module(pairlist).
147 :- use_module(a_star).
148 :- use_module(listmap).
149 :- use_module(clean_code).
150 :- use_module(builtins).
152 :- use_module(binomialheap).
153 :- use_module(guard_entailment).
154 :- use_module(chr_compiler_options).
155 :- use_module(chr_compiler_utility).
156 :- use_module(chr_compiler_errors).
158 :- op(1150, fx, chr_type).
159 :- op(1150, fx, chr_declaration).
160 :- op(1130, xfx, --->).
164 :- op(1150, fx, constraints).
165 :- op(1150, fx, chr_constraint).
168 :- chr_option(debug,off).
169 :- chr_option(optimize,full).
170 :- chr_option(check_guard_bindings,off).
172 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
173 % Type Declarations {{{
174 :- chr_type list(T) ---> [] ; [T|list(T)].
176 :- chr_type list == list(any).
178 :- chr_type mode ---> (+) ; (-) ; (?).
180 :- chr_type maybe(T) ---> yes(T) ; no.
182 :- chr_type constraint ---> any / any.
184 :- chr_type module_name == any.
186 :- chr_type pragma_rule ---> pragma(rule,idspair,list(pragma_type),maybe(rule_name),rule_nb).
187 :- chr_type rule ---> rule(list(any),list(any),goal,goal).
188 :- chr_type idspair ---> ids(list(id),list(id)).
190 :- chr_type pragma_type ---> passive(id)
193 ; already_in_heads(id)
195 ; history(history_name,list(id)).
196 :- chr_type history_name== any.
198 :- chr_type rule_name == any.
199 :- chr_type rule_nb == natural.
200 :- chr_type id == natural.
201 :- chr_type occurrence == int.
203 :- chr_type goal == any.
205 :- chr_type store_type ---> default
206 ; multi_store(list(store_type))
207 ; multi_hash(list(list(int)))
208 ; multi_inthash(list(list(int)))
211 % EXPERIMENTAL STORES
212 ; atomic_constants(list(int),list(any),coverage)
213 ; ground_constants(list(int),list(any),coverage)
214 ; var_assoc_store(int,list(int))
215 ; identifier_store(int)
216 ; type_indexed_identifier_store(int,any).
217 :- chr_type coverage ---> complete ; incomplete.
219 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
221 %------------------------------------------------------------------------------%
222 :- chr_constraint chr_source_file/1.
223 :- chr_option(mode,chr_source_file(+)).
224 :- chr_option(type_declaration,chr_source_file(module_name)).
225 %------------------------------------------------------------------------------%
226 chr_source_file(_) \ chr_source_file(_) <=> true.
228 %------------------------------------------------------------------------------%
229 :- chr_constraint get_chr_source_file/1.
230 :- chr_option(mode,get_chr_source_file(-)).
231 :- chr_option(type_declaration,get_chr_source_file(module_name)).
232 %------------------------------------------------------------------------------%
233 chr_source_file(Mod) \ get_chr_source_file(Query)
235 get_chr_source_file(Query)
239 %------------------------------------------------------------------------------%
240 :- chr_constraint target_module/1.
241 :- chr_option(mode,target_module(+)).
242 :- chr_option(type_declaration,target_module(module_name)).
243 %------------------------------------------------------------------------------%
244 target_module(_) \ target_module(_) <=> true.
246 %------------------------------------------------------------------------------%
247 :- chr_constraint get_target_module/1.
248 :- chr_option(mode,get_target_module(-)).
249 :- chr_option(type_declaration,get_target_module(module_name)).
250 %------------------------------------------------------------------------------%
251 target_module(Mod) \ get_target_module(Query)
253 get_target_module(Query)
256 %------------------------------------------------------------------------------%
257 :- chr_constraint line_number/2.
258 :- chr_option(mode,line_number(+,+)).
259 :- chr_option(type_declaration,line_number(rule_nb,int)).
260 %------------------------------------------------------------------------------%
261 line_number(RuleNb,LineNb) \ line_number(RuleNb,LineNumber) <=> true.
263 %------------------------------------------------------------------------------%
264 :- chr_constraint get_line_number/2.
265 :- chr_option(mode,get_line_number(+,-)).
266 :- chr_option(type_declaration,get_line_number(rule_nb,int)).
267 %------------------------------------------------------------------------------%
268 line_number(RuleNb,LineNb) \ get_line_number(RuleNb,Q) <=> Q = LineNb.
269 get_line_number(RuleNb,Q) <=> Q = 0. % no line number available
271 :- chr_constraint indexed_argument/2. % argument instantiation may enable applicability of rule
272 :- chr_option(mode,indexed_argument(+,+)).
273 :- chr_option(type_declaration,indexed_argument(constraint,int)).
275 :- chr_constraint is_indexed_argument/2.
276 :- chr_option(mode,is_indexed_argument(+,+)).
277 :- chr_option(type_declaration,is_indexed_argument(constraint,int)).
279 :- chr_constraint constraint_mode/2.
280 :- chr_option(mode,constraint_mode(+,+)).
281 :- chr_option(type_declaration,constraint_mode(constraint,list(mode))).
283 :- chr_constraint get_constraint_mode/2.
284 :- chr_option(mode,get_constraint_mode(+,-)).
285 :- chr_option(type_declaration,get_constraint_mode(constraint,list(mode))).
287 :- chr_constraint may_trigger/1.
288 :- chr_option(mode,may_trigger(+)).
289 :- chr_option(type_declaration,may_trigger(constraint)).
291 :- chr_constraint only_ground_indexed_arguments/1.
292 :- chr_option(mode,only_ground_indexed_arguments(+)).
293 :- chr_option(type_declaration,only_ground_indexed_arguments(constraint)).
295 :- chr_constraint none_suspended_on_variables/0.
297 :- chr_constraint are_none_suspended_on_variables/0.
299 :- chr_constraint store_type/2.
300 :- chr_option(mode,store_type(+,+)).
301 :- chr_option(type_declaration,store_type(constraint,store_type)).
303 :- chr_constraint get_store_type/2.
304 :- chr_option(mode,get_store_type(+,?)).
305 :- chr_option(type_declaration,get_store_type(constraint,store_type)).
307 :- chr_constraint update_store_type/2.
308 :- chr_option(mode,update_store_type(+,+)).
309 :- chr_option(type_declaration,update_store_type(constraint,store_type)).
311 :- chr_constraint actual_store_types/2.
312 :- chr_option(mode,actual_store_types(+,+)).
313 :- chr_option(type_declaration,actual_store_types(constraint,list(store_type))).
315 :- chr_constraint assumed_store_type/2.
316 :- chr_option(mode,assumed_store_type(+,+)).
317 :- chr_option(type_declaration,assumed_store_type(constraint,store_type)).
319 :- chr_constraint validate_store_type_assumption/1.
320 :- chr_option(mode,validate_store_type_assumption(+)).
321 :- chr_option(type_declaration,validate_store_type_assumption(constraint)).
323 :- chr_constraint rule_count/1.
324 :- chr_option(mode,rule_count(+)).
325 :- chr_option(type_declaration,rule_count(natural)).
327 :- chr_constraint inc_rule_count/1.
328 :- chr_option(mode,inc_rule_count(-)).
329 :- chr_option(type_declaration,inc_rule_count(natural)).
331 rule_count(_) \ rule_count(_)
333 rule_count(C), inc_rule_count(NC)
334 <=> NC is C + 1, rule_count(NC).
336 <=> NC = 1, rule_count(NC).
338 :- chr_constraint passive/2.
339 :- chr_option(mode,passive(+,+)).
341 :- chr_constraint is_passive/2.
342 :- chr_option(mode,is_passive(+,+)).
344 :- chr_constraint any_passive_head/1.
345 :- chr_option(mode,any_passive_head(+)).
347 :- chr_constraint new_occurrence/4.
348 :- chr_option(mode,new_occurrence(+,+,+,+)).
350 :- chr_constraint occurrence/5.
351 :- chr_option(mode,occurrence(+,+,+,+,+)).
352 :- chr_type occurrence_type ---> simplification ; propagation.
353 :- chr_option(type_declaration,occurrence(constraint,occurrence,rule_nb,id,occurrence_type)).
355 :- chr_constraint get_occurrence/4.
356 :- chr_option(mode,get_occurrence(+,+,-,-)).
358 :- chr_constraint get_occurrence_from_id/4.
359 :- chr_option(mode,get_occurrence_from_id(+,-,+,+)).
361 :- chr_constraint max_occurrence/2.
362 :- chr_option(mode,max_occurrence(+,+)).
364 :- chr_constraint get_max_occurrence/2.
365 :- chr_option(mode,get_max_occurrence(+,-)).
367 :- chr_constraint allocation_occurrence/2.
368 :- chr_option(mode,allocation_occurrence(+,+)).
370 :- chr_constraint get_allocation_occurrence/2.
371 :- chr_option(mode,get_allocation_occurrence(+,-)).
373 :- chr_constraint rule/2.
374 :- chr_option(mode,rule(+,+)).
375 :- chr_option(type_declaration,rule(rule_nb,pragma_rule)).
377 :- chr_constraint get_rule/2.
378 :- chr_option(mode,get_rule(+,-)).
379 :- chr_option(type_declaration,get_rule(int,pragma_rule)).
381 :- chr_constraint least_occurrence/2.
382 :- chr_option(mode,least_occurrence(+,+)).
383 :- chr_option(type_declaration,least_occurrence(any,list)).
385 :- chr_constraint is_least_occurrence/1.
386 :- chr_option(mode,is_least_occurrence(+)).
389 indexed_argument(FA,I) \ indexed_argument(FA,I) <=> true.
390 indexed_argument(FA,I) \ is_indexed_argument(FA,I) <=> true.
391 is_indexed_argument(_,_) <=> fail.
393 %%% C O N S T R A I N T M O D E %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
395 constraint_mode(FA,_) \ constraint_mode(FA,_) <=> true.
396 constraint_mode(FA,Mode) \ get_constraint_mode(FA,Q) <=>
398 get_constraint_mode(FA,Q) <=>
402 %%% M A Y T R I G G E R %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
404 may_trigger(FA) <=> \+ has_active_occurrence(FA) | fail.
405 constraint_mode(FA,Mode), indexed_argument(FA,I) \ may_trigger(FA) <=>
409 may_trigger(FA) <=> chr_pp_flag(debugable,on). % in debug mode, we assume everything can be triggered
411 constraint_mode(FA,Mode), indexed_argument(FA,I) \ only_ground_indexed_arguments(FA)
417 only_ground_indexed_arguments(_) <=>
420 none_suspended_on_variables \ none_suspended_on_variables <=> true.
421 none_suspended_on_variables \ are_none_suspended_on_variables <=> true.
422 are_none_suspended_on_variables <=> fail.
423 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
426 % The functionality for inspecting and deciding on the different types of constraint
427 % store / indexes for constraints.
429 store_type(FA,StoreType)
430 ==> chr_pp_flag(verbose,on)
432 format('The indexes for ~w are:\n',[FA]),
433 format_storetype(StoreType).
434 % chr_info(verbose,'Storetype of ~w is ~w.\n',[FA,StoreType]).
436 format_storetype(multi_store(StoreTypes)) :- !,
437 maplist(format_storetype,StoreTypes).
438 format_storetype(atomic_constants(Index,Constants,_)) :-
439 format('\t* a trie index on the argument(s) ~w for the ground terms ~w\n',[Index,Constants]).
440 format_storetype(ground_constants(Index,Constants,_)) :-
441 format('\t* a trie index on the argument(s) ~w for the ground terms ~w\n',[Index,Constants]).
442 format_storetype(StoreType) :-
443 format('\t* ~w\n',[StoreType]).
451 get_store_type_normal @
452 store_type(FA,Store) \ get_store_type(FA,Query)
455 get_store_type_assumed @
456 assumed_store_type(FA,Store) \ get_store_type(FA,Query)
459 get_store_type_default @
460 get_store_type(_,Query)
463 % 2. Store type registration
464 % ~~~~~~~~~~~~~~~~~~~~~~~~~~
466 actual_store_types(C,STs) \ update_store_type(C,ST)
467 <=> memberchk(ST,STs) | true.
468 update_store_type(C,ST), actual_store_types(C,STs)
470 actual_store_types(C,[ST|STs]).
471 update_store_type(C,ST)
473 actual_store_types(C,[ST]).
475 % 3. Final decision on store types
476 % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
478 validate_store_type_assumption(C) \ actual_store_types(C,STs), actual_atomic_multi_hash_keys(C,Index,Keys)
480 true % chr_pp_flag(experiment,on)
482 delete(STs,multi_hash([Index]),STs0),
484 ( get_constraint_arg_type(C,IndexPos,Type),
485 enumerated_atomic_type(Type,Atoms) ->
486 /* use the type constants rather than the collected keys */
488 Completeness = complete
491 Completeness = incomplete
493 actual_store_types(C,[atomic_constants(Index,Constants,Completeness)|STs0]).
494 validate_store_type_assumption(C) \ actual_store_types(C,STs), actual_ground_multi_hash_keys(C,Index,Constants0)
496 true % chr_pp_flag(experiment,on)
498 ( Index = [IndexPos],
499 get_constraint_arg_type(C,IndexPos,Type),
500 % ( fail , is_chr_constants_type(Type,Key,_) -> get_chr_constants(Key,Constants)
502 Type = chr_enum(Constants) % -> true
505 Completeness = complete
507 Constants = Constants0,
508 Completeness = incomplete
510 delete(STs,multi_hash([Index]),STs0),
511 actual_store_types(C,[ground_constants(Index,Constants,Completeness)|STs0]).
513 get_constraint_arg_type(C,Pos,Type) :-
514 get_constraint_type(C,Types),
515 nth1(Pos,Types,Type0),
516 unalias_type(Type0,Type).
518 validate_store_type_assumption(C) \ actual_store_types(C,STs)
520 % chr_pp_flag(experiment,on),
521 memberchk(multi_hash([[Index]]),STs),
522 get_constraint_type(C,Types),
523 nth1(Index,Types,Type),
524 enumerated_atomic_type(Type,Atoms)
526 delete(STs,multi_hash([[Index]]),STs0),
527 actual_store_types(C,[atomic_constants([Index],Atoms,complete)|STs0]).
528 validate_store_type_assumption(C) \ actual_store_types(C,STs)
530 memberchk(multi_hash([[Index]]),STs),
531 get_constraint_arg_type(C,Index,Type),
533 Type = chr_enum(Constants) % -> true
534 % ; fail, is_chr_constants_type(Type,Key,_) -> get_chr_constants(Key,Constants)
537 delete(STs,multi_hash([[Index]]),STs0),
538 actual_store_types(C,[ground_constants([Index],Constants,complete)|STs0]).
539 validate_store_type_assumption(C), actual_store_types(C,STs), assumed_store_type(C,_) % automatic assumption
541 ( /* chr_pp_flag(experiment,on), */ maplist(partial_store,STs) ->
542 Stores = [global_ground|STs]
546 store_type(C,multi_store(Stores)).
547 validate_store_type_assumption(C), actual_store_types(C,STs), store_type(C,_) % user assumption
549 store_type(C,multi_store(STs)).
550 validate_store_type_assumption(C), assumed_store_type(C,_) % no lookups on constraint in debug mode
552 chr_pp_flag(debugable,on)
554 store_type(C,default).
555 validate_store_type_assumption(C), assumed_store_type(C,_) % no lookups on constraint
556 <=> store_type(C,global_ground).
557 validate_store_type_assumption(C)
560 partial_store(ground_constants(_,_,incomplete)).
561 partial_store(atomic_constants(_,_,incomplete)).
563 %%% P A S S I V E %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
564 passive(R,ID) \ passive(R,ID) <=> true.
566 passive(RuleNb,ID) \ is_passive(RuleNb,ID) <=> true.
567 is_passive(_,_) <=> fail.
569 passive(RuleNb,_) \ any_passive_head(RuleNb)
573 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
575 max_occurrence(C,N) \ max_occurrence(C,M)
578 max_occurrence(C,MO), new_occurrence(C,RuleNb,ID,Type) <=>
580 occurrence(C,NO,RuleNb,ID,Type),
581 max_occurrence(C,NO).
582 new_occurrence(C,RuleNb,ID,_) <=>
583 chr_error(internal,'new_occurrence: missing max_occurrence for ~w in rule ~w\n',[C,RuleNb]).
585 max_occurrence(C,MON) \ get_max_occurrence(C,Q)
587 get_max_occurrence(C,Q)
588 <=> chr_error(internal,'get_max_occurrence: missing max occurrence for ~w\n',[C]).
590 occurrence(C,ON,Rule,ID,_) \ get_occurrence(C,ON,QRule,QID)
591 <=> Rule = QRule, ID = QID.
592 get_occurrence(C,O,_,_)
593 <=> chr_error(internal,'get_occurrence: missing occurrence ~w:~w\n',[C,O]).
595 occurrence(C,ON,Rule,ID,_) \ get_occurrence_from_id(QC,QON,Rule,ID)
596 <=> QC = C, QON = ON.
597 get_occurrence_from_id(C,O,_,_)
598 <=> chr_error(internal,'get_occurrence_from_id: missing occurrence ~w:~w\n',[]).
600 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
603 late_allocation_analysis(Cs) :-
604 ( chr_pp_flag(late_allocation,on) ->
605 maplist(late_allocation, Cs)
610 late_allocation(C) :- late_allocation(C,0).
611 late_allocation(C,O) :- allocation_occurrence(C,O), !.
612 late_allocation(C,O) :- NO is O + 1, late_allocation(C,NO).
614 % A L L O C C A T I O N O C C U R R E N C E %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
616 allocation_occurrence(C,0) ==> stored_in_guard_before_next_kept_occurrence(C,0).
618 rule(RuleNb,Rule), occurrence(C,O,RuleNb,Id,Type), allocation_occurrence(C,O) ==>
619 \+ is_passive(RuleNb,Id),
621 ( stored_in_guard_before_next_kept_occurrence(C,O) ->
623 ; Rule = pragma(rule([_|_],_,_,_),_,_,_,_) -> % simpagation rule
625 ; is_least_occurrence(RuleNb) -> % propagation rule
631 stored_in_guard_before_next_kept_occurrence(C,O) :-
632 chr_pp_flag(store_in_guards, on),
634 stored_in_guard_lookahead(C,NO).
636 :- chr_constraint stored_in_guard_lookahead/2.
637 :- chr_option(mode, stored_in_guard_lookahead(+,+)).
639 occurrence(C,O,RuleNb,Id,_), passive(RuleNb,Id) \ stored_in_guard_lookahead(C,O) <=>
640 NO is O + 1, stored_in_guard_lookahead(C,NO).
641 occurrence(C,O,RuleNb,Id,Type) \ stored_in_guard_lookahead(C,O) <=>
642 Type == simplification,
643 ( is_stored_in_guard(C,RuleNb) ->
646 NO is O + 1, stored_in_guard_lookahead(C,NO)
648 stored_in_guard_lookahead(_,_) <=> fail.
651 rule(RuleNb,Rule), occurrence(C,O,RuleNb,ID,_), allocation_occurrence(C,AO)
652 \ least_occurrence(RuleNb,[ID|IDs])
653 <=> AO >= O, \+ may_trigger(C) |
654 least_occurrence(RuleNb,IDs).
655 rule(RuleNb,Rule), passive(RuleNb,ID)
656 \ least_occurrence(RuleNb,[ID|IDs])
657 <=> least_occurrence(RuleNb,IDs).
660 ==> Rule = pragma(rule([],_,_,_),ids([],IDs),_,_,_) |
661 least_occurrence(RuleNb,IDs).
663 least_occurrence(RuleNb,[]) \ is_least_occurrence(RuleNb)
665 is_least_occurrence(_)
668 allocation_occurrence(C,O) \ get_allocation_occurrence(C,Q)
670 get_allocation_occurrence(_,Q)
671 <=> chr_pp_flag(late_allocation,off), Q=0.
672 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
674 rule(RuleNb,Rule) \ get_rule(RuleNb,Q)
679 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
681 %%% C O N S T R A I N T I N D E X %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
683 % Default store constraint index assignment.
685 :- chr_constraint constraint_index/2. % constraint_index(F/A,DefaultStoreAndAttachedIndex)
686 :- chr_option(mode,constraint_index(+,+)).
687 :- chr_option(type_declaration,constraint_index(constraint,int)).
689 :- chr_constraint get_constraint_index/2.
690 :- chr_option(mode,get_constraint_index(+,-)).
691 :- chr_option(type_declaration,get_constraint_index(constraint,int)).
693 :- chr_constraint get_indexed_constraint/2.
694 :- chr_option(mode,get_indexed_constraint(+,-)).
695 :- chr_option(type_declaration,get_indexed_constraint(int,constraint)).
697 :- chr_constraint max_constraint_index/1. % max_constraint_index(MaxDefaultStoreAndAttachedIndex)
698 :- chr_option(mode,max_constraint_index(+)).
699 :- chr_option(type_declaration,max_constraint_index(int)).
701 :- chr_constraint get_max_constraint_index/1.
702 :- chr_option(mode,get_max_constraint_index(-)).
703 :- chr_option(type_declaration,get_max_constraint_index(int)).
705 constraint_index(C,Index) \ get_constraint_index(C,Query)
707 get_constraint_index(C,Query)
710 constraint_index(C,Index) \ get_indexed_constraint(Index,Q)
712 get_indexed_constraint(Index,Q)
715 max_constraint_index(Index) \ get_max_constraint_index(Query)
717 get_max_constraint_index(Query)
720 set_constraint_indices(Constraints) :-
721 set_constraint_indices(Constraints,1).
722 set_constraint_indices([],M) :-
724 max_constraint_index(N).
725 set_constraint_indices([C|Cs],N) :-
726 ( ( chr_pp_flag(debugable, on) ; \+ only_ground_indexed_arguments(C), is_stored(C) ; is_stored(C), get_store_type(C,default)
727 ; get_store_type(C,var_assoc_store(_,_))) ->
728 constraint_index(C,N),
730 set_constraint_indices(Cs,M)
732 set_constraint_indices(Cs,N)
735 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
738 :- chr_constraint identifier_size/1.
739 :- chr_option(mode,identifier_size(+)).
740 :- chr_option(type_declaration,identifier_size(natural)).
742 identifier_size(_) \ identifier_size(_)
746 :- chr_constraint get_identifier_size/1.
747 :- chr_option(mode,get_identifier_size(-)).
748 :- chr_option(type_declaration,get_identifier_size(natural)).
750 identifier_size(Size) \ get_identifier_size(Q)
754 get_identifier_size(Q)
758 :- chr_constraint identifier_index/3.
759 :- chr_option(mode,identifier_index(+,+,+)).
760 :- chr_option(type_declaration,identifier_index(constraint,natural,natural)).
762 identifier_index(C,I,_) \ identifier_index(C,I,_)
766 :- chr_constraint get_identifier_index/3.
767 :- chr_option(mode,get_identifier_index(+,+,-)).
768 :- chr_option(type_declaration,get_identifier_index(constraint,natural,natural)).
770 identifier_index(C,I,II) \ get_identifier_index(C,I,Q)
773 identifier_size(Size), get_identifier_index(C,I,Q)
776 identifier_index(C,I,NSize),
777 identifier_size(NSize),
779 get_identifier_index(C,I,Q)
781 identifier_index(C,I,2),
785 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
786 % Type Indexed Identifier Indexes
788 :- chr_constraint type_indexed_identifier_size/2.
789 :- chr_option(mode,type_indexed_identifier_size(+,+)).
790 :- chr_option(type_declaration,type_indexed_identifier_size(any,natural)).
792 type_indexed_identifier_size(IndexType,_) \ type_indexed_identifier_size(IndexType,_)
796 :- chr_constraint get_type_indexed_identifier_size/2.
797 :- chr_option(mode,get_type_indexed_identifier_size(+,-)).
798 :- chr_option(type_declaration,get_type_indexed_identifier_size(any,natural)).
800 type_indexed_identifier_size(IndexType,Size) \ get_type_indexed_identifier_size(IndexType,Q)
804 get_type_indexed_identifier_size(IndexType,Q)
808 :- chr_constraint type_indexed_identifier_index/4.
809 :- chr_option(mode,type_indexed_identifier_index(+,+,+,+)).
810 :- chr_option(type_declaration,type_indexed_identifier_index(any,constraint,natural,natural)).
812 type_indexed_identifier_index(_,C,I,_) \ type_indexed_identifier_index(_,C,I,_)
816 :- chr_constraint get_type_indexed_identifier_index/4.
817 :- chr_option(mode,get_type_indexed_identifier_index(+,+,+,-)).
818 :- chr_option(type_declaration,get_type_indexed_identifier_index(any,constraint,natural,natural)).
820 type_indexed_identifier_index(IndexType,C,I,II) \ get_type_indexed_identifier_index(IndexType,C,I,Q)
823 type_indexed_identifier_size(IndexType,Size), get_type_indexed_identifier_index(IndexType,C,I,Q)
826 type_indexed_identifier_index(IndexType,C,I,NSize),
827 type_indexed_identifier_size(IndexType,NSize),
829 get_type_indexed_identifier_index(IndexType,C,I,Q)
831 type_indexed_identifier_index(IndexType,C,I,2),
832 type_indexed_identifier_size(IndexType,2),
835 type_indexed_identifier_structure(IndexType,Structure) :-
836 type_indexed_identifier_name(IndexType,type_indexed_identifier_struct,Functor),
837 get_type_indexed_identifier_size(IndexType,Arity),
838 functor(Structure,Functor,Arity).
839 type_indexed_identifier_name(IndexType,Prefix,Name) :-
841 IndexTypeName = IndexType
843 term_to_atom(IndexType,IndexTypeName)
845 atom_concat_list([Prefix,'_',IndexTypeName],Name).
847 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
852 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
856 chr_translate(Declarations,NewDeclarations) :-
857 chr_translate_line_info(Declarations,'bootstrap',NewDeclarations).
859 chr_translate_line_info(Declarations0,File,NewDeclarations) :-
861 restart_after_flattening(Declarations0,Declarations),
863 chr_source_file(File),
864 /* sort out the interesting stuff from the input */
865 partition_clauses(Declarations,Constraints0,Rules0,OtherClauses),
866 chr_compiler_options:sanity_check,
868 dump_code(Declarations),
870 check_declared_constraints(Constraints0),
871 generate_show_constraint(Constraints0,Constraints,Rules0,Rules1),
872 add_constraints(Constraints),
874 generate_never_stored_rules(Constraints,NewRules),
876 append(Rules1,NewRules,Rules),
877 chr_analysis(Rules,Constraints,Declarations),
878 time('constraint code generation',chr_translate:constraints_code(Constraints,ConstraintClauses)),
879 time('validate store assumptions',chr_translate:validate_store_type_assumptions(Constraints)),
880 phase_end(validate_store_type_assumptions),
882 time('store code generation',chr_translate:store_management_preds(Constraints,StoreClauses)), % depends on actual code used
883 insert_declarations(OtherClauses, Clauses0),
884 chr_module_declaration(CHRModuleDeclaration),
885 append([StoreClauses,ConstraintClauses,CHRModuleDeclaration,[end_of_file]],StuffyGeneratedClauses),
886 clean_clauses(StuffyGeneratedClauses,GeneratedClauses),
887 append([Clauses0,GeneratedClauses], NewDeclarations),
888 dump_code(NewDeclarations),
889 !. /* cut choicepoint of restart_after_flattening */
891 chr_analysis(Rules,Constraints,Declarations) :-
892 check_rules(Rules,Constraints),
893 time('type checking',chr_translate:static_type_check),
895 collect_constants(Rules,Constraints,Declarations),
896 add_occurrences(Rules),
897 time('functional dependency',chr_translate:functional_dependency_analysis(Rules)),
898 time('set semantics',chr_translate:set_semantics_rules(Rules)),
899 time('symmetry analysis',chr_translate:symmetry_analysis(Rules)),
900 time('guard simplification',chr_translate:guard_simplification),
901 time('late storage',chr_translate:storage_analysis(Constraints)),
902 time('observation',chr_translate:observation_analysis(Constraints)),
903 time('ai observation',chr_translate:ai_observation_analysis(Constraints)),
904 time('late allocation',chr_translate:late_allocation_analysis(Constraints)),
905 partial_wake_analysis,
906 time('assume constraint stores',chr_translate:assume_constraint_stores(Constraints)),
907 time('default constraint indices',chr_translate:set_constraint_indices(Constraints)),
908 time('check storedness assertions',chr_translate:check_storedness_assertions(Constraints)),
909 time('continuation analysis',chr_translate:continuation_analysis(Constraints)).
911 store_management_preds(Constraints,Clauses) :-
912 generate_attach_detach_a_constraint_all(Constraints,AttachAConstraintClauses),
913 generate_attr_unify_hook(AttrUnifyHookClauses),
914 generate_attach_increment(AttachIncrementClauses),
915 generate_extra_clauses(Constraints,ExtraClauses),
916 generate_insert_delete_constraints(Constraints,DeleteClauses),
917 generate_attach_code(Constraints,StoreClauses),
918 generate_counter_code(CounterClauses),
919 generate_dynamic_type_check_clauses(TypeCheckClauses),
920 append([AttachAConstraintClauses
921 ,AttachIncrementClauses
922 ,AttrUnifyHookClauses
932 insert_declarations(Clauses0, Clauses) :-
933 findall(:- use_module(chr(Module)),(auxiliary_module(Module), is_used_auxiliary_module(Module)),Decls),
934 append(Clauses0, [:- use_module(chr(chr_runtime))|Decls], Clauses).
936 auxiliary_module(chr_hashtable_store).
937 auxiliary_module(chr_integertable_store).
938 auxiliary_module(chr_assoc_store).
940 generate_counter_code(Clauses) :-
941 ( chr_pp_flag(store_counter,on) ->
943 ('$counter_init'(N1) :- nb_setval(N1,0)) ,
944 ('$counter'(N2,X1) :- nb_getval(N2,X1)),
945 ('$counter_inc'(N) :- nb_getval(N,X), Y is X + 1, nb_setval(N,Y)),
946 (:- '$counter_init'('$insert_counter')),
947 (:- '$counter_init'('$delete_counter')),
948 ('$insert_counter_inc' :- '$counter_inc'('$insert_counter')),
949 ('$delete_counter_inc' :- '$counter_inc'('$delete_counter')),
950 ( counter_stats(I,D) :- '$counter'('$insert_counter',I),'$counter'('$delete_counter',D))
956 % for systems with multifile declaration
957 chr_module_declaration(CHRModuleDeclaration) :-
958 get_target_module(Mod),
959 ( Mod \== chr_translate, chr_pp_flag(toplevel_show_store,on) ->
960 CHRModuleDeclaration = [
961 (:- multifile chr:'$chr_module'/1),
962 chr:'$chr_module'(Mod)
965 CHRModuleDeclaration = []
969 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
971 %% Partitioning of clauses into constraint declarations, chr rules and other
974 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
975 %% partition_clauses(+Clauses,-ConstraintDeclarations,-Rules,-OtherClauses) is det.
976 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
977 partition_clauses([],[],[],[]).
978 partition_clauses([Clause|Clauses],ConstraintDeclarations,Rules,OtherClauses) :-
979 ( parse_rule(Clause,Rule) ->
980 ConstraintDeclarations = RestConstraintDeclarations,
981 Rules = [Rule|RestRules],
982 OtherClauses = RestOtherClauses
983 ; is_declaration(Clause,ConstraintDeclaration) ->
984 append(ConstraintDeclaration,RestConstraintDeclarations,ConstraintDeclarations),
986 OtherClauses = RestOtherClauses
987 ; is_module_declaration(Clause,Mod) ->
989 ConstraintDeclarations = RestConstraintDeclarations,
991 OtherClauses = [Clause|RestOtherClauses]
992 ; is_type_definition(Clause) ->
993 ConstraintDeclarations = RestConstraintDeclarations,
995 OtherClauses = RestOtherClauses
996 ; is_chr_declaration(Clause) ->
997 ConstraintDeclarations = RestConstraintDeclarations,
999 OtherClauses = RestOtherClauses
1000 ; Clause = (handler _) ->
1001 chr_warning(deprecated(Clause),'Backward compatibility: ignoring handler/1 declaration.\n',[]),
1002 ConstraintDeclarations = RestConstraintDeclarations,
1004 OtherClauses = RestOtherClauses
1005 ; Clause = (rules _) ->
1006 chr_warning(deprecated(Clause),'Backward compatibility: ignoring rules/1 declaration.\n',[]),
1007 ConstraintDeclarations = RestConstraintDeclarations,
1009 OtherClauses = RestOtherClauses
1010 ; Clause = option(OptionName,OptionValue) ->
1011 chr_warning(deprecated(Clause),'Instead use `:-chr_option(~w,~w).\'\n',[OptionName,OptionValue]),
1012 handle_option(OptionName,OptionValue),
1013 ConstraintDeclarations = RestConstraintDeclarations,
1015 OtherClauses = RestOtherClauses
1016 ; Clause = (:-chr_option(OptionName,OptionValue)) ->
1017 handle_option(OptionName,OptionValue),
1018 ConstraintDeclarations = RestConstraintDeclarations,
1020 OtherClauses = RestOtherClauses
1021 ; Clause = ('$chr_compiled_with_version'(_)) ->
1022 ConstraintDeclarations = RestConstraintDeclarations,
1024 OtherClauses = ['$chr_compiled_with_version'(3)|RestOtherClauses]
1025 ; ConstraintDeclarations = RestConstraintDeclarations,
1027 OtherClauses = [Clause|RestOtherClauses]
1029 partition_clauses(Clauses,RestConstraintDeclarations,RestRules,RestOtherClauses).
1031 '$chr_compiled_with_version'(2).
1033 is_declaration(D, Constraints) :- %% constraint declaration
1034 ( D = (:- Decl), Decl =.. [F,Cs], F == (chr_constraint) ->
1035 conj2list(Cs,Constraints0)
1038 Decl =.. [constraints,Cs]
1040 D =.. [constraints,Cs]
1042 conj2list(Cs,Constraints0),
1043 chr_warning(deprecated(D),'Instead use :- chr_constraint ~w.\n',[Cs])
1045 extract_type_mode(Constraints0,Constraints).
1047 extract_type_mode([],[]).
1048 extract_type_mode([F/A|R],[F/A|R2]) :- !,extract_type_mode(R,R2).
1049 extract_type_mode([C0|R],[ConstraintSymbol|R2]) :-
1050 ( C0 = C # Annotation ->
1052 extract_annotation(Annotation,F/A)
1057 ConstraintSymbol = F/A,
1059 extract_types_and_modes(Args,ArgTypes,ArgModes),
1060 assert_constraint_type(ConstraintSymbol,ArgTypes),
1061 constraint_mode(ConstraintSymbol,ArgModes),
1062 extract_type_mode(R,R2).
1064 extract_annotation(stored,Symbol) :-
1065 stored_assertion(Symbol).
1066 extract_annotation(default(Goal),Symbol) :-
1067 never_stored_default(Symbol,Goal).
1069 extract_types_and_modes([],[],[]).
1070 extract_types_and_modes([X|R],[T|R2],[M|R3]) :-
1071 extract_type_and_mode(X,T,M),
1072 extract_types_and_modes(R,R2,R3).
1074 extract_type_and_mode(+(T),T,(+)) :- !.
1075 extract_type_and_mode(?(T),T,(?)) :- !.
1076 extract_type_and_mode(-(T),T,(-)) :- !.
1077 extract_type_and_mode((+),any,(+)) :- !.
1078 extract_type_and_mode((?),any,(?)) :- !.
1079 extract_type_and_mode((-),any,(-)) :- !.
1080 extract_type_and_mode(Illegal,_,_) :-
1081 chr_error(syntax(Illegal),'Illegal mode/type declaration.\n\tCorrect syntax is +type, -type or ?type\n\tor +, - or ?.\n',[]).
1083 is_chr_declaration(Declaration) :-
1084 Declaration = (:- chr_declaration Decl),
1085 ( Decl = (Pattern ---> Information) ->
1086 background_info(Pattern,Information)
1087 ; Decl = Information ->
1088 background_info([Information])
1090 is_type_definition(Declaration) :-
1091 is_type_definition(Declaration,Result),
1092 assert_type_definition(Result).
1094 assert_type_definition(typedef(Name,DefList)) :- type_definition(Name,DefList).
1095 assert_type_definition(alias(Alias,Name)) :- type_alias(Alias,Name).
1097 is_type_definition(Declaration,Result) :-
1098 ( Declaration = (:- TDef) ->
1103 TDef =.. [chr_type,TypeDef],
1104 ( TypeDef = (Name ---> Def) ->
1105 tdisj2list(Def,DefList),
1106 Result = typedef(Name,DefList)
1107 ; TypeDef = (Alias == Name) ->
1108 Result = alias(Alias,Name)
1110 Result = typedef(TypeDef,[]),
1111 chr_warning(syntax,'Empty type definition `~w\'.\nAre you sure you want to declare a phantom type?\n',[Declaration])
1114 %% tdisj2list(+Goal,-ListOfGoals) is det.
1116 % no removal of fails, e.g. :- type bool ---> true ; fail.
1117 tdisj2list(Conj,L) :-
1118 tdisj2list(Conj,L,[]).
1120 tdisj2list(Conj,L,T) :-
1122 tdisj2list(G1,L,T1),
1123 tdisj2list(G2,T1,T).
1124 tdisj2list(G,[G | T],T).
1127 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
1128 %% parse_rule(+term,-pragma_rule) is semidet.
1129 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
1130 parse_rule(RI,R) :- %% name @ rule
1131 RI = (Name @ RI2), !,
1132 rule(RI2,yes(Name),R).
1136 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
1137 %% parse_rule(+term,-pragma_rule) is semidet.
1138 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
1140 RI = (RI2 pragma P), !, %% pragmas
1142 Ps = [_] % intercept variable
1146 inc_rule_count(RuleCount),
1147 R = pragma(R1,IDs,Ps,Name,RuleCount),
1148 is_rule(RI2,R1,IDs,R).
1150 inc_rule_count(RuleCount),
1151 R = pragma(R1,IDs,[],Name,RuleCount),
1152 is_rule(RI,R1,IDs,R).
1154 is_rule(RI,R,IDs,RC) :- %% propagation rule
1156 conj2list(H,Head2i),
1157 get_ids(Head2i,IDs2,Head2,RC),
1160 R = rule([],Head2,G,RB)
1162 R = rule([],Head2,true,B)
1164 is_rule(RI,R,IDs,RC) :- %% simplification/simpagation rule
1173 conj2list(H1,Head2i),
1174 conj2list(H2,Head1i),
1175 get_ids(Head2i,IDs2,Head2,0,N,RC),
1176 get_ids(Head1i,IDs1,Head1,N,_,RC),
1177 IDs = ids(IDs1,IDs2)
1178 ; conj2list(H,Head1i),
1180 get_ids(Head1i,IDs1,Head1,RC),
1183 R = rule(Head1,Head2,Guard,Body).
1185 get_ids(Cs,IDs,NCs,RC) :-
1186 get_ids(Cs,IDs,NCs,0,_,RC).
1188 get_ids([],[],[],N,N,_).
1189 get_ids([C|Cs],[N|IDs],[NC|NCs],N,NN,RC) :-
1194 check_direct_pragma(N1,N,RC)
1200 get_ids(Cs,IDs,NCs, M,NN,RC).
1202 check_direct_pragma(passive,Id,PragmaRule) :- !,
1203 PragmaRule = pragma(_,_,_,_,RuleNb),
1205 check_direct_pragma(Abbrev,Id,PragmaRule) :-
1206 ( direct_pragma(FullPragma),
1207 atom_concat(Abbrev,Remainder,FullPragma) ->
1208 chr_warning(problem_pragma(Abbrev,PragmaRule),'completed `~w\' to `~w\'\n',[Abbrev,FullPragma])
1210 chr_warning(unsupported_pragma(Abbrev,PragmaRule),'',[])
1213 direct_pragma(passive).
1215 is_module_declaration((:- module(Mod)),Mod).
1216 is_module_declaration((:- module(Mod,_)),Mod).
1218 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1220 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1222 add_constraints([]).
1223 add_constraints([C|Cs]) :-
1224 max_occurrence(C,0),
1228 constraint_mode(C,Mode),
1229 add_constraints(Cs).
1233 add_rules([Rule|Rules]) :-
1234 Rule = pragma(_,_,_,_,RuleNb),
1238 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1240 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1241 %% Some input verification:
1243 check_declared_constraints(Constraints) :-
1244 tree_set_empty(Acc),
1245 check_declared_constraints(Constraints,Acc).
1247 check_declared_constraints([],_).
1248 check_declared_constraints([C|Cs],Acc) :-
1249 ( tree_set_memberchk(C,Acc) ->
1250 chr_error(syntax(C),'Constraint multiply defined: ~w.\n\tRemove redundant declaration!\n',[C])
1254 tree_set_add(Acc,C,NAcc),
1255 check_declared_constraints(Cs,NAcc).
1257 %% - all constraints in heads are declared constraints
1258 %% - all passive pragmas refer to actual head constraints
1261 check_rules([PragmaRule|Rest],Decls) :-
1262 check_rule(PragmaRule,Decls),
1263 check_rules(Rest,Decls).
1265 check_rule(PragmaRule,Decls) :-
1266 check_rule_indexing(PragmaRule),
1267 check_trivial_propagation_rule(PragmaRule),
1268 PragmaRule = pragma(Rule,_IDs,Pragmas,_Name,_N),
1269 Rule = rule(H1,H2,_,_),
1270 append(H1,H2,HeadConstraints),
1271 check_head_constraints(HeadConstraints,Decls,PragmaRule),
1272 check_pragmas(Pragmas,PragmaRule).
1274 % Make all heads passive in trivial propagation rule
1275 % ... ==> ... | true.
1276 check_trivial_propagation_rule(PragmaRule) :-
1277 PragmaRule = pragma(Rule,IDs,Pragmas,Name,RuleNb),
1278 ( Rule = rule([],_,_,true) ->
1279 chr_warning(weird_program,'Ignoring propagation rule with empty body: ~@.\n\t\n',[format_rule(PragmaRule)]),
1280 set_all_passive(RuleNb)
1285 check_head_constraints([],_,_).
1286 check_head_constraints([Constr|Rest],Decls,PragmaRule) :-
1287 functor(Constr,F,A),
1288 ( memberchk(F/A,Decls) ->
1289 check_head_constraints(Rest,Decls,PragmaRule)
1291 chr_error(syntax(Constr),'Undeclared constraint ~w in head of ~@.\n\tConstraint should be one of ~w.\n', [F/A,format_rule(PragmaRule),Decls])
1294 check_pragmas([],_).
1295 check_pragmas([Pragma|Pragmas],PragmaRule) :-
1296 check_pragma(Pragma,PragmaRule),
1297 check_pragmas(Pragmas,PragmaRule).
1299 check_pragma(Pragma,PragmaRule) :-
1301 chr_error(syntax(Pragma),'Invalid pragma ~w in ~@.\n\tPragma should not be a variable!\n',[Pragma,format_rule(PragmaRule)]).
1302 check_pragma(passive(ID), PragmaRule) :-
1304 PragmaRule = pragma(_,ids(IDs1,IDs2),_,_,RuleNb),
1305 ( memberchk_eq(ID,IDs1) ->
1307 ; memberchk_eq(ID,IDs2) ->
1310 chr_error(syntax(ID),'Invalid identifier ~w in pragma passive in ~@.\n', [ID,format_rule(PragmaRule)])
1314 check_pragma(mpassive(IDs), PragmaRule) :-
1316 PragmaRule = pragma(_,_,_,_,RuleNb),
1317 chr_warning(experimental,'Experimental pragma ~w. Use with care!\n',[mpassive(IDs)]),
1318 maplist(passive(RuleNb),IDs).
1320 check_pragma(Pragma, PragmaRule) :-
1321 Pragma = already_in_heads,
1323 chr_warning(unsupported_pragma(Pragma,PragmaRule),'Termination and correctness may be affected.\n',[]).
1325 check_pragma(Pragma, PragmaRule) :-
1326 Pragma = already_in_head(_),
1328 chr_warning(unsupported_pragma(Pragma,PragmaRule),'Termination and correctness may be affected.\n',[]).
1330 check_pragma(Pragma, PragmaRule) :-
1331 Pragma = no_history,
1333 chr_warning(experimental,'Experimental pragma no_history. Use with care!\n',[]),
1334 PragmaRule = pragma(_,_,_,_,N),
1337 check_pragma(Pragma, PragmaRule) :-
1338 Pragma = history(HistoryName,IDs),
1340 PragmaRule = pragma(_,ids(IDs1,IDs2),_,_,RuleNb),
1341 chr_warning(experimental,'Experimental pragma ~w. Use with care!\n',[Pragma]),
1343 chr_error(syntax(Pragma),'Pragma history only implemented for propagation rules.\n',[])
1344 ; \+ atom(HistoryName) ->
1345 chr_error(syntax(Pragma),'Illegal argument for pragma history: ~w is not an atom (rule number ~w).\n',[HistoryName,RuleNb])
1347 chr_error(syntax(Pragma),'Illegal argument for pragma history: ~w is not a set (rule number ~w).\n',[IDs,RuleNb])
1348 ; check_history_pragma_ids(IDs,IDs1,IDs2) ->
1349 history(RuleNb,HistoryName,IDs)
1351 chr_error(syntax(Pragma),'Invalid identifier(s) in pragma ~w of rule number ~w.\n',[Pragma,RuleNb])
1353 check_pragma(Pragma,PragmaRule) :-
1354 Pragma = line_number(LineNumber),
1356 PragmaRule = pragma(_,_,_,_,RuleNb),
1357 line_number(RuleNb,LineNumber).
1359 check_history_pragma_ids([], _, _).
1360 check_history_pragma_ids([ID|IDs],IDs1,IDs2) :-
1361 ( memberchk_eq(ID,IDs2) ; memberchk_eq(ID,IDs1) ),
1362 check_history_pragma_ids(IDs,IDs1,IDs2).
1364 check_pragma(Pragma,PragmaRule) :-
1365 chr_error(syntax(Pragma),'Unknown pragma ~w in ~@.\n', [Pragma,format_rule(PragmaRule)]).
1367 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1368 %% no_history(+RuleNb) is det.
1369 :- chr_constraint no_history/1.
1370 :- chr_option(mode,no_history(+)).
1371 :- chr_option(type_declaration,no_history(int)).
1373 %% has_no_history(+RuleNb) is semidet.
1374 :- chr_constraint has_no_history/1.
1375 :- chr_option(mode,has_no_history(+)).
1376 :- chr_option(type_declaration,has_no_history(int)).
1378 no_history(RuleNb) \ has_no_history(RuleNb) <=> true.
1379 has_no_history(_) <=> fail.
1381 :- chr_constraint history/3.
1382 :- chr_option(mode,history(+,+,+)).
1383 :- chr_option(type_declaration,history(any,any,list)).
1385 :- chr_constraint named_history/3.
1387 history(RuleNb,_,_), history(RuleNb,_,_) ==>
1388 chr_error(syntax,'Only one pragma history allowed per rule (rule number ~w)\n',[RuleNb]). %'
1390 history(RuleNb1,Name,IDs1), history(RuleNb2,Name,IDs2) ==>
1391 length(IDs1,L1), length(IDs2,L2),
1393 chr_error(syntax,'The history named ~w does not always range over an equal amount of occurrences.\n',[Name])
1395 test_named_history_id_pairs(RuleNb1,IDs1,RuleNb2,IDs2)
1398 test_named_history_id_pairs(_, [], _, []).
1399 test_named_history_id_pairs(RuleNb1, [ID1|IDs1], RuleNb2, [ID2|IDs2]) :-
1400 test_named_history_id_pair(RuleNb1,ID1,RuleNb2,ID2),
1401 test_named_history_id_pairs(RuleNb1,IDs1,RuleNb2,IDs2).
1403 :- chr_constraint test_named_history_id_pair/4.
1404 :- chr_option(mode,test_named_history_id_pair(+,+,+,+)).
1406 occurrence(C,_,RuleNb1,ID1,_), occurrence(C,_,RuleNb2,ID2,_)
1407 \ test_named_history_id_pair(RuleNb1,ID1,RuleNb2,ID2) <=> true.
1408 test_named_history_id_pair(RuleNb1,ID1,RuleNb2,ID2) <=>
1409 chr_error(syntax,'Occurrences of shared history in rules number ~w and ~w do not correspond\n', [RuleNb2,RuleNb1]).
1411 history(RuleNb,Name,IDs) \ named_history(RuleNb,QName,QIDs) <=> QName = Name, QIDs = IDs.
1412 named_history(_,_,_) <=> fail.
1414 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1417 format_rule(PragmaRule) :-
1418 PragmaRule = pragma(_,_,_,MaybeName,RuleNumber),
1419 ( MaybeName = yes(Name) ->
1420 write('rule '), write(Name)
1422 write('rule number '), write(RuleNumber)
1424 get_line_number(RuleNumber,LineNumber),
1429 check_rule_indexing(PragmaRule) :-
1430 PragmaRule = pragma(Rule,_,_,_,_),
1431 Rule = rule(H1,H2,G,_),
1432 term_variables(H1-H2,HeadVars),
1433 remove_anti_monotonic_guards(G,HeadVars,NG),
1434 check_indexing(H1,NG-H2),
1435 check_indexing(H2,NG-H1),
1437 ( chr_pp_flag(term_indexing,on) ->
1438 term_variables(NG,GuardVariables),
1439 append(H1,H2,Heads),
1440 check_specs_indexing(Heads,GuardVariables,Specs)
1445 :- chr_constraint indexing_spec/2.
1446 :- chr_option(mode,indexing_spec(+,+)).
1448 :- chr_constraint get_indexing_spec/2.
1449 :- chr_option(mode,get_indexing_spec(+,-)).
1452 indexing_spec(FA,Spec) \ get_indexing_spec(FA,R) <=> R = Spec.
1453 get_indexing_spec(_,Spec) <=> Spec = [].
1455 indexing_spec(FA,Specs1), indexing_spec(FA,Specs2)
1457 append(Specs1,Specs2,Specs),
1458 indexing_spec(FA,Specs).
1460 remove_anti_monotonic_guards(G,Vars,NG) :-
1462 remove_anti_monotonic_guard_list(GL,Vars,NGL),
1465 remove_anti_monotonic_guard_list([],_,[]).
1466 remove_anti_monotonic_guard_list([G|Gs],Vars,NGs) :-
1467 ( G = var(X), memberchk_eq(X,Vars) ->
1469 % TODO: this is not correct
1470 % ; G = functor(Term,Functor,Arity), % isotonic
1471 % \+ memberchk_eq(Functor,Vars), \+ memberchk_eq(Arity,Vars) ->
1476 remove_anti_monotonic_guard_list(Gs,Vars,RGs).
1478 check_indexing([],_).
1479 check_indexing([Head|Heads],Other) :-
1482 term_variables(Heads-Other,OtherVars),
1483 check_indexing(Args,1,F/A,OtherVars),
1484 check_indexing(Heads,[Head|Other]).
1486 check_indexing([],_,_,_).
1487 check_indexing([Arg|Args],I,FA,OtherVars) :-
1488 ( is_indexed_argument(FA,I) ->
1491 indexed_argument(FA,I)
1493 term_variables(Args,ArgsVars),
1494 append(ArgsVars,OtherVars,RestVars),
1495 ( memberchk_eq(Arg,RestVars) ->
1496 indexed_argument(FA,I)
1502 term_variables(Arg,NVars),
1503 append(NVars,OtherVars,NOtherVars),
1504 check_indexing(Args,J,FA,NOtherVars).
1506 check_specs_indexing([],_,[]).
1507 check_specs_indexing([Head|Heads],Variables,Specs) :-
1508 Specs = [Spec|RSpecs],
1509 term_variables(Heads,OtherVariables,Variables),
1510 check_spec_indexing(Head,OtherVariables,Spec),
1511 term_variables(Head,NVariables,Variables),
1512 check_specs_indexing(Heads,NVariables,RSpecs).
1514 check_spec_indexing(Head,OtherVariables,Spec) :-
1516 Spec = spec(F,A,ArgSpecs),
1518 check_args_spec_indexing(Args,1,OtherVariables,ArgSpecs),
1519 indexing_spec(F/A,[ArgSpecs]).
1521 check_args_spec_indexing([],_,_,[]).
1522 check_args_spec_indexing([Arg|Args],I,OtherVariables,ArgSpecs) :-
1523 term_variables(Args,Variables,OtherVariables),
1524 ( check_arg_spec_indexing(Arg,I,Variables,ArgSpec) ->
1525 ArgSpecs = [ArgSpec|RArgSpecs]
1527 ArgSpecs = RArgSpecs
1530 term_variables(Arg,NOtherVariables,OtherVariables),
1531 check_args_spec_indexing(Args,J,NOtherVariables,RArgSpecs).
1533 check_arg_spec_indexing(Arg,I,Variables,ArgSpec) :-
1535 memberchk_eq(Arg,Variables),
1536 ArgSpec = specinfo(I,any,[])
1539 ArgSpec = specinfo(I,F/A,[ArgSpecs]),
1541 check_args_spec_indexing(Args,1,Variables,ArgSpecs)
1544 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1546 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1549 add_occurrences([]).
1550 add_occurrences([Rule|Rules]) :-
1551 Rule = pragma(rule(H1,H2,_,_),ids(IDs1,IDs2),_,_,Nb),
1552 add_occurrences(H1,IDs1,simplification,Nb),
1553 add_occurrences(H2,IDs2,propagation,Nb),
1554 add_occurrences(Rules).
1556 add_occurrences([],[],_,_).
1557 add_occurrences([H|Hs],[ID|IDs],Type,RuleNb) :-
1560 new_occurrence(FA,RuleNb,ID,Type),
1561 add_occurrences(Hs,IDs,Type,RuleNb).
1563 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1565 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1566 % Observation Analysis
1576 :- chr_constraint observation_analysis/1.
1577 :- chr_option(mode, observation_analysis(+)).
1579 observation_analysis(Cs), rule(RuleNb,PragmaRule) # Id ==>
1580 PragmaRule = pragma(rule(_,_,Guard,Body),_,_,_,_),
1581 ( chr_pp_flag(store_in_guards, on) ->
1582 observation_analysis(RuleNb, Guard, guard, Cs)
1586 observation_analysis(RuleNb, Body, body, Cs)
1589 observation_analysis(_) <=> true.
1591 observation_analysis(RuleNb, Term, GB, Cs) :-
1592 ( all_spawned(RuleNb,GB) ->
1595 spawns_all(RuleNb,GB)
1603 observation_analysis(RuleNb,T1,GB,Cs),
1604 observation_analysis(RuleNb,T2,GB,Cs)
1606 observation_analysis(RuleNb,T1,GB,Cs),
1607 observation_analysis(RuleNb,T2,GB,Cs)
1608 ; Term = (T1->T2) ->
1609 observation_analysis(RuleNb,T1,GB,Cs),
1610 observation_analysis(RuleNb,T2,GB,Cs)
1612 observation_analysis(RuleNb,T,GB,Cs)
1613 ; functor(Term,F,A), memberchk(F/A,Cs) ->
1614 spawns(RuleNb,GB,F/A)
1616 spawns_all_triggers(RuleNb,GB)
1617 ; Term = (_ is _) ->
1618 spawns_all_triggers(RuleNb,GB)
1619 ; builtin_binds_b(Term,Vars) ->
1623 spawns_all_triggers(RuleNb,GB)
1626 spawns_all(RuleNb,GB)
1629 :- chr_constraint spawns/3.
1630 :- chr_option(mode, spawns(+,+,+)).
1631 :- chr_type spawns_type ---> guard ; body.
1632 :- chr_option(type_declaration,spawns(any,spawns_type,any)).
1634 :- chr_constraint spawns_all/2, spawns_all_triggers/2.
1635 :- chr_option(mode, spawns_all(+,+)).
1636 :- chr_option(type_declaration,spawns_all(any,spawns_type)).
1637 :- chr_option(mode, spawns_all_triggers(+,+)).
1638 :- chr_option(type_declaration,spawns_all_triggers(any,spawns_type)).
1640 spawns_all(RuleNb,GB) \ spawns_all(RuleNb,GB) <=> true.
1641 spawns_all(RuleNb,guard) \ spawns_all(RuleNb,body) <=> true.
1642 spawns_all_triggers(RuleNb,GB) \ spawns_all_triggers(RuleNb,GB) <=> true.
1643 spawns_all_triggers(RuleNb,guard) \ spawns_all_triggers(RuleNb,body) <=> true.
1644 spawns(RuleNb,GB,C) \ spawns(RuleNb,GB,C) <=> true.
1645 spawns(RuleNb,guard,C) \ spawns(RuleNb,body,C) <=> true.
1647 spawns_all(RuleNb,GB) \ spawns(RuleNb,GB,_) <=> true.
1648 spawns_all(RuleNb,guard) \ spawns(RuleNb,body,_) <=> true.
1649 spawns_all(RuleNb,GB) \ spawns_all_triggers(RuleNb,GB) <=> true.
1650 spawns_all(RuleNb,guard) \ spawns_all_triggers(RuleNb,body) <=> true.
1652 spawns_all_triggers(RuleNb,GB) \ spawns(RuleNb,GB,C) <=> may_trigger(C) | true.
1653 spawns_all_triggers(RuleNb,guard) \ spawns(RuleNb,body,C) <=> may_trigger(C) | true.
1655 spawns_all(RuleNb2,_), occurrence(C1,_,RuleNb2,O,_)#Id
1657 spawns(RuleNb1,GB,C1)
1659 \+ is_passive(RuleNb2,O)
1661 spawns_all(RuleNb1,GB)
1665 occurrence(C1,_,RuleNb2,O,_)#Id, spawns_all(RuleNb2,_)
1667 \+(\+ spawns_all_triggers_implies_spawns_all), % in the hope it schedules this guard early...
1668 \+ is_passive(RuleNb2,O), may_trigger(C1)
1670 spawns_all_triggers_implies_spawns_all
1674 :- chr_constraint spawns_all_triggers_implies_spawns_all/0.
1675 spawns_all_triggers_implies_spawns_all, spawns_all_triggers_implies_spawns_all <=> fail.
1676 spawns_all_triggers_implies_spawns_all \
1677 spawns_all_triggers(RuleNb,GB) <=> spawns_all(RuleNb,GB).
1679 spawns_all_triggers(RuleNb2,_), occurrence(C1,_,RuleNb2,O,_)#Id
1681 spawns(RuleNb1,GB,C1)
1684 \+ is_passive(RuleNb2,O)
1686 spawns_all_triggers(RuleNb1,GB)
1690 spawns_all_triggers(RuleNb2,_), occurrence(C1,_,RuleNb2,O,_)#Id,
1691 spawns(RuleNb1,GB,C1)
1694 \+ is_passive(RuleNb2,O)
1696 spawns_all_triggers(RuleNb1,GB)
1700 % a bit dangerous this rule: could start propagating too much too soon?
1701 spawns(RuleNb2,_,C2), occurrence(C1,_,RuleNb2,O,_)#Id,
1702 spawns(RuleNb1,GB,C1)
1704 RuleNb1 \== RuleNb2, C1 \== C2,
1705 \+ is_passive(RuleNb2,O)
1707 spawns(RuleNb1,GB,C2)
1711 spawns(RuleNb2,_,C2), occurrence(C1,_,RuleNb2,O,_)#Id,
1712 spawns_all_triggers(RuleNb1,GB)
1714 \+ is_passive(RuleNb2,O), may_trigger(C1), \+ may_trigger(C2)
1716 spawns(RuleNb1,GB,C2)
1721 :- chr_constraint all_spawned/2.
1722 :- chr_option(mode, all_spawned(+,+)).
1723 spawns_all(RuleNb,guard) \ all_spawned(RuleNb,_) <=> true.
1724 spawns_all(RuleNb,GB) \ all_spawned(RuleNb,GB) <=> true.
1725 all_spawned(RuleNb,GB) <=> fail.
1728 % Overview of the supported queries:
1729 % is_observed(+functor/artiy, +occurrence_number, +(guard;body))
1730 % only succeeds if the occurrence is observed by the
1731 % guard resp. body (depending on the last argument) of its rule
1732 % is_observed(+functor/artiy, +occurrence_number, -)
1733 % succeeds if the occurrence is observed by either the guard or
1734 % the body of its rule
1735 % NOTE: the last argument is NOT bound by this query
1737 % do_is_observed(+functor/artiy,+rule_number,+(guard;body))
1738 % succeeds if the given constraint is observed by the given
1740 % do_is_observed(+functor/artiy,+rule_number)
1741 % succeeds if the given constraint is observed by the given
1742 % rule (either its guard or its body)
1747 ai_is_observed(C,O).
1749 is_stored_in_guard(C,RuleNb) :-
1750 chr_pp_flag(store_in_guards, on),
1751 do_is_observed(C,RuleNb,guard).
1753 :- chr_constraint is_observed/3.
1754 :- chr_option(mode, is_observed(+,+,+)).
1755 occurrence(C,O,RuleNb,_,_) \ is_observed(C,O,GB) <=> do_is_observed(C,RuleNb,GB).
1756 is_observed(_,_,_) <=> fail. % this will not happen in practice
1759 :- chr_constraint do_is_observed/3.
1760 :- chr_option(mode, do_is_observed(+,+,?)).
1761 :- chr_constraint do_is_observed/2.
1762 :- chr_option(mode, do_is_observed(+,+)).
1764 do_is_observed(C,RuleNb,GB) <=> var(GB) | do_is_observed(C,RuleNb).
1767 % a constraint C is observed if the GB of the rule it occurs in spawns all,
1768 % and some non-passive occurrence of some (possibly other) constraint
1769 % exists in a rule (could be same rule) with at least one occurrence of C
1771 spawns_all(RuleNb,GB),
1772 occurrence(_,_,RuleNb2,O,_), occurrence(C,_,RuleNb2,_,_)
1774 do_is_observed(C,RuleNb,GB)
1776 \+ is_passive(RuleNb2,O)
1780 spawns_all(RuleNb,_),
1781 occurrence(_,_,RuleNb2,O,_), occurrence(C,_,RuleNb2,_,_)
1783 do_is_observed(C,RuleNb)
1785 \+ is_passive(RuleNb2,O)
1790 % a constraint C is observed if the GB of the rule it occurs in spawns a
1791 % constraint C2 that occurs non-passively in a rule (possibly the same rule)
1792 % as an occurrence of C
1794 spawns(RuleNb,GB,C2),
1795 occurrence(C2,_,RuleNb2,O,_), occurrence(C,_,RuleNb2,_,_)
1797 do_is_observed(C,RuleNb,GB)
1799 \+ is_passive(RuleNb2,O)
1803 spawns(RuleNb,_,C2),
1804 occurrence(C2,_,RuleNb2,O,_), occurrence(C,_,RuleNb2,_,_)
1806 do_is_observed(C,RuleNb)
1808 \+ is_passive(RuleNb2,O)
1812 % (3) spawns_all_triggers
1813 % a constraint C is observed if the GB of the rule it occurs in spawns all triggers
1814 % and some non-passive occurrence of some (possibly other) constraint that may trigger
1815 % exists in a rule (could be same rule) with at least one occurrence of C
1817 spawns_all_triggers(RuleNb,GB),
1818 occurrence(C2,_,RuleNb2,O,_), occurrence(C,_,RuleNb2,_,_)
1820 do_is_observed(C,RuleNb,GB)
1822 \+ is_passive(RuleNb2,O), may_trigger(C2)
1826 spawns_all_triggers(RuleNb,_),
1827 occurrence(C2,_,RuleNb2,O,_), occurrence(C,_,RuleNb2,_,_)
1829 do_is_observed(C,RuleNb)
1831 \+ is_passive(RuleNb2,O), may_trigger(C2)
1835 % (4) conservativeness
1836 do_is_observed(_,_,_) <=> chr_pp_flag(observation_analysis,off).
1837 do_is_observed(_,_) <=> chr_pp_flag(observation_analysis,off).
1840 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1842 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1845 %% Generated predicates
1846 %% attach_$CONSTRAINT
1848 %% detach_$CONSTRAINT
1851 %% attach_$CONSTRAINT
1852 generate_attach_detach_a_constraint_all([],[]).
1853 generate_attach_detach_a_constraint_all([Constraint|Constraints],Clauses) :-
1854 ( ( chr_pp_flag(debugable,on) ; is_stored(Constraint), \+ only_ground_indexed_arguments(Constraint), \+ get_store_type(Constraint,var_assoc_store(_,_)) ) ->
1855 generate_attach_a_constraint(Constraint,Clauses1),
1856 generate_detach_a_constraint(Constraint,Clauses2)
1861 generate_attach_detach_a_constraint_all(Constraints,Clauses3),
1862 append([Clauses1,Clauses2,Clauses3],Clauses).
1864 generate_attach_a_constraint(Constraint,[Clause1,Clause2]) :-
1865 generate_attach_a_constraint_nil(Constraint,Clause1),
1866 generate_attach_a_constraint_cons(Constraint,Clause2).
1868 attach_constraint_atom(FA,Vars,Susp,Atom) :-
1869 make_name('attach_',FA,Name),
1870 Atom =.. [Name,Vars,Susp].
1872 generate_attach_a_constraint_nil(FA,Clause) :-
1873 Clause = (Head :- true),
1874 attach_constraint_atom(FA,[],_,Head).
1876 generate_attach_a_constraint_cons(FA,Clause) :-
1877 Clause = (Head :- Body),
1878 attach_constraint_atom(FA,[Var|Vars],Susp,Head),
1879 attach_constraint_atom(FA,Vars,Susp,RecursiveCall),
1880 Body = ( AttachBody, Subscribe, RecursiveCall ),
1881 get_max_constraint_index(N),
1883 generate_attach_body_1(FA,Var,Susp,AttachBody)
1885 generate_attach_body_n(FA,Var,Susp,AttachBody)
1887 % SWI-Prolog specific code
1888 chr_pp_flag(solver_events,NMod),
1890 Args = [[Var|_],Susp],
1891 get_target_module(Mod),
1892 use_auxiliary_predicate(run_suspensions),
1893 Subscribe = clp_events:subscribe(Var,NMod,Mod,Mod:'$run_suspensions'([Susp]))
1898 generate_attach_body_1(FA,Var,Susp,Body) :-
1899 get_target_module(Mod),
1901 ( get_attr(Var, Mod, Susps) ->
1902 put_attr(Var, Mod, [Susp|Susps])
1904 put_attr(Var, Mod, [Susp])
1907 generate_attach_body_n(F/A,Var,Susp,Body) :-
1908 get_constraint_index(F/A,Position),
1909 get_max_constraint_index(Total),
1910 get_target_module(Mod),
1911 add_attr(Total,Susp,Position,TAttr,AddGoal,NTAttr),
1912 singleton_attr(Total,Susp,Position,NewAttr3),
1914 ( get_attr(Var,Mod,TAttr) ->
1916 put_attr(Var,Mod,NTAttr)
1918 put_attr(Var,Mod,NewAttr3)
1921 %% detach_$CONSTRAINT
1922 generate_detach_a_constraint(Constraint,[Clause1,Clause2]) :-
1923 generate_detach_a_constraint_nil(Constraint,Clause1),
1924 generate_detach_a_constraint_cons(Constraint,Clause2).
1926 detach_constraint_atom(FA,Vars,Susp,Atom) :-
1927 make_name('detach_',FA,Name),
1928 Atom =.. [Name,Vars,Susp].
1930 generate_detach_a_constraint_nil(FA,Clause) :-
1931 Clause = ( Head :- true),
1932 detach_constraint_atom(FA,[],_,Head).
1934 generate_detach_a_constraint_cons(FA,Clause) :-
1935 Clause = (Head :- Body),
1936 detach_constraint_atom(FA,[Var|Vars],Susp,Head),
1937 detach_constraint_atom(FA,Vars,Susp,RecursiveCall),
1938 Body = ( DetachBody, RecursiveCall ),
1939 get_max_constraint_index(N),
1941 generate_detach_body_1(FA,Var,Susp,DetachBody)
1943 generate_detach_body_n(FA,Var,Susp,DetachBody)
1946 generate_detach_body_1(FA,Var,Susp,Body) :-
1947 get_target_module(Mod),
1949 ( get_attr(Var,Mod,Susps) ->
1950 'chr sbag_del_element'(Susps,Susp,NewSusps),
1954 put_attr(Var,Mod,NewSusps)
1960 generate_detach_body_n(F/A,Var,Susp,Body) :-
1961 get_constraint_index(F/A,Position),
1962 get_max_constraint_index(Total),
1963 rem_attr(Total,Var,Susp,Position,TAttr,RemGoal),
1964 get_target_module(Mod),
1966 ( get_attr(Var,Mod,TAttr) ->
1972 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1973 %-------------------------------------------------------------------------------
1974 %% generate_indexed_variables_body(+ConstraintSymbol,+ArgList,-Body,-VarList) is det.
1975 :- chr_constraint generate_indexed_variables_body/4.
1976 :- chr_option(mode,generate_indexed_variables_body(+,?,+,?)).
1977 :- chr_option(type_declaration,generate_indexed_variables_body(constraint,any,any,any)).
1978 %-------------------------------------------------------------------------------
1979 constraint_mode(F/A,ArgModes) \ generate_indexed_variables_body(F/A,Args,Body,Vars) <=>
1980 get_indexing_spec(F/A,Specs),
1981 ( chr_pp_flag(term_indexing,on) ->
1982 spectermvars(Specs,Args,F,A,Body,Vars)
1984 get_constraint_type_det(F/A,ArgTypes),
1985 create_indexed_variables_body(Args,ArgModes,ArgTypes,Vars,1,F/A,MaybeBody,N),
1986 ( MaybeBody == empty ->
1993 Term =.. [term|Args]
1995 Body = term_variables(Term,Vars)
2000 generate_indexed_variables_body(FA,_,_,_) <=>
2001 chr_error(internal,'generate_indexed_variables_body: missing mode info for ~w.\n',[FA]).
2002 %===============================================================================
2004 create_indexed_variables_body([],[],[],_,_,_,empty,0).
2005 create_indexed_variables_body([V|Vs],[Mode|Modes],[Type|Types],Vars,I,FA,Body,N) :-
2007 create_indexed_variables_body(Vs,Modes,Types,Tail,J,FA,RBody,M),
2009 is_indexed_argument(FA,I) ->
2010 ( atomic_type(Type) ->
2021 Continuation = true, Tail = []
2023 Continuation = RBody
2027 Body = term_variables(V,Vars)
2029 Body = (term_variables(V,Vars,Tail),RBody)
2033 ; Mode == (-), is_indexed_argument(FA,I) ->
2037 Body = (Vars = [V|Tail],RBody)
2045 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2047 spectermvars(Specs,Args,F,A,Goal,Vars) :-
2048 spectermvars(Args,1,Specs,F,A,Vars,[],Goal).
2050 spectermvars([],B,_,_,A,L,L,true) :- B > A, !.
2051 spectermvars([Arg|Args],I,Specs,F,A,L,T,Goal) :-
2052 Goal = (ArgGoal,RGoal),
2053 argspecs(Specs,I,TempArgSpecs,RSpecs),
2054 merge_argspecs(TempArgSpecs,ArgSpecs),
2055 arggoal(ArgSpecs,Arg,ArgGoal,L,L1),
2057 spectermvars(Args,J,RSpecs,F,A,L1,T,RGoal).
2059 argspecs([],_,[],[]).
2060 argspecs([[]|Rest],I,ArgSpecs,RestSpecs) :-
2061 argspecs(Rest,I,ArgSpecs,RestSpecs).
2062 argspecs([[specinfo(J,Spec,Args)|Specs]|Rest],I,ArgSpecs,RestSpecs) :-
2064 ArgSpecs = [specinfo(J,Spec,Args)|RArgSpecs],
2066 RRestSpecs = RestSpecs
2068 RestSpecs = [Specs|RRestSpecs]
2071 ArgSpecs = RArgSpecs,
2072 RestSpecs = [[specinfo(J,Spec,Args)|Specs]|RRestSpecs]
2074 argspecs(Rest,I,RArgSpecs,RRestSpecs).
2076 merge_argspecs(In,Out) :-
2078 merge_argspecs_(Sorted,Out).
2080 merge_argspecs_([],[]).
2081 merge_argspecs_([X],R) :- !, R = [X].
2082 merge_argspecs_([specinfo(I,F1,A1),specinfo(I,F2,A2)|Rest],R) :-
2083 ( (F1 == any ; F2 == any) ->
2084 merge_argspecs_([specinfo(I,any,[])|Rest],R)
2087 merge_argspecs_([specinfo(I,F1,A)|Rest],R)
2089 R = [specinfo(I,F1,A1)|RR],
2090 merge_argspecs_([specinfo(I,F2,A2)|Rest],RR)
2093 arggoal(List,Arg,Goal,L,T) :-
2097 ; List = [specinfo(_,any,_)] ->
2098 Goal = term_variables(Arg,L,T)
2106 arggoal_cases(List,Arg,L,T,Cases)
2109 arggoal_cases([],_,L,T,L=T).
2110 arggoal_cases([specinfo(_,FA,ArgSpecs)|Rest],Arg,L,T,Cases) :-
2113 ; ArgSpecs == [[]] ->
2116 Cases = (Case ; RCases),
2119 Case = (Arg = Term -> ArgsGoal),
2120 spectermvars(Args,1,ArgSpecs,F,A,L,T,ArgsGoal)
2122 arggoal_cases(Rest,Arg,L,T,RCases).
2123 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2125 generate_extra_clauses(Constraints,List) :-
2126 generate_activate_clauses(Constraints,List,Tail0),
2127 generate_remove_clauses(Constraints,Tail0,Tail1),
2128 generate_allocate_clauses(Constraints,Tail1,Tail2),
2129 generate_insert_constraint_internal_clauses(Constraints,Tail2,Tail3),
2130 generate_novel_production(Tail3,Tail4),
2131 generate_extend_history(Tail4,Tail5),
2132 generate_run_suspensions_clauses(Constraints,Tail5,Tail6),
2133 generate_empty_named_history_initialisations(Tail6,Tail7),
2136 %~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
2137 % remove_constraint_internal/[1/3]
2139 generate_remove_clauses([],List,List).
2140 generate_remove_clauses([C|Cs],List,Tail) :-
2141 generate_remove_clause(C,List,List1),
2142 generate_remove_clauses(Cs,List1,Tail).
2144 remove_constraint_goal(Constraint,Susp,Agenda,DeleteNo,DeleteYes,Role,Goal) :-
2145 uses_state(Constraint,removed),
2146 ( chr_pp_flag(inline_insertremove,off) ->
2147 use_auxiliary_predicate(remove_constraint_internal,Constraint),
2148 Goal = ( DeleteGoal, ( Delete == yes -> DeleteYes ; DeleteNo) ),
2149 remove_constraint_atom(Constraint,Susp,Agenda,Delete,DeleteGoal)
2151 delay_phase_end(validate_store_type_assumptions,
2152 generate_remove_body(Constraint,Susp,Agenda,DeleteNo,DeleteYes,Role,Goal)
2156 remove_constraint_atom(Constraint,Susp,Agenda,Delete,Goal) :-
2157 make_name('$remove_constraint_internal_',Constraint,Name),
2158 ( chr_pp_flag(debugable,off), ( only_ground_indexed_arguments(Constraint) ; get_store_type(Constraint,var_assoc_store(_,_)) ) ->
2159 Goal =.. [Name, Susp,Delete]
2161 Goal =.. [Name,Susp,Agenda,Delete]
2164 generate_remove_clause(Constraint,List,Tail) :-
2165 ( is_used_auxiliary_predicate(remove_constraint_internal,Constraint) ->
2166 List = [RemoveClause|Tail],
2167 RemoveClause = (Head :- RemoveBody),
2168 remove_constraint_atom(Constraint,Susp,Agenda,Delete,Head),
2169 generate_remove_body(Constraint,Susp,Agenda,Delete = no,Delete = yes,active,RemoveBody)
2174 generate_remove_body(Constraint,Susp,Agenda,DeleteNo,DeleteYes,Role,RemoveBody) :-
2175 ( chr_pp_flag(debugable,off), ( only_ground_indexed_arguments(Constraint) ; get_store_type(Constraint,var_assoc_store(_,_))) ->
2177 get_update_suspension_field(Constraint,Susp,state,State,removed,GetState,GetStateValue0,UpdateState),
2178 if_used_state(Constraint,not_stored_yet,GetStateValue0,true,GetStateValue),
2179 if_used_state(Constraint,not_stored_yet,(State == not_stored_yet -> DeleteNo ; DeleteYes),DeleteYes,MaybeDelete)
2180 ; Role == partner ->
2181 get_update_suspension_field(Constraint,Susp,state,State,removed,GetState,_,UpdateState),
2182 GetStateValue = true,
2183 MaybeDelete = DeleteYes
2193 static_suspension_term(Constraint,Susp2),
2194 get_static_suspension_term_field(arguments,Constraint,Susp2,Args),
2195 generate_indexed_variables_body(Constraint,Args,IndexedVariablesBody,Agenda),
2196 ( chr_pp_flag(debugable,on) ->
2197 Constraint = Functor / _,
2198 get_static_suspension_term_field(functor,Constraint,Susp2,Functor)
2203 get_update_static_suspension_field(Constraint,Susp,Susp2,state,State,removed,GetStateValue0,UpdateState),
2204 if_used_state(Constraint,not_stored_yet,GetStateValue0,true,GetStateValue),
2205 if_used_state(Constraint,not_stored_yet,(State == not_stored_yet -> Agenda = [], DeleteNo ; IndexedVariablesBody, DeleteYes),(IndexedVariablesBody,DeleteYes),MaybeDelete)
2206 ; Role == partner ->
2207 get_update_static_suspension_field(Constraint,Susp,Susp2,state,State,removed,_,UpdateState),
2208 GetStateValue = true,
2209 MaybeDelete = (IndexedVariablesBody, DeleteYes)
2220 %~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
2221 % activate_constraint/4
2223 generate_activate_clauses([],List,List).
2224 generate_activate_clauses([C|Cs],List,Tail) :-
2225 generate_activate_clause(C,List,List1),
2226 generate_activate_clauses(Cs,List1,Tail).
2228 activate_constraint_goal(Constraint,StoreAction,Vars,Susp,Generation,Goal) :-
2229 ( chr_pp_flag(inline_insertremove,off) ->
2230 use_auxiliary_predicate(activate_constraint,Constraint),
2231 Goal = ( ActivateGoal , (Store == yes -> StoreAction ; true) ),
2232 activate_constraint_atom(Constraint,Store,Vars,Susp,Generation,ActivateGoal)
2234 delay_phase_end(validate_store_type_assumptions,
2235 activate_constraint_body(Constraint,StoreAction,true,Vars,Susp,Generation,Goal)
2239 activate_constraint_atom(Constraint,Store,Vars,Susp,Generation,Goal) :-
2240 make_name('$activate_constraint_',Constraint,Name),
2241 ( chr_pp_flag(debugable,off), only_ground_indexed_arguments(Constraint) ->
2242 Goal =.. [Name,Store, Susp]
2243 ; chr_pp_flag(debugable,off), may_trigger(Constraint), get_store_type(Constraint,var_assoc_store(_,_)) ->
2244 Goal =.. [Name,Store, Susp, Generation]
2245 ; chr_pp_flag(debugable,off), may_trigger(Constraint), get_store_type(Constraint,var_assoc_store(_,_)) ->
2246 Goal =.. [Name,Store, Vars, Susp, Generation]
2248 Goal =.. [Name,Store, Vars, Susp]
2251 generate_activate_clause(Constraint,List,Tail) :-
2252 ( is_used_auxiliary_predicate(activate_constraint,Constraint) ->
2253 List = [Clause|Tail],
2254 Clause = (Head :- Body),
2255 activate_constraint_atom(Constraint,Store,Vars,Susp,Generation,Head),
2256 activate_constraint_body(Constraint,Store = yes, Store = no,Vars,Susp,Generation,Body)
2261 activate_constraint_body(Constraint,StoreYes,StoreNo,Vars,Susp,Generation,Body) :-
2262 ( chr_pp_flag(debugable,off), may_trigger(Constraint), uses_field(Constraint,generation) ->
2263 get_update_suspension_field(Constraint,Susp,generation,Gen,Generation,GetGeneration,GetGenerationValue,UpdateGeneration),
2264 GenerationHandling = (GetGeneration, GetGenerationValue, Generation is Gen+1, UpdateGeneration)
2266 GenerationHandling = true
2268 get_update_suspension_field(Constraint,Susp,state,State,active,GetState,GetStateValue0,UpdateState),
2269 if_used_state(Constraint,not_stored_yet,GetStateValue0,true,GetStateValue),
2270 ( chr_pp_flag(debugable,off), ( only_ground_indexed_arguments(Constraint) ; get_store_type(Constraint,var_assoc_store(_,_))) ->
2271 if_used_state(Constraint,not_stored_yet,( State == not_stored_yet -> StoreYes ; StoreNo ),StoreNo,StoreVarsGoal)
2273 get_dynamic_suspension_term_field(arguments,Constraint,Susp,Arguments,ArgumentsGoal),
2274 generate_indexed_variables_body(Constraint,Arguments,IndexedVariablesBody,Vars),
2275 ( chr_pp_flag(guard_locks,off) ->
2278 NoneLocked = 'chr none_locked'( Vars)
2280 if_used_state(Constraint,not_stored_yet,
2281 ( State == not_stored_yet ->
2283 IndexedVariablesBody,
2290 % (Vars = [],StoreNo),StoreVarsGoal)
2291 StoreNo,StoreVarsGoal)
2301 %~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
2302 % allocate_constraint/4
2304 generate_allocate_clauses([],List,List).
2305 generate_allocate_clauses([C|Cs],List,Tail) :-
2306 generate_allocate_clause(C,List,List1),
2307 generate_allocate_clauses(Cs,List1,Tail).
2309 allocate_constraint_goal(Constraint,Susp,Args,Goal) :-
2310 uses_state(Constraint,not_stored_yet),
2311 ( chr_pp_flag(inline_insertremove,off) ->
2312 use_auxiliary_predicate(allocate_constraint,Constraint),
2313 allocate_constraint_atom(Constraint,Susp,Args,Goal)
2315 Goal = (Susp = Suspension, Goal0),
2316 delay_phase_end(validate_store_type_assumptions,
2317 allocate_constraint_body(Constraint,Suspension,Args,Goal0)
2321 allocate_constraint_atom(Constraint, Susp, Args,Goal) :-
2322 make_name('$allocate_constraint_',Constraint,Name),
2323 Goal =.. [Name,Susp|Args].
2325 generate_allocate_clause(Constraint,List,Tail) :-
2326 ( is_used_auxiliary_predicate(allocate_constraint,Constraint) ->
2327 List = [Clause|Tail],
2328 Clause = (Head :- Body),
2331 allocate_constraint_atom(Constraint,Susp,Args,Head),
2332 allocate_constraint_body(Constraint,Susp,Args,Body)
2337 allocate_constraint_body(Constraint,Susp,Args,Body) :-
2338 static_suspension_term(Constraint,Suspension),
2339 get_static_suspension_term_field(arguments,Constraint,Suspension,Args),
2340 ( chr_pp_flag(debugable,on) ->
2341 Constraint = Functor / _,
2342 get_static_suspension_term_field(functor,Constraint,Suspension,Functor)
2346 ( chr_pp_flag(debugable,on) ->
2347 ( may_trigger(Constraint) ->
2348 append(Args,[Susp],VarsSusp),
2349 build_head(F,A,[0],VarsSusp, ContinuationGoal),
2350 get_target_module(Mod),
2351 Continuation = Mod : ContinuationGoal
2355 Init = (Susp = Suspension),
2356 create_static_suspension_field(Constraint,Suspension,continuation,Continuation,CreateContinuation),
2357 create_static_suspension_field(Constraint,Suspension,generation,0,CreateGeneration)
2358 ; may_trigger(Constraint), uses_field(Constraint,generation) ->
2359 create_static_suspension_field(Constraint,Suspension,generation,0,CreateGeneration),
2360 Susp = Suspension, Init = true, CreateContinuation = true
2362 CreateGeneration = true, Susp = Suspension, Init = true, CreateContinuation = true
2364 ( uses_history(Constraint) ->
2365 create_static_suspension_field(Constraint,Suspension,history,t,CreateHistory)
2367 CreateHistory = true
2369 create_static_suspension_field(Constraint,Suspension,state,not_stored_yet,CreateState),
2370 ( has_suspension_field(Constraint,id) ->
2371 get_static_suspension_term_field(id,Constraint,Suspension,Id),
2386 gen_id(Id,'chr gen_id'(Id)).
2387 %~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
2388 % insert_constraint_internal
2390 generate_insert_constraint_internal_clauses([],List,List).
2391 generate_insert_constraint_internal_clauses([C|Cs],List,Tail) :-
2392 generate_insert_constraint_internal_clause(C,List,List1),
2393 generate_insert_constraint_internal_clauses(Cs,List1,Tail).
2395 insert_constraint_internal_constraint_goal(Constraint, Vars, Suspension, Continuation, Args,Goal) :-
2396 ( chr_pp_flag(inline_insertremove,off) ->
2397 use_auxiliary_predicate(remove_constraint_internal,Constraint),
2398 insert_constraint_internal_constraint_atom(Constraint,Vars,Suspension,Continuation,Args,Goal)
2400 delay_phase_end(validate_store_type_assumptions,
2401 generate_insert_constraint_internal_body(Constraint,Suspension,Continuation,Args,Vars,Goal)
2406 insert_constraint_internal_constraint_atom(Constraint,Vars,Self,Closure,Args,Goal) :-
2407 insert_constraint_internal_constraint_name(Constraint,Name),
2408 ( chr_pp_flag(debugable,on) ->
2409 Goal =.. [Name, Vars, Self, Closure | Args]
2410 ; ( only_ground_indexed_arguments(Constraint) ; get_store_type(Constraint,var_assoc_store(_,_)))->
2411 Goal =.. [Name,Self | Args]
2413 Goal =.. [Name,Vars, Self | Args]
2416 insert_constraint_internal_constraint_name(Constraint,Name) :-
2417 make_name('$insert_constraint_internal_',Constraint,Name).
2419 generate_insert_constraint_internal_clause(Constraint,List,Tail) :-
2420 ( is_used_auxiliary_predicate(insert_constraint_internal,Constraint) ->
2421 List = [Clause|Tail],
2422 Clause = (Head :- Body),
2425 insert_constraint_internal_constraint_atom(Constraint, Vars, Suspension, Continuation,Args,Head),
2426 generate_insert_constraint_internal_body(Constraint,Suspension,Continuation,Args,Vars,Body)
2432 generate_insert_constraint_internal_body(Constraint,Susp,Continuation,Args,Vars,Body) :-
2433 static_suspension_term(Constraint,Suspension),
2434 create_static_suspension_field(Constraint,Suspension,state,active,CreateState),
2435 ( chr_pp_flag(debugable,on) ->
2436 get_static_suspension_term_field(continuation,Constraint,Suspension,Continuation),
2437 create_static_suspension_field(Constraint,Suspension,generation,0,CreateGeneration)
2438 ; may_trigger(Constraint), uses_field(Constraint,generation) ->
2439 create_static_suspension_field(Constraint,Suspension,generation,0,CreateGeneration)
2441 CreateGeneration = true
2443 ( chr_pp_flag(debugable,on) ->
2444 Constraint = Functor / _,
2445 get_static_suspension_term_field(functor,Constraint,Suspension,Functor)
2449 ( uses_history(Constraint) ->
2450 create_static_suspension_field(Constraint,Suspension,history,t,CreateHistory)
2452 CreateHistory = true
2454 get_static_suspension_term_field(arguments,Constraint,Suspension,Args),
2455 List = [Clause|Tail],
2456 ( chr_pp_flag(debugable,off), ( only_ground_indexed_arguments(Constraint) ; get_store_type(Constraint,var_assoc_store(_,_)))->
2457 suspension_term_base_fields(Constraint,BaseFields),
2458 ( has_suspension_field(Constraint,id) ->
2459 get_static_suspension_term_field(id,Constraint,Suspension,Id),
2473 ( has_suspension_field(Constraint,id) ->
2474 get_static_suspension_term_field(id,Constraint,Suspension,Id),
2479 generate_indexed_variables_body(Constraint,Args,IndexedVariablesBody,Vars),
2480 ( chr_pp_flag(guard_locks,off) ->
2483 NoneLocked = 'chr none_locked'( Vars)
2488 IndexedVariablesBody,
2497 %~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
2498 % novel_production/2
2500 generate_novel_production(List,Tail) :-
2501 ( is_used_auxiliary_predicate(novel_production) ->
2502 List = [Clause|Tail],
2505 '$novel_production'( Self, Tuple) :-
2506 % arg( 3, Self, Ref), % ARGXXX
2507 % 'chr get_mutable'( History, Ref),
2508 arg( 3, Self, History), % ARGXXX
2509 ( hprolog:get_ds( Tuple, History, _) ->
2519 %~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
2522 generate_extend_history(List,Tail) :-
2523 ( is_used_auxiliary_predicate(extend_history) ->
2524 List = [Clause|Tail],
2527 '$extend_history'( Self, Tuple) :-
2528 % arg( 3, Self, Ref), % ARGXXX
2529 % 'chr get_mutable'( History, Ref),
2530 arg( 3, Self, History), % ARGXXX
2531 hprolog:put_ds( Tuple, History, x, NewHistory),
2532 setarg( 3, Self, NewHistory) % ARGXXX
2538 %~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
2541 empty_named_history_initialisations/2,
2542 generate_empty_named_history_initialisation/1,
2543 find_empty_named_histories/0.
2545 generate_empty_named_history_initialisations(List, Tail) :-
2546 empty_named_history_initialisations(List, Tail),
2547 find_empty_named_histories.
2549 find_empty_named_histories, history(_, Name, []) ==>
2550 generate_empty_named_history_initialisation(Name).
2552 generate_empty_named_history_initialisation(Name) \
2553 generate_empty_named_history_initialisation(Name) <=> true.
2554 generate_empty_named_history_initialisation(Name) \
2555 empty_named_history_initialisations(List, Tail) # Passive
2557 empty_named_history_global_variable(Name, GlobalVariable),
2558 List = [(:- nb_setval(GlobalVariable, 0))|Rest],
2559 empty_named_history_initialisations(Rest, Tail)
2560 pragma passive(Passive).
2562 find_empty_named_histories \
2563 generate_empty_named_history_initialisation(_) # Passive <=> true
2564 pragma passive(Passive).
2566 find_empty_named_histories,
2567 empty_named_history_initialisations(List, Tail) # Passive <=> List = Tail
2568 pragma passive(Passive).
2570 find_empty_named_histories <=>
2571 chr_error(internal, 'find_empty_named_histories was not removed', []).
2574 empty_named_history_global_variable(Name, GlobalVariable) :-
2575 atom_concat('chr empty named history ', Name, GlobalVariable).
2577 empty_named_history_novel_production(Name, nb_getval(GlobalVariable, 0)) :-
2578 empty_named_history_global_variable(Name, GlobalVariable).
2580 empty_named_history_extend_history(Name, b_setval(GlobalVariable, 1)) :-
2581 empty_named_history_global_variable(Name, GlobalVariable).
2584 %~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
2587 generate_run_suspensions_clauses([],List,List).
2588 generate_run_suspensions_clauses([C|Cs],List,Tail) :-
2589 generate_run_suspensions_clause(C,List,List1),
2590 generate_run_suspensions_clauses(Cs,List1,Tail).
2592 run_suspensions_goal(Constraint,Suspensions,Goal) :-
2593 make_name('$run_suspensions_',Constraint,Name),
2594 Goal =.. [Name,Suspensions].
2596 generate_run_suspensions_clause(Constraint,List,Tail) :-
2597 ( is_used_auxiliary_predicate(run_suspensions,Constraint) ->
2598 List = [Clause1,Clause2|Tail],
2599 run_suspensions_goal(Constraint,[],Clause1),
2600 ( chr_pp_flag(debugable,on) ->
2601 run_suspensions_goal(Constraint,[Suspension|Suspensions],Clause2Head),
2602 get_update_suspension_field(Constraint,Suspension,state,State,triggered,GetState,GetStateValue,UpdateState),
2603 get_update_suspension_field(Constraint,Suspension,state,Post,active,GetPost,GetPostValue,UpdatePost),
2604 get_update_suspension_field(Constraint,Suspension,generation,Gen,Generation,GetGeneration,GetGenerationValue,UpdateGeneration),
2605 get_dynamic_suspension_term_field(continuation,Constraint,Suspension,Continuation,GetContinuation),
2606 run_suspensions_goal(Constraint,Suspensions,Clause2Recursion),
2616 Generation is Gen+1,
2620 'chr debug_event'(wake(Suspension)),
2623 'chr debug_event'(fail(Suspension)), !,
2627 'chr debug_event'(exit(Suspension))
2629 'chr debug_event'(redo(Suspension)),
2634 ( Post==triggered ->
2635 UpdatePost % catching constraints that did not do anything
2645 run_suspensions_goal(Constraint,[Suspension|Suspensions],Clause2Head),
2646 static_suspension_term(Constraint,SuspensionTerm),
2647 get_static_suspension_term_field(arguments,Constraint,SuspensionTerm,Arguments),
2648 append(Arguments,[Suspension],VarsSusp),
2649 make_suspension_continuation_goal(Constraint,VarsSusp,Continuation),
2650 run_suspensions_goal(Constraint,Suspensions,Clause2Recursion),
2651 ( uses_field(Constraint,generation) ->
2652 get_update_static_suspension_field(Constraint,Suspension,SuspensionTerm,generation,Gen,Generation,GetGeneration,UpdateGeneration),
2653 GenerationHandling = ( GetGeneration, Generation is Gen+1, UpdateGeneration)
2655 GenerationHandling = true
2657 get_update_static_suspension_field(Constraint,Suspension,SuspensionTerm,state,State,triggered,GetState,UpdateState),
2658 get_update_static_suspension_field(Constraint,Suspension,SuspensionTerm,state,Post,active,GetPostState,UpdatePostState),
2659 if_used_state(Constraint,removed,
2662 -> ReactivateConstraint
2664 ),ReactivateConstraint,CondReactivate),
2665 ReactivateConstraint =
2671 ( Post==triggered ->
2672 UpdatePostState % catching constraints that did not do anything
2680 Suspension = SuspensionTerm,
2689 %~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
2691 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2692 generate_attach_increment(Clauses) :-
2693 get_max_constraint_index(N),
2694 ( is_used_auxiliary_predicate(attach_increment), N > 0 ->
2695 Clauses = [Clause1,Clause2],
2696 generate_attach_increment_empty(Clause1),
2698 generate_attach_increment_one(Clause2)
2700 generate_attach_increment_many(N,Clause2)
2706 generate_attach_increment_empty((attach_increment([],_) :- true)).
2708 generate_attach_increment_one(Clause) :-
2709 Head = attach_increment([Var|Vars],Susps),
2710 get_target_module(Mod),
2711 ( chr_pp_flag(guard_locks,off) ->
2714 NotLocked = 'chr not_locked'( Var)
2719 ( get_attr(Var,Mod,VarSusps) ->
2720 sort(VarSusps,SortedVarSusps),
2721 'chr merge_attributes'(Susps,SortedVarSusps,MergedSusps),
2722 put_attr(Var,Mod,MergedSusps)
2724 put_attr(Var,Mod,Susps)
2726 attach_increment(Vars,Susps)
2728 Clause = (Head :- Body).
2730 generate_attach_increment_many(N,Clause) :-
2731 Head = attach_increment([Var|Vars],TAttr1),
2732 % writeln(merge_attributes_1_before),
2733 merge_attributes(N,TAttr1,TAttr2,MergeGoal,Attr),
2734 % writeln(merge_attributes_1_after),
2735 get_target_module(Mod),
2736 ( chr_pp_flag(guard_locks,off) ->
2739 NotLocked = 'chr not_locked'( Var)
2744 ( get_attr(Var,Mod,TAttr2) ->
2746 put_attr(Var,Mod,Attr)
2748 put_attr(Var,Mod,TAttr1)
2750 attach_increment(Vars,TAttr1)
2752 Clause = (Head :- Body).
2755 generate_attr_unify_hook(Clauses) :-
2756 get_max_constraint_index(N),
2761 generate_attr_unify_hook_one(Clauses)
2763 generate_attr_unify_hook_many(N,Clauses)
2767 generate_attr_unify_hook_one([Clause]) :-
2768 Head = attr_unify_hook(Susps,Other),
2769 get_target_module(Mod),
2770 get_indexed_constraint(1,C),
2771 ( get_store_type(C,ST),
2772 ( ST = default ; ST = multi_store(STs), memberchk(default,STs) ) ->
2773 make_run_suspensions(NewSusps,SortedSusps,WakeNewSusps),
2774 make_run_suspensions(SortedSusps,SortedSusps,WakeSusps),
2775 ( atomic_types_suspended_constraint(C) ->
2777 SortedSusps = Susps,
2779 SortedOtherSusps = OtherSusps,
2780 MergeGoal = (append(Susps,OtherSusps,List), sort(List,NewSusps)),
2783 SortGoal1 = sort(Susps, SortedSusps),
2784 SortGoal2 = sort(OtherSusps,SortedOtherSusps),
2785 MergeGoal = 'chr merge_attributes'(SortedSusps,SortedOtherSusps,NewSusps),
2786 use_auxiliary_predicate(attach_increment),
2788 ( compound(Other) ->
2789 term_variables(Other,OtherVars),
2790 attach_increment(OtherVars, SortedSusps)
2799 ( get_attr(Other,Mod,OtherSusps) ->
2802 put_attr(Other,Mod,NewSusps),
2805 put_attr(Other,Mod,SortedSusps),
2813 Clause = (Head :- Body)
2814 ; get_store_type(C,var_assoc_store(VarIndex,KeyIndex)) ->
2815 make_run_suspensions(List,List,WakeNewSusps),
2816 MergeGoal = (merge_into_assoc_store(Susps,OtherSusps,List)),
2818 ( get_attr(Other,Mod,OtherSusps) ->
2822 put_attr(Other,Mod,Susps)
2824 Clause = (Head :- Body)
2828 generate_attr_unify_hook_many(N,[Clause]) :-
2829 chr_pp_flag(dynattr,off), !,
2830 Head = attr_unify_hook(Attr,Other),
2831 get_target_module(Mod),
2832 make_attr(N,Mask,SuspsList,Attr),
2833 bagof(Sort,A ^ B ^ ( member(A,SuspsList) , Sort = sort(A,B) ) , SortGoalList),
2834 list2conj(SortGoalList,SortGoals),
2835 bagof(B, A ^ member(sort(A,B),SortGoalList), SortedSuspsList),
2836 merge_attributes2(N,Mask,SortedSuspsList,TOtherAttr,MergeGoal,MergedAttr),
2837 get_all_suspensions2(N,MergedAttr,MergedSuspsList),
2838 make_attr(N,Mask,SortedSuspsList,SortedAttr),
2839 make_run_suspensions_loop(MergedSuspsList,SortedSuspsList,WakeMergedSusps),
2840 make_run_suspensions_loop(SortedSuspsList,SortedSuspsList,WakeSortedSusps),
2841 ( forall((between(1,N,Index), get_indexed_constraint(Index,Constraint)),atomic_types_suspended_constraint(Constraint)) ->
2844 use_auxiliary_predicate(attach_increment),
2846 ( compound(Other) ->
2847 term_variables(Other,OtherVars),
2848 attach_increment(OtherVars,SortedAttr)
2857 ( get_attr(Other,Mod,TOtherAttr) ->
2859 put_attr(Other,Mod,MergedAttr),
2862 put_attr(Other,Mod,SortedAttr),
2870 Clause = (Head :- Body).
2873 generate_attr_unify_hook_many(N,Clauses) :-
2874 Head = attr_unify_hook(Attr,Other),
2875 get_target_module(Mod),
2876 normalize_attr(Attr,NormalGoal,NormalAttr),
2877 normalize_attr(OtherAttr,NormalOtherGoal,NormalOtherAttr),
2878 merge_attributes(N,NormalAttr,NormalOtherAttr,MergeGoal,MergedAttr),
2879 make_run_suspensions(N),
2880 ( forall((between(1,N,Index), get_indexed_constraint(Index,Constraint)),atomic_types_suspended_constraint(Constraint)) ->
2883 use_auxiliary_predicate(attach_increment),
2885 ( compound(Other) ->
2886 term_variables(Other,OtherVars),
2887 attach_increment(OtherVars,NormalAttr)
2896 ( get_attr(Other,Mod,OtherAttr) ->
2899 put_attr(Other,Mod,MergedAttr),
2900 '$dispatch_run_suspensions'(MergedAttr)
2902 put_attr(Other,Mod,NormalAttr),
2903 '$dispatch_run_suspensions'(NormalAttr)
2907 '$dispatch_run_suspensions'(NormalAttr)
2910 Clause = (Head :- Body),
2911 Clauses = [Clause,DispatchList1,DispatchList2|Dispatchers],
2912 DispatchList1 = ('$dispatch_run_suspensions'([])),
2913 DispatchList2 = ('$dispatch_run_suspensions'([Pos-List|Rest]) :- '$dispatch_run_suspensions'(Pos,List),'$dispatch_run_suspensions'(Rest)),
2914 run_suspensions_dispatchers(N,[],Dispatchers).
2917 run_suspensions_dispatchers(N,Acc,Dispatchers) :-
2919 get_indexed_constraint(N,C),
2920 NAcc = [('$dispatch_run_suspensions'(N,List) :- Body)|Acc],
2922 run_suspensions_goal(C,List,Body)
2927 run_suspensions_dispatchers(M,NAcc,Dispatchers)
2933 make_run_suspensions(N) :-
2935 ( get_indexed_constraint(N,C),
2937 use_auxiliary_predicate(run_suspensions,C)
2942 make_run_suspensions(M)
2947 make_run_suspensions(AllSusps,OneSusps,Goal) :-
2948 make_run_suspensions(1,AllSusps,OneSusps,Goal).
2950 make_run_suspensions(Index,AllSusps,OneSusps,Goal) :-
2951 ( get_indexed_constraint(Index,C), may_trigger(C) ->
2952 use_auxiliary_predicate(run_suspensions,C),
2953 ( wakes_partially(C) ->
2954 run_suspensions_goal(C,OneSusps,Goal)
2956 run_suspensions_goal(C,AllSusps,Goal)
2962 make_run_suspensions_loop(AllSuspsList,OneSuspsList,Goal) :-
2963 make_run_suspensions_loop(AllSuspsList,OneSuspsList,1,Goal).
2965 make_run_suspensions_loop([],[],_,true).
2966 make_run_suspensions_loop([AllSusps|AllSuspsList],[OneSusps|OneSuspsList],I,(Goal,Goals)) :-
2967 make_run_suspensions(I,AllSusps,OneSusps,Goal),
2969 make_run_suspensions_loop(AllSuspsList,OneSuspsList,J,Goals).
2971 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2972 % $insert_in_store_F/A
2973 % $delete_from_store_F/A
2975 generate_insert_delete_constraints([],[]).
2976 generate_insert_delete_constraints([FA|Rest],Clauses) :-
2978 generate_insert_delete_constraint(FA,Clauses,RestClauses)
2980 Clauses = RestClauses
2982 generate_insert_delete_constraints(Rest,RestClauses).
2984 generate_insert_delete_constraint(FA,Clauses,RestClauses) :-
2985 insert_constraint_clause(FA,Clauses,RestClauses1),
2986 delete_constraint_clause(FA,RestClauses1,RestClauses).
2988 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
2991 insert_constraint_goal(FA,Susp,Vars,Goal) :-
2992 ( chr_pp_flag(inline_insertremove,off) ->
2993 use_auxiliary_predicate(insert_in_store,FA),
2994 insert_constraint_atom(FA,Susp,Goal)
2996 delay_phase_end(validate_store_type_assumptions,
2997 ( insert_constraint_body(FA,Susp,UsedVars,Goal),
2998 insert_constraint_direct_used_vars(UsedVars,Vars)
3003 insert_constraint_direct_used_vars([],_).
3004 insert_constraint_direct_used_vars([Index-Var|Rest],Vars) :-
3005 nth1(Index,Vars,Var),
3006 insert_constraint_direct_used_vars(Rest,Vars).
3008 insert_constraint_atom(FA,Susp,Call) :-
3009 make_name('$insert_in_store_',FA,Functor),
3010 Call =.. [Functor,Susp].
3012 insert_constraint_clause(C,Clauses,RestClauses) :-
3013 ( is_used_auxiliary_predicate(insert_in_store,C) ->
3014 Clauses = [Clause|RestClauses],
3015 Clause = (Head :- InsertCounterInc,VarsBody,Body),
3016 insert_constraint_atom(C,Susp,Head),
3017 insert_constraint_body(C,Susp,UsedVars,Body),
3018 insert_constraint_used_vars(UsedVars,C,Susp,VarsBody),
3019 ( chr_pp_flag(store_counter,on) ->
3020 InsertCounterInc = '$insert_counter_inc'
3022 InsertCounterInc = true
3025 Clauses = RestClauses
3028 insert_constraint_used_vars([],_,_,true).
3029 insert_constraint_used_vars([Index-Var|Rest],C,Susp,(Goal,Goals)) :-
3030 get_dynamic_suspension_term_field(argument(Index),C,Susp,Var,Goal),
3031 insert_constraint_used_vars(Rest,C,Susp,Goals).
3033 insert_constraint_body(C,Susp,UsedVars,Body) :-
3034 get_store_type(C,StoreType),
3035 insert_constraint_body(StoreType,C,Susp,UsedVars,Body).
3037 insert_constraint_body(default,C,Susp,[],Body) :-
3038 global_list_store_name(C,StoreName),
3039 make_get_store_goal(StoreName,Store,GetStoreGoal),
3040 make_update_store_goal(StoreName,Cell,UpdateStoreGoal),
3041 ( chr_pp_flag(debugable,on) ->
3042 Cell = [Susp|Store],
3049 set_dynamic_suspension_term_field(global_list_prev,C,NextSusp,Cell,SetGoal),
3053 Cell = [Susp|Store],
3055 ( Store = [NextSusp|_] ->
3062 % get_target_module(Mod),
3063 % get_max_constraint_index(Total),
3065 % generate_attach_body_1(C,Store,Susp,AttachBody)
3067 % generate_attach_body_n(C,Store,Susp,AttachBody)
3071 % 'chr default_store'(Store),
3074 insert_constraint_body(multi_inthash(Indexes),C,Susp,[],Body) :-
3075 generate_multi_inthash_insert_constraint_bodies(Indexes,C,Susp,Body).
3076 insert_constraint_body(multi_hash(Indexes),C,Susp,MixedUsedVars,Body) :-
3077 generate_multi_hash_insert_constraint_bodies(Indexes,C,Susp,Body,MixedUsedVars),
3078 sort_out_used_vars(MixedUsedVars,UsedVars).
3079 insert_constraint_body(atomic_constants(Index,_,_),C,Susp,UsedVars,Body) :-
3080 multi_hash_key_direct(C,Index,Susp,Key,UsedVars),
3081 constants_store_index_name(C,Index,IndexName),
3082 IndexLookup =.. [IndexName,Key,StoreName],
3085 nb_getval(StoreName,Store),
3086 b_setval(StoreName,[Susp|Store])
3090 insert_constraint_body(ground_constants(Index,_,_),C,Susp,UsedVars,Body) :-
3091 multi_hash_key_direct(C,Index,Susp,Key,UsedVars),
3092 constants_store_index_name(C,Index,IndexName),
3093 IndexLookup =.. [IndexName,Key,StoreName],
3096 nb_getval(StoreName,Store),
3097 b_setval(StoreName,[Susp|Store])
3101 insert_constraint_body(global_ground,C,Susp,[],Body) :-
3102 global_ground_store_name(C,StoreName),
3103 make_get_store_goal(StoreName,Store,GetStoreGoal),
3104 make_update_store_goal(StoreName,Cell,UpdateStoreGoal),
3105 ( chr_pp_flag(debugable,on) ->
3106 Cell = [Susp|Store],
3113 set_dynamic_suspension_term_field(global_list_prev,C,NextSusp,Cell,SetGoal),
3117 Cell = [Susp|Store],
3119 ( Store = [NextSusp|_] ->
3126 % global_ground_store_name(C,StoreName),
3127 % make_get_store_goal(StoreName,Store,GetStoreGoal),
3128 % make_update_store_goal(StoreName,[Susp|Store],UpdateStoreGoal),
3131 % GetStoreGoal, % nb_getval(StoreName,Store),
3132 % UpdateStoreGoal % b_setval(StoreName,[Susp|Store])
3134 insert_constraint_body(var_assoc_store(VarIndex,AssocIndex),C,Susp,[VarIndex-Variable,AssocIndex-Key],Body) :-
3135 % TODO: generalize to more than one !!!
3136 get_target_module(Module),
3137 Body = ( get_attr(Variable,Module,AssocStore) ->
3138 insert_assoc_store(AssocStore,Key,Susp)
3140 new_assoc_store(AssocStore),
3141 put_attr(Variable,Module,AssocStore),
3142 insert_assoc_store(AssocStore,Key,Susp)
3145 insert_constraint_body(global_singleton,C,Susp,[],Body) :-
3146 global_singleton_store_name(C,StoreName),
3147 make_update_store_goal(StoreName,Susp,UpdateStoreGoal),
3152 insert_constraint_body(multi_store(StoreTypes),C,Susp,UsedVars,Body) :-
3153 maplist(insert_constraint_body1(C,Susp),StoreTypes,NestedUsedVars,Bodies),
3154 list2conj(Bodies,Body),
3155 sort_out_used_vars(NestedUsedVars,UsedVars).
3156 insert_constraint_body1(C,Susp,StoreType,UsedVars,Body) :-
3157 insert_constraint_body(StoreType,C,Susp,UsedVars,Body).
3158 insert_constraint_body(identifier_store(Index),C,Susp,UsedVars,Body) :-
3159 UsedVars = [Index-Var],
3160 get_identifier_size(ISize),
3161 functor(Struct,struct,ISize),
3162 get_identifier_index(C,Index,IIndex),
3163 arg(IIndex,Struct,Susps),
3164 Body = (Var = Struct, setarg(IIndex,Var,[Susp|Susps])).
3165 insert_constraint_body(type_indexed_identifier_store(Index,IndexType),C,Susp,UsedVars,Body) :-
3166 UsedVars = [Index-Var],
3167 type_indexed_identifier_structure(IndexType,Struct),
3168 get_type_indexed_identifier_index(IndexType,C,Index,IIndex),
3169 arg(IIndex,Struct,Susps),
3170 Body = (Var = Struct, setarg(IIndex,Var,[Susp|Susps])).
3172 sort_out_used_vars(NestedUsedVars,UsedVars) :-
3173 flatten(NestedUsedVars,FlatUsedVars),
3174 sort(FlatUsedVars,SortedFlatUsedVars),
3175 sort_out_used_vars1(SortedFlatUsedVars,UsedVars).
3177 sort_out_used_vars1([],[]).
3178 sort_out_used_vars1([I-V],L) :- !, L = [I-V].
3179 sort_out_used_vars1([I-X,J-Y|R],L) :-
3182 sort_out_used_vars1([I-X|R],L)
3185 sort_out_used_vars1([J-Y|R],T)
3188 generate_multi_inthash_insert_constraint_bodies([],_,_,true).
3189 generate_multi_inthash_insert_constraint_bodies([Index|Indexes],FA,Susp,(Body,Bodies)) :-
3190 multi_hash_store_name(FA,Index,StoreName),
3191 multi_hash_key(FA,Index,Susp,KeyBody,Key),
3195 nb_getval(StoreName,Store),
3196 insert_iht(Store,Key,Susp)
3198 generate_multi_inthash_insert_constraint_bodies(Indexes,FA,Susp,Bodies).
3200 generate_multi_hash_insert_constraint_bodies([],_,_,true,[]).
3201 generate_multi_hash_insert_constraint_bodies([Index|Indexes],FA,Susp,(Body,Bodies),[UsedVars|MoreUsedVars]) :-
3202 multi_hash_store_name(FA,Index,StoreName),
3203 multi_hash_key_direct(FA,Index,Susp,Key,UsedVars),
3204 make_get_store_goal(StoreName,Store,GetStoreGoal),
3205 ( chr_pp_flag(ht_removal,on)
3206 -> ht_prev_field(Index,PrevField),
3207 set_dynamic_suspension_term_field(PrevField,FA,NextSusp,Result,
3212 insert_ht(Store,Key,Susp,Result),
3213 ( Result = [_,NextSusp|_]
3221 insert_ht(Store,Key,Susp)
3224 generate_multi_hash_insert_constraint_bodies(Indexes,FA,Susp,Bodies,MoreUsedVars).
3226 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
3229 delete_constraint_clause(C,Clauses,RestClauses) :-
3230 ( is_used_auxiliary_predicate(delete_from_store,C) ->
3231 Clauses = [Clause|RestClauses],
3232 Clause = (Head :- Body),
3233 delete_constraint_atom(C,Susp,Head),
3236 delete_constraint_body(C,Head,Susp,[],Body)
3238 Clauses = RestClauses
3241 delete_constraint_goal(Head,Susp,VarDict,Goal) :-
3244 ( chr_pp_flag(inline_insertremove,off) ->
3245 use_auxiliary_predicate(delete_from_store,C),
3246 delete_constraint_atom(C,Susp,Goal)
3248 delay_phase_end(validate_store_type_assumptions, delete_constraint_body(C,Head,Susp,VarDict,Goal))
3251 delete_constraint_atom(C,Susp,Atom) :-
3252 make_name('$delete_from_store_',C,Functor),
3253 Atom =.. [Functor,Susp].
3256 delete_constraint_body(C,Head,Susp,VarDict,Body) :-
3257 Body = (CounterBody,DeleteBody),
3258 ( chr_pp_flag(store_counter,on) ->
3259 CounterBody = '$delete_counter_inc'
3263 get_store_type(C,StoreType),
3264 delete_constraint_body(StoreType,C,Head,Susp,VarDict,DeleteBody).
3266 delete_constraint_body(default,C,_,Susp,_,Body) :-
3267 ( chr_pp_flag(debugable,on) ->
3268 global_list_store_name(C,StoreName),
3269 make_get_store_goal(StoreName,Store,GetStoreGoal),
3270 make_update_store_goal(StoreName,NStore,UpdateStoreGoal),
3273 GetStoreGoal, % nb_getval(StoreName,Store),
3274 'chr sbag_del_element'(Store,Susp,NStore),
3275 UpdateStoreGoal % b_setval(StoreName,NStore)
3278 get_dynamic_suspension_term_field(global_list_prev,C,Susp,PredCell,GetGoal),
3279 global_list_store_name(C,StoreName),
3280 make_get_store_goal(StoreName,Store,GetStoreGoal),
3281 make_update_store_goal(StoreName,Tail,UpdateStoreGoal),
3282 set_dynamic_suspension_term_field(global_list_prev,C,NextSusp,_,SetGoal1),
3283 set_dynamic_suspension_term_field(global_list_prev,C,NextSusp,PredCell,SetGoal2),
3288 GetStoreGoal, % nb_getval(StoreName,Store),
3291 ( Tail = [NextSusp|_] ->
3297 PredCell = [_,_|Tail],
3298 setarg(2,PredCell,Tail),
3299 ( Tail = [NextSusp|_] ->
3307 % get_target_module(Mod),
3308 % get_max_constraint_index(Total),
3310 % generate_detach_body_1(C,Store,Susp,DetachBody),
3313 % 'chr default_store'(Store),
3317 % generate_detach_body_n(C,Store,Susp,DetachBody),
3320 % 'chr default_store'(Store),
3324 delete_constraint_body(multi_inthash(Indexes),C,_,Susp,_,Body) :-
3325 generate_multi_inthash_delete_constraint_bodies(Indexes,C,Susp,Body).
3326 delete_constraint_body(multi_hash(Indexes),C,Head,Susp,VarDict,Body) :-
3327 generate_multi_hash_delete_constraint_bodies(Indexes,C,Head,Susp,VarDict,Body).
3328 delete_constraint_body(atomic_constants(Index,_,_),C,Head,Susp,VarDict,Body) :-
3329 multi_hash_key(C,Head,Index,Susp,VarDict,KeyBody,Key),
3330 constants_store_index_name(C,Index,IndexName),
3331 IndexLookup =.. [IndexName,Key,StoreName],
3335 nb_getval(StoreName,Store),
3336 'chr sbag_del_element'(Store,Susp,NStore),
3337 b_setval(StoreName,NStore)
3341 delete_constraint_body(ground_constants(Index,_,_),C,Head,Susp,VarDict,Body) :-
3342 multi_hash_key(C,Head,Index,Susp,VarDict,KeyBody,Key),
3343 constants_store_index_name(C,Index,IndexName),
3344 IndexLookup =.. [IndexName,Key,StoreName],
3348 nb_getval(StoreName,Store),
3349 'chr sbag_del_element'(Store,Susp,NStore),
3350 b_setval(StoreName,NStore)
3354 delete_constraint_body(global_ground,C,_,Susp,_,Body) :-
3355 ( chr_pp_flag(debugable,on) ->
3356 global_ground_store_name(C,StoreName),
3357 make_get_store_goal(StoreName,Store,GetStoreGoal),
3358 make_update_store_goal(StoreName,NStore,UpdateStoreGoal),
3361 GetStoreGoal, % nb_getval(StoreName,Store),
3362 'chr sbag_del_element'(Store,Susp,NStore),
3363 UpdateStoreGoal % b_setval(StoreName,NStore)
3366 get_dynamic_suspension_term_field(global_list_prev,C,Susp,PredCell,GetGoal),
3367 global_ground_store_name(C,StoreName),
3368 make_get_store_goal(StoreName,Store,GetStoreGoal),
3369 make_update_store_goal(StoreName,Tail,UpdateStoreGoal),
3370 set_dynamic_suspension_term_field(global_list_prev,C,NextSusp,_,SetGoal1),
3371 set_dynamic_suspension_term_field(global_list_prev,C,NextSusp,PredCell,SetGoal2),
3376 GetStoreGoal, % nb_getval(StoreName,Store),
3379 ( Tail = [NextSusp|_] ->
3385 PredCell = [_,_|Tail],
3386 setarg(2,PredCell,Tail),
3387 ( Tail = [NextSusp|_] ->
3395 % global_ground_store_name(C,StoreName),
3396 % make_get_store_goal(StoreName,Store,GetStoreGoal),
3397 % make_update_store_goal(StoreName,NStore,UpdateStoreGoal),
3400 % GetStoreGoal, % nb_getval(StoreName,Store),
3401 % 'chr sbag_del_element'(Store,Susp,NStore),
3402 % UpdateStoreGoal % b_setval(StoreName,NStore)
3404 delete_constraint_body(var_assoc_store(VarIndex,AssocIndex),C,_,Susp,_,Body) :-
3405 get_target_module(Module),
3406 get_dynamic_suspension_term_field(argument(VarIndex),C,Susp,Variable,VariableGoal),
3407 get_dynamic_suspension_term_field(argument(AssocIndex),C,Susp,Key,KeyGoal),
3410 get_attr(Variable,Module,AssocStore),
3412 delete_assoc_store(AssocStore,Key,Susp)
3414 delete_constraint_body(global_singleton,C,_,_Susp,_,Body) :-
3415 global_singleton_store_name(C,StoreName),
3416 make_update_store_goal(StoreName,[],UpdateStoreGoal),
3419 UpdateStoreGoal % b_setval(StoreName,[])
3421 delete_constraint_body(multi_store(StoreTypes),C,Head,Susp,VarDict,Body) :-
3422 maplist(delete_constraint_body1(C,Head,Susp,VarDict),StoreTypes,Bodies),
3423 list2conj(Bodies,Body).
3424 delete_constraint_body1(C,Head,Susp,VarDict,StoreType,Body) :-
3425 delete_constraint_body(StoreType,C,Head,Susp,VarDict,Body).
3426 delete_constraint_body(identifier_store(Index),C,Head,Susp,VarDict,Body) :-
3427 get_suspension_argument_possibly_in_scope(Head,VarDict,Susp,Index,Variable,VariableGoal),
3428 get_identifier_size(ISize),
3429 functor(Struct,struct,ISize),
3430 get_identifier_index(C,Index,IIndex),
3431 arg(IIndex,Struct,Susps),
3435 'chr sbag_del_element'(Susps,Susp,NSusps),
3436 setarg(IIndex,Variable,NSusps)
3438 delete_constraint_body(type_indexed_identifier_store(Index,IndexType),C,Head,Susp,VarDict,Body) :-
3439 get_suspension_argument_possibly_in_scope(Head,VarDict,Susp,Index,Variable,VariableGoal),
3440 type_indexed_identifier_structure(IndexType,Struct),
3441 get_type_indexed_identifier_index(IndexType,C,Index,IIndex),
3442 arg(IIndex,Struct,Susps),
3446 'chr sbag_del_element'(Susps,Susp,NSusps),
3447 setarg(IIndex,Variable,NSusps)
3450 generate_multi_inthash_delete_constraint_bodies([],_,_,true).
3451 generate_multi_inthash_delete_constraint_bodies([Index|Indexes],FA,Susp,(Body,Bodies)) :-
3452 multi_hash_store_name(FA,Index,StoreName),
3453 multi_hash_key(FA,Index,Susp,KeyBody,Key),
3457 nb_getval(StoreName,Store),
3458 delete_iht(Store,Key,Susp)
3460 generate_multi_inthash_delete_constraint_bodies(Indexes,FA,Susp,Bodies).
3461 generate_multi_hash_delete_constraint_bodies([],_,_,_,_,true).
3462 generate_multi_hash_delete_constraint_bodies([Index|Indexes],C,Head,Susp,VarDict,(Body,Bodies)) :-
3463 multi_hash_store_name(C,Index,StoreName),
3464 multi_hash_key(C,Head,Index,Susp,VarDict,KeyBody,Key),
3465 make_get_store_goal(StoreName,Store,GetStoreGoal),
3466 ( chr_pp_flag(ht_removal,on)
3467 -> ht_prev_field(Index,PrevField),
3468 get_dynamic_suspension_term_field(PrevField,C,Susp,Prev,GetGoal),
3469 set_dynamic_suspension_term_field(PrevField,C,NextSusp,_,
3471 set_dynamic_suspension_term_field(PrevField,C,NextSusp,Prev,
3479 delete_first_ht(Store,Key,Values),
3480 ( Values = [NextSusp|_]
3484 ; Prev = [_,_|Values],
3485 setarg(2,Prev,Values),
3486 ( Values = [NextSusp|_]
3495 GetStoreGoal, % nb_getval(StoreName,Store),
3496 delete_ht(Store,Key,Susp)
3499 generate_multi_hash_delete_constraint_bodies(Indexes,FA,Head,Susp,VarDict,Bodies).
3501 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3504 module_initializer/1,
3505 module_initializers/1.
3507 module_initializers(G), module_initializer(Initializer) <=>
3508 G = (Initializer,Initializers),
3509 module_initializers(Initializers).
3511 module_initializers(G) <=>
3514 generate_attach_code(Constraints,Clauses) :-
3515 enumerate_stores_code(Constraints,Enumerate),
3516 append(Enumerate,L,Clauses),
3517 generate_attach_code(Constraints,L,T),
3518 module_initializers(Initializers),
3519 prolog_global_variables_code(PrologGlobalVariables),
3520 % Do not rename or the 'chr_initialization' predicate
3521 % without warning SSS
3522 T = [('$chr_initialization' :- Initializers),(:- initialization '$chr_initialization')|PrologGlobalVariables].
3524 generate_attach_code([],L,L).
3525 generate_attach_code([C|Cs],L,T) :-
3526 get_store_type(C,StoreType),
3527 generate_attach_code(StoreType,C,L,L1),
3528 generate_attach_code(Cs,L1,T).
3530 generate_attach_code(default,C,L,T) :-
3531 global_list_store_initialisation(C,L,T).
3532 generate_attach_code(multi_inthash(Indexes),C,L,T) :-
3533 multi_inthash_store_initialisations(Indexes,C,L,L1),
3534 multi_inthash_via_lookups(Indexes,C,L1,T).
3535 generate_attach_code(multi_hash(Indexes),C,L,T) :-
3536 multi_hash_store_initialisations(Indexes,C,L,L1),
3537 multi_hash_lookups(Indexes,C,L1,T).
3538 generate_attach_code(atomic_constants(Index,Constants,_),C,L,T) :-
3539 constants_initializers(C,Index,Constants),
3540 atomic_constants_code(C,Index,Constants,L,T).
3541 generate_attach_code(ground_constants(Index,Constants,_),C,L,T) :-
3542 constants_initializers(C,Index,Constants),
3543 ground_constants_code(C,Index,Constants,L,T).
3544 generate_attach_code(global_ground,C,L,T) :-
3545 global_ground_store_initialisation(C,L,T).
3546 generate_attach_code(var_assoc_store(_,_),_,L,L) :-
3547 use_auxiliary_module(chr_assoc_store).
3548 generate_attach_code(global_singleton,C,L,T) :-
3549 global_singleton_store_initialisation(C,L,T).
3550 generate_attach_code(multi_store(StoreTypes),C,L,T) :-
3551 multi_store_generate_attach_code(StoreTypes,C,L,T).
3552 generate_attach_code(identifier_store(Index),C,L,T) :-
3553 get_identifier_index(C,Index,IIndex),
3555 get_identifier_size(ISize),
3556 functor(Struct,struct,ISize),
3557 Struct =.. [_,Label|Stores],
3558 set_elems(Stores,[]),
3559 Clause1 = new_identifier(Label,Struct),
3560 functor(Struct2,struct,ISize),
3561 arg(1,Struct2,Label2),
3563 ( user:portray(Struct2) :-
3568 functor(Struct3,struct,ISize),
3569 arg(1,Struct3,Label3),
3570 Clause3 = identifier_label(Struct3,Label3),
3571 L = [Clause1,Clause2,Clause3|T]
3575 generate_attach_code(type_indexed_identifier_store(Index,IndexType),C,L,T) :-
3576 get_type_indexed_identifier_index(IndexType,C,Index,IIndex),
3578 identifier_store_initialization(IndexType,L,L1),
3579 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
3580 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
3581 get_type_indexed_identifier_size(IndexType,ISize),
3582 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
3583 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
3584 type_indexed_identifier_structure(IndexType,Struct),
3585 Struct =.. [_,Label|Stores],
3586 set_elems(Stores,[]),
3587 type_indexed_identifier_name(IndexType,new_identifier,Name1),
3588 Clause1 =.. [Name1,Label,Struct],
3589 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
3590 Goal1 =.. [Name1,Label1b,S1b],
3591 type_indexed_identifier_structure(IndexType,Struct1b),
3592 Struct1b =.. [_,Label1b|Stores1b],
3593 set_elems(Stores1b,[]),
3594 Expansion1 = (S1b = Struct1b),
3595 Clause1b = user:goal_expansion(Goal1,Expansion1),
3596 % writeln(Clause1-Clause1b),
3597 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
3598 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
3599 type_indexed_identifier_structure(IndexType,Struct2),
3600 arg(1,Struct2,Label2),
3602 ( user:portray(Struct2) :-
3607 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
3608 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
3609 type_indexed_identifier_structure(IndexType,Struct3),
3610 arg(1,Struct3,Label3),
3611 type_indexed_identifier_name(IndexType,identifier_label,Name3),
3612 Clause3 =.. [Name3,Struct3,Label3],
3613 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
3614 Goal3b =.. [Name3,S3b,L3b],
3615 type_indexed_identifier_structure(IndexType,Struct3b),
3616 arg(1,Struct3b,L3b),
3617 Expansion3b = (S3 = Struct3b),
3618 Clause3b = ( user:goal_expansion(Goal3b,Expansion3b) :- writeln(expanding)),
3619 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
3620 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
3621 identifier_store_name(IndexType,GlobalVariable),
3622 lookup_identifier_atom(IndexType,X,IX,LookupAtom),
3623 type_indexed_identifier_name(IndexType,new_identifier,NewIdentifierFunctor),
3624 NewIdentifierGoal =.. [NewIdentifierFunctor,X,IX],
3627 nb_getval(GlobalVariable,HT),
3628 ( lookup_ht(HT,X,[IX]) ->
3635 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
3636 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
3637 L1 = [(:- multifile goal_expansion/2),(:- dynamic goal_expansion/2),Clause1,Clause1b,Clause2,Clause3,Clause3b,Clause4|T]
3642 constants_initializers(C,Index,Constants) :-
3643 maplist(constant_initializer(C,Index),Constants).
3645 constant_initializer(C,Index,Constant) :-
3646 constants_store_name(C,Index,Constant,StoreName),
3647 module_initializer(nb_setval(StoreName,[])).
3649 lookup_identifier_atom(Key,X,IX,Atom) :-
3650 atom_concat('lookup_identifier_',Key,LookupFunctor),
3651 Atom =.. [LookupFunctor,X,IX].
3653 identifier_label_atom(IndexType,IX,X,Atom) :-
3654 type_indexed_identifier_name(IndexType,identifier_label,Name),
3655 Atom =.. [Name,IX,X].
3657 multi_store_generate_attach_code([],_,L,L).
3658 multi_store_generate_attach_code([ST|STs],C,L,T) :-
3659 generate_attach_code(ST,C,L,L1),
3660 multi_store_generate_attach_code(STs,C,L1,T).
3662 multi_inthash_store_initialisations([],_,L,L).
3663 multi_inthash_store_initialisations([Index|Indexes],FA,L,T) :-
3664 use_auxiliary_module(chr_integertable_store),
3665 multi_hash_store_name(FA,Index,StoreName),
3666 module_initializer((new_iht(HT),nb_setval(StoreName,HT))),
3667 % L = [(:- (chr_integertable_store:new_ht(HT),nb_setval(StoreName,HT)) )|L1],
3669 multi_inthash_store_initialisations(Indexes,FA,L1,T).
3670 multi_hash_store_initialisations([],_,L,L).
3671 multi_hash_store_initialisations([Index|Indexes],FA,L,T) :-
3672 use_auxiliary_module(chr_hashtable_store),
3673 multi_hash_store_name(FA,Index,StoreName),
3674 prolog_global_variable(StoreName),
3675 make_init_store_goal(StoreName,HT,InitStoreGoal),
3676 module_initializer((new_ht(HT),InitStoreGoal)),
3678 multi_hash_store_initialisations(Indexes,FA,L1,T).
3680 global_list_store_initialisation(C,L,T) :-
3682 global_list_store_name(C,StoreName),
3683 prolog_global_variable(StoreName),
3684 make_init_store_goal(StoreName,[],InitStoreGoal),
3685 module_initializer(InitStoreGoal)
3690 global_ground_store_initialisation(C,L,T) :-
3691 global_ground_store_name(C,StoreName),
3692 prolog_global_variable(StoreName),
3693 make_init_store_goal(StoreName,[],InitStoreGoal),
3694 module_initializer(InitStoreGoal),
3696 global_singleton_store_initialisation(C,L,T) :-
3697 global_singleton_store_name(C,StoreName),
3698 prolog_global_variable(StoreName),
3699 make_init_store_goal(StoreName,[],InitStoreGoal),
3700 module_initializer(InitStoreGoal),
3702 identifier_store_initialization(IndexType,L,T) :-
3703 use_auxiliary_module(chr_hashtable_store),
3704 identifier_store_name(IndexType,StoreName),
3705 prolog_global_variable(StoreName),
3706 make_init_store_goal(StoreName,HT,InitStoreGoal),
3707 module_initializer((new_ht(HT),InitStoreGoal)),
3711 multi_inthash_via_lookups([],_,L,L).
3712 multi_inthash_via_lookups([Index|Indexes],C,L,T) :-
3713 multi_hash_lookup_head(C,Index,Key,SuspsList,Head),
3714 multi_hash_lookup_body(C,inthash,Index,Key,SuspsList,Body),
3715 L = [(Head :- Body)|L1],
3716 multi_inthash_via_lookups(Indexes,C,L1,T).
3717 multi_hash_lookups([],_,L,L).
3718 multi_hash_lookups([Index|Indexes],C,L,T) :-
3719 multi_hash_lookup_head(C,Index,Key,SuspsList,Head),
3720 multi_hash_lookup_body(C,hash,Index,Key,SuspsList,Body),
3721 L = [(Head :- Body)|L1],
3722 multi_hash_lookups(Indexes,C,L1,T).
3724 multi_hash_lookup_head(ConstraintSymbol,Index,Key,SuspsList,Head) :-
3725 multi_hash_lookup_name(ConstraintSymbol,Index,Name),
3726 Head =.. [Name,Key,SuspsList].
3728 %% multi_hash_lookup_body(+ConstraintSymbol,+HashType,+Index,+Key,+SuspsList,-Goal) is det.
3730 % Returns goal that performs hash table lookup.
3731 multi_hash_lookup_body(ConstraintSymbol,HashType,Index,Key,SuspsList,Goal) :-
3733 get_store_type(ConstraintSymbol,multi_store(Stores)),
3734 ( memberchk(atomic_constants(Index,Constants,_),Stores) ->
3736 constants_store_name(ConstraintSymbol,Index,Key,StoreName),
3737 Goal = nb_getval(StoreName,SuspsList)
3739 constants_store_index_name(ConstraintSymbol,Index,IndexName),
3740 Lookup =.. [IndexName,Key,StoreName],
3741 Goal = (Lookup, nb_getval(StoreName,SuspsList))
3743 ; memberchk(ground_constants(Index,Constants,_),Stores) ->
3745 constants_store_name(ConstraintSymbol,Index,Key,StoreName),
3746 Goal = nb_getval(StoreName,SuspsList)
3748 constants_store_index_name(ConstraintSymbol,Index,IndexName),
3749 Lookup =.. [IndexName,Key,StoreName],
3750 Goal = (Lookup, nb_getval(StoreName,SuspsList))
3752 ; memberchk(multi_hash([Index]),Stores) ->
3753 multi_hash_store_name(ConstraintSymbol,Index,StoreName),
3754 make_get_store_goal(StoreName,HT,GetStoreGoal),
3755 ( HashType == hash, specialized_hash_term_call(ConstraintSymbol,Index,Key,Hash,HashCall) ->
3758 GetStoreGoal, % nb_getval(StoreName,HT),
3759 HashCall, % hash_term(Key,Hash),
3760 lookup_ht1(HT,Hash,Key,SuspsList)
3763 lookup_hash_call(HashType,HT,Key,SuspsList,Lookup),
3766 GetStoreGoal, % nb_getval(StoreName,HT),
3770 ; HashType == inthash ->
3771 multi_hash_store_name(ConstraintSymbol,Index,StoreName),
3772 make_get_store_goal(StoreName,HT,GetStoreGoal),
3773 lookup_hash_call(HashType,HT,Key,SuspsList,Lookup),
3776 GetStoreGoal, % nb_getval(StoreName,HT),
3779 % ; % chr_error(internal,'Index ~w for constraint ~w does not exist!\n',[Index,ConstraintSymbol])
3780 % find alternative index
3781 % -> SubIndex + RestIndex
3782 % -> SubKey + RestKeys
3783 % multi_hash_lookup_goal(ConstraintSymbol,HashType,SubIndex,SubKey,SuspsList,SubGoal),
3784 % instantiate rest goal?
3785 % Goal = (SubGoal,RestGoal)
3789 lookup_hash_call(hash,HT,Key,SuspsList,lookup_ht(HT,Key,SuspsList)).
3790 lookup_hash_call(inthash,HT,Key,SuspsList,lookup_iht(HT,Key,SuspsList)).
3792 specialized_hash_term_call(Constraint,Index,Key,Hash,Call) :-
3794 % This is based on a property of SWI-Prolog's
3795 % hash_term/2 predicate:
3796 % the hash value is stable over repeated invocations
3798 hash_term(Key,Hash),
3800 % ; Index = [IndexPos],
3801 % get_constraint_type(Constraint,ArgTypes),
3802 % nth1(IndexPos,ArgTypes,Type),
3803 % unalias_type(Type,NormalType),
3804 % memberchk_eq(NormalType,[int,natural]) ->
3805 % ( NormalType == int ->
3806 % Call = (Hash is abs(Key))
3813 % specialize_hash_term(Key,NewKey),
3815 % Call = hash_term(NewKey,Hash)
3818 % specialize_hash_term(Term,NewTerm) :-
3820 % hash_term(Term,NewTerm)
3824 % Term =.. [F|Args],
3825 % maplist(specialize_hash_term,Args,NewArgs),
3826 % NewTerm =.. [F|NewArgs]
3829 multi_hash_lookup_goal(ConstraintSymbol,HashType,Index,Key,SuspsList,Goal) :-
3830 % format(' * lookup of ~w on ~w with ~w.\n',[ConstraintSymbol,Index,Key]),
3831 ( /* chr_pp_flag(experiment,off) ->
3834 actual_atomic_multi_hash_keys(ConstraintSymbol,Index,[Key])
3836 actual_ground_multi_hash_keys(ConstraintSymbol,Index,[Key])
3839 get_constraint_arg_type(ConstraintSymbol,Pos,Type),
3840 is_chr_constants_type(Type,_,_)
3844 actual_non_ground_multi_hash_key(ConstraintSymbol,Index)
3847 delay_phase_end(validate_store_type_assumptions,
3848 multi_hash_lookup_body(ConstraintSymbol,HashType,Index,Key,SuspsList,Goal)).
3850 :- chr_constraint actual_atomic_multi_hash_keys/3.
3851 :- chr_option(mode,actual_atomic_multi_hash_keys(+,+,?)).
3853 :- chr_constraint actual_ground_multi_hash_keys/3.
3854 :- chr_option(mode,actual_ground_multi_hash_keys(+,+,?)).
3856 :- chr_constraint actual_non_ground_multi_hash_key/2.
3857 :- chr_option(mode,actual_non_ground_multi_hash_key(+,+)).
3860 actual_atomic_multi_hash_keys(C,Index,Keys)
3861 ==> format('Keys: ~w - ~w : ~w\n', [C,Index,Keys]).
3863 actual_ground_multi_hash_keys(C,Index,Keys)
3864 ==> format('Keys: ~w - ~w : ~w\n', [C,Index,Keys]).
3866 actual_non_ground_multi_hash_key(C,Index)
3867 ==> format('Keys: ~w - ~w : N/A\n', [C,Index]).
3869 actual_atomic_multi_hash_keys(C,Index,Keys1), actual_atomic_multi_hash_keys(C,Index,Keys2)
3870 <=> append(Keys1,Keys2,Keys0),
3872 actual_atomic_multi_hash_keys(C,Index,Keys).
3874 actual_ground_multi_hash_keys(C,Index,Keys1), actual_atomic_multi_hash_keys(C,Index,Keys2)
3875 <=> append(Keys1,Keys2,Keys0),
3877 actual_ground_multi_hash_keys(C,Index,Keys).
3879 actual_ground_multi_hash_keys(C,Index,Keys1), actual_ground_multi_hash_keys(C,Index,Keys2)
3880 <=> append(Keys1,Keys2,Keys0),
3882 actual_ground_multi_hash_keys(C,Index,Keys).
3884 actual_non_ground_multi_hash_key(C,Index) \ actual_non_ground_multi_hash_key(C,Index)
3887 actual_non_ground_multi_hash_key(C,Index) \ actual_atomic_multi_hash_keys(C,Index,_)
3890 actual_non_ground_multi_hash_key(C,Index) \ actual_ground_multi_hash_keys(C,Index,_)
3893 %% multi_hash_lookup_name(+ConstraintSymbol,+Index,-Name)
3895 % Returns predicate name of hash table lookup predicate.
3896 multi_hash_lookup_name(F/A,Index,Name) :-
3897 atom_concat_list(Index,IndexName),
3898 atom_concat_list(['$via1_multi_hash_',F,'___',A,'-',IndexName],Name).
3900 multi_hash_store_name(F/A,Index,Name) :-
3901 get_target_module(Mod),
3902 atom_concat_list(Index,IndexName),
3903 atom_concat_list(['$chr_store_multi_hash_',Mod,'____',F,'___',A,'-',IndexName],Name).
3905 multi_hash_key(FA,Index,Susp,KeyBody,Key) :-
3907 get_dynamic_suspension_term_field(argument(I),FA,Susp,Key,KeyBody)
3909 maplist(get_dynamic_suspension_term_field1(FA,Susp),Index,Keys,Bodies),
3911 list2conj(Bodies,KeyBody)
3914 get_dynamic_suspension_term_field1(FA,Susp,I,KeyI,Goal) :-
3915 get_dynamic_suspension_term_field(argument(I),FA,Susp,KeyI,Goal).
3917 multi_hash_key(C,Head,Index,Susp,VarDict,KeyBody,Key) :-
3919 get_suspension_argument_possibly_in_scope(Head,VarDict,Susp,I,Key,KeyBody)
3921 maplist(get_suspension_argument_possibly_in_scope(Head,VarDict,Susp),Index,Keys,Bodies),
3923 list2conj(Bodies,KeyBody)
3926 get_suspension_argument_possibly_in_scope(Head,VarDict,Susp,Index,Arg,Goal) :-
3927 arg(Index,Head,OriginalArg),
3928 ( term_variables(OriginalArg,OriginalVars),
3929 copy_term_nat(OriginalArg-OriginalVars,Arg-Vars),
3930 translate(OriginalVars,VarDict,Vars) ->
3935 get_dynamic_suspension_term_field(argument(Index),C,Susp,Arg,Goal)
3938 multi_hash_key_direct(FA,Index,Susp,Key,UsedVars) :-
3942 pairup(Index,Keys,UsedVars),
3946 args(Index,Head,KeyArgs) :-
3947 maplist(arg1(Head),Index,KeyArgs).
3949 split_args(Indexes,Args,IArgs,NIArgs) :-
3950 split_args(Indexes,Args,1,IArgs,NIArgs).
3952 split_args([],Args,_,[],Args).
3953 split_args([I|Is],[Arg|Args],J,IArgs,NIArgs) :-
3957 split_args(Is,Args,NJ,Rest,NIArgs)
3959 NIArgs = [Arg|Rest],
3960 split_args([I|Is],Args,NJ,IArgs,Rest)
3964 %-------------------------------------------------------------------------------
3965 atomic_constants_code(C,Index,Constants,L,T) :-
3966 constants_store_index_name(C,Index,IndexName),
3967 maplist(atomic_constant_code(C,Index,IndexName),Constants,Clauses),
3968 append(Clauses,T,L).
3970 atomic_constant_code(C,Index,IndexName,Constant,Clause) :-
3971 constants_store_name(C,Index,Constant,StoreName),
3972 Clause =.. [IndexName,Constant,StoreName].
3974 %-------------------------------------------------------------------------------
3975 ground_constants_code(C,Index,Terms,L,T) :-
3976 constants_store_index_name(C,Index,IndexName),
3977 maplist(constants_store_name(C,Index),Terms,StoreNames),
3979 replicate(N,[],More),
3980 trie_index([Terms|More],StoreNames,IndexName,L,T).
3982 constants_store_name(F/A,Index,Term,Name) :-
3983 get_target_module(Mod),
3984 term_to_atom(Term,Constant),
3985 term_to_atom(Index,IndexAtom),
3986 atom_concat_list(['$chr_store_constants_',Mod,'____',F,'___',A,'___',IndexAtom,'___',Constant],Name).
3988 constants_store_index_name(F/A,Index,Name) :-
3989 get_target_module(Mod),
3990 term_to_atom(Index,IndexAtom),
3991 atom_concat_list(['$chr_store_constants_',Mod,'____',F,'___',A,'___',IndexAtom],Name).
3993 % trie index code {{{
3994 trie_index([Patterns|MorePatterns],Results,Prefix,Clauses,Tail) :-
3995 trie_step(Patterns,Prefix,Prefix,MorePatterns,Results,Clauses,Tail).
3997 trie_step([],_,_,[],[],L,L) :- !.
3998 % length MorePatterns == length Patterns == length Results
3999 trie_step(Patterns,Symbol,Prefix,MorePatterns,Results,Clauses,T) :-
4000 MorePatterns = [List|_],
4002 aggregate_all(set(F/A),
4003 ( member(Pattern,Patterns),
4004 functor(Pattern,F,A)
4008 trie_step_cases(FAs,N1,Patterns,MorePatterns,Results,Symbol,Prefix,Clauses,T).
4010 trie_step_cases([],_,_,_,_,_,_,Clauses,Clauses).
4011 trie_step_cases([FA|FAs],N,Pattern,MorePatterns,Results,Symbol,Prefix,Clauses,Tail) :-
4012 trie_step_case(FA,N,Pattern,MorePatterns,Results,Symbol,Prefix,Clauses,Clauses1),
4013 trie_step_cases(FAs,N,Pattern,MorePatterns,Results,Symbol,Prefix,Clauses1,Tail).
4015 trie_step_case(F/A,N,Patterns,MorePatterns,Results,Symbol,Prefix,[Clause|List],Tail) :-
4016 Clause = (Head :- Body),
4017 /* Head = Symbol(IndexPattern,V2,...,Vn,Result) */
4019 functor(Head,Symbol,N1),
4020 arg(1,Head,IndexPattern),
4021 Head =.. [_,_|RestArgs],
4022 once(append(Vs,[Result],RestArgs)),
4023 /* IndexPattern = F() */
4024 functor(IndexPattern,F,A),
4025 IndexPattern =.. [_|Args],
4026 append(Args,RestArgs,RecArgs),
4027 ( RecArgs == [Result] ->
4028 /* nothing more to match on */
4031 rec_cases(Patterns,_,Results,F/A,_,_,MoreResults),
4032 MoreResults = [Result]
4033 ; /* more things to match on */
4034 rec_cases(Patterns,MorePatterns,Results,F/A,Cases,MoreCases,MoreResults),
4035 ( MoreCases = [OneMoreCase] ->
4036 /* only one more thing to match on */
4039 append([Cases,OneMoreCase,MoreResults],RecArgs)
4041 /* more than one thing to match on */
4045 pairup(Cases,MoreCases,CasePairs),
4046 common_pattern(CasePairs,CommonPatternPair,DiffVars,Differences),
4047 append(Args,Vs,[First|Rest]),
4048 First-Rest = CommonPatternPair,
4049 % Body = RSymbol(DiffVars,Result)
4050 gensym(Prefix,RSymbol),
4051 append(DiffVars,[Result],RecCallVars),
4052 Body =.. [RSymbol|RecCallVars],
4053 maplist(head_tail,Differences,CHs,CTs),
4054 trie_step(CHs,RSymbol,Prefix,CTs,MoreResults,List,Tail)
4058 head_tail([H|T],H,T).
4060 rec_cases([],[],[],_,[],[],[]).
4061 rec_cases([Pattern|Patterns],[MorePattern|MorePatterns],[Result|Results],F/A,Cases,MoreCases,MoreResults) :-
4062 ( functor(Pattern,F,A), Pattern =.. [_|ArgPatterns], append(ArgPatterns,MorePattern,[Case|MoreCase]) ->
4063 Cases = [Case|NCases],
4064 MoreCases = [MoreCase|NMoreCases],
4065 MoreResults = [Result|NMoreResults],
4066 rec_cases(Patterns,MorePatterns,Results,F/A,NCases,NMoreCases,NMoreResults)
4068 rec_cases(Patterns,MorePatterns,Results,F/A,Cases,MoreCases,MoreResults)
4072 %% common_pattern(+terms,-term,-vars,-differences) is det.
4073 common_pattern(Ts,T,Vars,Differences) :-
4075 term_variables(T,Vars),
4076 findall(Vars,member(T,Ts),Differences).
4081 gct_(T1,T2,T,Dict0,Dict) :-
4092 maplist_dcg(gct_,Args1,Args2,Args,Dict0,Dict)
4094 /* T is a variable */
4095 ( lookup_eq(Dict0,T1+T2,T) ->
4096 /* we already have a variable for this difference */
4099 /* T is a fresh variable */
4100 Dict = [(T1+T2)-T|Dict0]
4105 fold1(P,[Head|Tail],Result) :-
4106 fold(Tail,P,Head,Result).
4109 fold([X|Xs],P,Acc,Res) :-
4111 fold(Xs,P,NAcc,Res).
4113 maplist_dcg(P,L1,L2,L) -->
4114 maplist_dcg_(L1,L2,L,P).
4116 maplist_dcg_([],[],[],_) --> [].
4117 maplist_dcg_([X|Xs],[Y|Ys],[Z|Zs],P) -->
4119 maplist_dcg_(Xs,Ys,Zs,P).
4121 %-------------------------------------------------------------------------------
4122 global_list_store_name(F/A,Name) :-
4123 get_target_module(Mod),
4124 atom_concat_list(['$chr_store_global_list_',Mod,'____',F,'___',A],Name).
4125 global_ground_store_name(F/A,Name) :-
4126 get_target_module(Mod),
4127 atom_concat_list(['$chr_store_global_ground_',Mod,'____',F,'___',A],Name).
4128 global_singleton_store_name(F/A,Name) :-
4129 get_target_module(Mod),
4130 atom_concat_list(['$chr_store_global_singleton_',Mod,'____',F,'___',A],Name).
4132 identifier_store_name(TypeName,Name) :-
4133 get_target_module(Mod),
4134 atom_concat_list(['$chr_identifier_lookup_',Mod,'____',TypeName],Name).
4136 :- chr_constraint prolog_global_variable/1.
4137 :- chr_option(mode,prolog_global_variable(+)).
4139 :- chr_constraint prolog_global_variables/1.
4140 :- chr_option(mode,prolog_global_variables(-)).
4142 prolog_global_variable(Name) \ prolog_global_variable(Name) <=> true.
4144 prolog_global_variables(List), prolog_global_variable(Name) <=>
4146 prolog_global_variables(Tail).
4147 prolog_global_variables(List) <=> List = [].
4150 prolog_global_variables_code(Code) :-
4151 prolog_global_variables(Names),
4155 maplist(wrap_in_functor('$chr_prolog_global_variable'),Names,NameDeclarations),
4156 Code = [(:- dynamic user:exception/3),
4157 (:- multifile user:exception/3),
4158 (user:exception(undefined_global_variable,Name,retry) :-
4160 '$chr_prolog_global_variable'(Name),
4161 '$chr_initialization'
4170 % prolog_global_variables_code([]).
4172 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4173 %sbag_member_call(S,L,sysh:mem(S,L)).
4174 sbag_member_call(S,L,'chr sbag_member'(S,L)).
4175 %sbag_member_call(S,L,member(S,L)).
4176 update_mutable_call(A,B,'chr update_mutable'( A, B)).
4177 %update_mutable_call(A,B,setarg(1, B, A)).
4178 create_mutable_call(Value,Mutable,true) :- Mutable = mutable(Value).
4179 % create_mutable_call(Value,Mutable,'chr create_mutable'(Value,Mutable)).
4181 % get_suspension_field(Constraint,Susp,FieldName,Value,(Get0,Get1)) :-
4182 % get_dynamic_suspension_term_field(FieldName,Constraint,Susp,Field,Get0),
4183 % create_get_mutable(Value,Field,Get1).
4185 % update_suspension_field(Constraint,Susp,FieldName,NewValue,(Get,Set)) :-
4186 % get_dynamic_suspension_term_field(FieldName,Constraint,Susp,Field,Get),
4187 % update_mutable_call(NewValue,Field,Set).
4189 % get_update_suspension_field(Constraint,Susp,FieldName,Value,NewValue,Get0,Get1,Set) :-
4190 % get_dynamic_suspension_term_field(FieldName,Constraint,Susp,Field,Get0),
4191 % create_get_mutable_ref(Value,Field,Get1),
4192 % update_mutable_call(NewValue,Field,Set).
4194 % create_static_suspension_field(Constraint,Susp,FieldName,Value,Create) :-
4195 % get_static_suspension_term_field(FieldName,Constraint,Susp,Field),
4196 % create_mutable_call(Value,Field,Create).
4198 % get_static_suspension_field(Constraint,Susp,FieldName,Value,Get) :-
4199 % get_static_suspension_term_field(FieldName,Constraint,Susp,Field),
4200 % create_get_mutable(Value,Field,Get).
4202 % get_update_static_suspension_field(Constraint,Susp,SuspTerm,FieldName,Value,NewValue,Get,Set) :-
4203 % get_static_suspension_term_field(FieldName,Constraint,SuspTerm,Field),
4204 % create_get_mutable_ref(Value,Field,Get),
4205 % update_mutable_call(NewValue,Field,Set).
4207 get_suspension_field(Constraint,Susp,FieldName,Value,Get) :-
4208 get_dynamic_suspension_term_field(FieldName,Constraint,Susp,Value,Get).
4210 update_suspension_field(Constraint,Susp,FieldName,NewValue,Set) :-
4211 set_dynamic_suspension_term_field(FieldName,Constraint,Susp,NewValue,Set).
4213 get_update_suspension_field(Constraint,Susp,FieldName,Value,NewValue,true,Get,Set) :-
4214 get_dynamic_suspension_term_field(FieldName,Constraint,Susp,Value,Get),
4215 set_dynamic_suspension_term_field(FieldName,Constraint,Susp,NewValue,Set).
4217 create_static_suspension_field(Constraint,Susp,FieldName,Value,true) :-
4218 get_static_suspension_term_field(FieldName,Constraint,Susp,Value).
4220 get_static_suspension_field(Constraint,Susp,FieldName,Value,true) :-
4221 get_static_suspension_term_field(FieldName,Constraint,Susp,Value).
4223 get_update_static_suspension_field(Constraint,Susp,SuspTerm,FieldName,Value,NewValue,true,Set) :-
4224 get_static_suspension_term_field(FieldName,Constraint,SuspTerm,Value),
4225 set_dynamic_suspension_term_field(FieldName,Constraint,Susp,NewValue,Set).
4227 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4229 enumerate_stores_code(Constraints,[Clause|List]) :-
4230 Head = '$enumerate_constraints'(Constraint),
4231 Clause = ( Head :- Body),
4232 enumerate_store_bodies(Constraints,Constraint,List),
4236 Body = ( nonvar(Constraint) ->
4237 functor(Constraint,Functor,_),
4238 '$enumerate_constraints'(Functor,Constraint)
4240 '$enumerate_constraints'(_,Constraint)
4244 enumerate_store_bodies([],_,[]).
4245 enumerate_store_bodies([C|Cs],Constraint,L) :-
4247 get_store_type(C,StoreType),
4248 ( enumerate_store_body(StoreType,C,Suspension,SuspensionBody) ->
4251 chr_error(internal,'Could not generate enumeration code for constraint ~w.\n',[C])
4253 get_dynamic_suspension_term_field(arguments,C,Suspension,Arguments,DynamicGoal),
4255 Constraint0 =.. [F|Arguments],
4256 Head = '$enumerate_constraints'(F,Constraint),
4257 Body = (SuspensionBody, DynamicGoal, Constraint = Constraint0),
4258 L = [(Head :- Body)|T]
4262 enumerate_store_bodies(Cs,Constraint,T).
4264 enumerate_store_body(default,C,Susp,Body) :-
4265 global_list_store_name(C,StoreName),
4266 sbag_member_call(Susp,List,Sbag),
4267 make_get_store_goal(StoreName,List,GetStoreGoal),
4270 GetStoreGoal, % nb_getval(StoreName,List),
4273 % get_constraint_index(C,Index),
4274 % get_target_module(Mod),
4275 % get_max_constraint_index(MaxIndex),
4278 % 'chr default_store'(GlobalStore),
4279 % get_attr(GlobalStore,Mod,Attr)
4282 % NIndex is Index + 1,
4283 % sbag_member_call(Susp,List,Sbag),
4286 % arg(NIndex,Attr,List),
4290 % sbag_member_call(Susp,Attr,Sbag),
4293 % Body = (Body1,Body2).
4294 enumerate_store_body(multi_inthash([Index|_]),C,Susp,Body) :-
4295 multi_inthash_enumerate_store_body(Index,C,Susp,Body).
4296 enumerate_store_body(multi_hash([Index|_]),C,Susp,Body) :-
4297 multi_hash_enumerate_store_body(Index,C,Susp,Body).
4298 enumerate_store_body(atomic_constants(Index,Constants,Completeness),C,Susp,Body) :-
4299 Completeness == complete, % fail if incomplete
4300 maplist(enumerate_constant_store_body(C,Index,Susps),Constants,Disjuncts),
4301 list2disj(Disjuncts, Disjunction),
4302 Body = ( Disjunction, member(Susp,Susps) ).
4303 enumerate_constant_store_body(C,Index,Susps,Constant,nb_getval(StoreName,Susps)) :-
4304 constants_store_name(C,Index,Constant,StoreName).
4306 enumerate_store_body(ground_constants(Index,Constants,Completeness),C,Susp,Body) :-
4307 enumerate_store_body(atomic_constants(Index,Constants,Completeness),C,Susp,Body).
4308 enumerate_store_body(global_ground,C,Susp,Body) :-
4309 global_ground_store_name(C,StoreName),
4310 sbag_member_call(Susp,List,Sbag),
4311 make_get_store_goal(StoreName,List,GetStoreGoal),
4314 GetStoreGoal, % nb_getval(StoreName,List),
4317 enumerate_store_body(var_assoc_store(_,_),C,_,Body) :-
4319 enumerate_store_body(global_singleton,C,Susp,Body) :-
4320 global_singleton_store_name(C,StoreName),
4321 make_get_store_goal(StoreName,Susp,GetStoreGoal),
4324 GetStoreGoal, % nb_getval(StoreName,Susp),
4327 enumerate_store_body(multi_store(STs),C,Susp,Body) :-
4328 ( memberchk(global_ground,STs) ->
4329 enumerate_store_body(global_ground,C,Susp,Body)
4333 enumerate_store_body(ST,C,Susp,Body)
4336 enumerate_store_body(identifier_store(Index),C,Susp,Body) :-
4338 enumerate_store_body(type_indexed_identifier_store(Index,IndexType),C,Susp,Body) :-
4341 multi_inthash_enumerate_store_body(I,C,Susp,B) :-
4342 multi_hash_store_name(C,I,StoreName),
4345 nb_getval(StoreName,HT),
4348 multi_hash_enumerate_store_body(I,C,Susp,B) :-
4349 multi_hash_store_name(C,I,StoreName),
4350 make_get_store_goal(StoreName,HT,GetStoreGoal),
4353 GetStoreGoal, % nb_getval(StoreName,HT),
4357 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4358 % BACKGROUND INFORMATION (declared using :- chr_declaration)
4359 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4366 get_bg_info_answer/1.
4368 background_info(X), background_info(Y) <=>
4369 append(X,Y,XY), background_info(XY).
4370 background_info(X) \ get_bg_info(Q) <=> Q=X.
4371 get_bg_info(Q) <=> Q = [].
4373 background_info(T,I), get_bg_info(A,Q) ==>
4374 copy_term_nat(T,T1),
4377 copy_term_nat(T-I,A-X),
4378 get_bg_info_answer([X]).
4379 get_bg_info_answer(X), get_bg_info_answer(Y) <=>
4380 append(X,Y,XY), get_bg_info_answer(XY).
4382 get_bg_info_answer(X) # Id, get_bg_info(A,Q) <=> Q=X pragma passive(Id).
4383 get_bg_info(_,Q) <=> Q=[]. % no info found on this term
4385 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4394 :- chr_option(mode,prev_guard_list(+,+,+,+,+,+,+,+)).
4395 :- chr_option(mode,prev_guard_list(+,+,+,+,+,+)).
4396 :- chr_option(type_declaration,prev_guard_list(any,any,any,any,any,list)).
4397 :- chr_option(mode,simplify_guards(+)).
4398 :- chr_option(mode,set_all_passive(+)).
4400 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4401 % GUARD SIMPLIFICATION
4402 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4403 % If the negation of the guards of earlier rules entails (part of)
4404 % the current guard, the current guard can be simplified. We can only
4405 % use earlier rules with a head that matches if the head of the current
4406 % rule does, and which make it impossible for the current rule to match
4407 % if they fire (i.e. they shouldn't be propagation rules and their
4408 % head constraints must be subsets of those of the current rule).
4409 % At this point, we know for sure that the negation of the guard
4410 % of such a rule has to be true (otherwise the earlier rule would have
4411 % fired, because of the refined operational semantics), so we can use
4412 % that information to simplify the guard by replacing all entailed
4413 % conditions by true/0. As a consequence, the never-stored analysis
4414 % (in a further phase) will detect more cases of never-stored constraints.
4416 % e.g. c(X),d(Y) <=> X > 0 | ...
4417 % e(X) <=> X < 0 | ...
4418 % c(X) \ d(Y),e(Z) <=> X =< 0, Z >= 0, ... | ...
4422 guard_simplification :-
4423 ( chr_pp_flag(guard_simplification,on) ->
4424 precompute_head_matchings,
4430 % for every rule, we create a prev_guard_list where the last argument
4431 % eventually is a list of the negations of earlier guards
4432 rule(RuleNb,Rule) \ simplify_guards(RuleNb)
4434 Rule = pragma(rule(Head1,Head2,Guard,_B),ids(IDs1,IDs2),_Pragmas,_Name,RuleNb),
4435 append(Head1,Head2,Heads),
4436 make_head_matchings_explicit_not_negated(Heads,MatchingFreeHeads,Matchings),
4437 tree_set_empty(Done),
4438 multiple_occ_constraints_checked(Done),
4439 apply_guard_wrt_term(Heads,Guard,SubstitutedHeads),
4441 append(IDs1,IDs2,IDs),
4442 findall(tuple(C,O,RuleNb)-(-RuleNb),(member(ID,IDs),get_occurrence_from_id(C,O,RuleNb,ID)),HeapData),
4444 insert_list_q(HeapData,EmptyHeap,Heap),
4445 next_prev_rule(Heap,_,Heap1),
4446 next_prev_rule(Heap1,PrevRuleNb,NHeap),
4447 prev_guard_list(RuleNb,PrevRuleNb,NHeap,MatchingFreeHeads,Guard,[],Matchings,[SubstitutedHeads]),
4448 NextRule is RuleNb+1,
4449 simplify_guards(NextRule).
4451 next_prev_rule(Heap,RuleNb,NHeap) :-
4452 ( find_min_q(Heap,_-Priority) ->
4453 Priority = (-RuleNb),
4454 normalize_heap(Heap,Priority,NHeap)
4460 normalize_heap(Heap,Priority,NHeap) :-
4461 ( find_min_q(Heap,_-Priority) ->
4462 delete_min_q(Heap,Heap1,tuple(C,O,_)-_),
4465 get_occurrence(C,NO,RuleNb,_),
4466 insert_q(Heap1,tuple(C,NO,RuleNb)-(-RuleNb),Heap2)
4470 normalize_heap(Heap2,Priority,NHeap)
4480 % The negation of the guard of a non-propagation rule is added
4481 % if its kept head constraints are a subset of the kept constraints of
4482 % the rule we're working on, and its removed head constraints (at least one)
4483 % are a subset of the removed constraints.
4485 rule(PrevRuleNb,PrevRule) \ prev_guard_list(RuleNb,PrevRuleNb,Heap,CurrentHeads,G,GuardList,Matchings,GH)
4487 PrevRule = pragma(rule(H1,H2,PrevGuard,_B),_Ids,_Pragmas,_Name,_PrevRuleNb), % PrevRuleNb == _PrevRuleNb
4489 make_head_matchings_explicit(PrevRuleNb,MatchingFreeHeads,PrevMatchings),
4490 setof(Renaming,chr_translate:head_subset(MatchingFreeHeads,CurrentHeads,Renaming),Renamings)
4492 append(H1,H2,Heads),
4493 compute_derived_info(Renamings,PrevMatchings,MatchingFreeHeads,Heads,PrevGuard,Matchings,CurrentHeads,GH,DerivedInfo,GH_New1),
4494 append(GuardList,DerivedInfo,GL1),
4495 normalize_conj_list(GL1,GL),
4496 append(GH_New1,GH,GH1),
4497 normalize_conj_list(GH1,GH_New),
4498 next_prev_rule(Heap,PrevPrevRuleNb,NHeap),
4499 % PrevPrevRuleNb is PrevRuleNb-1,
4500 prev_guard_list(RuleNb,PrevPrevRuleNb,NHeap,CurrentHeads,G,GL,Matchings,GH_New).
4502 % if this isn't the case, we skip this one and try the next rule
4503 prev_guard_list(RuleNb,N,Heap,H,G,GuardList,M,GH)
4506 next_prev_rule(Heap,N1,NHeap),
4508 prev_guard_list(RuleNb,N1,NHeap,H,G,GuardList,M,GH)
4510 prev_guard_list(RuleNb,H,G,GuardList,M,GH)
4513 prev_guard_list(RuleNb,H,G,GuardList,M,GH)
4517 head_types_modes_condition(GH,H,TypeInfo),
4518 conj2list(TypeInfo,TI),
4519 term_variables(H,HeadVars),
4520 append([chr_pp_headvariables(HeadVars)|TI],GuardList,Info),
4521 normalize_conj_list(Info,InfoL),
4522 append(H,InfoL,RelevantTerms),
4523 add_background_info([G|RelevantTerms],BGInfo),
4524 append(InfoL,BGInfo,AllInfo_),
4525 normalize_conj_list(AllInfo_,AllInfo),
4526 prev_guard_list(RuleNb,H,G,AllInfo,M,[]).
4528 head_types_modes_condition([],H,true).
4529 head_types_modes_condition([GH|GHs],H,(TI1, TI2)) :-
4530 types_modes_condition(H,GH,TI1),
4531 head_types_modes_condition(GHs,H,TI2).
4533 add_background_info(Term,Info) :-
4534 get_bg_info(GeneralInfo),
4535 add_background_info2(Term,TermInfo),
4536 append(GeneralInfo,TermInfo,Info).
4538 add_background_info2(X,[]) :- var(X), !.
4539 add_background_info2([],[]) :- !.
4540 add_background_info2([X|Xs],Info) :- !,
4541 add_background_info2(X,Info1),
4542 add_background_info2(Xs,Infos),
4543 append(Info1,Infos,Info).
4545 add_background_info2(X,Info) :-
4546 (functor(X,_,A), A>0 ->
4548 add_background_info2(XArgs,XArgInfo)
4552 get_bg_info(X,XInfo),
4553 append(XInfo,XArgInfo,Info).
4556 % when all earlier guards are added or skipped, we simplify the guard.
4557 % if it's different from the original one, we change the rule
4559 prev_guard_list(RuleNb,H,G,GuardList,M,[]), rule(RuleNb,Rule)
4561 Rule = pragma(rule(Head1,Head2,G,B),Ids,Pragmas,Name,RuleNb),
4562 G \== true, % let's not try to simplify this ;)
4563 append(M,GuardList,Info),
4564 (% if guard + context is a contradiction, it should be simplified to "fail"
4565 conj2list(G,GL), append(Info,GL,GuardWithContext),
4566 guard_entailment:entails_guard(GuardWithContext,fail) ->
4569 % otherwise we try to remove redundant conjuncts
4570 simplify_guard(G,B,Info,SimpleGuard,NB)
4572 G \== SimpleGuard % only do this if we can change the guard
4574 rule(RuleNb,pragma(rule(Head1,Head2,SimpleGuard,NB),Ids,Pragmas,Name,RuleNb)),
4575 prev_guard_list(RuleNb,H,SimpleGuard,GuardList,M,[]).
4577 %% normalize_conj_list(+List,-NormalList) is det.
4579 % Removes =true= elements and flattens out conjunctions.
4581 normalize_conj_list(List,NormalList) :-
4582 list2conj(List,Conj),
4583 conj2list(Conj,NormalList).
4585 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4586 % AUXILIARY PREDICATES (GUARD SIMPLIFICATION)
4587 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4589 compute_derived_info([],_PrevMatchings,_MatchingFreeHeads,_Heads,_PrevGuard,_Matchings,_H,_GH,[],[]).
4590 compute_derived_info([Renaming1|RestRenamings],PrevMatchings,PrevMatchingFreeHeads,PrevHeads,PrevGuard,Matchings,H,GH,[DerivedInfo1|DerivedInfo2],[GH3|GH_New2]) :-
4591 copy_term(PrevMatchings-PrevGuard,FreshMatchings),
4592 variable_replacement(PrevMatchings-PrevGuard,FreshMatchings,ExtraRenaming),
4593 append(Renaming1,ExtraRenaming,Renaming2),
4594 list2conj(PrevMatchings,Match),
4595 negate_b(Match,HeadsDontMatch),
4596 make_head_matchings_explicit_not_negated2(PrevHeads,PrevMatchingFreeHeads,HeadsMatch),
4597 list2conj(HeadsMatch,HeadsMatchBut),
4598 term_variables(Renaming2,RenVars),
4599 term_variables(PrevMatchings-PrevGuard-HeadsMatch,MGVars),
4600 new_vars(MGVars,RenVars,ExtraRenaming2),
4601 append(Renaming2,ExtraRenaming2,Renaming),
4602 ( PrevGuard == true -> % true can't fail
4603 Info_ = HeadsDontMatch
4605 negate_b(PrevGuard,TheGuardFailed),
4606 Info_ = (HeadsDontMatch ; (HeadsMatchBut, TheGuardFailed))
4608 copy_with_variable_replacement(Info_,DerivedInfo1,Renaming),
4609 copy_with_variable_replacement(PrevGuard,RenamedG2,Renaming),
4610 copy_with_variable_replacement(PrevMatchings,RenamedMatchings_,Renaming),
4611 list2conj(RenamedMatchings_,RenamedMatchings),
4612 apply_guard_wrt_term(H,RenamedG2,GH2),
4613 apply_guard_wrt_term(GH2,RenamedMatchings,GH3),
4614 compute_derived_info(RestRenamings,PrevMatchings,PrevMatchingFreeHeads,PrevHeads,PrevGuard,Matchings,H,GH,DerivedInfo2,GH_New2).
4616 simplify_guard(G,B,Info,SG,NB) :-
4618 % writeq(guard_entailment:simplify_guards(Info,B,LG,SGL,NB)),nl,
4619 guard_entailment:simplify_guards(Info,B,LG,SGL,NB),
4624 new_vars([A|As],RV,ER) :-
4625 ( memberchk_eq(A,RV) ->
4628 ER = [A-NewA,NewA-A|ER2],
4632 %% head_subset(+Subset,+MultiSet,-Renaming) is nondet.
4634 % check if a list of constraints is a subset of another list of constraints
4635 % (multiset-subset), meanwhile computing a variable renaming to convert
4636 % one into the other.
4637 head_subset(H,Head,Renaming) :-
4638 head_subset(H,Head,Renaming,[],_).
4640 head_subset([],Remainder,Renaming,Renaming,Remainder).
4641 head_subset([X|Xs],MultiSet,Renaming,Acc,Remainder) :-
4642 head_member(MultiSet,X,NAcc,Acc,Remainder1),
4643 head_subset(Xs,Remainder1,Renaming,NAcc,Remainder).
4645 % check if A is in the list, remove it from Headleft
4646 head_member([X|Xs],A,Renaming,Acc,Remainder) :-
4647 ( variable_replacement(A,X,Acc,Renaming),
4650 Remainder = [X|RRemainder],
4651 head_member(Xs,A,Renaming,Acc,RRemainder)
4653 %-------------------------------------------------------------------------------%
4654 % memoing code to speed up repeated computation
4656 :- chr_constraint precompute_head_matchings/0.
4658 rule(RuleNb,PragmaRule), precompute_head_matchings ==>
4659 PragmaRule = pragma(rule(H1,H2,_G,_B),_Ids,_Pragmas,_Name,_PrevRuleNb),
4660 append(H1,H2,Heads),
4661 make_head_matchings_explicit_(Heads,MatchingFreeHeads,Matchings),
4662 copy_term_nat(MatchingFreeHeads-Matchings,A-B),
4663 make_head_matchings_explicit_memo_table(RuleNb,A,B).
4665 precompute_head_matchings <=> true.
4667 :- chr_constraint make_head_matchings_explicit_memo_table/3.
4668 :- chr_constraint make_head_matchings_explicit_memo_lookup/3.
4670 :- chr_option(mode,make_head_matchings_explicit_memo_table(+,?,?)).
4671 :- chr_option(mode,make_head_matchings_explicit_memo_lookup(+,?,?)).
4673 make_head_matchings_explicit_memo_table(RuleNb,NHeads,Matchings) \
4674 make_head_matchings_explicit_memo_lookup(RuleNb,Q1,Q2)
4678 make_head_matchings_explicit_memo_lookup(_,_,_) <=> fail.
4680 make_head_matchings_explicit(RuleNb,MatchingFreeHeads,Matchings) :-
4681 make_head_matchings_explicit_memo_lookup(RuleNb,A,B),
4682 copy_term_nat(A-B,MatchingFreeHeads-Matchings).
4683 %-------------------------------------------------------------------------------%
4685 make_head_matchings_explicit_(Heads,MatchingFreeHeads,Matchings) :-
4686 extract_arguments(Heads,Arguments),
4687 make_matchings_explicit(Arguments,FreeVariables,[],[],_,Matchings),
4688 substitute_arguments(Heads,FreeVariables,MatchingFreeHeads).
4690 make_head_matchings_explicit_not_negated(Heads,MatchingFreeHeads,Matchings) :-
4691 extract_arguments(Heads,Arguments),
4692 make_matchings_explicit_not_negated(Arguments,FreshVariables,Matchings),
4693 substitute_arguments(Heads,FreshVariables,MatchingFreeHeads).
4695 make_head_matchings_explicit_not_negated2(Heads,MatchingFreeHeads,Matchings) :-
4696 extract_arguments(Heads,Arguments1),
4697 extract_arguments(MatchingFreeHeads,Arguments2),
4698 make_matchings_explicit_not_negated(Arguments1,Arguments2,Matchings).
4700 %% extract_arguments(+ListOfConstraints,-ListOfVariables) is det.
4702 % Returns list of arguments of given list of constraints.
4703 extract_arguments([],[]).
4704 extract_arguments([Constraint|Constraints],AllArguments) :-
4705 Constraint =.. [_|Arguments],
4706 append(Arguments,RestArguments,AllArguments),
4707 extract_arguments(Constraints,RestArguments).
4709 %% substitute_arguments(+InListOfConstraints,ListOfVariables,-OutListOfConstraints) is det.
4711 % Substitutes arguments of constraints with those in the given list.
4713 substitute_arguments([],[],[]).
4714 substitute_arguments([Constraint|Constraints],Variables,[NConstraint|NConstraints]) :-
4715 functor(Constraint,F,N),
4716 split_at(N,Variables,Arguments,RestVariables),
4717 NConstraint =.. [F|Arguments],
4718 substitute_arguments(Constraints,RestVariables,NConstraints).
4720 make_matchings_explicit([],[],_,MC,MC,[]).
4721 make_matchings_explicit([Arg|Args],[NewVar|NewVars],VarAcc,MatchingCondition,MatchingConditionO,Matchings) :-
4723 ( memberchk_eq(Arg,VarAcc) ->
4724 list2disj(MatchingCondition,MatchingCondition_disj),
4725 Matchings = [(MatchingCondition_disj ; NewVar == Arg)|RestMatchings], % or only = ??
4728 Matchings = RestMatchings,
4730 NVarAcc = [Arg|VarAcc]
4732 MatchingCondition2 = MatchingCondition
4735 Arg =.. [F|RecArgs],
4736 make_matchings_explicit(RecArgs,RecVars,VarAcc,MatchingCondition,MatchingCondition_,RecMatchings),
4737 FlatArg =.. [F|RecVars],
4738 ( RecMatchings == [] ->
4739 Matchings = [functor(NewVar,F,A)|RestMatchings]
4741 list2conj(RecMatchings,ArgM_conj),
4742 list2disj(MatchingCondition,MatchingCondition_disj),
4743 ArgM_ = (NewVar \= FlatArg ; MatchingCondition_disj ; ArgM_conj),
4744 Matchings = [ functor(NewVar,F,A) , ArgM_|RestMatchings]
4746 MatchingCondition2 = [ NewVar \= FlatArg |MatchingCondition_],
4747 term_variables(Args,ArgVars),
4748 append(ArgVars,VarAcc,NVarAcc)
4750 make_matchings_explicit(Args,NewVars,NVarAcc,MatchingCondition2,MatchingConditionO,RestMatchings).
4753 %% make_matchings_explicit_not_negated(+ListOfTerms,-ListOfVariables,-ListOfMatchings) is det.
4755 % Returns list of new variables and list of pairwise unifications between given list and variables.
4757 make_matchings_explicit_not_negated([],[],[]).
4758 make_matchings_explicit_not_negated([X|Xs],[Var|Vars],Matchings) :-
4759 Matchings = [Var = X|RMatchings],
4760 make_matchings_explicit_not_negated(Xs,Vars,RMatchings).
4762 %% apply_guard_wrt_term(+ListOfConstraints,+Goal,-NewListOfConstraints) is det.
4764 % (Partially) applies substitutions of =Goal= to given list.
4766 apply_guard_wrt_term([],_Guard,[]).
4767 apply_guard_wrt_term([Term|RH],Guard,[NTerm|RGH]) :-
4769 apply_guard_wrt_variable(Guard,Term,NTerm)
4772 apply_guard_wrt_term(HArgs,Guard,NewHArgs),
4773 NTerm =.. [F|NewHArgs]
4775 apply_guard_wrt_term(RH,Guard,RGH).
4777 %% apply_guard_wrt_variable(+Goal,+Variable,-NVariable) is det.
4779 % (Partially) applies goal =Guard= wrt variable.
4781 apply_guard_wrt_variable((Guard1,Guard2),Variable,NVariable) :- !,
4782 apply_guard_wrt_variable(Guard1,Variable,NVariable1),
4783 apply_guard_wrt_variable(Guard2,NVariable1,NVariable).
4784 apply_guard_wrt_variable(Guard,Variable,NVariable) :-
4785 ( Guard = (X = Y), Variable == X ->
4787 ; Guard = functor(AVariable,Functor,Arity), Variable == AVariable, ground(Functor), ground(Arity) ->
4788 functor(NVariable,Functor,Arity)
4790 NVariable = Variable
4794 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4795 % ALWAYS FAILING GUARDS
4796 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4798 prev_guard_list(RuleNb,H,G,GuardList,M,[]),rule(RuleNb,Rule)
4800 chr_pp_flag(check_impossible_rules,on),
4801 Rule = pragma(rule(_,_,G,_),_Ids,_Pragmas,_Name,RuleNb),
4803 append(M,GuardList,Info),
4804 append(Info,GL,GuardWithContext),
4805 guard_entailment:entails_guard(GuardWithContext,fail)
4807 chr_warning(weird_program,'Heads will never match or guard will always fail in ~@.\n\tThis rule will never fire!\n',[format_rule(Rule)]),
4808 set_all_passive(RuleNb).
4810 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4811 % HEAD SIMPLIFICATION
4812 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4814 % now we check the head matchings (guard may have been simplified meanwhile)
4815 prev_guard_list(RuleNb,H,G,GuardList,M,[]) \ rule(RuleNb,Rule)
4817 Rule = pragma(rule(Head1,Head2,G,B),Ids,Pragmas,Name,RuleNb),
4818 simplify_heads(M,GuardList,G,B,NewM,NewB),
4820 extract_arguments(Head1,VH1),
4821 extract_arguments(Head2,VH2),
4822 extract_arguments(H,VH),
4823 replace_some_heads(VH1,VH2,VH,NewM,H1,H2,G,B,NewB_),
4824 substitute_arguments(Head1,H1,NewH1),
4825 substitute_arguments(Head2,H2,NewH2),
4826 append(NewB,NewB_,NewBody),
4827 list2conj(NewBody,BodyMatchings),
4828 NewRule = pragma(rule(NewH1,NewH2,G,(BodyMatchings,B)),Ids,Pragmas,Name,RuleNb),
4829 (Head1 \== NewH1 ; Head2 \== NewH2 )
4831 rule(RuleNb,NewRule).
4833 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4834 % AUXILIARY PREDICATES (HEAD SIMPLIFICATION)
4835 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4837 replace_some_heads(H1,H2,NH,[],H1,H2,G,Body,[]) :- !.
4838 replace_some_heads([],[H2|RH2],[NH|RNH],[M|RM],[],[H2_|RH2_],G,Body,NewB) :- !,
4841 replace_some_heads([],RH2,RNH,RM,[],RH2_,G,Body,NewB)
4843 (M = functor(X,F,A), NH == X ->
4849 H2 =.. [F|OrigArgs],
4850 use_same_args(OrigArgs,A_args,A_args_,G,Body,NewB1),
4853 replace_some_heads([],RH2,RNH,RM,[],RH2_,G,Body,NewB2),
4854 append(NewB1,NewB2,NewB)
4857 replace_some_heads([],RH2,RNH,[M|RM],[],RH2_,G,Body,NewB)
4861 replace_some_heads([H1|RH1],H2,[NH|RNH],[M|RM],[H1_|RH1_],H2_,G,Body,NewB) :- !,
4864 replace_some_heads(RH1,H2,RNH,RM,RH1_,H2_,G,Body,NewB)
4866 (M = functor(X,F,A), NH == X ->
4872 H1 =.. [F|OrigArgs],
4873 use_same_args(OrigArgs,A_args,A_args_,G,Body,NewB1),
4876 replace_some_heads(RH1,H2,RNH,RM,RH1_,H2_,G,Body,NewB2),
4877 append(NewB1,NewB2,NewB)
4880 replace_some_heads(RH1,H2,RNH,[M|RM],RH1_,H2_,G,Body,NewB)
4884 use_same_args([],[],[],_,_,[]).
4885 use_same_args([OA|ROA],[NA|RNA],[Out|ROut],G,Body,NewB) :-
4888 use_same_args(ROA,RNA,ROut,G,Body,NewB).
4889 use_same_args([OA|ROA],[NA|RNA],[Out|ROut],G,Body,NewB) :-
4891 ( common_variables(OA,Body) ->
4892 NewB = [NA = OA|NextB]
4897 use_same_args(ROA,RNA,ROut,G,Body,NextB).
4900 simplify_heads([],_GuardList,_G,_Body,[],[]).
4901 simplify_heads([M|RM],GuardList,G,Body,NewM,NewB) :-
4903 ( (nonvar(B) ; common_variables(B,RM-GuardList)),
4904 guard_entailment:entails_guard(GuardList,(A=B)) ->
4905 ( common_variables(B,G-RM-GuardList) ->
4909 ( common_variables(B,Body) ->
4910 NewB = [A = B|NextB]
4917 ( nonvar(B), functor(B,BFu,BAr),
4918 guard_entailment:entails_guard([functor(A,BFu,BAr)|GuardList],(A=B)) ->
4920 ( common_variables(B,G-RM-GuardList) ->
4923 NewM = [functor(A,BFu,BAr)|NextM]
4930 simplify_heads(RM,[M|GuardList],G,Body,NextM,NextB).
4932 common_variables(B,G) :-
4933 term_variables(B,BVars),
4934 term_variables(G,GVars),
4935 intersect_eq(BVars,GVars,L),
4939 set_all_passive(RuleNb), occurrence(_,_,RuleNb,ID,_) ==> passive(RuleNb,ID).
4940 set_all_passive(_) <=> true.
4944 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4945 % OCCURRENCE SUBSUMPTION
4946 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4949 first_occ_in_rule/4,
4952 :- chr_option(mode,first_occ_in_rule(+,+,+,+)).
4953 :- chr_option(mode,next_occ_in_rule(+,+,+,+,+,+)).
4955 :- chr_constraint multiple_occ_constraints_checked/1.
4956 :- chr_option(mode,multiple_occ_constraints_checked(+)).
4958 prev_guard_list(RuleNb,H,G,GuardList,M,[]),
4959 occurrence(C,O,RuleNb,ID,_),
4960 occurrence(C,O2,RuleNb,ID2,_),
4963 multiple_occ_constraints_checked(Done)
4966 chr_pp_flag(occurrence_subsumption,on),
4967 Rule = pragma(rule(H1,H2,_G,_B),_Ids,_Pragmas,_Name,_RuleNb), % RuleNb == _RuleNb
4969 \+ tree_set_memberchk(C,Done)
4971 first_occ_in_rule(RuleNb,C,O,ID),
4972 tree_set_add(Done,C,NDone),
4973 multiple_occ_constraints_checked(NDone).
4975 % Find first occurrence of constraint =C= in rule =RuleNb=
4976 occurrence(C,O,RuleNb,ID,_) \ first_occ_in_rule(RuleNb,C,O2,_)
4980 first_occ_in_rule(RuleNb,C,O,ID).
4982 first_occ_in_rule(RuleNb,C,O,ID_o1)
4985 functor(FreshHead,F,A),
4986 next_occ_in_rule(RuleNb,C,O,ID_o1,[],FreshHead).
4988 % Skip passive occurrences.
4989 passive(RuleNb,ID_o2), occurrence(C,O2,RuleNb,ID_o2,_) \ next_occ_in_rule(RuleNb,C,O,ID_o1,Cond,FH)
4993 next_occ_in_rule(RuleNb,C,O2,ID_o1,NewCond,FH).
4995 prev_guard_list(RuleNb,H,G,GuardList,M,[]), occurrence(C,O2,RuleNb,ID_o2,_), rule(RuleNb,Rule) \ next_occ_in_rule(RuleNb,C,O,ID_o1,Cond,FH)
4998 Rule = pragma(rule(H1,H2,G,B),ids(ID1,ID2),_Pragmas,_Name,RuleNb)
5000 append(H1,H2,Heads),
5001 add_failing_occ(Rule,Heads,H,ID_o1,ExtraCond,FH,M,C,Repl),
5002 ( ExtraCond == [chr_pp_void_info] ->
5003 next_occ_in_rule(RuleNb,C,O2,ID_o2,Cond,FH)
5005 append(ExtraCond,Cond,NewCond),
5006 add_failing_occ(Rule,Heads,H,ID_o2,CheckCond,FH,M,C,Repl2),
5007 copy_term(GuardList,FGuardList),
5008 variable_replacement(GuardList,FGuardList,GLRepl),
5009 copy_with_variable_replacement(GuardList,GuardList2,Repl),
5010 copy_with_variable_replacement(GuardList,GuardList3_,Repl2),
5011 copy_with_variable_replacement(GuardList3_,GuardList3,GLRepl),
5012 append(NewCond,GuardList2,BigCond),
5013 append(BigCond,GuardList3,BigCond2),
5014 copy_with_variable_replacement(M,M2,Repl),
5015 copy_with_variable_replacement(M,M3,Repl2),
5016 append(M3,BigCond2,BigCond3),
5017 append([chr_pp_active_constraint(FH)|M2],BigCond3,Info),
5018 list2conj(CheckCond,OccSubsum),
5019 copy_term((NewCond,BigCond2,Info,OccSubsum,FH),(NewCond2,BigCond2_,Info2,OccSubsum2,FH2)),
5020 ( OccSubsum \= chr_pp_void_info ->
5021 ( guard_entailment:entails_guard(Info2,OccSubsum2) ->
5022 passive(RuleNb,ID_o2)
5029 next_occ_in_rule(RuleNb,C,O2,ID_o2,NewCond,FH)
5033 next_occ_in_rule(RuleNb,C,O,ID,Cond,Args)
5037 prev_guard_list(RuleNb,H,G,GuardList,M,[]), multiple_occ_constraints_checked(Done)
5041 add_failing_occ(Rule,Heads,NH,ID_o1,FailCond,FH,M,C,Repl) :-
5042 Rule = pragma(rule(H1,H2,G,B),ids(ID1,ID2),_Pragmas,_Name,RuleNb),
5043 append(ID2,ID1,IDs),
5044 missing_partner_cond(Heads,NH,IDs,ID_o1,MPCond,H,C),
5045 copy_term((H,Heads,NH),(FH2,FHeads,NH2)),
5046 variable_replacement((H,Heads,NH),(FH2,FHeads,NH2),Repl),
5047 copy_with_variable_replacement(G,FG,Repl),
5048 extract_explicit_matchings(FG,FG2),
5049 negate_b(FG2,NotFG),
5050 copy_with_variable_replacement(MPCond,FMPCond,Repl),
5051 ( subsumes(FH,FH2) ->
5052 FailCond = [(NotFG;FMPCond)]
5054 % in this case, not much can be done
5055 % e.g. c(f(...)), c(g(...)) <=> ...
5056 FailCond = [chr_pp_void_info]
5059 missing_partner_cond([],[],[],ID_o1,fail,H2,C).
5060 missing_partner_cond([H|Hs],[H2|H2s],[ID_o1|IDs],ID_o1,Cond,H,C) :- !,
5061 missing_partner_cond(Hs,H2s,IDs,ID_o1,Cond,H,C).
5062 missing_partner_cond([H|Hs],[NH|NHs],[ID|IDs],ID_o1,Cond,H2,F/A) :-
5063 Cond = (chr_pp_not_in_store(H);Cond1),
5064 missing_partner_cond(Hs,NHs,IDs,ID_o1,Cond1,H2,F/A).
5066 extract_explicit_matchings((A,B),D) :- !,
5067 ( extract_explicit_matchings(A) ->
5068 extract_explicit_matchings(B,D)
5071 extract_explicit_matchings(B,E)
5073 extract_explicit_matchings(A,D) :- !,
5074 ( extract_explicit_matchings(A) ->
5080 extract_explicit_matchings(A=B) :-
5081 var(A), var(B), !, A=B.
5082 extract_explicit_matchings(A==B) :-
5083 var(A), var(B), !, A=B.
5085 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5087 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5093 get_type_definition/2,
5094 get_constraint_type/2.
5097 :- chr_option(mode,type_definition(?,?)).
5098 :- chr_option(mode,get_type_definition(?,?)).
5099 :- chr_option(mode,type_alias(?,?)).
5100 :- chr_option(mode,constraint_type(+,+)).
5101 :- chr_option(mode,get_constraint_type(+,-)).
5103 assert_constraint_type(Constraint,ArgTypes) :-
5104 ( ground(ArgTypes) ->
5105 constraint_type(Constraint,ArgTypes)
5107 chr_error(type_error,'Declared argument types "~w" for constraint "~w" must be ground!\n',[ArgTypes,Constraint])
5110 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5111 % Consistency checks of type aliases
5113 type_alias(T1,T2) <=>
5116 chr_error(type_error,'Variable alias definition: "~w".\n',[(:- chr_type T1 == T2)]).
5118 type_alias(T1,T2) <=>
5121 chr_error(type_error,'Variable alias definition: "~w".\n',[(:- chr_type T1 == T2)]).
5123 type_alias(T,T2) <=>
5126 copy_term((T,T2),(X,Y)), subsumes(X,Y)
5128 chr_error(type_error,'Cyclic alias definition: "~w".\n',[(T == T2)]).
5130 type_alias(T1,A1), type_alias(T2,A2) <=>
5135 copy_term_nat(T1,T1_),
5136 copy_term_nat(T2,T2_),
5138 chr_error(type_error,
5139 'Ambiguous type aliases: you have defined \n\t`~w\'\n\t`~w\'\n\tresulting in two definitions for "~w".\n',[T1==A1,T2==A2,T1_]).
5141 type_alias(T,B) \ type_alias(X,T2) <=>
5144 copy_term_nat((X,T2,T,B),(X2,T3,T1,D1)),
5147 % chr_info(type_information,'Inferring `~w\' from `~w\' and `~w\'.\n',[X2==D1,X==T2,T==B]),
5150 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5151 % Consistency checks of type definitions
5153 type_definition(T1,_), type_definition(T2,_)
5155 functor(T1,F,A), functor(T2,F,A)
5157 chr_error(type_error,'Multiple definitions for type: ~w/~w.\n',[F,A]).
5159 type_definition(T1,_), type_alias(T2,_)
5161 functor(T1,F,A), functor(T2,F,A)
5163 chr_error(type_error,'Multiple definitions for type, once in a type definition and once as a type alias: ~w/~w.\n',[F,A]).
5165 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5166 %% get_type_definition(+Type,-Definition) is semidet.
5167 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5169 get_type_definition(T,Def)
5173 chr_error(type_error,'Non-ground type in constraint definition: "~w".\n',[T]).
5175 type_alias(T,D) \ get_type_definition(T2,Def)
5177 nonvar(T),nonvar(T2),functor(T,F,A),functor(T2,F,A),
5178 copy_term_nat((T,D),(T1,D1)),T1=T2
5180 ( get_type_definition(D1,Def) ->
5183 chr_error(type_error,'Could not find type definition for "~w" (accessed via alias "~w").\n',[D1,T1]), fail
5186 type_definition(T,D) \ get_type_definition(T2,Def)
5188 nonvar(T),nonvar(T2),functor(T,F,A),functor(T2,F,A),
5189 copy_term_nat((T,D),(T1,D1)),T1=T2
5193 get_type_definition(Type,Def)
5195 atomic_builtin_type(Type,_,_)
5199 get_type_definition(Type,Def)
5201 compound_builtin_type(Type,_,_,_)
5205 get_type_definition(X,Y) <=> fail.
5207 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5208 %% get_type_definition_det(+Type,-Definition) is det.
5209 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5210 get_type_definition_det(Type,Definition) :-
5211 ( get_type_definition(Type,Definition) ->
5214 chr_error(type,'Could not find type definition for type `~w\'.\n',[Type])
5217 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
5218 %% get_constraint_type(+ConstraintSymbol,-Types) is semidet.
5220 % Return argument types of =ConstraintSymbol=, but fails if none where
5222 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
5223 constraint_type(C,T) \ get_constraint_type(C,Type) <=> Type = T.
5224 get_constraint_type(_,_) <=> fail.
5226 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
5227 %% get_constraint_type_det(+ConstraintSymbol,-Types) is det.
5229 % Like =get_constraint_type/2=, but returns list of =any= types when
5230 % no types are declared.
5231 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
5232 get_constraint_type_det(ConstraintSymbol,Types) :-
5233 ( get_constraint_type(ConstraintSymbol,Types) ->
5236 ConstraintSymbol = _ / N,
5237 replicate(N,any,Types)
5239 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
5240 %% unalias_type(+Alias,-Type) is det.
5242 % Follows alias chain until base type is reached.
5243 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
5244 :- chr_constraint unalias_type/2.
5247 unalias_type(Alias,BaseType)
5254 type_alias(AliasProtoType,ProtoType) \ unalias_type(Alias,BaseType)
5256 nonvar(AliasProtoType),
5258 functor(AliasProtoType,F,A),
5260 copy_term_nat((AliasProtoType,ProtoType),(AliasInstance,Type)),
5261 Alias = AliasInstance
5263 unalias_type(Type,BaseType).
5265 unalias_type_definition @
5266 type_definition(ProtoType,Definition) \ unalias_type(Alias,BaseType)
5270 functor(ProtoType,F,A),
5275 unalias_atomic_builtin @
5276 unalias_type(Alias,BaseType)
5278 atomic_builtin_type(Alias,_,_)
5282 unalias_compound_builtin @
5283 unalias_type(Alias,BaseType)
5285 compound_builtin_type(Alias,_,_,_)
5289 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
5290 %% types_modes_condition(+Heads,+UnrollHeads,-Condition) is det.
5291 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
5292 :- chr_constraint types_modes_condition/3.
5293 :- chr_option(mode,types_modes_condition(+,+,?)).
5294 :- chr_option(type_declaration,types_modes_condition(list,list,goal)).
5296 types_modes_condition([],[],T) <=> T=true.
5298 constraint_mode(F/A,Modes) \ types_modes_condition([Head|Heads],[UnrollHead|UnrollHeads],Condition)
5303 Condition = (ModesCondition, TypesCondition, RestCondition),
5304 modes_condition(Modes,Args,ModesCondition),
5305 get_constraint_type_det(F/A,Types),
5306 UnrollHead =.. [_|RealArgs],
5307 types_condition(Types,Args,RealArgs,Modes,TypesCondition),
5308 types_modes_condition(Heads,UnrollHeads,RestCondition).
5310 types_modes_condition([Head|_],_,_)
5313 chr_error(internal,'Mode information missing for ~w.\n',[F/A]).
5316 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
5317 %% modes_condition(+Modes,+Args,-Condition) is det.
5319 % Return =Condition= on =Args= that checks =Modes=.
5320 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
5321 modes_condition([],[],true).
5322 modes_condition([Mode|Modes],[Arg|Args],Condition) :-
5324 Condition = ( ground(Arg) , RCondition )
5326 Condition = ( var(Arg) , RCondition )
5328 Condition = RCondition
5330 modes_condition(Modes,Args,RCondition).
5332 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
5333 %% types_condition(+Types,+Args,+UnrollArgs,+Modes,-Condition) is det.
5335 % Return =Condition= on =Args= that checks =Types= given =Modes=.
5336 % =UnrollArgs= controls the depth of type definition unrolling.
5337 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
5338 types_condition([],[],[],[],true).
5339 types_condition([Type|Types],[Arg|Args],[UnrollArg|UnrollArgs],[Mode|Modes],(DisjTypeConditionList,RCondition)) :-
5341 TypeConditionList = [true] % TypeConditionList = [var(Arg)] already encoded in modes_condition
5343 get_type_definition_det(Type,Def),
5344 type_condition(Def,Arg,UnrollArg,Mode,TypeConditionList1),
5346 TypeConditionList = TypeConditionList1
5348 TypeConditionList = [(\+ ground(Arg))|TypeConditionList1]
5351 list2disj(TypeConditionList,DisjTypeConditionList),
5352 types_condition(Types,Args,UnrollArgs,Modes,RCondition).
5354 type_condition([],_,_,_,[]).
5355 type_condition([DefCase|DefCases],Arg,UnrollArg,Mode,[Condition|Conditions]) :-
5357 chr_error(type,'Unexpected variable type in type definition!\n',[]) % Condition = true
5358 ; atomic_builtin_type(DefCase,Arg,Condition) ->
5360 ; compound_builtin_type(DefCase,Arg,Condition,_) ->
5363 type_def_case_condition(DefCase,Arg,UnrollArg,Mode,Condition)
5365 type_condition(DefCases,Arg,UnrollArg,Mode,Conditions).
5367 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
5368 :- chr_type atomic_builtin_type ---> any
5375 ; chr_identifier(any)
5376 ; /* all possible values are given */
5378 ; /* all possible values appear in rule heads;
5379 to distinguish between multiple chr_constants
5382 ; /* all relevant values appear in rule heads;
5383 for other values a handler is provided */
5384 chr_constants(any,any).
5385 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
5387 atomic_builtin_type(any,_Arg,true).
5388 atomic_builtin_type(dense_int,Arg,(integer(Arg),Arg>=0)).
5389 atomic_builtin_type(int,Arg,integer(Arg)).
5390 atomic_builtin_type(number,Arg,number(Arg)).
5391 atomic_builtin_type(float,Arg,float(Arg)).
5392 atomic_builtin_type(natural,Arg,(integer(Arg),Arg>=0)).
5393 atomic_builtin_type(chr_identifier,_Arg,true).
5395 compound_builtin_type(chr_constants(_),_Arg,true,true).
5396 compound_builtin_type(chr_constants(_,_),_Arg,true,true).
5397 compound_builtin_type(chr_identifier(_),_Arg,true,true).
5398 compound_builtin_type(chr_enum(Constants),Arg,(ground(Arg), memberchk(Arg,Constants)),
5399 once(( member(Constant,Constants),
5400 unifiable(Arg,Constant,_)
5405 is_chr_constants_type(chr_constants(Key),Key,no).
5406 is_chr_constants_type(chr_constants(Key,ErrorHandler),Key,yes(ErrorHandler)).
5408 type_def_case_condition(DefCase,Arg,UnrollArg,Mode,Condition) :-
5409 ( nonvar(DefCase) ->
5410 functor(DefCase,F,A),
5412 Condition = (Arg = DefCase)
5414 Condition = functor(Arg,F,A)
5415 ; functor(UnrollArg,F,A) ->
5416 Condition = (functor(Arg,F,A),Arg=Template,ArgsCondition),
5417 DefCase =.. [_|ArgTypes],
5418 UnrollArg =.. [_|UnrollArgs],
5419 functor(Template,F,A),
5420 Template =.. [_|TemplateArgs],
5421 replicate(A,Mode,ArgModes),
5422 types_condition(ArgTypes,TemplateArgs,UnrollArgs,ArgModes,ArgsCondition)
5424 Condition = functor(Arg,F,A)
5427 chr_error(internal,'Illegal type definition (must be nonvar).\n',[])
5431 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5432 % STATIC TYPE CHECKING
5433 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5434 % Checks head constraints and CHR constraint calls in bodies.
5437 % - type clashes involving built-in types
5438 % - Prolog built-ins in guard and body
5439 % - indicate position in terms in error messages
5440 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5442 static_type_check/0.
5445 % 1. Check the declared types
5447 constraint_type(Constraint,ArgTypes), static_type_check
5450 ( member(ArgType,ArgTypes), sub_term(ArgType,Type) ),
5451 ( get_type_definition(Type,_) ->
5454 chr_error(type_error,'Undefined type "~w" used in type declaration of "~w".\n',[Type,Constraint])
5458 % 2. Check the rules
5460 :- chr_type type_error_src ---> head(any) ; body(any).
5462 rule(_,Rule), static_type_check
5464 copy_term_nat(Rule,RuleCopy),
5465 RuleCopy = pragma(rule(Head1,Head2,G,Body),ids(IDs1,IDs2),Pragmas,Name,RuleNb),
5468 ( static_type_check_heads(Head1),
5469 static_type_check_heads(Head2),
5470 conj2list(Body,GoalList),
5471 static_type_check_body(GoalList)
5474 ( Error = invalid_functor(Src,Term,Type) ->
5475 chr_error(type_error,'Invalid functor in ~@ of ~@:\n\t\tfound `~w\',\n\t\texpected type `~w\'!\n',
5476 [chr_translate:format_src(Src),format_rule(Rule),Term,Type])
5477 ; Error = type_clash(Var,Src1,Src2,Type1,Type2) ->
5478 chr_error(type_error,'Type clash for variable ~w in ~@:\n\t\texpected type ~w in ~@\n\t\texpected type ~w in ~@\n',
5479 [Var,format_rule(Rule),Type1,chr_translate:format_src(Src1),Type2,chr_translate:format_src(Src2)])
5482 fail % cleanup constraints
5488 static_type_check <=> true.
5490 static_type_check_heads([]).
5491 static_type_check_heads([Head|Heads]) :-
5492 static_type_check_head(Head),
5493 static_type_check_heads(Heads).
5495 static_type_check_head(Head) :-
5497 get_constraint_type_det(F/A,Types),
5499 maplist(static_type_check_term(head(Head)),Args,Types).
5501 static_type_check_body([]).
5502 static_type_check_body([Goal|Goals]) :-
5504 get_constraint_type_det(F/A,Types),
5506 maplist(static_type_check_term(body(Goal)),Args,Types),
5507 static_type_check_body(Goals).
5509 :- chr_constraint static_type_check_term/3.
5510 :- chr_option(mode,static_type_check_term(?,?,?)).
5511 :- chr_option(type_declaration,static_type_check_term(type_error_src,any,any)).
5513 static_type_check_term(Src,Term,Type)
5517 static_type_check_var(Src,Term,Type).
5518 static_type_check_term(Src,Term,Type)
5520 atomic_builtin_type(Type,Term,Goal)
5525 throw(type_error(invalid_functor(Src,Term,Type)))
5527 static_type_check_term(Src,Term,Type)
5529 compound_builtin_type(Type,Term,_,Goal)
5534 throw(type_error(invalid_functor(Src,Term,Type)))
5536 type_alias(AType,ADef) \ static_type_check_term(Src,Term,Type)
5541 copy_term_nat(AType-ADef,Type-Def),
5542 static_type_check_term(Src,Term,Def).
5544 type_definition(AType,ADef) \ static_type_check_term(Src,Term,Type)
5549 copy_term_nat(AType-ADef,Type-Variants),
5550 functor(Term,TF,TA),
5551 ( member(Variant,Variants), functor(Variant,TF,TA) ->
5553 Variant =.. [_|Types],
5554 maplist(static_type_check_term(Src),Args,Types)
5556 throw(type_error(invalid_functor(Src,Term,Type)))
5559 static_type_check_term(Src,Term,Type)
5561 chr_error(internal,'Undefined type ~w while type checking term ~w in ~@.\n',[Type,Term,chr_translate:format_src(Src)]).
5563 :- chr_constraint static_type_check_var/3.
5564 :- chr_option(mode,static_type_check_var(?,-,?)).
5565 :- chr_option(type_declaration,static_type_check_term(type_error_src,any,any)).
5567 type_alias(AType,ADef) \ static_type_check_var(Src,Var,Type)
5572 copy_term_nat(AType-ADef,Type-Def),
5573 static_type_check_var(Src,Var,Def).
5575 static_type_check_var(Src,Var,Type)
5577 atomic_builtin_type(Type,_,_)
5579 static_atomic_builtin_type_check_var(Src,Var,Type).
5581 static_type_check_var(Src,Var,Type)
5583 compound_builtin_type(Type,_,_,_)
5588 static_type_check_var(Src1,Var,Type1), static_type_check_var(Src2,Var,Type2)
5592 throw(type_error(type_clash(Var,Src1,Src2,Type1,Type2))).
5594 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
5595 %% static_atomic_builtin_type_check_var(+type_error_src,-Var,+atomic_builtin_type)
5596 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
5597 :- chr_constraint static_atomic_builtin_type_check_var/3.
5598 :- chr_option(mode,static_type_check_var(?,-,+)).
5599 :- chr_option(type_declaration,static_type_check_term(type_error_src,any,atomic_builtin_type)).
5601 static_atomic_builtin_type_check_var(_,_,any) <=> true.
5602 static_atomic_builtin_type_check_var(_,Var,BuiltinType) \ static_atomic_builtin_type_check_var(_,Var,BuiltinType)
5605 static_atomic_builtin_type_check_var(_,Var,float) \ static_atomic_builtin_type_check_var(_,Var,number)
5608 static_atomic_builtin_type_check_var(_,Var,int) \ static_atomic_builtin_type_check_var(_,Var,number)
5611 static_atomic_builtin_type_check_var(_,Var,natural) \ static_atomic_builtin_type_check_var(_,Var,number)
5614 static_atomic_builtin_type_check_var(_,Var,dense_int) \ static_atomic_builtin_type_check_var(_,Var,number)
5617 static_atomic_builtin_type_check_var(_,Var,natural) \ static_atomic_builtin_type_check_var(_,Var,int)
5620 static_atomic_builtin_type_check_var(_,Var,dense_int) \ static_atomic_builtin_type_check_var(_,Var,int)
5623 static_atomic_builtin_type_check_var(_,Var,dense_int) \ static_atomic_builtin_type_check_var(_,Var,natural)
5626 static_atomic_builtin_type_check_var(Src1,Var,Type1), static_atomic_builtin_type_check_var(Src2,Var,Type2)
5628 throw(type_error(type_clash(Var,Src1,Src2,Type1,Type2))).
5630 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
5631 %% format_src(+type_error_src) is det.
5632 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
5633 format_src(head(Head)) :- format('head ~w',[Head]).
5634 format_src(body(Goal)) :- format('body goal ~w',[Goal]).
5636 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5637 % Dynamic type checking
5638 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5641 dynamic_type_check/0,
5642 dynamic_type_check_clauses/1,
5643 get_dynamic_type_check_clauses/1.
5645 generate_dynamic_type_check_clauses(Clauses) :-
5646 ( chr_pp_flag(debugable,on) ->
5648 get_dynamic_type_check_clauses(Clauses0),
5650 [('$dynamic_type_check'(Type,Term) :-
5651 throw(error(type_error(Type,Term),context(_,'CHR Runtime Type Error')))
5658 type_definition(T,D), dynamic_type_check
5660 copy_term_nat(T-D,Type-Definition),
5661 maplist(dynamic_type_check_clause(Type),Definition,DynamicChecks),
5662 dynamic_type_check_clauses(DynamicChecks).
5663 type_alias(A,B), dynamic_type_check
5665 copy_term_nat(A-B,Alias-Body),
5666 dynamic_type_check_alias_clause(Alias,Body,Clause),
5667 dynamic_type_check_clauses([Clause]).
5669 dynamic_type_check <=>
5671 ('$dynamic_type_check'(Type,Term) :- Goal),
5672 ( atomic_builtin_type(Type,Term,Goal) ; compound_builtin_type(Type,Term,Goal,_) ),
5675 dynamic_type_check_clauses(BuiltinChecks).
5677 dynamic_type_check_clause(T,DC,Clause) :-
5678 copy_term(T-DC,Type-DefinitionClause),
5679 functor(DefinitionClause,F,A),
5681 DefinitionClause =.. [_|DCArgs],
5682 Term =.. [_|TermArgs],
5683 maplist(dynamic_type_check_call,DCArgs,TermArgs,RecursiveCallList),
5684 list2conj(RecursiveCallList,RecursiveCalls),
5686 '$dynamic_type_check'(Type,Term) :-
5690 dynamic_type_check_alias_clause(Alias,Body,Clause) :-
5692 '$dynamic_type_check'(Alias,Term) :-
5693 '$dynamic_type_check'(Body,Term)
5696 dynamic_type_check_call(Type,Term,Call) :-
5697 % ( nonvar(Type), atomic_builtin_type(Type,Term,Goal) ->
5698 % Call = when(nonvar(Term),Goal)
5699 % ; nonvar(Type), compound_builtin_type(Type,Term,Goal) ->
5700 % Call = when(nonvar(Term),Goal)
5705 Call = when(nonvar(Term),once('$dynamic_type_check'(Type,Term)))
5710 dynamic_type_check_clauses(C1), dynamic_type_check_clauses(C2)
5713 dynamic_type_check_clauses(C).
5715 get_dynamic_type_check_clauses(Q), dynamic_type_check_clauses(C)
5718 get_dynamic_type_check_clauses(Q)
5722 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5724 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5725 % Some optimizations can be applied for atomic types...
5726 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5728 atomic_types_suspended_constraint(C) :-
5730 get_constraint_type(C,ArgTypes),
5731 get_constraint_mode(C,ArgModes),
5732 numlist(1,N,Indexes),
5733 maplist(atomic_types_suspended_constraint(C),ArgTypes,ArgModes,Indexes).
5735 atomic_types_suspended_constraint(C,Type,Mode,Index) :-
5736 ( is_indexed_argument(C,Index) ->
5746 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
5747 %% atomic_type(+Type) is semidet.
5749 % Succeeds when all values of =Type= are atomic.
5750 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
5751 :- chr_constraint atomic_type/1.
5753 atomic_type(Type) <=> atomic_builtin_type(Type,_,_) | Type \== any.
5755 type_definition(TypePat,Def) \ atomic_type(Type)
5757 functor(Type,F,A), functor(TypePat,F,A)
5759 maplist(atomic,Def).
5761 type_alias(TypePat,Alias) \ atomic_type(Type)
5763 functor(Type,F,A), functor(TypePat,F,A)
5766 copy_term_nat(TypePat-Alias,Type-NType),
5769 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
5770 %% enumerated_atomic_type(+Type,-Atoms) is semidet.
5772 % Succeeds when all values of =Type= are atomic
5773 % and the atom values are finitely enumerable.
5774 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
5775 :- chr_constraint enumerated_atomic_type/2.
5777 enumerated_atomic_type(Type,_) <=> atomic_builtin_type(Type,_,_) | fail.
5779 type_definition(TypePat,Def) \ enumerated_atomic_type(Type,Atoms)
5781 functor(Type,F,A), functor(TypePat,F,A)
5783 maplist(atomic,Def),
5786 type_alias(TypePat,Alias) \ enumerated_atomic_type(Type,Atoms)
5788 functor(Type,F,A), functor(TypePat,F,A)
5791 copy_term_nat(TypePat-Alias,Type-NType),
5792 enumerated_atomic_type(NType,Atoms).
5793 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5796 stored/3, % constraint,occurrence,(yes/no/maybe)
5797 stored_completing/3,
5800 is_finally_stored/1,
5801 check_all_passive/2.
5803 :- chr_option(mode,stored(+,+,+)).
5804 :- chr_option(type_declaration,stored(any,int,storedinfo)).
5805 :- chr_type storedinfo ---> yes ; no ; maybe.
5806 :- chr_option(mode,stored_complete(+,+,+)).
5807 :- chr_option(mode,maybe_complementary_guards(+,+,?,?)).
5808 :- chr_option(mode,guard_list(+,+,+,+)).
5809 :- chr_option(mode,check_all_passive(+,+)).
5810 :- chr_option(type_declaration,check_all_passive(any,list)).
5812 % change yes in maybe when yes becomes passive
5813 passive(RuleNb,ID), occurrence(C,O,RuleNb,ID,_) \
5814 stored(C,O,yes), stored_complete(C,RO,Yesses)
5815 <=> O < RO | NYesses is Yesses - 1,
5816 stored(C,O,maybe), stored_complete(C,RO,NYesses).
5817 % change yes in maybe when not observed
5818 ai_not_observed(C,O) \ stored(C,O,yes), stored_complete(C,RO,Yesses)
5820 NYesses is Yesses - 1,
5821 stored(C,O,maybe), stored_complete(C,RO,NYesses).
5823 occurrence(_,_,RuleNb,ID,_), occurrence(C2,_,RuleNb,_,_), stored_complete(C2,RO,0), max_occurrence(C2,MO2)
5824 ==> RO =< MO2 | % C2 is never stored
5830 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5832 rule(RuleNb,Rule),passive(RuleNb,Id) ==>
5833 Rule = pragma(rule(Head1,Head2,G,B),ids([Id|IDs1],IDs2),Pragmas,Name,RuleNb) |
5834 append(IDs1,IDs2,I), check_all_passive(RuleNb,I).
5836 rule(RuleNb,Rule),passive(RuleNb,Id) ==>
5837 Rule = pragma(rule(Head1,Head2,G,B),ids([],[Id|IDs2]),Pragmas,Name,RuleNb) |
5838 check_all_passive(RuleNb,IDs2).
5840 passive(RuleNb,Id) \ check_all_passive(RuleNb,[Id|IDs]) <=>
5841 check_all_passive(RuleNb,IDs).
5843 rule(RuleNb,Rule) \ check_all_passive(RuleNb,[]) <=>
5844 chr_warning(weird_program,'All heads passive in ~@.\n\tThis rule never fires. Please check your program.\n',[format_rule(Rule)]).
5846 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5848 % collect the storage information
5849 stored(C,O,yes) \ stored_completing(C,O,Yesses)
5850 <=> NO is O + 1, NYesses is Yesses + 1,
5851 stored_completing(C,NO,NYesses).
5852 stored(C,O,maybe) \ stored_completing(C,O,Yesses)
5854 stored_completing(C,NO,Yesses).
5856 stored(C,O,no) \ stored_completing(C,O,Yesses)
5857 <=> stored_complete(C,O,Yesses).
5858 stored_completing(C,O,Yesses)
5859 <=> stored_complete(C,O,Yesses).
5861 stored_complete(C,O,Yesses), occurrence(C,O2,RuleNb,Id,_) ==>
5862 O2 > O | passive(RuleNb,Id).
5864 % decide whether a constraint is stored
5865 max_occurrence(C,MO), stored_complete(C,RO,0) \ is_stored(C)
5866 <=> RO =< MO | fail.
5867 is_stored(C) <=> true.
5869 % decide whether a constraint is suspends after occurrences
5870 max_occurrence(C,MO), stored_complete(C,RO,_) \ is_finally_stored(C)
5871 <=> RO =< MO | fail.
5872 is_finally_stored(C) <=> true.
5874 storage_analysis(Constraints) :-
5875 ( chr_pp_flag(storage_analysis,on) ->
5876 check_constraint_storages(Constraints)
5881 check_constraint_storages([]).
5882 check_constraint_storages([C|Cs]) :-
5883 check_constraint_storage(C),
5884 check_constraint_storages(Cs).
5886 check_constraint_storage(C) :-
5887 get_max_occurrence(C,MO),
5888 check_occurrences_storage(C,1,MO).
5890 check_occurrences_storage(C,O,MO) :-
5892 stored_completing(C,1,0)
5894 check_occurrence_storage(C,O),
5896 check_occurrences_storage(C,NO,MO)
5899 check_occurrence_storage(C,O) :-
5900 get_occurrence(C,O,RuleNb,ID),
5901 ( is_passive(RuleNb,ID) ->
5904 get_rule(RuleNb,PragmaRule),
5905 PragmaRule = pragma(rule(Heads1,Heads2,Guard,Body),ids(IDs1,IDs2),_,_,_),
5906 ( select2(ID,Head1,IDs1,Heads1,RIDs1,RHeads1) ->
5907 check_storage_head1(Head1,O,Heads1,Heads2,Guard)
5908 ; select2(ID,Head2,IDs2,Heads2,RIDs2,RHeads2) ->
5909 check_storage_head2(Head2,O,Heads1,Body)
5913 check_storage_head1(Head,O,H1,H2,G) :-
5918 % writeq(guard_entailment:entails_guard([chr_pp_headvariables(Head)],G)),nl,
5919 guard_entailment:entails_guard([chr_pp_headvariables(Head)],G),
5921 no_matching(L,[]) ->
5928 no_matching([X|Xs],Prev) :-
5930 \+ memberchk_eq(X,Prev),
5931 no_matching(Xs,[X|Prev]).
5933 check_storage_head2(Head,O,H1,B) :-
5937 ( H1 \== [], B == true )
5939 % \+ is_observed(F/A,O) % always fails because observation analysis has not been performed yet
5947 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5949 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5950 %% ____ _ ____ _ _ _ _
5951 %% | _ \ _ _| | ___ / ___|___ _ __ ___ _ __ (_) | __ _| |_(_) ___ _ __
5952 %% | |_) | | | | |/ _ \ | | / _ \| '_ ` _ \| '_ \| | |/ _` | __| |/ _ \| '_ \
5953 %% | _ <| |_| | | __/ | |__| (_) | | | | | | |_) | | | (_| | |_| | (_) | | | |
5954 %% |_| \_\\__,_|_|\___| \____\___/|_| |_| |_| .__/|_|_|\__,_|\__|_|\___/|_| |_|
5957 constraints_code(Constraints,Clauses) :-
5958 (chr_pp_flag(reduced_indexing,on),
5959 forall(C,Constraints,chr_translate:only_ground_indexed_arguments(C)) ->
5960 none_suspended_on_variables
5964 constraints_code1(Constraints,Clauses,[]).
5966 %===============================================================================
5967 :- chr_constraint constraints_code1/3.
5968 :- chr_option(mode,constraints_code1(+,+,+)).
5969 :- chr_option(type_declaration,constraints_code1(list,any,any)).
5970 %-------------------------------------------------------------------------------
5971 constraints_code1([],L,T) <=> L = T.
5972 constraints_code1([C|RCs],L,T)
5974 constraint_code(C,L,T1),
5975 constraints_code1(RCs,T1,T).
5976 %===============================================================================
5977 :- chr_constraint constraint_code/3.
5978 :- chr_option(mode,constraint_code(+,+,+)).
5979 %-------------------------------------------------------------------------------
5980 %% Generate code for a single CHR constraint
5981 constraint_code(Constraint, L, T)
5983 | ( (chr_pp_flag(debugable,on) ;
5984 is_stored(Constraint), ( has_active_occurrence(Constraint); chr_pp_flag(late_allocation,off)),
5985 ( may_trigger(Constraint) ;
5986 get_allocation_occurrence(Constraint,AO),
5987 get_max_occurrence(Constraint,MO), MO >= AO ) )
5989 constraint_prelude(Constraint,Clause),
5990 add_dummy_location(Clause,LocatedClause),
5991 L = [LocatedClause | L1]
5996 occurrences_code(Constraint,1,Id,NId,L1,L2),
5997 gen_cond_attach_clause(Constraint,NId,L2,T).
5999 %===============================================================================
6000 %% Generate prelude predicate for a constraint.
6001 %% f(...) :- f/a_0(...,Susp).
6002 constraint_prelude(F/A, Clause) :-
6003 vars_susp(A,Vars,Susp,VarsSusp),
6004 Head =.. [ F | Vars],
6005 make_suspension_continuation_goal(F/A,VarsSusp,Continuation),
6006 build_head(F,A,[0],VarsSusp,Delegate),
6007 ( chr_pp_flag(debugable,on) ->
6008 insert_constraint_goal(F/A,Susp,Vars,InsertCall),
6009 attach_constraint_atom(F/A,Vars2,Susp,AttachCall),
6010 delay_phase_end(validate_store_type_assumptions,chr_translate:update_suspension_field(F/A,Susp,state,inactive,Inactive)),
6011 insert_constraint_internal_constraint_goal(F/A, Vars2, Susp, Continuation, Vars,InsertGoal),
6013 ( get_constraint_type(F/A,ArgTypeList) ->
6014 maplist(dynamic_type_check_call,ArgTypeList,Vars,DynamicTypeCheckList),
6015 list2conj(DynamicTypeCheckList,DynamicTypeChecks)
6017 DynamicTypeChecks = true
6027 'chr debug_event'(insert(Head#Susp)),
6029 'chr debug_event'(call(Susp)),
6032 'chr debug_event'(fail(Susp)), !,
6036 'chr debug_event'(exit(Susp))
6038 'chr debug_event'(redo(Susp)),
6042 ; get_allocation_occurrence(F/A,0) ->
6043 gen_insert_constraint_internal_goal(F/A,Goal,VarsSusp,Vars,Susp),
6044 delay_phase_end(validate_store_type_assumptions,chr_translate:update_suspension_field(F/A,Susp,state,inactive,Inactive)),
6045 Clause = ( Head :- Goal, Inactive, Delegate )
6047 Clause = ( Head :- Delegate )
6050 make_suspension_continuation_goal(F/A,VarsSusp,Goal) :-
6051 ( may_trigger(F/A) ->
6052 build_head(F,A,[0],VarsSusp,Delegate),
6053 ( chr_pp_flag(debugable,off) ->
6056 get_target_module(Mod),
6063 %===============================================================================
6064 :- chr_constraint has_active_occurrence/1, has_active_occurrence/2.
6065 :- chr_option(mode,has_active_occurrence(+)).
6066 :- chr_option(mode,has_active_occurrence(+,+)).
6068 :- chr_constraint memo_has_active_occurrence/1.
6069 :- chr_option(mode,memo_has_active_occurrence(+)).
6070 %-------------------------------------------------------------------------------
6071 memo_has_active_occurrence(C) \ has_active_occurrence(C) <=> true.
6072 has_active_occurrence(C) <=> has_active_occurrence(C,1), memo_has_active_occurrence(C).
6074 max_occurrence(C,MO) \ has_active_occurrence(C,O) <=>
6076 passive(RuleNb,ID),occurrence(C,O,RuleNb,ID,_) \
6077 has_active_occurrence(C,O) <=>
6079 has_active_occurrence(C,NO).
6080 has_active_occurrence(C,O) <=> true.
6081 %===============================================================================
6083 gen_cond_attach_clause(F/A,Id,L,T) :-
6084 ( is_finally_stored(F/A) ->
6085 get_allocation_occurrence(F/A,AllocationOccurrence),
6086 get_max_occurrence(F/A,MaxOccurrence),
6087 ( chr_pp_flag(debugable,off), MaxOccurrence < AllocationOccurrence ->
6088 ( only_ground_indexed_arguments(F/A) ->
6089 gen_insert_constraint_internal_goal(F/A,Body,AllArgs,Args,Susp)
6091 gen_cond_attach_goal(F/A,Body,AllArgs,Args,Susp)
6093 ; vars_susp(A,Args,Susp,AllArgs),
6094 gen_uncond_attach_goal(F/A,Susp,Args,Body,_)
6096 build_head(F,A,Id,AllArgs,Head),
6097 Clause = ( Head :- Body ),
6098 add_dummy_location(Clause,LocatedClause),
6099 L = [LocatedClause | T]
6104 :- chr_constraint use_auxiliary_predicate/1.
6105 :- chr_option(mode,use_auxiliary_predicate(+)).
6107 :- chr_constraint use_auxiliary_predicate/2.
6108 :- chr_option(mode,use_auxiliary_predicate(+,+)).
6110 :- chr_constraint is_used_auxiliary_predicate/1.
6111 :- chr_option(mode,is_used_auxiliary_predicate(+)).
6113 :- chr_constraint is_used_auxiliary_predicate/2.
6114 :- chr_option(mode,is_used_auxiliary_predicate(+,+)).
6117 use_auxiliary_predicate(P) \ use_auxiliary_predicate(P) <=> true.
6119 use_auxiliary_predicate(P,C) \ use_auxiliary_predicate(P,C) <=> true.
6121 use_auxiliary_predicate(P) \ is_used_auxiliary_predicate(P) <=> true.
6123 use_auxiliary_predicate(P,_) \ is_used_auxiliary_predicate(P) <=> true.
6125 is_used_auxiliary_predicate(P) <=> fail.
6127 use_auxiliary_predicate(P) \ is_used_auxiliary_predicate(P,_) <=> true.
6128 use_auxiliary_predicate(P,C) \ is_used_auxiliary_predicate(P,C) <=> true.
6130 is_used_auxiliary_predicate(P,C) <=> fail.
6132 %------------------------------------------------------------------------------%
6133 % Only generate import statements for actually used modules.
6134 %------------------------------------------------------------------------------%
6136 :- chr_constraint use_auxiliary_module/1.
6137 :- chr_option(mode,use_auxiliary_module(+)).
6139 :- chr_constraint is_used_auxiliary_module/1.
6140 :- chr_option(mode,is_used_auxiliary_module(+)).
6143 use_auxiliary_module(P) \ use_auxiliary_module(P) <=> true.
6145 use_auxiliary_module(P) \ is_used_auxiliary_module(P) <=> true.
6147 is_used_auxiliary_module(P) <=> fail.
6149 % only called for constraints with
6151 % non-ground indexed argument
6152 gen_cond_attach_goal(F/A,Goal,AllArgs,Args,Susp) :-
6153 vars_susp(A,Args,Susp,AllArgs),
6154 make_suspension_continuation_goal(F/A,AllArgs,Closure),
6155 ( get_store_type(F/A,var_assoc_store(_,_)) ->
6158 attach_constraint_atom(F/A,Vars,Susp,Attach)
6161 insert_constraint_goal(F/A,Susp,Args,InsertCall),
6162 insert_constraint_internal_constraint_goal(F/A, Vars, Susp, Closure, Args,InsertGoal),
6163 ( may_trigger(F/A) ->
6164 activate_constraint_goal(F/A,(InsertCall,Attach),Vars,Susp,_,ActivateGoal),
6168 InsertGoal, % insert_constraint_internal(Stored,Vars,Susp,Closure,F,Args)
6172 ActivateGoal % activate_constraint(Stored,Vars,Susp,_)
6178 InsertGoal, % insert_constraint_internal(Stored,Vars,Susp,Closure,F,Args),
6184 gen_insert_constraint_internal_goal(F/A,Goal,AllArgs,Args,Susp) :-
6185 vars_susp(A,Args,Susp,AllArgs),
6186 make_suspension_continuation_goal(F/A,AllArgs,Cont),
6187 ( \+ only_ground_indexed_arguments(F/A), \+ get_store_type(F/A,var_assoc_store(_,_)) ->
6188 attach_constraint_atom(F/A,Vars,Susp,Attach)
6193 insert_constraint_goal(F/A,Susp,Args,InsertCall),
6194 insert_constraint_internal_constraint_goal(F/A, Vars, Susp, Cont, Args,InsertInternalGoal),
6195 ( only_ground_indexed_arguments(F/A), chr_pp_flag(debugable,off) ->
6198 InsertInternalGoal, % insert_constraint_internal(Susp,F,Args),
6204 InsertInternalGoal, % insert_constraint_internal(_,Vars,Susp,Cont,F,Args),
6210 gen_uncond_attach_goal(FA,Susp,Args,AttachGoal,Generation) :-
6211 ( \+ only_ground_indexed_arguments(FA), \+ get_store_type(FA,var_assoc_store(_,_)) ->
6212 attach_constraint_atom(FA,Vars,Susp,Attach)
6216 insert_constraint_goal(FA,Susp,Args,InsertCall),
6217 ( chr_pp_flag(late_allocation,on) ->
6218 activate_constraint_goal(FA,(InsertCall,Attach),Vars,Susp,Generation,AttachGoal)
6220 activate_constraint_goal(FA,true,Vars,Susp,Generation,AttachGoal)
6223 %-------------------------------------------------------------------------------
6224 :- chr_constraint occurrences_code/6.
6225 :- chr_option(mode,occurrences_code(+,+,+,+,+,+)).
6226 %-------------------------------------------------------------------------------
6227 max_occurrence(C,MO) \ occurrences_code(C,O,Id,NId,L,T)
6230 occurrences_code(C,O,Id,NId,L,T)
6232 occurrence_code(C,O,Id,Id1,L,L1),
6234 occurrences_code(C,NO,Id1,NId,L1,T).
6235 %-------------------------------------------------------------------------------
6236 :- chr_constraint occurrence_code/6.
6237 :- chr_option(mode,occurrence_code(+,+,+,+,+,+)).
6238 %-------------------------------------------------------------------------------
6239 occurrence(C,O,RuleNb,ID,_), passive(RuleNb,ID) \ occurrence_code(C,O,Id,NId,L,T)
6241 ( named_history(RuleNb,_,_) ->
6242 does_use_history(C,O)
6248 occurrence(C,O,RuleNb,ID,_), rule(RuleNb,PragmaRule) \ occurrence_code(C,O,Id,NId,L,T)
6250 PragmaRule = pragma(rule(Heads1,Heads2,_,_),ids(IDs1,IDs2),_,_,_),
6251 ( select2(ID,Head1,IDs1,Heads1,RIDs1,RHeads1) ->
6253 head1_code(Head1,ID,RHeads1,RIDs1,PragmaRule,C,O,Id,L,T)
6254 ; select2(ID,Head2,IDs2,Heads2,RIDs2,RHeads2) ->
6256 head2_code(Head2,ID,RHeads2,RIDs2,PragmaRule,C,O,Id,L,L1),
6257 ( should_skip_to_next_id(C,O) ->
6259 ( unconditional_occurrence(C,O) ->
6262 gen_alloc_inc_clause(C,O,Id,L1,T)
6270 occurrence_code(C,O,_,_,_,_)
6272 chr_error(internal,'occurrence_code/6: missing information to compile ~w:~w\n',[C,O]).
6273 %-------------------------------------------------------------------------------
6275 %% Generate code based on one removed head of a CHR rule
6276 head1_code(Head,ID,OtherHeads,OtherIDs,PragmaRule,FA,O,Id,L,T) :-
6277 PragmaRule = pragma(Rule,_,_,_Name,RuleNb),
6278 Rule = rule(_,Head2,_,_),
6280 reorder_heads(RuleNb,Head,OtherHeads,OtherIDs,NOtherHeads,NOtherIDs),
6281 simplification_code(Head,ID,NOtherHeads,NOtherIDs,PragmaRule,FA,O,Id,L,T)
6283 simpagation_head1_code(Head,ID,OtherHeads,OtherIDs,PragmaRule,FA,O,Id,L,T)
6286 %% Generate code based on one persistent head of a CHR rule
6287 head2_code(Head,ID,OtherHeads,OtherIDs,PragmaRule,FA,O,Id,L,T) :-
6288 PragmaRule = pragma(Rule,_,_,_Name,RuleNb),
6289 Rule = rule(Head1,_,_,_),
6291 reorder_heads(RuleNb,Head,OtherHeads,OtherIDs,NOtherHeads,NOtherIDs),
6292 propagation_code(Head,ID,NOtherHeads,NOtherIDs,Rule,RuleNb,FA,O,Id,L,T)
6294 simpagation_head2_code(Head,ID,OtherHeads,OtherIDs,PragmaRule,FA,O,Id,L,T)
6297 gen_alloc_inc_clause(F/A,O,Id,L,T) :-
6298 vars_susp(A,Vars,Susp,VarsSusp),
6299 build_head(F,A,Id,VarsSusp,Head),
6301 build_head(F,A,IncId,VarsSusp,CallHead),
6302 gen_occ_allocation(F/A,O,Vars,Susp,ConditionalAlloc),
6309 add_dummy_location(Clause,LocatedClause),
6310 L = [LocatedClause|T].
6312 gen_occ_allocation(FA,O,Vars,Susp,Goal) :-
6313 get_allocation_occurrence(FA,AO),
6314 get_occurrence_code_id(FA,AO,AId),
6315 get_occurrence_code_id(FA,O,Id),
6316 ( chr_pp_flag(debugable,off), Id == AId ->
6317 allocate_constraint_goal(FA,Susp,Vars,Goal0),
6318 ( may_trigger(FA) ->
6319 Goal = (var(Susp) -> Goal0 ; true)
6327 gen_occ_allocation_in_guard(FA,O,Vars,Susp,Goal) :-
6328 get_allocation_occurrence(FA,AO),
6329 ( chr_pp_flag(debugable,off), O < AO ->
6330 allocate_constraint_goal(FA,Susp,Vars,Goal0),
6331 ( may_trigger(FA) ->
6332 Goal = (var(Susp) -> Goal0 ; true)
6340 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6342 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6344 % Reorders guard goals with respect to partner constraint retrieval goals and
6345 % active constraint. Returns combined partner retrieval + guard goal.
6347 guard_via_reschedule_new(Retrievals,GuardList,Prelude,GuardListSkeleton,LookupSkeleton,GoalSkeleton) :-
6348 ( chr_pp_flag(guard_via_reschedule,on) ->
6349 guard_via_reschedule_main_new(Retrievals,GuardList,Prelude,GuardListSkeleton,LookupSkeleton,ScheduleSkeleton),
6350 list2conj(ScheduleSkeleton,GoalSkeleton)
6352 length(Retrievals,RL), length(LookupSkeleton,RL),
6353 length(GuardList,GL), length(GuardListSkeleton,GL),
6354 append(LookupSkeleton,GuardListSkeleton,GoalListSkeleton),
6355 list2conj(GoalListSkeleton,GoalSkeleton)
6357 guard_via_reschedule_main_new(PartnerLookups,GuardList,ActiveHead,
6358 GuardListSkeleton,LookupSkeleton,ScheduleSkeleton) :-
6359 initialize_unit_dictionary(ActiveHead,Dict),
6360 maplist(wrap_in_functor(lookup),PartnerLookups,WrappedPartnerLookups),
6361 maplist(wrap_in_functor(guard),GuardList,WrappedGuardList),
6362 build_units(WrappedPartnerLookups,WrappedGuardList,Dict,Units),
6363 dependency_reorder(Units,NUnits),
6364 wrappedunits2lists(NUnits,IndexedGuardListSkeleton,LookupSkeleton,ScheduleSkeleton),
6365 sort(IndexedGuardListSkeleton,SortedIndexedGuardListSkeleton),
6366 snd_of_pairs(SortedIndexedGuardListSkeleton,GuardListSkeleton).
6368 wrappedunits2lists([],[],[],[]).
6369 wrappedunits2lists([unit(N,WrappedGoal,_,_)|Units],Gs,Ls,Ss) :-
6370 Ss = [GoalCopy|TSs],
6371 ( WrappedGoal = lookup(Goal) ->
6372 Ls = [GoalCopy|TLs],
6374 ; WrappedGoal = guard(Goal) ->
6375 Gs = [N-GoalCopy|TGs],
6378 wrappedunits2lists(Units,TGs,TLs,TSs).
6380 guard_splitting(Rule,SplitGuardList) :-
6381 Rule = rule(H1,H2,Guard,_),
6382 append(H1,H2,Heads),
6383 conj2list(Guard,GuardList),
6384 term_variables(Heads,HeadVars),
6385 split_off_simple_guard_new(GuardList,HeadVars,GuardPrefix,RestGuardList),
6386 append(GuardPrefix,[RestGuard],SplitGuardList),
6387 term_variables(RestGuardList,GuardVars1),
6388 % variables that are declared to be ground don't need to be locked
6389 ground_vars(Heads,GroundVars),
6390 list_difference_eq(HeadVars,GroundVars,LockableHeadVars),
6391 intersect_eq(LockableHeadVars,GuardVars1,GuardVars),
6392 ( chr_pp_flag(guard_locks,on),
6393 bagof(('chr lock'(X)) - ('chr unlock'(X)), (lists:member(X,GuardVars)), LocksUnlocks) ->
6394 once(pairup(Locks,Unlocks,LocksUnlocks))
6399 list2conj(Locks,LockPhase),
6400 list2conj(Unlocks,UnlockPhase),
6401 list2conj(RestGuardList,RestGuard1),
6402 RestGuard = (LockPhase,(RestGuard1,UnlockPhase)).
6404 guard_body_copies3(Rule,GuardList,VarDict,GuardCopyList,BodyCopy) :-
6405 Rule = rule(_,_,_,Body),
6406 my_term_copy(GuardList,VarDict,VarDict2,GuardCopyList),
6407 my_term_copy(Body,VarDict2,BodyCopy).
6410 split_off_simple_guard_new([],_,[],[]).
6411 split_off_simple_guard_new([G|Gs],VarDict,S,C) :-
6412 ( simple_guard_new(G,VarDict) ->
6414 split_off_simple_guard_new(Gs,VarDict,Ss,C)
6420 % simple guard: cheap and benign (does not bind variables)
6421 simple_guard_new(G,Vars) :-
6422 builtin_binds_b(G,BoundVars),
6423 not(( member(V,BoundVars),
6424 memberchk_eq(V,Vars)
6427 dependency_reorder(Units,NUnits) :-
6428 dependency_reorder(Units,[],NUnits).
6430 dependency_reorder([],Acc,Result) :-
6431 reverse(Acc,Result).
6433 dependency_reorder([Unit|Units],Acc,Result) :-
6434 Unit = unit(_GID,_Goal,Type,GIDs),
6438 dependency_insert(Acc,Unit,GIDs,NAcc)
6440 dependency_reorder(Units,NAcc,Result).
6442 dependency_insert([],Unit,_,[Unit]).
6443 dependency_insert([X|Xs],Unit,GIDs,L) :-
6444 X = unit(GID,_,_,_),
6445 ( memberchk(GID,GIDs) ->
6449 dependency_insert(Xs,Unit,GIDs,T)
6452 build_units(Retrievals,Guard,InitialDict,Units) :-
6453 build_retrieval_units(Retrievals,1,N,InitialDict,Dict,Units,Tail),
6454 build_guard_units(Guard,N,Dict,Tail).
6456 build_retrieval_units([],N,N,Dict,Dict,L,L).
6457 build_retrieval_units([U|Us],N,M,Dict,NDict,L,T) :-
6458 term_variables(U,Vs),
6459 update_unit_dictionary(Vs,N,Dict,Dict1,[],GIDs),
6460 L = [unit(N,U,fixed,GIDs)|L1],
6462 build_retrieval_units(Us,N1,M,Dict1,NDict,L1,T).
6464 initialize_unit_dictionary(Term,Dict) :-
6465 term_variables(Term,Vars),
6466 pair_all_with(Vars,0,Dict).
6468 update_unit_dictionary([],_,Dict,Dict,GIDs,GIDs).
6469 update_unit_dictionary([V|Vs],This,Dict,NDict,GIDs,NGIDs) :-
6470 ( lookup_eq(Dict,V,GID) ->
6471 ( (GID == This ; memberchk(GID,GIDs) ) ->
6478 Dict1 = [V - This|Dict],
6481 update_unit_dictionary(Vs,This,Dict1,NDict,GIDs1,NGIDs).
6483 build_guard_units(Guard,N,Dict,Units) :-
6485 Units = [unit(N,Goal,fixed,[])]
6486 ; Guard = [Goal|Goals] ->
6487 term_variables(Goal,Vs),
6488 update_unit_dictionary2(Vs,N,Dict,NDict,[],GIDs),
6489 Units = [unit(N,Goal,movable,GIDs)|RUnits],
6491 build_guard_units(Goals,N1,NDict,RUnits)
6494 update_unit_dictionary2([],_,Dict,Dict,GIDs,GIDs).
6495 update_unit_dictionary2([V|Vs],This,Dict,NDict,GIDs,NGIDs) :-
6496 ( lookup_eq(Dict,V,GID) ->
6497 ( (GID == This ; memberchk(GID,GIDs) ) ->
6502 Dict1 = [V - This|Dict]
6504 Dict1 = [V - This|Dict],
6507 update_unit_dictionary2(Vs,This,Dict1,NDict,GIDs1,NGIDs).
6509 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6511 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6513 %% / ___| ___| |_ / ___| ___ _ __ ___ __ _ _ __ | |_(_) ___ ___ _
6514 %% \___ \ / _ \ __| \___ \ / _ \ '_ ` _ \ / _` | '_ \| __| |/ __/ __(_)
6515 %% ___) | __/ |_ ___) | __/ | | | | | (_| | | | | |_| | (__\__ \_
6516 %% |____/ \___|\__| |____/ \___|_| |_| |_|\__,_|_| |_|\__|_|\___|___(_)
6519 %% | | | |_ __ (_) __ _ _ _ ___ |_ _|_ __ / _| ___ _ __ ___ _ __ ___ ___
6520 %% | | | | '_ \| |/ _` | | | |/ _ \ | || '_ \| |_ / _ \ '__/ _ \ '_ \ / __/ _ \
6521 %% | |_| | | | | | (_| | |_| | __/ | || | | | _| __/ | | __/ | | | (_| __/
6522 %% \___/|_| |_|_|\__, |\__,_|\___| |___|_| |_|_| \___|_| \___|_| |_|\___\___|
6525 functional_dependency/4,
6526 get_functional_dependency/4.
6528 :- chr_option(mode,functional_dependency(+,+,?,?)).
6529 :- chr_option(mode,get_functional_dependency(+,+,?,?)).
6531 allocation_occurrence(C,AO), occurrence(C,O,RuleNb,_,_) \ functional_dependency(C,RuleNb,Pattern,Key)
6535 functional_dependency(C,1,Pattern,Key).
6537 functional_dependency(C,RuleNb1,Pattern,Key) \ get_functional_dependency(C,RuleNb2,QPattern,QKey)
6541 QPattern = Pattern, QKey = Key.
6542 get_functional_dependency(_,_,_,_)
6546 functional_dependency_analysis(Rules) :-
6547 ( fail, chr_pp_flag(functional_dependency_analysis,on) ->
6548 functional_dependency_analysis_main(Rules)
6553 functional_dependency_analysis_main([]).
6554 functional_dependency_analysis_main([PRule|PRules]) :-
6555 ( discover_unique_pattern(PRule,C,RuleNb,Pattern,Key) ->
6556 functional_dependency(C,RuleNb,Pattern,Key)
6560 functional_dependency_analysis_main(PRules).
6562 discover_unique_pattern(PragmaRule,F/A,RuleNb,Pattern,Key) :-
6563 PragmaRule = pragma(Rule,_,_,Name,RuleNb),
6564 Rule = rule(H1,H2,Guard,_),
6572 check_unique_constraints(C1,C2,Guard,RuleNb,List),
6573 term_variables(C1,Vs),
6576 lookup_eq(List,V1,V2),
6579 select_pragma_unique_variables(Vs,List,Key1),
6580 copy_term_nat(C1-Key1,Pattern-Key),
6583 select_pragma_unique_variables([],_,[]).
6584 select_pragma_unique_variables([V|Vs],List,L) :-
6585 ( lookup_eq(List,V,_) ->
6590 select_pragma_unique_variables(Vs,List,T).
6592 % depends on functional dependency analysis
6593 % and shape of rule: C1 \ C2 <=> true.
6594 set_semantics_rules(Rules) :-
6595 ( fail, chr_pp_flag(set_semantics_rule,on) ->
6596 set_semantics_rules_main(Rules)
6601 set_semantics_rules_main([]).
6602 set_semantics_rules_main([R|Rs]) :-
6603 set_semantics_rule_main(R),
6604 set_semantics_rules_main(Rs).
6606 set_semantics_rule_main(PragmaRule) :-
6607 PragmaRule = pragma(Rule,IDs,Pragmas,_,RuleNb),
6608 ( Rule = rule([C1],[C2],true,_),
6609 IDs = ids([ID1],[ID2]),
6610 \+ is_passive(RuleNb,ID1),
6612 get_functional_dependency(F/A,RuleNb,Pattern,Key),
6613 copy_term_nat(Pattern-Key,C1-Key1),
6614 copy_term_nat(Pattern-Key,C2-Key2),
6621 check_unique_constraints(C1,C2,G,RuleNb,List) :-
6622 \+ any_passive_head(RuleNb),
6623 variable_replacement(C1-C2,C2-C1,List),
6624 copy_with_variable_replacement(G,OtherG,List),
6626 once(entails_b(NotG,OtherG)).
6628 % checks for rules of the shape ...,C1,C2... (<|=)=> ...
6629 % where C1 and C2 are symmteric constraints
6630 symmetry_analysis(Rules) :-
6631 ( chr_pp_flag(check_unnecessary_active,off) ->
6634 symmetry_analysis_main(Rules)
6637 symmetry_analysis_main([]).
6638 symmetry_analysis_main([R|Rs]) :-
6639 R = pragma(Rule,ids(IDs1,IDs2),_,_,RuleNb),
6640 Rule = rule(H1,H2,_,_),
6641 ( ( \+ chr_pp_flag(check_unnecessary_active,simplification) ; H2 == [] ), H1 \== [] ->
6642 symmetry_analysis_heads_simplification(H1,IDs1,[],[],Rule,RuleNb),
6643 symmetry_analysis_heads_propagation(H2,IDs2,[],[],Rule,RuleNb)
6647 symmetry_analysis_main(Rs).
6649 symmetry_analysis_heads_simplification([],[],_,_,_,_).
6650 symmetry_analysis_heads_simplification([H|Hs],[ID|IDs],PreHs,PreIDs,Rule,RuleNb) :-
6651 ( \+ is_passive(RuleNb,ID),
6652 member2(PreHs,PreIDs,PreH-PreID),
6653 \+ is_passive(RuleNb,PreID),
6654 variable_replacement(PreH,H,List),
6655 copy_with_variable_replacement(Rule,Rule2,List),
6656 identical_guarded_rules(Rule,Rule2) ->
6661 symmetry_analysis_heads_simplification(Hs,IDs,[H|PreHs],[ID|PreIDs],Rule,RuleNb).
6663 symmetry_analysis_heads_propagation([],[],_,_,_,_).
6664 symmetry_analysis_heads_propagation([H|Hs],[ID|IDs],PreHs,PreIDs,Rule,RuleNb) :-
6665 ( \+ is_passive(RuleNb,ID),
6666 member2(PreHs,PreIDs,PreH-PreID),
6667 \+ is_passive(RuleNb,PreID),
6668 variable_replacement(PreH,H,List),
6669 copy_with_variable_replacement(Rule,Rule2,List),
6670 identical_rules(Rule,Rule2) ->
6675 symmetry_analysis_heads_propagation(Hs,IDs,[H|PreHs],[ID|PreIDs],Rule,RuleNb).
6677 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6679 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6680 %% ____ _ _ _ __ _ _ _
6681 %% / ___|(_)_ __ ___ _ __ | (_)/ _(_) ___ __ _| |_(_) ___ _ __
6682 %% \___ \| | '_ ` _ \| '_ \| | | |_| |/ __/ _` | __| |/ _ \| '_ \
6683 %% ___) | | | | | | | |_) | | | _| | (_| (_| | |_| | (_) | | | |
6684 %% |____/|_|_| |_| |_| .__/|_|_|_| |_|\___\__,_|\__|_|\___/|_| |_|
6688 simplification_code(Head,ID,RestHeads,RestIDs,PragmaRule,F/A,O,Id,L,T) :-
6689 PragmaRule = pragma(Rule,_,Pragmas,_,RuleNb),
6690 head_info(Head,A,_Vars,Susp,HeadVars,HeadPairs),
6691 build_head(F,A,Id,HeadVars,ClauseHead),
6692 get_constraint_mode(F/A,Mode),
6693 head_arg_matches(HeadPairs,Mode,[],FirstMatching,VarDict1,[],GroundVars),
6696 guard_splitting(Rule,GuardList0),
6697 ( is_stored_in_guard(F/A, RuleNb) ->
6698 GuardList = [Hole1|GuardList0]
6700 GuardList = GuardList0
6702 guard_via_reschedule_new(RestHeads,GuardList,Head,GuardCopyList,GetRestHeads,RescheduledTest),
6704 rest_heads_retrieval_and_matching(RestHeads,RestIDs,Head,GetRestHeads,Susps,VarDict1,VarDict,[],[],[],GroundVars,_),
6706 guard_body_copies3(Rule,GuardList,VarDict,GuardCopyList,BodyCopy),
6708 ( is_stored_in_guard(F/A, RuleNb) ->
6709 gen_occ_allocation_in_guard(F/A,O,Vars,Susp,Allocation),
6710 gen_uncond_attach_goal(F/A,Susp,Vars,Attachment,_),
6711 GuardCopyList = [Hole1Copy|_],
6712 Hole1Copy = (Allocation, Attachment)
6718 partner_constraint_detachments(Susps,RestHeads,VarDict,SuspsDetachments),
6719 active_constraint_detachment(Id,Susp,Head,VarDict,SuspDetachment),
6721 ( chr_pp_flag(debugable,on) ->
6722 Rule = rule(_,_,Guard,Body),
6723 my_term_copy(Guard - Body, VarDict, DebugGuard - DebugBody),
6724 sort_by_key([Susp|Susps],[ID|RestIDs],SortedSusps),
6725 DebugTry = 'chr debug_event'( try(SortedSusps,[],DebugGuard,DebugBody)),
6726 DebugApply = 'chr debug_event'(apply(SortedSusps,[],DebugGuard,DebugBody)),
6727 instrument_goal(ActualCut,DebugTry,DebugApply,Cut)
6731 ( unconditional_occurrence(F/A,O), chr_pp_flag(late_allocation,on) -> ActualCut = true ; ActualCut = (!) ),
6732 Clause = ( ClauseHead :-
6740 add_location(Clause,RuleNb,LocatedClause),
6741 L = [LocatedClause | T].
6745 add_location(Clause,RuleNb,NClause) :-
6746 ( chr_pp_flag(line_numbers,on) ->
6747 get_chr_source_file(File),
6748 get_line_number(RuleNb,LineNb),
6749 NClause = '$source_location'(File,LineNb):Clause
6754 add_dummy_location(Clause,NClause) :-
6755 ( chr_pp_flag(line_numbers,on) ->
6756 get_chr_source_file(File),
6757 NClause = '$source_location'(File,1):Clause
6761 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
6762 %% head_arg_matches(+Pairs,+Modes,+VarDict,-Goal,-NVarDict) is det.
6764 % Return goal matching newly introduced variables with variables in
6765 % previously looked-up heads.
6766 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
6767 head_arg_matches(Pairs,Modes,VarDict,Goal,NVarDict) :-
6768 head_arg_matches(Pairs,Modes,VarDict,Goal,NVarDict,[],_).
6770 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
6771 %% head_arg_matches(+Pairs,+Modes,+VarDict,-Goal,-NVarDict,+GroundVars,-NGroundVars) is det.
6772 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
6773 head_arg_matches(Pairs,Modes,VarDict,Goal,NVarDict,GroundVars,NGroundVars) :-
6774 head_arg_matches_(Pairs,Modes,VarDict,GroundVars,GoalList,NVarDict,NGroundVars),
6775 list2conj(GoalList,Goal).
6777 head_arg_matches_([],[],VarDict,GroundVars,[],VarDict,GroundVars).
6778 head_arg_matches_([silent(Arg-Var)| Rest],[Mode|Modes],VarDict,GroundVars,GoalList,NVarDict,NGroundVars) :- !,
6780 term_variables(Arg,GroundVars0,GroundVars),
6781 head_arg_matches_(Rest,Modes,VarDict,GroundVars0,GoalList,NVarDict,NGroundVars)
6783 head_arg_matches_(Rest,Modes,VarDict,GroundVars,GoalList,NVarDict,NGroundVars)
6785 head_arg_matches_([Arg-Var| Rest],[Mode|Modes],VarDict,GroundVars,GoalList,NVarDict,NGroundVars) :-
6787 ( lookup_eq(VarDict,Arg,OtherVar) ->
6789 ( memberchk_eq(Arg,GroundVars) ->
6790 GoalList = [Var = OtherVar | RestGoalList],
6791 GroundVars1 = GroundVars
6793 GoalList = [Var == OtherVar | RestGoalList],
6794 GroundVars1 = [Arg|GroundVars]
6797 GoalList = [Var == OtherVar | RestGoalList],
6798 GroundVars1 = GroundVars
6802 VarDict1 = [Arg-Var | VarDict],
6803 GoalList = RestGoalList,
6805 GroundVars1 = [Arg|GroundVars]
6807 GroundVars1 = GroundVars
6812 ; ground(Arg), Arg = '$chr_identifier_match'(ActualArg,IndexType) ->
6813 identifier_label_atom(IndexType,Var,ActualArg,Goal),
6814 GoalList = [Goal|RestGoalList],
6816 GroundVars1 = GroundVars,
6821 GoalList = [ Var = Arg | RestGoalList]
6823 GoalList = [ Var == Arg | RestGoalList]
6826 GroundVars1 = GroundVars,
6829 ; Mode == (+), is_ground(GroundVars,Arg) ->
6830 copy_with_variable_replacement(Arg,ArgCopy,VarDict),
6831 GoalList = [ Var = ArgCopy | RestGoalList],
6833 GroundVars1 = GroundVars,
6836 ; Mode == (?), is_ground(GroundVars,Arg) ->
6837 copy_with_variable_replacement(Arg,ArgCopy,VarDict),
6838 GoalList = [ Var == ArgCopy | RestGoalList],
6840 GroundVars1 = GroundVars,
6845 functor(Term,Fct,N),
6848 GoalList = [ Var = Term | RestGoalList ]
6850 GoalList = [ nonvar(Var), Var = Term | RestGoalList ]
6852 pairup(Args,Vars,NewPairs),
6853 append(NewPairs,Rest,Pairs),
6854 replicate(N,Mode,NewModes),
6855 append(NewModes,Modes,RestModes),
6857 GroundVars1 = GroundVars
6859 head_arg_matches_(Pairs,RestModes,VarDict1,GroundVars1,RestGoalList,NVarDict,NGroundVars).
6861 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
6862 % add_heads_types(+ListOfHeads,+VarTypes,-NVarTypes) is det.
6863 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
6864 add_heads_types([],VarTypes,VarTypes).
6865 add_heads_types([Head|Heads],VarTypes,NVarTypes) :-
6866 add_head_types(Head,VarTypes,VarTypes1),
6867 add_heads_types(Heads,VarTypes1,NVarTypes).
6869 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
6870 % add_head_types(+Head,+VarTypes,-NVarTypes) is det.
6871 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
6872 add_head_types(Head,VarTypes,NVarTypes) :-
6874 get_constraint_type_det(F/A,ArgTypes),
6876 add_args_types(Args,ArgTypes,VarTypes,NVarTypes).
6878 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
6879 % add_args_types(+Terms,+Types,+VarTypes,-NVarTypes) is det.
6880 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
6881 add_args_types([],[],VarTypes,VarTypes).
6882 add_args_types([Arg|Args],[Type|Types],VarTypes,NVarTypes) :-
6883 add_arg_types(Arg,Type,VarTypes,VarTypes1),
6884 add_args_types(Args,Types,VarTypes1,NVarTypes).
6886 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
6887 % add_arg_types(+Term,+Type,+VarTypes,-NVarTypes) is det.
6888 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
6889 add_arg_types(Term,Type,VarTypes,NVarTypes) :-
6891 ( lookup_eq(VarTypes,Term,_) ->
6892 NVarTypes = VarTypes
6894 NVarTypes = [Term-Type|VarTypes]
6897 NVarTypes = VarTypes
6898 ; % TODO improve approximation!
6899 term_variables(Term,Vars),
6901 replicate(VarNb,any,Types),
6902 add_args_types(Vars,Types,VarTypes,NVarTypes)
6907 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
6908 %% add_heads_ground_variables(+ListOfHeads,+GroundVars,-NGroundVars) is det.
6910 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
6911 add_heads_ground_variables([],GroundVars,GroundVars).
6912 add_heads_ground_variables([Head|Heads],GroundVars,NGroundVars) :-
6913 add_head_ground_variables(Head,GroundVars,GroundVars1),
6914 add_heads_ground_variables(Heads,GroundVars1,NGroundVars).
6916 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
6917 %% add_head_ground_variables(+Head,+GroundVars,-GroundVars) is det.
6919 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
6920 add_head_ground_variables(Head,GroundVars,NGroundVars) :-
6922 get_constraint_mode(F/A,ArgModes),
6924 add_arg_ground_variables(Args,ArgModes,GroundVars,NGroundVars).
6927 add_arg_ground_variables([],[],GroundVars,GroundVars).
6928 add_arg_ground_variables([Arg|Args],[Mode|Modes],GroundVars,NGroundVars) :-
6930 term_variables(Arg,Vars),
6931 add_var_ground_variables(Vars,GroundVars,GroundVars1)
6933 GroundVars = GroundVars1
6935 add_arg_ground_variables(Args,Modes,GroundVars1,NGroundVars).
6937 add_var_ground_variables([],GroundVars,GroundVars).
6938 add_var_ground_variables([Var|Vars],GroundVars,NGroundVars) :-
6939 ( memberchk_eq(Var,GroundVars) ->
6940 GroundVars1 = GroundVars
6942 GroundVars1 = [Var|GroundVars]
6944 add_var_ground_variables(Vars,GroundVars1,NGroundVars).
6945 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
6946 %% is_ground(+GroundVars,+Term) is semidet.
6948 % Determine whether =Term= is always ground.
6949 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
6950 is_ground(GroundVars,Term) :-
6955 maplist(is_ground(GroundVars),Args)
6957 memberchk_eq(Term,GroundVars)
6960 %% check_ground(+GroundVars,+Term,-Goal) is det.
6962 % Return runtime check to see whether =Term= is ground.
6963 check_ground(GroundVars,Term,Goal) :-
6964 term_variables(Term,Variables),
6965 check_ground_variables(Variables,GroundVars,Goal).
6967 check_ground_variables([],_,true).
6968 check_ground_variables([Var|Vars],GroundVars,Goal) :-
6969 ( memberchk_eq(Var,GroundVars) ->
6970 check_ground_variables(Vars,GroundVars,Goal)
6972 Goal = (ground(Var), RGoal),
6973 check_ground_variables(Vars,GroundVars,RGoal)
6976 rest_heads_retrieval_and_matching(Heads,IDs,ActiveHead,GoalList,Susps,VarDict,NVarDict,PrevHs,PrevSusps,AttrDict) :-
6977 rest_heads_retrieval_and_matching(Heads,IDs,ActiveHead,GoalList,Susps,VarDict,NVarDict,PrevHs,PrevSusps,AttrDict,[],_).
6979 rest_heads_retrieval_and_matching(Heads,IDs,ActiveHead,GoalList,Susps,VarDict,NVarDict,PrevHs,PrevSusps,AttrDict,GroundVars,NGroundVars) :-
6981 rest_heads_retrieval_and_matching_n(Heads,IDs,PrevHs,PrevSusps,ActiveHead,GoalList,Susps,VarDict,NVarDict,AttrDict,GroundVars,NGroundVars)
6986 GroundVars = NGroundVars
6989 rest_heads_retrieval_and_matching_n([],_,_,_,_,[],[],VarDict,VarDict,_AttrDict,GroundVars,GroundVars).
6990 rest_heads_retrieval_and_matching_n([H|Hs],[ID|IDs],PrevHs,PrevSusps,ActiveHead,
6991 [Goal|Goals],[Susp|Susps],VarDict,NVarDict,_AttrDict,GroundVars,NGroundVars) :-
6993 head_info(H,A,Vars,_,_,Pairs),
6994 get_store_type(F/A,StoreType),
6995 ( StoreType == default ->
6996 passive_head_via(H,[ActiveHead|PrevHs],VarDict,ViaGoal,VarSusps),
6997 delay_phase_end(validate_store_type_assumptions,
6998 ( static_suspension_term(F/A,Suspension),
6999 get_static_suspension_term_field(arguments,F/A,Suspension,Vars),
7000 get_static_suspension_field(F/A,Suspension,state,active,GetState)
7003 % create_get_mutable_ref(active,State,GetMutable),
7004 get_constraint_mode(F/A,Mode),
7005 head_arg_matches(Pairs,Mode,VarDict,MatchingGoal,VarDict1,GroundVars,GroundVars1),
7007 sbag_member_call(Susp,VarSusps,Sbag),
7008 ExistentialLookup = (
7011 Susp = Suspension, % not inlined
7015 delay_phase_end(validate_store_type_assumptions,
7016 ( static_suspension_term(F/A,Suspension),
7017 get_static_suspension_term_field(arguments,F/A,Suspension,Vars)
7020 existential_lookup(StoreType,H,[ActiveHead|PrevHs],VarDict,GroundVars,Suspension,ExistentialLookup,Susp,Pairs,NPairs),
7021 get_constraint_mode(F/A,Mode),
7022 NMode = Mode, % filter_mode(NPairs,Pairs,Mode,NMode),
7023 head_arg_matches(NPairs,NMode,VarDict,MatchingGoal,VarDict1,GroundVars,GroundVars1)
7025 different_from_other_susps(H,Susp,PrevHs,PrevSusps,DiffSuspGoals),
7026 filter_append(NPairs,VarDict1,DA_), % order important here
7027 translate(GroundVars1,DA_,GroundVarsA),
7028 translate(GroundVars1,VarDict1,GroundVarsB),
7029 inline_matching_goal(MatchingGoal,MatchingGoal2,GroundVarsA,GroundVarsB),
7036 rest_heads_retrieval_and_matching_n(Hs,IDs,[H|PrevHs],[Susp|PrevSusps],ActiveHead,Goals,Susps,VarDict1,NVarDict,_NewAttrDict,GroundVars1,NGroundVars).
7038 inline_matching_goal(A==B,true,GVA,GVB) :-
7039 memberchk_eq(A,GVA),
7040 memberchk_eq(B,GVB),
7043 % inline_matching_goal(A=B,true,_,_) :- A=B, !.
7044 inline_matching_goal((A,B),(A2,B2),GVA,GVB) :- !,
7045 inline_matching_goal(A,A2,GVA,GVB),
7046 inline_matching_goal(B,B2,GVA,GVB).
7047 inline_matching_goal(X,X,_,_).
7050 filter_mode([],_,_,[]).
7051 filter_mode([Arg-Var|Rest],[_-V|R],[M|Ms],Modes) :-
7054 filter_mode(Rest,R,Ms,MT)
7056 filter_mode([Arg-Var|Rest],R,Ms,Modes)
7059 filter_append([],VarDict,VarDict).
7060 filter_append([X|Xs],VarDict,NVarDict) :-
7062 filter_append(Xs,VarDict,NVarDict)
7064 NVarDict = [X|NVarDict0],
7065 filter_append(Xs,VarDict,NVarDict0)
7068 check_unique_keys([],_).
7069 check_unique_keys([V|Vs],Dict) :-
7070 lookup_eq(Dict,V,_),
7071 check_unique_keys(Vs,Dict).
7073 % Generates tests to ensure the found constraint differs from previously found constraints
7074 % TODO: detect more cases where constraints need be different
7075 different_from_other_susps(Head,Susp,Heads,Susps,DiffSuspGoals) :-
7076 different_from_other_susps_(Heads,Susps,Head,Susp,DiffSuspGoalList),
7077 list2conj(DiffSuspGoalList,DiffSuspGoals).
7079 different_from_other_susps_(_,[],_,_,[]) :- !.
7080 different_from_other_susps_([PreHead|Heads],[PreSusp|Susps],Head,Susp,List) :-
7081 ( functor(Head,F,A), functor(PreHead,F,A),
7082 copy_term_nat(PreHead-Head,PreHeadCopy-HeadCopy),
7083 \+ \+ PreHeadCopy = HeadCopy ->
7085 List = [Susp \== PreSusp | Tail]
7089 different_from_other_susps_(Heads,Susps,Head,Susp,Tail).
7091 % passive_head_via(in,in,in,in,out,out,out) :-
7092 passive_head_via(Head,PrevHeads,VarDict,Goal,AllSusps) :-
7094 get_constraint_index(F/A,Pos),
7095 /* which static variables may contain runtime variables */
7096 common_variables(Head,PrevHeads,CommonVars0),
7097 ground_vars([Head],GroundVars),
7098 list_difference_eq(CommonVars0,GroundVars,CommonVars),
7099 /********************************************************/
7100 global_list_store_name(F/A,Name),
7101 GlobalGoal = nb_getval(Name,AllSusps),
7102 get_constraint_mode(F/A,ArgModes),
7105 ; member(CommonVar,CommonVars), nth1(I,ArgModes,(-)), arg(I,Head,Arg), Arg == CommonVar ->
7106 translate([CommonVar],VarDict,[Var]),
7107 gen_get_mod_constraints(F/A,Var,AttrGoal,AllSusps),
7110 translate(CommonVars,VarDict,Vars),
7111 add_heads_types(PrevHeads,[],TypeDict),
7112 my_term_copy(TypeDict,VarDict,TypeDictCopy),
7113 gen_get_mod_constraints(F/A,Vars,TypeDictCopy,ViaGoal,AttrGoal,AllSusps),
7122 common_variables(T,Ts,Vs) :-
7123 term_variables(T,V1),
7124 term_variables(Ts,V2),
7125 intersect_eq(V1,V2,Vs).
7127 gen_get_mod_constraints(FA,Vars,TypeDict,ViaGoal,AttrGoal,AllSusps) :-
7128 via_goal(Vars,TypeDict,ViaGoal,Var),
7129 get_target_module(Mod),
7131 ( get_attr(Var,Mod,TSusps),
7132 TSuspsEqSusps % TSusps = Susps
7134 get_max_constraint_index(N),
7136 TSuspsEqSusps = true, % TSusps = Susps
7139 get_constraint_index(FA,Pos),
7140 get_suspensions(N,Pos,TSusps,TSuspsEqSusps,AllSusps)
7142 via_goal(Vars,TypeDict,ViaGoal,Var) :-
7146 lookup_eq(TypeDict,A,Type),
7147 ( atomic_type(Type) ->
7151 ViaGoal = 'chr newvia_1'(A,Var)
7154 ViaGoal = 'chr newvia_2'(A,B,Var)
7156 ViaGoal = 'chr newvia'(Vars,Var)
7158 gen_get_mod_constraints(FA,Var,AttrGoal,AllSusps) :-
7159 get_target_module(Mod),
7161 ( get_attr(Var,Mod,TSusps),
7162 TSuspsEqSusps % TSusps = Susps
7164 get_max_constraint_index(N),
7166 TSuspsEqSusps = true, % TSusps = Susps
7169 get_constraint_index(FA,Pos),
7170 get_suspensions(N,Pos,TSusps,TSuspsEqSusps,AllSusps)
7173 guard_body_copies(Rule,VarDict,GuardCopy,BodyCopy) :-
7174 guard_body_copies2(Rule,VarDict,GuardCopyList,BodyCopy),
7175 list2conj(GuardCopyList,GuardCopy).
7177 guard_body_copies2(Rule,VarDict,GuardCopyList,BodyCopy) :-
7178 Rule = rule(_,H,Guard,Body),
7179 conj2list(Guard,GuardList),
7180 split_off_simple_guard(GuardList,VarDict,GuardPrefix,RestGuardList),
7181 my_term_copy(GuardPrefix-RestGuardList,VarDict,VarDict2,GuardPrefixCopy-RestGuardListCopyCore),
7183 append(GuardPrefixCopy,[RestGuardCopy],GuardCopyList),
7184 term_variables(RestGuardList,GuardVars),
7185 term_variables(RestGuardListCopyCore,GuardCopyVars),
7186 % variables that are declared to be ground don't need to be locked
7187 ground_vars(H,GroundVars),
7188 list_difference_eq(GuardVars,GroundVars,LockedGuardVars),
7189 ( chr_pp_flag(guard_locks,on),
7190 bagof(('chr lock'(Y)) - ('chr unlock'(Y)),
7191 X ^ (lists:member(X,LockedGuardVars), % X is a variable appearing in the original guard
7192 pairlist:lookup_eq(VarDict,X,Y), % translate X into new variable
7193 memberchk_eq(Y,GuardCopyVars) % redundant check? or multiple entries for X possible?
7196 once(pairup(Locks,Unlocks,LocksUnlocks))
7201 list2conj(Locks,LockPhase),
7202 list2conj(Unlocks,UnlockPhase),
7203 list2conj(RestGuardListCopyCore,RestGuardCopyCore),
7204 RestGuardCopy = (LockPhase,(RestGuardCopyCore,UnlockPhase)),
7205 my_term_copy(Body,VarDict2,BodyCopy).
7208 split_off_simple_guard([],_,[],[]).
7209 split_off_simple_guard([G|Gs],VarDict,S,C) :-
7210 ( simple_guard(G,VarDict) ->
7212 split_off_simple_guard(Gs,VarDict,Ss,C)
7218 % simple guard: cheap and benign (does not bind variables)
7219 simple_guard(G,VarDict) :-
7221 \+ (( member(V,Vars),
7222 lookup_eq(VarDict,V,_)
7225 active_constraint_detachment(Id,Susp,Head,VarDict,SuspDetachment) :-
7231 Id == [0], chr_pp_flag(store_in_guards, off)
7233 ( get_allocation_occurrence(C,AO),
7234 get_max_occurrence(C,MO),
7237 only_ground_indexed_arguments(C), chr_pp_flag(late_allocation,on) ->
7238 SuspDetachment = true
7240 gen_uncond_susp_detachment(Head,Susp,active,VarDict,UnCondSuspDetachment),
7241 ( chr_pp_flag(late_allocation,on) ->
7246 UnCondSuspDetachment
7249 SuspDetachment = UnCondSuspDetachment
7253 SuspDetachment = true
7256 partner_constraint_detachments([],[],_,true).
7257 partner_constraint_detachments([Susp|Susps],[Head|Heads],VarDict,(SuspDetachment,SuspsDetachments)) :-
7258 gen_uncond_susp_detachment(Head,Susp,partner,VarDict,SuspDetachment),
7259 partner_constraint_detachments(Susps,Heads,VarDict,SuspsDetachments).
7261 gen_uncond_susp_detachment(Head,Susp,Role,VarDict,SuspDetachment) :-
7265 SuspDetachment = ( DebugEvent, RemoveInternalGoal),
7266 ( chr_pp_flag(debugable,on) ->
7267 DebugEvent = 'chr debug_event'(remove(Susp))
7271 remove_constraint_goal(C,Susp,Vars,true,(DeleteCall,Detach),Role,RemoveInternalGoal),
7272 delete_constraint_goal(Head,Susp,VarDict,DeleteCall),
7273 ( \+ only_ground_indexed_arguments(C), \+ get_store_type(C,var_assoc_store(_,_)) ->
7274 detach_constraint_atom(C,Vars,Susp,Detach)
7279 SuspDetachment = true
7282 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7284 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7286 %% / ___|(_)_ __ ___ _ __ __ _ __ _ __ _| |_(_) ___ _ __ / |
7287 %% \___ \| | '_ ` _ \| '_ \ / _` |/ _` |/ _` | __| |/ _ \| '_ \ | |
7288 %% ___) | | | | | | | |_) | (_| | (_| | (_| | |_| | (_) | | | | | |
7289 %% |____/|_|_| |_| |_| .__/ \__,_|\__, |\__,_|\__|_|\___/|_| |_| |_|
7293 simpagation_head1_code(Head,ID,RestHeads,OtherIDs,PragmaRule,F/A,O,Id,L,T) :-
7294 PragmaRule = pragma(Rule,ids(_,Heads2IDs),Pragmas,_Name,RuleNb),
7295 Rule = rule(_Heads,Heads2,Guard,Body),
7297 head_info(Head,A,Vars,Susp,HeadVars,HeadPairs),
7298 get_constraint_mode(F/A,Mode),
7299 head_arg_matches(HeadPairs,Mode,[],FirstMatching,VarDict1,[],GroundVars),
7301 build_head(F,A,Id,HeadVars,ClauseHead),
7303 append(RestHeads,Heads2,Heads),
7304 append(OtherIDs,Heads2IDs,IDs),
7305 reorder_heads(RuleNb,Head,Heads,IDs,NHeads,NIDs),
7307 guard_splitting(Rule,GuardList0),
7308 ( is_stored_in_guard(F/A, RuleNb) ->
7309 GuardList = [Hole1|GuardList0]
7311 GuardList = GuardList0
7313 guard_via_reschedule_new(NHeads,GuardList,Head,GuardCopyList,GetRestHeads,RescheduledTest),
7315 rest_heads_retrieval_and_matching(NHeads,NIDs,Head,GetRestHeads,Susps,VarDict1,VarDict,[],[],[],GroundVars,_),
7316 split_by_ids(NIDs,Susps,OtherIDs,Susps1,Susps1IDs,Susps2,Susps2IDs),
7318 guard_body_copies3(Rule,GuardList,VarDict,GuardCopyList,BodyCopy),
7320 ( is_stored_in_guard(F/A, RuleNb) ->
7321 gen_uncond_attach_goal(F/A,Susp,Vars,Attachment,_),
7322 GuardCopyList = [Hole1Copy|_],
7323 Hole1Copy = Attachment
7328 sort_by_key(Susps1,Susps1IDs,SortedSusps1),
7329 partner_constraint_detachments(SortedSusps1,RestHeads,VarDict,SuspsDetachments),
7330 active_constraint_detachment(Id,Susp,Head,VarDict,SuspDetachment),
7332 ( chr_pp_flag(debugable,on) ->
7333 my_term_copy(Guard - Body, VarDict, DebugGuard - DebugBody),
7334 sort_by_key([Susp|Susps1],[ID|Susps1IDs],RemovedSusps),
7335 sort_by_key(Susps2,Susps2IDs,KeptSusps),
7336 DebugTry = 'chr debug_event'( try(RemovedSusps,KeptSusps,DebugGuard,DebugBody)),
7337 DebugApply = 'chr debug_event'(apply(RemovedSusps,KeptSusps,DebugGuard,DebugBody)),
7338 instrument_goal((!),DebugTry,DebugApply,Cut)
7343 Clause = ( ClauseHead :-
7351 add_location(Clause,RuleNb,LocatedClause),
7352 L = [LocatedClause | T].
7356 split_by_ids([],[],_,[],[]).
7357 split_by_ids([I|Is],[S|Ss],I1s,S1s,S2s) :-
7358 ( memberchk_eq(I,I1s) ->
7365 split_by_ids(Is,Ss,I1s,R1s,R2s).
7367 split_by_ids([],[],_,[],[],[],[]).
7368 split_by_ids([I|Is],[S|Ss],I1s,S1s,SI1s,S2s,SI2s) :-
7369 ( memberchk_eq(I,I1s) ->
7380 split_by_ids(Is,Ss,I1s,R1s,RSI1s,R2s,RSI2s).
7381 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7384 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7386 %% / ___|(_)_ __ ___ _ __ __ _ __ _ __ _| |_(_) ___ _ __ |___ \
7387 %% \___ \| | '_ ` _ \| '_ \ / _` |/ _` |/ _` | __| |/ _ \| '_ \ __) |
7388 %% ___) | | | | | | | |_) | (_| | (_| | (_| | |_| | (_) | | | | / __/
7389 %% |____/|_|_| |_| |_| .__/ \__,_|\__, |\__,_|\__|_|\___/|_| |_| |_____|
7392 %% Genereate prelude + worker predicate
7393 %% prelude calls worker
7394 %% worker iterates over one type of removed constraints
7395 simpagation_head2_code(Head2,ID,RestHeads2,RestIDs,PragmaRule,FA,O,Id,L,T) :-
7396 PragmaRule = pragma(Rule,ids(IDs1,IDs2),Pragmas,_Name,RuleNb),
7397 Rule = rule(Heads1,_,Guard,Body),
7398 append(Heads1,RestHeads2,Heads),
7399 append(IDs1,RestIDs,IDs),
7400 reorder_heads(RuleNb,Head2,Heads,IDs,[NHead|NHeads],[NID|NIDs]),
7401 simpagation_head2_prelude(Head2,NHead,[NHeads,Guard,Body],FA,O,Id,L,L1),
7403 ( memberchk_eq(NID,IDs2) ->
7404 simpagation_universal_searches(NHeads,NIDs,IDs2,[NHead,Head2],Rule,FA,O,NextHeads,PreHeads,NextIDs,Id1,Id2,L1,L2)
7406 L1 = L2, Id1 = Id2,NextHeads = NHeads, PreHeads = [NHead,Head2], NextIDs = NIDs
7408 universal_search_iterator_end(PreHeads,NextHeads,Rule,FA,O,Id2,L2,L3),
7409 simpagation_head2_worker(PreHeads,NextHeads,NextIDs,ID,PragmaRule,FA,O,Id2,L3,T).
7411 simpagation_universal_searches([],[],_,PreHeads,_,_,_,[],PreHeads,[],Id,Id,L,L).
7412 simpagation_universal_searches(Heads,[ID|IDs],IDs2,PreHeads,Rule,C,O,OutHeads,OutPreHeads,OutIDs,Id,NId,L,T) :-
7413 Heads = [Head|RHeads],
7415 universal_search_iterator_end(PreHeads,Heads,Rule,C,O,Id,L,L0),
7416 universal_search_iterator(Heads,PreHeads,Rule,C,O,Id,L0,L1),
7417 ( memberchk_eq(ID,IDs2) ->
7418 simpagation_universal_searches(RHeads,IDs,IDs2,[Head|PreHeads],Rule,C,O,OutHeads,OutPreHeads,OutIDs,Id1,NId,L1,T)
7420 NId = Id1, L1 = T, OutHeads = RHeads, OutPreHeads = [Head|PreHeads], IDs = OutIDs
7423 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7424 simpagation_head2_prelude(Head,Head1,Rest,F/A,O,Id1,L,T) :-
7425 head_info(Head,A,Vars,Susp,VarsSusp,HeadPairs),
7426 build_head(F,A,Id1,VarsSusp,ClauseHead),
7427 get_constraint_mode(F/A,Mode),
7428 head_arg_matches(HeadPairs,Mode,[],FirstMatching,VarDict,[],GroundVars),
7430 lookup_passive_head(Head1,[Head],VarDict,GroundVars,ModConstraintsGoal,AllSusps),
7432 gen_occ_allocation(F/A,O,Vars,Susp,ConstraintAllocationGoal),
7434 extend_id(Id1,DelegateId),
7435 extra_active_delegate_variables(Head,[Head1|Rest],VarDict,ExtraVars),
7436 append([AllSusps|VarsSusp],ExtraVars,DelegateCallVars),
7437 build_head(F,A,[O|DelegateId],DelegateCallVars,Delegate),
7444 ConstraintAllocationGoal,
7447 add_dummy_location(PreludeClause,LocatedPreludeClause),
7448 L = [LocatedPreludeClause|T].
7450 extra_active_delegate_variables(Term,Terms,VarDict,Vars) :-
7452 delegate_variables(Term,Terms,VarDict,Args,Vars).
7454 passive_delegate_variables(Term,PrevTerms,NextTerms,VarDict,Vars) :-
7455 term_variables(PrevTerms,PrevVars),
7456 delegate_variables(Term,NextTerms,VarDict,PrevVars,Vars).
7458 delegate_variables(Term,Terms,VarDict,PrevVars,Vars) :-
7459 term_variables(Term,V1),
7460 term_variables(Terms,V2),
7461 intersect_eq(V1,V2,V3),
7462 list_difference_eq(V3,PrevVars,V4),
7463 translate(V4,VarDict,Vars).
7466 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7467 simpagation_head2_worker([CurrentHead|PreHeads],NextHeads,NextIDs,ID,PragmaRule,F/A,O,Id,L,T) :-
7468 PragmaRule = pragma(Rule,ids(IDs1,_),Pragmas,_,RuleNb),
7469 Rule = rule(_,_,Guard,Body),
7470 get_prop_inner_loop_vars(PreHeads,[CurrentHead,NextHeads,Guard,Body],PreVarsAndSusps,VarDict,Susp,Vars,PreSusps),
7473 gen_var(OtherSusps),
7475 functor(CurrentHead,OtherF,OtherA),
7476 gen_vars(OtherA,OtherVars),
7477 head_info(CurrentHead,OtherA,OtherVars,OtherSusp,_VarsSusp,HeadPairs),
7478 get_constraint_mode(OtherF/OtherA,Mode),
7479 head_arg_matches(HeadPairs,Mode,VarDict,FirstMatching,VarDict1,[],GroundVars),
7481 delay_phase_end(validate_store_type_assumptions,
7482 ( static_suspension_term(OtherF/OtherA,OtherSuspension),
7483 get_static_suspension_field(OtherF/OtherA,OtherSuspension,state,active,GetState),
7484 get_static_suspension_term_field(arguments,OtherF/OtherA,OtherSuspension,OtherVars)
7487 % create_get_mutable_ref(active,State,GetMutable),
7488 different_from_other_susps(CurrentHead,OtherSusp,PreHeads,PreSusps,DiffSuspGoals),
7490 OtherSusp = OtherSuspension,
7496 ClauseVars = [[OtherSusp|OtherSusps]|PreVarsAndSusps],
7497 build_head(F,A,[O|Id],ClauseVars,ClauseHead),
7499 guard_splitting(Rule,GuardList0),
7500 ( is_stored_in_guard(F/A, RuleNb) ->
7501 GuardList = [Hole1|GuardList0]
7503 GuardList = GuardList0
7505 guard_via_reschedule_new(NextHeads,GuardList,[CurrentHead|PreHeads],GuardCopyList,RestSuspsRetrieval,RescheduledTest),
7507 rest_heads_retrieval_and_matching(NextHeads,NextIDs,[CurrentHead|PreHeads],RestSuspsRetrieval,Susps,VarDict1,VarDict2,[CurrentHead|PreHeads],[OtherSusp|PreSusps],[]),
7508 split_by_ids(NextIDs,Susps,IDs1,Susps1,Susps2),
7509 split_by_ids(NextIDs,NextHeads,IDs1,RestHeads1,_),
7511 partner_constraint_detachments([OtherSusp | Susps1],[CurrentHead|RestHeads1],VarDict2,Susps1Detachments),
7513 RecursiveVars = [OtherSusps|PreVarsAndSusps],
7514 build_head(F,A,[O|Id],RecursiveVars,RecursiveCall),
7515 RecursiveVars2 = [[]|PreVarsAndSusps],
7516 build_head(F,A,[O|Id],RecursiveVars2,RecursiveCall2),
7518 guard_body_copies3(Rule,GuardList,VarDict2,GuardCopyList,BodyCopy),
7519 ( is_stored_in_guard(F/A, RuleNb) ->
7520 GuardCopyList = [GuardAttachment|_] % once( ) ??
7525 ( is_observed(F/A,O) ->
7526 gen_uncond_attach_goal(F/A,Susp,Vars,Attachment,Generation),
7527 gen_state_cond_call(Susp,F/A,RecursiveCall,Generation,ConditionalRecursiveCall),
7528 gen_state_cond_call(Susp,F/A,RecursiveCall2,Generation,ConditionalRecursiveCall2)
7531 ConditionalRecursiveCall = RecursiveCall,
7532 ConditionalRecursiveCall2 = RecursiveCall2
7535 ( chr_pp_flag(debugable,on) ->
7536 my_term_copy(Guard - Body, VarDict, DebugGuard - DebugBody),
7537 DebugTry = 'chr debug_event'( try([OtherSusp|Susps1],[Susp|Susps2],DebugGuard,DebugBody)),
7538 DebugApply = 'chr debug_event'(apply([OtherSusp|Susps1],[Susp|Susps2],DebugGuard,DebugBody))
7544 ( is_stored_in_guard(F/A, RuleNb) ->
7545 GuardAttachment = Attachment,
7546 BodyAttachment = true
7548 GuardAttachment = true,
7549 BodyAttachment = Attachment % will be true if not observed at all
7552 ( member(unique(ID1,UniqueKeys), Pragmas),
7553 check_unique_keys(UniqueKeys,VarDict) ->
7556 ( CurrentSuspTest ->
7563 ConditionalRecursiveCall2
7581 ConditionalRecursiveCall
7587 add_location(Clause,RuleNb,LocatedClause),
7588 L = [LocatedClause | T].
7590 gen_state_cond_call(Susp,FA,Call,Generation,ConditionalCall) :-
7591 ( may_trigger(FA) ->
7592 does_use_field(FA,generation),
7593 delay_phase_end(validate_store_type_assumptions,
7594 ( static_suspension_term(FA,Suspension),
7595 get_update_static_suspension_field(FA,Susp,Suspension,state,active,inactive,GetState,UpdateState),
7596 get_static_suspension_field(FA,Suspension,generation,Generation,GetGeneration),
7597 get_static_suspension_term_field(arguments,FA,Suspension,Args)
7601 delay_phase_end(validate_store_type_assumptions,
7602 ( static_suspension_term(FA,Suspension),
7603 get_update_static_suspension_field(FA,Susp,Suspension,state,active,inactive,GetState,UpdateState),
7604 get_static_suspension_term_field(arguments,FA,Suspension,Args)
7607 GetGeneration = true
7610 ( Susp = Suspension,
7619 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7622 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7624 %% | _ \ _ __ ___ _ __ __ _ __ _ __ _| |_(_) ___ _ __
7625 %% | |_) | '__/ _ \| '_ \ / _` |/ _` |/ _` | __| |/ _ \| '_ \
7626 %% | __/| | | (_) | |_) | (_| | (_| | (_| | |_| | (_) | | | |
7627 %% |_| |_| \___/| .__/ \__,_|\__, |\__,_|\__|_|\___/|_| |_|
7630 propagation_code(Head,ID,RestHeads,RestIDs,Rule,RuleNb,FA,O,Id,L,T) :-
7631 ( RestHeads == [] ->
7632 propagation_single_headed(Head,ID,Rule,RuleNb,FA,O,Id,L,T)
7634 propagation_multi_headed(Head,RestHeads,RestIDs,Rule,RuleNb,FA,O,Id,L,T)
7636 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7637 %% Single headed propagation
7638 %% everything in a single clause
7639 propagation_single_headed(Head,ID,Rule,RuleNb,F/A,O,Id,ProgramList,ProgramTail) :-
7640 head_info(Head,A,Vars,Susp,VarsSusp,HeadPairs),
7641 build_head(F,A,Id,VarsSusp,ClauseHead),
7644 build_head(F,A,NextId,VarsSusp,NextHead),
7646 get_constraint_mode(F/A,Mode),
7647 head_arg_matches(HeadPairs,Mode,[],HeadMatching,VarDict,[],GroundVars),
7648 guard_body_copies(Rule,VarDict,GuardCopy,BodyCopy),
7650 % - recursive call -
7651 RecursiveCall = NextHead,
7653 ( unconditional_occurrence(F/A,O), chr_pp_flag(late_allocation,on) ->
7659 Rule = rule(_,_,Guard,Body),
7660 ( chr_pp_flag(debugable,on) ->
7661 my_term_copy(Guard - Body, VarDict, DebugGuard - DebugBody),
7662 DebugTry = 'chr debug_event'( try([],[Susp],DebugGuard,DebugBody)),
7663 DebugApply = 'chr debug_event'(apply([],[Susp],DebugGuard,DebugBody)),
7664 instrument_goal(ActualCut,DebugTry,DebugApply,Cut)
7668 ( may_trigger(F/A), \+ has_no_history(RuleNb)->
7669 use_auxiliary_predicate(novel_production),
7670 use_auxiliary_predicate(extend_history),
7671 does_use_history(F/A,O),
7672 gen_occ_allocation(F/A,O,Vars,Susp,Allocation),
7674 ( named_history(RuleNb,HistoryName,HistoryIDs) ->
7675 ( HistoryIDs == [] ->
7676 empty_named_history_novel_production(HistoryName,NovelProduction),
7677 empty_named_history_extend_history(HistoryName,ExtendHistory)
7685 ( var(NovelProduction) ->
7686 NovelProduction = '$novel_production'(Susp,Tuple),
7687 ExtendHistory = '$extend_history'(Susp,Tuple)
7692 ( is_observed(F/A,O) ->
7693 gen_uncond_attach_goal(F/A,Susp,Vars,Attachment,Generation),
7694 gen_state_cond_call(Susp,F/A,RecursiveCall,Generation,ConditionalRecursiveCall)
7697 ConditionalRecursiveCall = RecursiveCall
7701 NovelProduction = true,
7702 ExtendHistory = true,
7704 ( is_observed(F/A,O) ->
7705 get_allocation_occurrence(F/A,AllocO),
7707 gen_insert_constraint_internal_goal(F/A,Attachment,VarsSusp,Vars,Susp),
7709 ; % more room for improvement?
7710 Attachment = (Attachment1, Attachment2),
7711 gen_occ_allocation(F/A,O,Vars,Susp,Attachment1),
7712 gen_uncond_attach_goal(F/A,Susp,Vars,Attachment2,Generation)
7714 gen_state_cond_call(Susp,F/A,RecursiveCall,Generation,ConditionalRecursiveCall)
7716 gen_occ_allocation(F/A,O,Vars,Susp,Attachment),
7717 ConditionalRecursiveCall = RecursiveCall
7721 ( is_stored_in_guard(F/A, RuleNb) ->
7722 GuardAttachment = Attachment,
7723 BodyAttachment = true
7725 GuardAttachment = true,
7726 BodyAttachment = Attachment % will be true if not observed at all
7740 ConditionalRecursiveCall
7742 add_location(Clause,RuleNb,LocatedClause),
7743 ProgramList = [LocatedClause | ProgramTail].
7745 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7746 %% multi headed propagation
7747 %% prelude + predicates to accumulate the necessary combinations of suspended
7748 %% constraints + predicate to execute the body
7749 propagation_multi_headed(Head,RestHeads,RestIDs,Rule,RuleNb,FA,O,Id,L,T) :-
7750 RestHeads = [First|Rest],
7751 propagation_prelude(Head,RestHeads,Rule,FA,O,Id,L,L1),
7752 extend_id(Id,ExtendedId),
7753 propagation_nested_code(Rest,[First,Head],RestIDs,Rule,RuleNb,FA,O,ExtendedId,L1,T).
7755 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7756 propagation_prelude(Head,[First|Rest],Rule,F/A,O,Id,L,T) :-
7757 head_info(Head,A,Vars,Susp,VarsSusp,HeadPairs),
7758 build_head(F,A,Id,VarsSusp,PreludeHead),
7759 get_constraint_mode(F/A,Mode),
7760 head_arg_matches(HeadPairs,Mode,[],FirstMatching,VarDict,[],GroundVars),
7761 Rule = rule(_,_,Guard,Body),
7762 extra_active_delegate_variables(Head,[First,Rest,Guard,Body],VarDict,ExtraVars),
7764 lookup_passive_head(First,[Head],VarDict,GroundVars,FirstSuspGoal,Susps),
7766 gen_occ_allocation(F/A,O,Vars,Susp,CondAllocation),
7768 extend_id(Id,NestedId),
7769 append([Susps|VarsSusp],ExtraVars,NestedVars),
7770 build_head(F,A,[O|NestedId],NestedVars,NestedHead),
7771 NestedCall = NestedHead,
7781 add_dummy_location(Prelude,LocatedPrelude),
7782 L = [LocatedPrelude|T].
7784 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7785 propagation_nested_code([],[CurrentHead|PreHeads],RestIDs,Rule,RuleNb,FA,O,Id,L,T) :-
7786 universal_search_iterator_end([CurrentHead|PreHeads],[],Rule,FA,O,Id,L,L1),
7787 propagation_body(CurrentHead,PreHeads,RestIDs,Rule,RuleNb,FA,O,Id,L1,T).
7789 propagation_nested_code([Head|RestHeads],PreHeads,RestIDs,Rule,RuleNb,FA,O,Id,L,T) :-
7790 universal_search_iterator_end(PreHeads,[Head|RestHeads],Rule,FA,O,Id,L,L1),
7791 universal_search_iterator([Head|RestHeads],PreHeads,Rule,FA,O,Id,L1,L2),
7793 propagation_nested_code(RestHeads,[Head|PreHeads],RestIDs,Rule,RuleNb,FA,O,IncId,L2,T).
7795 %check_fd_lookup_condition(_,_,_,_) :- fail.
7796 check_fd_lookup_condition(F,A,_,_) :-
7797 get_store_type(F/A,global_singleton), !.
7798 check_fd_lookup_condition(F,A,CurrentHead,PreHeads) :-
7799 \+ may_trigger(F/A),
7800 get_functional_dependency(F/A,1,P,K),
7801 copy_term(P-K,CurrentHead-Key),
7802 term_variables(PreHeads,PreVars),
7803 intersect_eq(Key,PreVars,Key),!.
7805 propagation_body(CurrentHead,PreHeads,RestIDs,Rule,RuleNb,F/A,O,Id,L,T) :-
7806 Rule = rule(_,H2,Guard,Body),
7807 gen_var_susp_list_for_b(PreHeads,[CurrentHead,Guard,Body],VarDict1,PreVarsAndSuspsList,FirstVarsSusp,AllSusps,PrevIterators),
7808 flatten(PreVarsAndSuspsList,PreVarsAndSusps),
7809 init(AllSusps,RestSusps),
7810 last(AllSusps,Susp),
7812 gen_var(OtherSusps),
7813 functor(CurrentHead,OtherF,OtherA),
7814 gen_vars(OtherA,OtherVars),
7815 delay_phase_end(validate_store_type_assumptions,
7816 ( static_suspension_term(OtherF/OtherA,Suspension),
7817 get_static_suspension_field(OtherF/OtherA,Suspension,state,active,GetState),
7818 get_static_suspension_term_field(arguments,OtherF/OtherA,Suspension,OtherVars)
7821 % create_get_mutable_ref(active,State,GetMutable),
7823 OtherSusp = Suspension,
7826 ClauseVars = [[OtherSusp|OtherSusps]|PreVarsAndSusps],
7827 build_head(F,A,[O|Id],ClauseVars,ClauseHead),
7828 ( check_fd_lookup_condition(OtherF,OtherA,CurrentHead,PreHeads) -> % iterator (OtherSusps) is empty at runtime
7829 universal_search_iterator_failure_vars(PreHeads,Id,PreVarsAndSuspsList,FirstVarsSusp,PrevIterators,PreVarsAndSusps1,PrevId0),
7830 RecursiveVars = PreVarsAndSusps1
7832 RecursiveVars = [OtherSusps|PreVarsAndSusps],
7838 PrevId = [O|PrevId0]
7840 build_head(F,A,PrevId,RecursiveVars,RecursiveHead),
7841 RecursiveCall = RecursiveHead,
7842 CurrentHead =.. [_|OtherArgs],
7843 pairup(OtherArgs,OtherVars,OtherPairs),
7844 get_constraint_mode(OtherF/OtherA,Mode),
7845 head_arg_matches(OtherPairs,Mode,VarDict1,Matching,VarDict),
7847 different_from_other_susps(CurrentHead,OtherSusp,PreHeads,RestSusps,DiffSuspGoals),
7848 guard_body_copies(Rule,VarDict,GuardCopy,BodyCopy),
7849 get_occurrence(F/A,O,_,ID),
7851 ( is_observed(F/A,O) ->
7852 init(FirstVarsSusp,FirstVars),
7853 gen_uncond_attach_goal(F/A,Susp,FirstVars,Attachment,Generation),
7854 gen_state_cond_call(Susp,F/A,RecursiveCall,Generation,ConditionalRecursiveCall)
7857 ConditionalRecursiveCall = RecursiveCall
7859 ( (is_least_occurrence(RuleNb) ; has_no_history(RuleNb)) ->
7860 NovelProduction = true,
7861 ExtendHistory = true
7862 ; \+ may_trigger(F/A), maplist(is_passive(RuleNb),RestIDs) ->
7863 NovelProduction = true,
7864 ExtendHistory = true
7866 get_occurrence(F/A,O,_,ID),
7867 use_auxiliary_predicate(novel_production),
7868 use_auxiliary_predicate(extend_history),
7869 does_use_history(F/A,O),
7870 ( named_history(RuleNb,HistoryName,HistoryIDs) ->
7871 ( HistoryIDs == [] ->
7872 empty_named_history_novel_production(HistoryName,NovelProduction),
7873 empty_named_history_extend_history(HistoryName,ExtendHistory)
7875 reverse([OtherSusp|RestSusps],NamedSusps),
7876 named_history_susps(HistoryIDs,[ID|RestIDs],[Susp|NamedSusps],HistorySusps),
7877 HistorySusps = [HistorySusp|_],
7879 ( length(HistoryIDs, 1) ->
7880 ExtendHistory = '$extend_history'(HistorySusp,HistoryName),
7881 NovelProduction = '$novel_production'(HistorySusp,HistoryName)
7883 findall(ConstraintSymbol,(member(SomeID,HistoryIDs),get_occurrence_from_id(ConstraintSymbol,_,RuleNb,SomeID)),ConstraintSymbols),
7884 Tuple =.. [t,HistoryName|HistorySusps]
7889 maplist(extract_symbol,H2,ConstraintSymbols),
7890 sort([ID|RestIDs],HistoryIDs),
7891 history_susps(RestIDs,[OtherSusp|RestSusps],Susp,ID,HistorySusps),
7892 Tuple =.. [t,RuleNb|HistorySusps]
7895 ( var(NovelProduction) ->
7896 novel_production_calls(ConstraintSymbols,HistoryIDs,HistorySusps,RuleNb,TupleVar,NovelProductions),
7897 ExtendHistory = '$extend_history'(HistorySusp,TupleVar),
7898 NovelProduction = ( TupleVar = Tuple, NovelProductions )
7905 ( chr_pp_flag(debugable,on) ->
7906 Rule = rule(_,_,Guard,Body),
7907 my_term_copy(Guard - Body, VarDict, DebugGuard - DebugBody),
7908 get_occurrence(F/A,O,_,ID),
7909 sort_by_key([Susp,OtherSusp|RestSusps],[ID|RestIDs],KeptSusps),
7910 DebugTry = 'chr debug_event'( try([],KeptSusps,DebugGuard,DebugBody)),
7911 DebugApply = 'chr debug_event'(apply([],KeptSusps,DebugGuard,DebugBody))
7917 ( is_stored_in_guard(F/A, RuleNb) ->
7918 GuardAttachment = Attachment,
7919 BodyAttachment = true
7921 GuardAttachment = true,
7922 BodyAttachment = Attachment % will be true if not observed at all
7938 ConditionalRecursiveCall
7942 add_location(Clause,RuleNb,LocatedClause),
7943 L = [LocatedClause|T].
7945 extract_symbol(Head,F/A) :-
7948 novel_production_calls([],[],[],_,_,true).
7949 novel_production_calls([ConstraintSymbol|ConstraintSymbols],[ID|IDs],[Suspension|Suspensions],RuleNb,Tuple,(Goal,Goals)) :-
7950 get_occurrence_from_id(ConstraintSymbol,Occurrence,RuleNb,ID),
7951 delay_phase_end(validate_store_type_assumptions,novel_production_call(ConstraintSymbol,Occurrence,'$novel_production'(Suspension,Tuple),Goal)),
7952 novel_production_calls(ConstraintSymbols,IDs,Suspensions,RuleNb,Tuple,Goals).
7954 history_susps(RestIDs,ReversedRestSusps,Susp,ID,HistorySusps) :-
7955 reverse(ReversedRestSusps,RestSusps),
7956 sort_by_key([Susp|RestSusps],[ID|RestIDs],HistorySusps).
7958 named_history_susps([],_,_,[]).
7959 named_history_susps([HistoryID|HistoryIDs],IDs,Susps,[HistorySusp|HistorySusps]) :-
7960 select2(HistoryID,HistorySusp,IDs,Susps,RestIDs,RestSusps), !,
7961 named_history_susps(HistoryIDs,RestIDs,RestSusps,HistorySusps).
7965 gen_var_susp_list_for([Head],Terms,VarDict,HeadVars,VarsSusp,Susp) :-
7968 head_info(Head,A,_Vars,Susp,VarsSusp,HeadPairs),
7969 get_constraint_mode(F/A,Mode),
7970 head_arg_matches(HeadPairs,Mode,[],_,VarDict),
7971 extra_active_delegate_variables(Head,Terms,VarDict,ExtraVars),
7972 append(VarsSusp,ExtraVars,HeadVars).
7973 gen_var_susp_list_for([Head|Heads],Terms,NVarDict,VarsSusps,Rest,Susps) :-
7974 gen_var_susp_list_for(Heads,[Head|Terms],VarDict,Rest,_,_),
7977 head_info(Head,A,_Vars,Susp,_VarsSusp,HeadPairs),
7978 get_constraint_mode(F/A,Mode),
7979 head_arg_matches(HeadPairs,Mode,VarDict,_,NVarDict),
7980 passive_delegate_variables(Head,Heads,Terms,NVarDict,HeadVars),
7981 append(HeadVars,[Susp,Susps|Rest],VarsSusps).
7984 % VarDict for the copies of variables in the original heads
7985 % VarsSuspsList list of lists of arguments for the successive heads
7986 % FirstVarsSusp top level arguments
7987 % SuspList list of all suspensions
7988 % Iterators list of all iterators
7989 gen_var_susp_list_for_b([Head],NextHeads,VarDict,[HeadVars],VarsSusp,[Susp],[]) :-
7992 head_info(Head,A,_Vars,Susp,VarsSusp,Pairs), % make variables for argument positions
7993 get_constraint_mode(F/A,Mode),
7994 head_arg_matches(Pairs,Mode,[],_,VarDict), % copy variables inside arguments, build dictionary
7995 extra_active_delegate_variables(Head,NextHeads,VarDict,ExtraVars), % decide what additional variables are needed
7996 append(VarsSusp,ExtraVars,HeadVars). % add additional variables to head variables
7997 gen_var_susp_list_for_b([Head|Heads],NextHeads,NVarDict,[Vars|RestVars],FirstVarsSusp,[Susp|SuspList],[Susps|Iterators]) :-
7998 gen_var_susp_list_for_b(Heads,[Head|NextHeads],VarDict,RestVars,FirstVarsSusp,SuspList,Iterators),
8001 head_info(Head,A,_Vars,Susp,_VarsSusp,HeadPairs),
8002 get_constraint_mode(F/A,Mode),
8003 head_arg_matches(HeadPairs,Mode,VarDict,_,NVarDict),
8004 passive_delegate_variables(Head,Heads,NextHeads,NVarDict,HeadVars),
8005 append(HeadVars,[Susp,Susps],Vars).
8007 get_prop_inner_loop_vars([Head],NextHeads,HeadVars,VarDict,Susp,Vars,[]) :-
8010 head_info(Head,A,Vars,Susp,VarsSusp,Pairs),
8011 get_constraint_mode(F/A,Mode),
8012 head_arg_matches(Pairs,Mode,[],_,VarDict),
8013 extra_active_delegate_variables(Head,NextHeads,VarDict,ExtraVars),
8014 append(VarsSusp,ExtraVars,HeadVars).
8015 get_prop_inner_loop_vars([Head|Heads],Terms,VarsSusps,NVarDict,MainSusp,MainVars,[Susp|RestSusps]) :-
8016 get_prop_inner_loop_vars(Heads,[Head|Terms],RestVarsSusp,VarDict,MainSusp,MainVars,RestSusps),
8019 head_info(Head,A,_Vars,Susp,_VarsSusp,Pairs),
8020 get_constraint_mode(F/A,Mode),
8021 head_arg_matches(Pairs,Mode,VarDict,_,NVarDict),
8022 passive_delegate_variables(Head,Heads,Terms,NVarDict,HeadVars),
8023 append(HeadVars,[Susp,Susps|RestVarsSusp],VarsSusps).
8025 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8027 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8029 %% | _ \ __ _ ___ ___(_)_ _____ | | | | ___ __ _ __| |
8030 %% | |_) / _` / __/ __| \ \ / / _ \ | |_| |/ _ \/ _` |/ _` |
8031 %% | __/ (_| \__ \__ \ |\ V / __/ | _ | __/ (_| | (_| |
8032 %% |_| \__,_|___/___/_| \_/ \___| |_| |_|\___|\__,_|\__,_|
8035 %% | _ \ ___| |_ _ __(_) _____ ____ _| |
8036 %% | |_) / _ \ __| '__| |/ _ \ \ / / _` | |
8037 %% | _ < __/ |_| | | | __/\ V / (_| | |
8038 %% |_| \_\___|\__|_| |_|\___| \_/ \__,_|_|
8041 %% | _ \ ___ ___ _ __ __| | ___ _ __(_)_ __ __ _
8042 %% | |_) / _ \/ _ \| '__/ _` |/ _ \ '__| | '_ \ / _` |
8043 %% | _ < __/ (_) | | | (_| | __/ | | | | | | (_| |
8044 %% |_| \_\___|\___/|_| \__,_|\___|_| |_|_| |_|\__, |
8047 reorder_heads(RuleNb,Head,RestHeads,RestIDs,NRestHeads,NRestIDs) :-
8048 ( chr_pp_flag(reorder_heads,on), length(RestHeads,Length), Length =< 6 ->
8049 reorder_heads_main(RuleNb,Head,RestHeads,RestIDs,NRestHeads,NRestIDs)
8051 NRestHeads = RestHeads,
8055 reorder_heads_main(RuleNb,Head,RestHeads,RestIDs,NRestHeads,NRestIDs) :-
8056 term_variables(Head,Vars),
8057 InitialData = entry([],[],Vars,RestHeads,RestIDs,RuleNb),
8058 copy_term_nat(InitialData,InitialDataCopy),
8059 a_star(InitialDataCopy,FD^(chr_translate:final_data(FD)),N^EN^C^(chr_translate:expand_data(N,EN,C)),FinalData),
8060 InitialDataCopy = InitialData,
8061 FinalData = entry(RNRestHeads,RNRestIDs,_,_,_,_),
8062 reverse(RNRestHeads,NRestHeads),
8063 reverse(RNRestIDs,NRestIDs).
8065 final_data(Entry) :-
8066 Entry = entry(_,_,_,_,[],_).
8068 expand_data(Entry,NEntry,Cost) :-
8069 Entry = entry(Heads,IDs,Vars,NHeads,NIDs,RuleNb),
8070 select2(Head1,ID1,NHeads,NIDs,NHeads1,NIDs1),
8071 term_variables([Head1|Vars],Vars1),
8072 NEntry = entry([Head1|Heads],[ID1|IDs],Vars1,NHeads1,NIDs1,RuleNb),
8073 order_score(Head1,ID1,Vars,NHeads1,RuleNb,Cost).
8075 % Assigns score to head based on known variables and heads to lookup
8076 % order_score(+head,+id,+knownvars,+heads,+rule_nb,-score). {{{
8077 order_score(Head,ID,KnownVars,RestHeads,RuleNb,Score) :-
8079 get_store_type(F/A,StoreType),
8080 order_score(StoreType,Head,ID,KnownVars,RestHeads,RuleNb,99999,Score).
8083 %% order_score(+store+_type,+head,+id,+vars,+heads,+rule_nb,+score,-score) {{{
8084 order_score(default,Head,_ID,KnownVars,RestHeads,RuleNb,CScore,NScore) :-
8085 term_variables(Head,HeadVars0),
8086 term_variables(RestHeads,RestVars),
8087 ground_vars([Head],GroundVars),
8088 list_difference_eq(HeadVars0,GroundVars,HeadVars),
8089 order_score_vars(HeadVars,KnownVars,RestVars,Score),
8090 NScore is min(CScore,Score).
8091 order_score(multi_inthash(Indexes),Head,_ID,KnownVars,RestHeads,RuleNb,CScore,Score) :-
8095 order_score_indexes(Indexes,Head,KnownVars,Score)
8097 order_score(multi_hash(Indexes),Head,_ID,KnownVars,RestHeads,RuleNb,CScore,Score) :-
8101 order_score_indexes(Indexes,Head,KnownVars,Score)
8103 order_score(global_ground,Head,ID,KnownVars,RestHeads,RuleNb,CScore,NScore) :-
8104 term_variables(Head,HeadVars),
8105 term_variables(RestHeads,RestVars),
8106 order_score_vars(HeadVars,KnownVars,RestVars,Score_),
8107 Score is Score_ * 200,
8108 NScore is min(CScore,Score).
8109 order_score(var_assoc_store(_,_),_,_,_,_,_,_,1).
8110 order_score(global_singleton,_Head,ID,_KnownVars,_RestHeads,_RuleNb,_,Score) :-
8111 Score = 1. % guaranteed O(1)
8112 order_score(multi_store(StoreTypes),Head,ID,KnownVars,RestHeads,RuleNb,CScore,Score) :-
8113 multi_order_score(StoreTypes,Head,ID,KnownVars,RestHeads,RuleNb,CScore,Score).
8114 multi_order_score([],_,_,_,_,_,Score,Score).
8115 multi_order_score([StoreType|StoreTypes],Head,ID,KnownVars,RestHeads,RuleNb,Score0,Score) :-
8116 ( order_score(StoreType,Head,ID,KnownVars,RestHeads,RuleNb,Score0,Score1) -> true
8119 multi_order_score(StoreTypes,Head,ID,KnownVars,RestHeads,RuleNb,Score1,Score).
8121 order_score(identifier_store(Index),Head,ID,KnownVars,RestHeads,RuleNb,CScore,Score) :-
8122 Score is min(CScore,10).
8123 order_score(type_indexed_identifier_store(_,_),Head,ID,KnownVars,RestHeads,RuleNb,CScore,Score) :-
8124 Score is min(CScore,10).
8128 %% order_score_indexes(+indexes,+head,+vars,-score). {{{
8129 order_score_indexes(Indexes,Head,Vars,Score) :-
8130 copy_term_nat(Head+Vars,HeadCopy+VarsCopy),
8131 numbervars(VarsCopy,0,_),
8132 order_score_indexes(Indexes,HeadCopy,Score).
8134 order_score_indexes([I|Is],Head,Score) :-
8136 ( maplist(ground,Args) /* forall(Arg,Args,memberchk_eq(Arg,KnownVars)) */ ->
8139 order_score_indexes(Is,Head,Score)
8143 memberchk_eq_flip(List,Element) :- memberchk_eq(Element,List).
8145 order_score_vars(Vars,KnownVars,RestVars,Score) :-
8146 order_score_count_vars(Vars,KnownVars,RestVars,K-R-O),
8150 Score is max(10 - K,0)
8152 Score is max(10 - R,1) * 100
8154 Score is max(10-O,1) * 1000
8156 order_score_count_vars([],_,_,0-0-0).
8157 order_score_count_vars([V|Vs],KnownVars,RestVars,NK-NR-NO) :-
8158 order_score_count_vars(Vs,KnownVars,RestVars,K-R-O),
8159 ( memberchk_eq(V,KnownVars) ->
8162 ; memberchk_eq(V,RestVars) ->
8170 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8172 %% |_ _|_ __ | (_)_ __ (_)_ __ __ _
8173 %% | || '_ \| | | '_ \| | '_ \ / _` |
8174 %% | || | | | | | | | | | | | | (_| |
8175 %% |___|_| |_|_|_|_| |_|_|_| |_|\__, |
8179 create_get_mutable_ref(V,M,GM) :- GM = (M = mutable(V)).
8180 create_get_mutable(V,M,GM) :- M = mutable(V), GM = true.
8184 %% create_get_mutable(V,M,GM) :- GM = get_mutable(V,M).
8185 %% create_get_mutable_ref(V,M,GM) :- GM = get_mutable(V,M).
8188 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8190 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8192 %% | | | | |_(_) (_) |_ _ _
8193 %% | | | | __| | | | __| | | |
8194 %% | |_| | |_| | | | |_| |_| |
8195 %% \___/ \__|_|_|_|\__|\__, |
8198 % Create a fresh variable.
8201 % Create =N= fresh variables.
8205 head_info(Head,A,Vars,Susp,VarsSusp,HeadPairs) :-
8206 vars_susp(A,Vars,Susp,VarsSusp),
8208 pairup(Args,Vars,HeadPairs).
8210 inc_id([N|Ns],[O|Ns]) :-
8212 dec_id([N|Ns],[M|Ns]) :-
8215 extend_id(Id,[0|Id]).
8217 next_id([_,N|Ns],[O|Ns]) :-
8220 % return clause Head
8221 % for F/A constraint symbol, predicate identifier Id and arguments Head
8222 build_head(F,A,Id,Args,Head) :-
8223 buildName(F,A,Id,Name),
8224 ( (chr_pp_flag(debugable,on) ; is_stored(F/A), ( has_active_occurrence(F/A) ; chr_pp_flag(late_allocation,off)),
8225 ( may_trigger(F/A) ;
8226 get_allocation_occurrence(F/A,AO),
8227 get_max_occurrence(F/A,MO),
8229 Head =.. [Name|Args]
8231 init(Args,ArgsWOSusp), % XXX not entirely correct!
8232 Head =.. [Name|ArgsWOSusp]
8235 % return predicate name Result
8236 % for Fct/Aty constraint symbol and predicate identifier List
8237 buildName(Fct,Aty,List,Result) :-
8238 ( (chr_pp_flag(debugable,on) ; (once((is_stored(Fct/Aty), ( has_active_occurrence(Fct/Aty) ; chr_pp_flag(late_allocation,off)),
8239 ( may_trigger(Fct/Aty) ; get_allocation_occurrence(Fct/Aty,AO), get_max_occurrence(Fct/Aty,MO),
8240 MO >= AO ) ; List \= [0])) ) ) ->
8241 atom_concat(Fct, '___' ,FctSlash),
8242 atomic_concat(FctSlash,Aty,FctSlashAty),
8243 buildName_(List,FctSlashAty,Result)
8248 buildName_([],Name,Name).
8249 buildName_([N|Ns],Name,Result) :-
8250 buildName_(Ns,Name,Name1),
8251 atom_concat(Name1,'__',NameDash), % '_' is a char :-(
8252 atomic_concat(NameDash,N,Result).
8254 vars_susp(A,Vars,Susp,VarsSusp) :-
8256 append(Vars,[Susp],VarsSusp).
8258 or_pattern(Pos,Pat) :-
8260 Pat is 1 << Pow. % was 2 ** X
8262 and_pattern(Pos,Pat) :-
8264 Y is 1 << X, % was 2 ** X
8265 Pat is (-1)*(Y + 1).
8267 make_name(Prefix,F/A,Name) :-
8268 atom_concat_list([Prefix,F,'___',A],Name).
8270 %===============================================================================
8271 % Attribute for attributed variables
8273 make_attr(N,Mask,SuspsList,Attr) :-
8274 length(SuspsList,N),
8275 Attr =.. [v,Mask|SuspsList].
8277 get_all_suspensions2(N,Attr,SuspensionsList) :-
8278 chr_pp_flag(dynattr,off), !,
8279 make_attr(N,_,SuspensionsList,Attr).
8282 get_all_suspensions2(N,Attr,Goal,SuspensionsList) :-
8283 % writeln(get_all_suspensions2),
8284 length(SuspensionsList,N),
8285 Goal = 'chr all_suspensions'(SuspensionsList,1,Attr).
8289 normalize_attr(Attr,NormalGoal,NormalAttr) :-
8290 % writeln(normalize_attr),
8291 NormalGoal = 'chr normalize_attr'(Attr,NormalAttr).
8293 get_suspensions(N,Position,TAttr,(TAttr = Attr),Suspensions) :-
8294 chr_pp_flag(dynattr,off), !,
8295 make_attr(N,_,SuspsList,Attr),
8296 nth1(Position,SuspsList,Suspensions).
8299 get_suspensions(N,Position,TAttr,Goal,Suspensions) :-
8300 % writeln(get_suspensions),
8302 ( memberchk(Position-Suspensions,TAttr) ->
8308 %-------------------------------------------------------------------------------
8309 % +N: number of constraint symbols
8310 % +Suspension: source-level variable, for suspension
8311 % +Position: constraint symbol number
8312 % -Attr: source-level term, for new attribute
8313 singleton_attr(N,Suspension,Position,Attr) :-
8314 chr_pp_flag(dynattr,off), !,
8315 or_pattern(Position,Pattern),
8316 make_attr(N,Pattern,SuspsList,Attr),
8317 nth1(Position,SuspsList,[Suspension]),
8318 chr_delete(SuspsList,[Suspension],RestSuspsList),
8319 set_elems(RestSuspsList,[]).
8322 singleton_attr(N,Suspension,Position,Attr) :-
8323 % writeln(singleton_attr),
8324 Attr = [Position-[Suspension]].
8326 %-------------------------------------------------------------------------------
8327 % +N: number of constraint symbols
8328 % +Suspension: source-level variable, for suspension
8329 % +Position: constraint symbol number
8330 % +TAttr: source-level variable, for old attribute
8331 % -Goal: goal for creating new attribute
8332 % -NTAttr: source-level variable, for new attribute
8333 add_attr(N,Suspension,Position,TAttr,Goal,NTAttr) :-
8334 chr_pp_flag(dynattr,off), !,
8335 make_attr(N,Mask,SuspsList,Attr),
8336 or_pattern(Position,Pattern),
8337 nth1(Position,SuspsList,Susps),
8338 substitute_eq(Susps,SuspsList,[Suspension|Susps],SuspsList1),
8339 make_attr(N,Mask,SuspsList1,NewAttr1),
8340 substitute_eq(Susps,SuspsList,[Suspension],SuspsList2),
8341 make_attr(N,NewMask,SuspsList2,NewAttr2),
8344 ( Mask /\ Pattern =:= Pattern ->
8347 NewMask is Mask \/ Pattern,
8353 add_attr(N,Suspension,Position,TAttr,Goal,NTAttr) :-
8354 % writeln(add_attr),
8356 ( 'chr select'(TAttr,Position-Suspensions,RAttr) ->
8357 NTAttr = [Position-[Suspension|Suspensions]|RAttr]
8359 NTAttr = [Position-[Suspension]|TAttr]
8362 rem_attr(N,Var,Suspension,Position,TAttr,Goal) :-
8363 chr_pp_flag(dynattr,off), !,
8364 or_pattern(Position,Pattern),
8365 and_pattern(Position,DelPattern),
8366 make_attr(N,Mask,SuspsList,Attr),
8367 nth1(Position,SuspsList,Susps),
8368 substitute_eq(Susps,SuspsList,[],SuspsList1),
8369 make_attr(N,NewMask,SuspsList1,Attr1),
8370 substitute_eq(Susps,SuspsList,NewSusps,SuspsList2),
8371 make_attr(N,Mask,SuspsList2,Attr2),
8372 get_target_module(Mod),
8375 ( Mask /\ Pattern =:= Pattern ->
8376 'chr sbag_del_element'(Susps,Suspension,NewSusps),
8378 NewMask is Mask /\ DelPattern,
8382 put_attr(Var,Mod,Attr1)
8385 put_attr(Var,Mod,Attr2)
8393 rem_attr(N,Var,Suspension,Position,TAttr,Goal) :-
8394 % writeln(rem_attr),
8395 get_target_module(Mod),
8397 ( 'chr select'(TAttr,Position-Suspensions,RAttr) ->
8398 'chr sbag_del_element'(Suspensions,Suspension,NSuspensions),
8399 ( NSuspensions == [] ->
8403 put_attr(Var,Mod,RAttr)
8406 put_attr(Var,Mod,[Position-NSuspensions|RAttr])
8412 %-------------------------------------------------------------------------------
8413 % +N: number of constraint symbols
8414 % +TAttr1: source-level variable, for attribute
8415 % +TAttr2: source-level variable, for other attribute
8416 % -Goal: goal for merging the two attributes
8417 % -Attr: source-level term, for merged attribute
8418 merge_attributes(N,TAttr1,TAttr2,Goal,Attr) :-
8419 chr_pp_flag(dynattr,off), !,
8420 make_attr(N,Mask1,SuspsList1,Attr1),
8421 merge_attributes2(N,Mask1,SuspsList1,TAttr2,Goal2,Attr),
8428 merge_attributes(N,TAttr1,TAttr2,Goal,Attr) :-
8429 % writeln(merge_attributes),
8431 sort(TAttr1,Sorted1),
8432 sort(TAttr2,Sorted2),
8433 'chr new_merge_attributes'(Sorted1,Sorted2,Attr)
8437 %-------------------------------------------------------------------------------
8438 % +N: number of constraint symbols
8440 % +SuspsList1: static term, for suspensions list
8441 % +TAttr2: source-level variable, for other attribute
8442 % -Goal: goal for merging the two attributes
8443 % -Attr: source-level term, for merged attribute
8444 merge_attributes2(N,Mask1,SuspsList1,TAttr2,Goal,Attr) :-
8445 make_attr(N,Mask2,SuspsList2,Attr2),
8446 bagof(G,X ^ Y ^ SY ^ M ^ (member2(SuspsList1,SuspsList2,X-Y),G = (sort(Y,SY),'chr merge_attributes'(X,SY,M))),Gs),
8447 list2conj(Gs,SortGoals),
8448 bagof(MS,A ^ B ^ C ^ member((A,'chr merge_attributes'(B,C,MS)),Gs), SuspsList),
8449 make_attr(N,Mask,SuspsList,Attr),
8453 Mask is Mask1 \/ Mask2
8457 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8458 % Storetype dependent lookup
8460 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
8461 %% lookup_passive_head(+Head,+PreviousVars,+RenamingVarDict,
8462 %% -Goal,-SuspensionList) is det.
8464 % Create a universal lookup goal for given head.
8465 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
8466 lookup_passive_head(Head,PreJoin,VarDict,Goal,AllSusps) :-
8468 get_store_type(F/A,StoreType),
8469 lookup_passive_head(StoreType,Head,PreJoin,VarDict,[],Goal,AllSusps).
8471 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
8472 %% lookup_passive_head(+Head,+PreviousVars,+RenamingVarDict,+GroundVars,
8473 %% -Goal,-SuspensionList) is det.
8475 % Create a universal lookup goal for given head.
8476 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
8477 lookup_passive_head(Head,PreJoin,VarDict,GroundVars,Goal,AllSusps) :-
8479 get_store_type(F/A,StoreType),
8480 lookup_passive_head(StoreType,Head,PreJoin,VarDict,GroundVars,Goal,AllSusps).
8482 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
8483 %% lookup_passive_head(+StoreType,+Head,+PreviousVars,+RenamingVarDict,
8484 %% +GroundVars,-Goal,-SuspensionList) is det.
8486 % Create a universal lookup goal for given head.
8487 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
8488 lookup_passive_head(default,Head,PreJoin,VarDict,_,Goal,AllSusps) :-
8490 passive_head_via(Head,PreJoin,VarDict,Goal,AllSusps),
8491 update_store_type(F/A,default).
8492 lookup_passive_head(multi_inthash(Indexes),Head,_PreJoin,VarDict,GroundVars,Goal,AllSusps) :-
8493 hash_lookup_passive_head(inthash,Indexes,Head,VarDict,GroundVars,Goal,AllSusps,_).
8494 lookup_passive_head(multi_hash(Indexes),Head,_PreJoin,VarDict,GroundVars,Goal,AllSusps) :-
8495 hash_lookup_passive_head(hash,Indexes,Head,VarDict,GroundVars,Goal,AllSusps,_).
8496 lookup_passive_head(global_ground,Head,_PreJoin,_VarDict,_,Goal,AllSusps) :-
8498 global_ground_store_name(F/A,StoreName),
8499 make_get_store_goal(StoreName,AllSusps,Goal), % Goal = nb_getval(StoreName,AllSusps),
8500 update_store_type(F/A,global_ground).
8501 lookup_passive_head(var_assoc_store(VarIndex,KeyIndex),Head,_PreJoin,VarDict,_,Goal,AllSusps) :-
8502 arg(VarIndex,Head,OVar),
8503 arg(KeyIndex,Head,OKey),
8504 translate([OVar,OKey],VarDict,[Var,Key]),
8505 get_target_module(Module),
8507 get_attr(Var,Module,AssocStore),
8508 lookup_assoc_store(AssocStore,Key,AllSusps)
8510 lookup_passive_head(global_singleton,Head,_PreJoin,_VarDict,_,Goal,AllSusps) :-
8512 global_singleton_store_name(F/A,StoreName),
8513 make_get_store_goal(StoreName,Susp,GetStoreGoal),
8514 Goal = (GetStoreGoal,Susp \== [],AllSusps = [Susp]),
8515 update_store_type(F/A,global_singleton).
8516 lookup_passive_head(multi_store(StoreTypes),Head,PreJoin,VarDict,GroundVars,Goal,AllSusps) :-
8518 member(ST,StoreTypes),
8519 lookup_passive_head(ST,Head,PreJoin,VarDict,GroundVars,Goal,AllSusps)
8521 lookup_passive_head(identifier_store(Index),Head,PreJoin,VarDict,GroundVars,Goal,AllSusps) :-
8523 arg(Index,Head,Var),
8524 translate([Var],VarDict,[KeyVar]),
8525 delay_phase_end(validate_store_type_assumptions,
8526 identifier_lookup(F/A,Index,AllSusps,KeyVar,Goal)
8528 update_store_type(F/A,identifier_store(Index)),
8529 get_identifier_index(F/A,Index,_).
8530 lookup_passive_head(type_indexed_identifier_store(Index,IndexType),Head,PreJoin,VarDict,GroundVars,Goal,AllSusps) :-
8532 arg(Index,Head,Var),
8534 translate([Var],VarDict,[KeyVar]),
8536 ; ground(Var), Var = '$chr_identifier_match'(ActualVar,_) ->
8537 lookup_identifier_atom(IndexType,ActualVar,KeyVar,LookupGoal),
8538 Goal = (LookupGoal,StructGoal)
8540 delay_phase_end(validate_store_type_assumptions,
8541 type_indexed_identifier_lookup(F/A,Index,IndexType,AllSusps,KeyVar,StructGoal)
8543 update_store_type(F/A,type_indexed_identifier_store(Index,IndexType)),
8544 get_type_indexed_identifier_index(IndexType,F/A,Index,_).
8546 identifier_lookup(C,Index,AllSusps,KeyVar,Goal) :-
8547 get_identifier_size(ISize),
8548 functor(Struct,struct,ISize),
8549 get_identifier_index(C,Index,IIndex),
8550 arg(IIndex,Struct,AllSusps),
8551 Goal = (KeyVar = Struct).
8553 type_indexed_identifier_lookup(C,Index,IndexType,AllSusps,KeyVar,Goal) :-
8554 type_indexed_identifier_structure(IndexType,Struct),
8555 get_type_indexed_identifier_index(IndexType,C,Index,IIndex),
8556 arg(IIndex,Struct,AllSusps),
8557 Goal = (KeyVar = Struct).
8559 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
8560 %% hash_lookup_passive_head(+StoreType,+Indexes,+Head,+RenamingVarDict,
8561 %% +GroundVars,-Goal,-SuspensionList,-Index) is det.
8563 % Create a universal hash lookup goal for given head.
8564 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
8565 hash_lookup_passive_head(HashType,Indexes,Head,VarDict,GroundVars,Goal,AllSusps,Index) :-
8566 pick_hash_index(Indexes,Head,VarDict,Index,KeyArgs,KeyArgCopies),
8567 ( KeyArgCopies = [KeyCopy] ->
8570 KeyCopy =.. [k|KeyArgCopies]
8573 multi_hash_lookup_goal(F/A,HashType,Index,KeyCopy,AllSusps,LookupGoal),
8575 check_ground(GroundVars,KeyArgs,OriginalGroundCheck),
8576 my_term_copy(OriginalGroundCheck,VarDict,GroundCheck),
8578 Goal = (GroundCheck,LookupGoal),
8580 ( HashType == inthash ->
8581 update_store_type(F/A,multi_inthash([Index]))
8583 update_store_type(F/A,multi_hash([Index]))
8586 pick_hash_index(Indexes,Head,VarDict,Index,KeyArgs,KeyArgCopies) :-
8587 member(Index,Indexes),
8588 args(Index,Head,KeyArgs),
8589 key_in_scope(KeyArgs,VarDict,KeyArgCopies),
8592 % check whether we can copy the given terms
8593 % with the given dictionary, and, if so, do so
8594 key_in_scope([],VarDict,[]).
8595 key_in_scope([Arg|Args],VarDict,[ArgCopy|ArgCopies]) :-
8596 term_variables(Arg,Vars),
8597 translate(Vars,VarDict,VarCopies),
8598 copy_term(Arg/Vars,ArgCopy/VarCopies),
8599 key_in_scope(Args,VarDict,ArgCopies).
8601 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
8602 %% existential_lookup(+StoreType,+Head,+PrevVariablesHead,+RenamingVarDict,
8603 %% +GroundVariables,-SuspensionTerm,-Goal,-SuspVar,
8604 %% +VarArgDict,-NewVarArgDict) is det.
8606 % Create existential lookup goal for given head.
8607 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
8608 existential_lookup(var_assoc_store(VarIndex,KeyIndex),Head,PreJoin,VarDict,GroundVars,SuspTerm,Goal,Susp,Pairs,Pairs) :- !,
8609 lookup_passive_head(var_assoc_store(VarIndex,KeyIndex),Head,PreJoin,VarDict,GroundVars,UniversalGoal,AllSusps),
8610 sbag_member_call(Susp,AllSusps,Sbag),
8612 delay_phase_end(validate_store_type_assumptions,
8613 ( static_suspension_term(F/A,SuspTerm),
8614 get_static_suspension_field(F/A,SuspTerm,state,active,GetState)
8623 existential_lookup(global_singleton,Head,_PreJoin,_VarDict,_,SuspTerm,Goal,Susp,Pairs,Pairs) :- !,
8625 global_singleton_store_name(F/A,StoreName),
8626 make_get_store_goal(StoreName,Susp,GetStoreGoal),
8628 GetStoreGoal, % nb_getval(StoreName,Susp),
8632 update_store_type(F/A,global_singleton).
8633 existential_lookup(multi_store(StoreTypes),Head,PreJoin,VarDict,GroundVars,SuspTerm,Goal,Susp,Pairs,NPairs) :- !,
8635 member(ST,StoreTypes),
8636 existential_lookup(ST,Head,PreJoin,VarDict,GroundVars,SuspTerm,Goal,Susp,Pairs,NPairs)
8638 existential_lookup(multi_inthash(Indexes),Head,_,VarDict,GroundVars,SuspTerm,Goal,Susp,Pairs,NPairs) :- !,
8639 existential_hash_lookup(inthash,Indexes,Head,VarDict,GroundVars,SuspTerm,Goal,Susp,Pairs,NPairs).
8640 existential_lookup(multi_hash(Indexes),Head,_,VarDict,GroundVars,SuspTerm,Goal,Susp,Pairs,NPairs) :- !,
8641 existential_hash_lookup(hash,Indexes,Head,VarDict,GroundVars,SuspTerm,Goal,Susp,Pairs,NPairs).
8642 existential_lookup(identifier_store(Index),Head,PreJoin,VarDict,GroundVars,SuspTerm,Goal,Susp,Pairs,NPairs) :- !,
8643 lookup_passive_head(identifier_store(Index),Head,PreJoin,VarDict,GroundVars,LookupGoal,AllSusps),
8644 hash_index_filter(Pairs,Index,NPairs),
8647 ( check_fd_lookup_condition(F,A,Head,KeyArgs) ->
8648 Sbag = (AllSusps = [Susp])
8650 sbag_member_call(Susp,AllSusps,Sbag)
8652 delay_phase_end(validate_store_type_assumptions,
8653 ( static_suspension_term(F/A,SuspTerm),
8654 get_static_suspension_field(F/A,SuspTerm,state,active,GetState)
8660 Susp = SuspTerm, % not inlined
8663 existential_lookup(type_indexed_identifier_store(Index,IndexType),Head,PreJoin,VarDict,GroundVars,SuspTerm,Goal,Susp,Pairs,NPairs) :- !,
8664 lookup_passive_head(type_indexed_identifier_store(Index,IndexType),Head,PreJoin,VarDict,GroundVars,LookupGoal,AllSusps),
8665 hash_index_filter(Pairs,Index,NPairs),
8668 ( check_fd_lookup_condition(F,A,Head,KeyArgs) ->
8669 Sbag = (AllSusps = [Susp])
8671 sbag_member_call(Susp,AllSusps,Sbag)
8673 delay_phase_end(validate_store_type_assumptions,
8674 ( static_suspension_term(F/A,SuspTerm),
8675 get_static_suspension_field(F/A,SuspTerm,state,active,GetState)
8681 Susp = SuspTerm, % not inlined
8684 existential_lookup(StoreType,Head,PreJoin,VarDict,GroundVars,SuspTerm,Goal,Susp,Pairs,Pairs) :-
8685 lookup_passive_head(StoreType,Head,PreJoin,VarDict,GroundVars,UGoal,Susps),
8686 sbag_member_call(Susp,Susps,Sbag),
8688 delay_phase_end(validate_store_type_assumptions,
8689 ( static_suspension_term(F/A,SuspTerm),
8690 get_static_suspension_field(F/A,SuspTerm,state,active,GetState)
8696 Susp = SuspTerm, % not inlined
8700 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
8701 %% existential_hash_lookup(+StoreType,+Indexes,+Head,+RenamingVarDict,
8702 %% +GroundVariables,-SuspensionTerm,-Goal,-SuspVar,
8703 %% +VarArgDict,-NewVarArgDict) is det.
8705 % Create existential hash lookup goal for given head.
8706 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
8707 existential_hash_lookup(HashType,Indexes,Head,VarDict,GroundVars,SuspTerm,Goal,Susp,Pairs,NPairs) :-
8708 hash_lookup_passive_head(HashType,Indexes,Head,VarDict,GroundVars,LookupGoal,AllSusps,Index),
8710 hash_index_filter(Pairs,Index,NPairs),
8713 ( check_fd_lookup_condition(F,A,Head,KeyArgs) ->
8714 Sbag = (AllSusps = [Susp])
8716 sbag_member_call(Susp,AllSusps,Sbag)
8718 delay_phase_end(validate_store_type_assumptions,
8719 ( static_suspension_term(F/A,SuspTerm),
8720 get_static_suspension_field(F/A,SuspTerm,state,active,GetState)
8726 Susp = SuspTerm, % not inlined
8730 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
8731 %% hash_index_filter(+Pairs,+Index,-NPairs) is det.
8733 % Filter out pairs already covered by given hash index.
8734 % makes them 'silent'
8735 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
8736 hash_index_filter(Pairs,Index,NPairs) :-
8737 hash_index_filter(Pairs,Index,1,NPairs).
8739 hash_index_filter([],_,_,[]).
8740 hash_index_filter([P|Ps],Index,N,NPairs) :-
8745 hash_index_filter(Ps,[I|Is],NN,NPs)
8747 NPairs = [silent(P)|NPs],
8748 hash_index_filter(Ps,Is,NN,NPs)
8754 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8755 %------------------------------------------------------------------------------%
8756 %% assume_constraint_stores(+ConstraintSymbols) is det.
8758 % Compute all constraint store types that are possible for the given
8759 % =ConstraintSymbols=.
8760 %------------------------------------------------------------------------------%
8761 assume_constraint_stores([]).
8762 assume_constraint_stores([C|Cs]) :-
8763 ( chr_pp_flag(debugable,off),
8764 ( only_ground_indexed_arguments(C) ; chr_pp_flag(mixed_stores,on) ),
8766 get_store_type(C,default) ->
8767 get_indexed_arguments(C,AllIndexedArgs),
8768 get_constraint_mode(C,Modes),
8769 aggregate_all(bag(Index)-count,
8770 (member(Index,AllIndexedArgs),nth1(Index,Modes,+)),
8771 IndexedArgs-NbIndexedArgs),
8772 % Construct Index Combinations
8773 ( NbIndexedArgs > 10 ->
8774 findall([Index],member(Index,IndexedArgs),Indexes)
8776 findall(Index,(sublist(Index,IndexedArgs), Index \== []),UnsortedIndexes),
8777 predsort(longer_list,UnsortedIndexes,Indexes)
8779 % EXPERIMENTAL HEURISTIC
8781 % member(Arg1,IndexedArgs),
8782 % member(Arg2,IndexedArgs),
8784 % sort([Arg1,Arg2], Index)
8785 % ), UnsortedIndexes),
8786 % predsort(longer_list,UnsortedIndexes,Indexes),
8788 ( get_functional_dependency(C,1,Pattern,Key),
8789 all_distinct_var_args(Pattern), Key == [] ->
8790 assumed_store_type(C,global_singleton)
8791 ; ( only_ground_indexed_arguments(C) ; NbIndexedArgs > 0 ) ->
8792 get_constraint_type_det(C,ArgTypes),
8793 partition_indexes(Indexes,ArgTypes,HashIndexes,IntHashIndexes,IdentifierIndexes,CompoundIdentifierIndexes),
8795 ( IntHashIndexes = [] ->
8798 Stores = [multi_inthash(IntHashIndexes)|Stores1]
8800 ( HashIndexes = [] ->
8803 Stores1 = [multi_hash(HashIndexes)|Stores2]
8805 ( IdentifierIndexes = [] ->
8808 maplist(wrap_in_functor(identifier_store),IdentifierIndexes,WrappedIdentifierIndexes),
8809 append(WrappedIdentifierIndexes,Stores3,Stores2)
8811 append(CompoundIdentifierIndexes,Stores4,Stores3),
8812 ( only_ground_indexed_arguments(C)
8813 -> Stores4 = [global_ground]
8814 ; Stores4 = [default]
8816 assumed_store_type(C,multi_store(Stores))
8822 assume_constraint_stores(Cs).
8824 %------------------------------------------------------------------------------%
8825 %% partition_indexes(+Indexes,+Types,
8826 %% -HashIndexes,-IntHashIndexes,-IdentifierIndexes) is det.
8827 %------------------------------------------------------------------------------%
8828 partition_indexes([],_,[],[],[],[]).
8829 partition_indexes([Index|Indexes],Types,HashIndexes,IntHashIndexes,IdentifierIndexes,CompoundIdentifierIndexes) :-
8832 unalias_type(Type,UnAliasedType),
8833 UnAliasedType == chr_identifier ->
8834 IdentifierIndexes = [I|RIdentifierIndexes],
8835 IntHashIndexes = RIntHashIndexes,
8836 HashIndexes = RHashIndexes,
8837 CompoundIdentifierIndexes = RCompoundIdentifierIndexes
8840 unalias_type(Type,UnAliasedType),
8841 nonvar(UnAliasedType),
8842 UnAliasedType = chr_identifier(IndexType) ->
8843 CompoundIdentifierIndexes = [type_indexed_identifier_store(I,IndexType)|RCompoundIdentifierIndexes],
8844 IdentifierIndexes = RIdentifierIndexes,
8845 IntHashIndexes = RIntHashIndexes,
8846 HashIndexes = RHashIndexes
8849 unalias_type(Type,UnAliasedType),
8850 UnAliasedType == dense_int ->
8851 IntHashIndexes = [Index|RIntHashIndexes],
8852 HashIndexes = RHashIndexes,
8853 IdentifierIndexes = RIdentifierIndexes,
8854 CompoundIdentifierIndexes = RCompoundIdentifierIndexes
8857 unalias_type(Type,UnAliasedType),
8858 nonvar(UnAliasedType),
8859 UnAliasedType = chr_identifier(_) ->
8860 % don't use chr_identifiers in hash indexes
8861 IntHashIndexes = RIntHashIndexes,
8862 HashIndexes = RHashIndexes,
8863 IdentifierIndexes = RIdentifierIndexes,
8864 CompoundIdentifierIndexes = RCompoundIdentifierIndexes
8866 IntHashIndexes = RIntHashIndexes,
8867 HashIndexes = [Index|RHashIndexes],
8868 IdentifierIndexes = RIdentifierIndexes,
8869 CompoundIdentifierIndexes = RCompoundIdentifierIndexes
8871 partition_indexes(Indexes,Types,RHashIndexes,RIntHashIndexes,RIdentifierIndexes,RCompoundIdentifierIndexes).
8873 longer_list(R,L1,L2) :-
8883 all_distinct_var_args(Term) :-
8884 copy_term_nat(Term,TermCopy),
8886 functor(Pattern,F,A),
8887 Pattern =@= TermCopy.
8889 get_indexed_arguments(C,IndexedArgs) :-
8891 get_indexed_arguments(1,A,C,IndexedArgs).
8893 get_indexed_arguments(I,N,C,L) :-
8896 ; ( is_indexed_argument(C,I) ->
8902 get_indexed_arguments(J,N,C,T)
8905 validate_store_type_assumptions([]).
8906 validate_store_type_assumptions([C|Cs]) :-
8907 validate_store_type_assumption(C),
8908 validate_store_type_assumptions(Cs).
8910 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8911 % new code generation
8912 universal_search_iterator_end([CurrentHead|PrevHeads],NextHeads,Rule,F/A,O,Id,L,T) :-
8913 Rule = rule(H1,_,Guard,Body),
8914 gen_var_susp_list_for_b(PrevHeads,[CurrentHead,NextHeads,Guard,Body],_,VarsAndSuspsList,FirstVarsSusp,_,PrevIterators),
8915 universal_search_iterator_failure_vars(PrevHeads,Id,VarsAndSuspsList,FirstVarsSusp,PrevIterators,PrevVarsAndSusps,PrevId0),
8916 flatten(VarsAndSuspsList,VarsAndSusps),
8917 Vars = [ [] | VarsAndSusps],
8918 build_head(F,A,[O|Id],Vars,Head),
8920 get_success_continuation_code_id(F/A,O,PredictedPrevId),
8921 % format('~w == ~w ?\n',[PrevId0,PredictedPrevId]),
8922 PrevId = [PredictedPrevId] % PrevId = PrevId0
8924 PrevId = [O|PrevId0]
8926 build_head(F,A,PrevId,PrevVarsAndSusps,PredecessorCall),
8927 Clause = ( Head :- PredecessorCall),
8928 add_dummy_location(Clause,LocatedClause),
8929 L = [LocatedClause | T].
8931 % functor(CurrentHead,CF,CA),
8932 % check_fd_lookup_condition(CF,CA,CurrentHead,PrevHeads) ->
8935 % gen_var_susp_list_for_b(PrevHeads,[CurrentHead,NextHeads,Guard,Body],_,VarsAndSuspsList,FirstVarsSusp,_,PrevIterators),
8936 % universal_search_iterator_failure_vars(PrevHeads,Id,VarsAndSuspsList,FirstVarsSusp,PrevIterators,PrevVarsAndSusps,PrevId),
8937 % flatten(VarsAndSuspsList,VarsAndSusps),
8938 % Vars = [ [] | VarsAndSusps],
8939 % build_head(F,A,Id,Vars,Head),
8940 % build_head(F,A,PrevId,PrevVarsAndSusps,PredecessorCall),
8941 % Clause = ( Head :- PredecessorCall),
8945 % skips back intelligently over global_singleton lookups
8946 universal_search_iterator_failure_vars(PrevHeads,Id,VarsAndSuspsList,BaseCallArgs,PrevIterators,PrevVarsAndSusps,PrevId) :-
8948 % TOM: add partial success continuation optimization here!
8950 PrevVarsAndSusps = BaseCallArgs
8952 VarsAndSuspsList = [_|AllButFirstList],
8954 ( PrevHeads = [PrevHead|PrevHeads1],
8955 functor(PrevHead,F,A),
8956 check_fd_lookup_condition(F,A,PrevHead,PrevHeads1) ->
8957 PrevIterators = [_|PrevIterators1],
8958 universal_search_iterator_failure_vars(PrevHeads1,PrevId1,AllButFirstList,BaseCallArgs,PrevIterators1,PrevVarsAndSusps,PrevId)
8961 flatten(AllButFirstList,AllButFirst),
8962 PrevIterators = [PrevIterator|_],
8963 PrevVarsAndSusps = [PrevIterator|AllButFirst]
8967 universal_search_iterator([NextHead|RestHeads],[CurrentHead|PreHeads],Rule,F/A,O,Id,L,T) :-
8968 Rule = rule(_,_,Guard,Body),
8969 gen_var_susp_list_for_b(PreHeads,[CurrentHead,NextHead,RestHeads,Guard,Body],VarDict,PreVarsAndSuspsList,FirstVarsSusp,AllSusps,PrevIterators),
8970 init(AllSusps,PreSusps),
8971 flatten(PreVarsAndSuspsList,PreVarsAndSusps),
8972 gen_var(OtherSusps),
8973 functor(CurrentHead,OtherF,OtherA),
8974 gen_vars(OtherA,OtherVars),
8975 head_info(CurrentHead,OtherA,OtherVars,OtherSusp,_VarsSusp,HeadPairs),
8976 get_constraint_mode(OtherF/OtherA,Mode),
8977 head_arg_matches(HeadPairs,Mode,VarDict,FirstMatching,VarDict1),
8979 delay_phase_end(validate_store_type_assumptions,
8980 ( static_suspension_term(OtherF/OtherA,OtherSuspension),
8981 get_static_suspension_field(OtherF/OtherA,OtherSuspension,state,active,GetState),
8982 get_static_suspension_term_field(arguments,OtherF/OtherA,OtherSuspension,OtherVars)
8986 different_from_other_susps(CurrentHead,OtherSusp,PreHeads,PreSusps,DiffSuspGoals),
8987 % create_get_mutable_ref(active,State,GetMutable),
8989 OtherSusp = OtherSuspension,
8994 add_heads_ground_variables([CurrentHead|PreHeads],[],GroundVars),
8995 lookup_passive_head(NextHead,[CurrentHead|PreHeads],VarDict1,GroundVars,NextSuspGoal,NextSusps),
8996 inc_id(Id,NestedId),
8997 ClauseVars = [[OtherSusp|OtherSusps]|PreVarsAndSusps],
8998 build_head(F,A,[O|Id],ClauseVars,ClauseHead),
8999 passive_delegate_variables(CurrentHead,PreHeads,[NextHead,RestHeads,Guard,Body],VarDict1,CurrentHeadVars),
9000 append([NextSusps|CurrentHeadVars],[OtherSusp,OtherSusps|PreVarsAndSusps],NestedVars),
9001 build_head(F,A,[O|NestedId],NestedVars,NestedHead),
9003 ( check_fd_lookup_condition(OtherF,OtherA,CurrentHead,PreHeads) -> % iterator (OtherSusps) is empty at runtime
9004 universal_search_iterator_failure_vars(PreHeads,Id,PreVarsAndSuspsList,FirstVarsSusp,PrevIterators,PreVarsAndSusps1,PrevId0),
9005 RecursiveVars = PreVarsAndSusps1
9007 RecursiveVars = [OtherSusps|PreVarsAndSusps],
9013 PrevId = [O|PrevId0]
9015 build_head(F,A,PrevId,RecursiveVars,RecursiveHead),
9026 add_dummy_location(Clause,LocatedClause),
9027 L = [LocatedClause|T].
9029 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9031 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9032 % Observation Analysis
9037 % Analysis based on Abstract Interpretation paper.
9040 % stronger analysis domain [research]
9043 initial_call_pattern/1,
9045 call_pattern_worker/1,
9046 final_answer_pattern/2,
9047 abstract_constraints/1,
9051 ai_observed_internal/2,
9053 ai_not_observed_internal/2,
9057 ai_observation_gather_results/0.
9059 :- chr_type abstract_domain ---> odom(program_point,list(constraint)).
9060 :- chr_type program_point == any.
9062 :- chr_option(mode,initial_call_pattern(+)).
9063 :- chr_option(type_declaration,call_pattern(abstract_domain)).
9065 :- chr_option(mode,call_pattern(+)).
9066 :- chr_option(type_declaration,call_pattern(abstract_domain)).
9068 :- chr_option(mode,call_pattern_worker(+)).
9069 :- chr_option(type_declaration,call_pattern_worker(abstract_domain)).
9071 :- chr_option(mode,final_answer_pattern(+,+)).
9072 :- chr_option(type_declaration,final_answer_pattern(abstract_domain,abstract_domain)).
9074 :- chr_option(mode,abstract_constraints(+)).
9075 :- chr_option(type_declaration,abstract_constraints(list)).
9077 :- chr_option(mode,depends_on(+,+)).
9078 :- chr_option(type_declaration,depends_on(abstract_domain,abstract_domain)).
9080 :- chr_option(mode,depends_on_as(+,+,+)).
9081 :- chr_option(mode,depends_on_ap(+,+,+,+)).
9082 :- chr_option(mode,depends_on_goal(+,+)).
9083 :- chr_option(mode,ai_is_observed(+,+)).
9084 :- chr_option(mode,ai_not_observed(+,+)).
9085 % :- chr_option(mode,ai_observed(+,+)).
9086 :- chr_option(mode,ai_not_observed_internal(+,+)).
9087 :- chr_option(mode,ai_observed_internal(+,+)).
9090 abstract_constraints_fd @
9091 abstract_constraints(_) \ abstract_constraints(_) <=> true.
9093 ai_observed_internal(C,O) \ ai_not_observed_internal(C,O) <=> true.
9094 ai_not_observed_internal(C,O) \ ai_not_observed_internal(C,O) <=> true.
9095 ai_observed_internal(C,O) \ ai_observed_internal(C,O) <=> true.
9097 ai_not_observed(C,O) \ ai_is_observed(C,O) <=> fail.
9098 ai_is_observed(_,_) <=> true.
9100 ai_observation_gather_results \ ai_observed_internal(C,O) <=> true. % ai_observed(C,O).
9101 ai_observation_gather_results \ ai_not_observed_internal(C,O) <=> ai_not_observed(C,O).
9102 ai_observation_gather_results <=> true.
9104 %------------------------------------------------------------------------------%
9105 % Main Analysis Entry
9106 %------------------------------------------------------------------------------%
9107 ai_observation_analysis(ACs) :-
9108 ( chr_pp_flag(ai_observation_analysis,on),
9109 get_target_module(Module), '$chr_compiled_with_version'(3) -> % , Module \== guard_entailment ->
9110 list_to_ord_set(ACs,ACSet),
9111 abstract_constraints(ACSet),
9112 ai_observation_schedule_initial_calls(ACSet,ACSet),
9113 ai_observation_gather_results
9118 ai_observation_schedule_initial_calls([],_).
9119 ai_observation_schedule_initial_calls([AC|RACs],ACs) :-
9120 ai_observation_schedule_initial_call(AC,ACs),
9121 ai_observation_schedule_initial_calls(RACs,ACs).
9123 ai_observation_schedule_initial_call(AC,ACs) :-
9124 ai_observation_top(AC,CallPattern),
9125 % ai_observation_bot(AC,ACs,CallPattern),
9126 initial_call_pattern(CallPattern).
9128 ai_observation_schedule_new_calls([],AP).
9129 ai_observation_schedule_new_calls([AC|ACs],AP) :-
9131 initial_call_pattern(odom(AC,Set)),
9132 ai_observation_schedule_new_calls(ACs,AP).
9134 final_answer_pattern(CP,AP1) \ final_answer_pattern(CP,AP2)
9136 ai_observation_leq(AP2,AP1)
9140 initial_call_pattern(CP) \ initial_call_pattern(CP) <=> true.
9142 initial_call_pattern(CP) ==> call_pattern(CP).
9144 initial_call_pattern(CP), final_answer_pattern(CP,AP), abstract_constraints(ACs) # ID3
9146 ai_observation_schedule_new_calls(ACs,AP)
9150 call_pattern(CP) \ call_pattern(CP) <=> true.
9152 depends_on(CP1,CP2), final_answer_pattern(CP2,AP) ==>
9153 final_answer_pattern(CP1,AP).
9155 %call_pattern(CP) ==> writeln(call_pattern(CP)).
9157 call_pattern(CP) ==> call_pattern_worker(CP).
9159 %------------------------------------------------------------------------------%
9161 %------------------------------------------------------------------------------%
9164 %call_pattern(odom([],Set)) ==>
9165 % final_answer_pattern(odom([],Set),odom([],Set)).
9167 call_pattern_worker(odom([],Set)) <=>
9168 % writeln(' - AbstractGoal'(odom([],Set))),
9169 final_answer_pattern(odom([],Set),odom([],Set)).
9172 call_pattern_worker(odom([G|Gs],Set)) <=>
9173 % writeln(' - AbstractGoal'(odom([G|Gs],Set))),
9175 depends_on_goal(odom([G|Gs],Set),CP1),
9178 depends_on_goal(CP1,CP2), final_answer_pattern(CP2,AP2) \ depends_on(CP1,_) # ID
9179 <=> true pragma passive(ID).
9180 depends_on_goal(CP1,CP2), final_answer_pattern(CP2,AP2)
9182 CP1 = odom([_|Gs],_),
9186 depends_on(CP1,CCP).
9188 %------------------------------------------------------------------------------%
9189 % Abstract Disjunction
9190 %------------------------------------------------------------------------------%
9192 call_pattern_worker(odom((AG1;AG2),Set)) <=>
9193 CP = odom((AG1;AG2),Set),
9194 InitialAnswerApproximation = odom([],Set),
9195 final_answer_pattern(CP,InitialAnswerApproximation),
9196 CP1 = odom(AG1,Set),
9197 CP2 = odom(AG2,Set),
9200 depends_on_as(CP,CP1,CP2).
9202 %------------------------------------------------------------------------------%
9204 %------------------------------------------------------------------------------%
9205 call_pattern_worker(odom(builtin,Set)) <=>
9206 % writeln(' - AbstractSolve'(odom(builtin,Set))),
9207 ord_empty(EmptySet),
9208 final_answer_pattern(odom(builtin,Set),odom([],EmptySet)).
9210 %------------------------------------------------------------------------------%
9212 %------------------------------------------------------------------------------%
9213 max_occurrence(C,MO) # ID2 \ call_pattern_worker(odom(occ(C,O),Set))
9217 % writeln(' - AbstractDrop'(odom(occ(C,O),Set))),
9218 final_answer_pattern(odom(occ(C,O),Set),odom([],Set))
9222 %------------------------------------------------------------------------------%
9224 %------------------------------------------------------------------------------%
9225 call_pattern_worker(odom(AC,Set))
9229 % writeln(' - AbstractActivate'(odom(AC,Set))),
9230 CP = odom(occ(AC,1),Set),
9232 depends_on(odom(AC,Set),CP).
9234 %------------------------------------------------------------------------------%
9236 %------------------------------------------------------------------------------%
9237 occurrence(C,O,RuleNb,ID,_) # ID2 \ call_pattern_worker(odom(occ(C,O),Set))
9239 is_passive(RuleNb,ID)
9241 % writeln(' - AbstractPassive'(odom(occ(C,O),Set))),
9244 DCP = odom(occ(C,NO),Set),
9246 final_answer_pattern(odom(occ(C,O),Set),odom([],Set)),
9247 depends_on(odom(occ(C,O),Set),DCP)
9250 %------------------------------------------------------------------------------%
9252 %------------------------------------------------------------------------------%
9255 occurrence(C,O,RuleNb,ID,simplification) # ID2 \ call_pattern_worker(odom(occ(C,O),Set))
9257 \+ is_passive(RuleNb,ID)
9259 % writeln(' - AbstractPassive'(odom(occ(C,O),Set))),
9260 ai_observation_memo_simplification_rest_heads(C,O,AbstractRestHeads),
9261 ai_observation_observe_set(Set,AbstractRestHeads,Set2),
9262 ai_observation_memo_abstract_goal(RuleNb,AG),
9263 call_pattern(odom(AG,Set2)),
9266 DCP = odom(occ(C,NO),Set),
9268 depends_on_as(odom(occ(C,O),Set),odom(AG,Set2),DCP),
9269 % DEADLOCK AVOIDANCE
9270 final_answer_pattern(odom(occ(C,O),Set),odom([],Set))
9274 depends_on_as(CP,CPS,CPD),
9275 final_answer_pattern(CPS,APS),
9276 final_answer_pattern(CPD,APD) ==>
9277 ai_observation_lub(APS,APD,AP),
9278 final_answer_pattern(CP,AP).
9282 ai_observation_memo_simplification_rest_heads/3,
9283 ai_observation_memoed_simplification_rest_heads/3.
9285 :- chr_option(mode,ai_observation_memo_simplification_rest_heads(+,+,?)).
9286 :- chr_option(mode,ai_observation_memoed_simplification_rest_heads(+,+,+)).
9288 ai_observation_memoed_simplification_rest_heads(C,O,RH) \ ai_observation_memo_simplification_rest_heads(C,O,QRH)
9291 abstract_constraints(ACs) # ID1, occurrence(C,O,RuleNb,ID,_) # ID2, rule(RuleNb,Rule) # ID3 \ ai_observation_memo_simplification_rest_heads(C,O,QRH)
9293 Rule = pragma(rule(H1,H2,_,_),ids(IDs1,_),_,_,_),
9294 once(select2(ID,_,IDs1,H1,_,RestH1)),
9295 ai_observation_abstract_constraints(RestH1,ACs,ARestHeads),
9296 ai_observation_abstract_constraints(H2,ACs,AH2),
9297 append(ARestHeads,AH2,AbstractHeads),
9298 sort(AbstractHeads,QRH),
9299 ai_observation_memoed_simplification_rest_heads(C,O,QRH)
9305 ai_observation_memo_simplification_rest_heads(_,_,_) <=> fail.
9307 %------------------------------------------------------------------------------%
9308 % Abstract Propagate
9309 %------------------------------------------------------------------------------%
9313 occurrence(C,O,RuleNb,ID,propagation) # ID2 \ call_pattern_worker(odom(occ(C,O),Set))
9315 \+ is_passive(RuleNb,ID)
9317 % writeln(' - AbstractPropagate'(odom(occ(C,O),Set))),
9319 ai_observation_memo_propagation_rest_heads(C,O,AHs),
9320 ai_observation_observe_set(Set,AHs,Set2),
9321 ord_add_element(Set2,C,Set3),
9322 ai_observation_memo_abstract_goal(RuleNb,AG),
9323 call_pattern(odom(AG,Set3)),
9324 ( ord_memberchk(C,Set2) ->
9331 DCP = odom(occ(C,NO),Set),
9333 depends_on_ap(odom(occ(C,O),Set),odom(AG,Set3),DCP,Delete)
9338 ai_observation_memo_propagation_rest_heads/3,
9339 ai_observation_memoed_propagation_rest_heads/3.
9341 :- chr_option(mode,ai_observation_memo_propagation_rest_heads(+,+,?)).
9342 :- chr_option(mode,ai_observation_memoed_propagation_rest_heads(+,+,+)).
9344 ai_observation_memoed_propagation_rest_heads(C,O,RH) \ ai_observation_memo_propagation_rest_heads(C,O,QRH)
9347 abstract_constraints(ACs) # ID1, occurrence(C,O,RuleNb,ID,_) # ID2, rule(RuleNb,Rule) # ID3 \ ai_observation_memo_propagation_rest_heads(C,O,QRH)
9349 Rule = pragma(rule(H1,H2,_,_),ids(_,IDs2),_,_,_),
9350 once(select2(ID,_,IDs2,H2,_,RestH2)),
9351 ai_observation_abstract_constraints(RestH2,ACs,ARestHeads),
9352 ai_observation_abstract_constraints(H1,ACs,AH1),
9353 append(ARestHeads,AH1,AbstractHeads),
9354 sort(AbstractHeads,QRH),
9355 ai_observation_memoed_propagation_rest_heads(C,O,QRH)
9361 ai_observation_memo_propagation_rest_heads(_,_,_) <=> fail.
9363 depends_on_ap(CP,CPP,CPD,Delete), final_answer_pattern(CPD,APD) ==>
9364 final_answer_pattern(CP,APD).
9365 depends_on_ap(CP,CPP,CPD,Delete), final_answer_pattern(CPP,APP),
9366 final_answer_pattern(CPD,APD) ==>
9368 CP = odom(occ(C,O),_),
9369 ( ai_observation_is_observed(APP,C) ->
9370 ai_observed_internal(C,O)
9372 ai_not_observed_internal(C,O)
9375 APP = odom([],Set0),
9376 ord_del_element(Set0,C,Set),
9381 ai_observation_lub(NAPP,APD,AP),
9382 final_answer_pattern(CP,AP).
9384 %------------------------------------------------------------------------------%
9386 %------------------------------------------------------------------------------%
9388 call_pattern_worker(CP) <=> chr_error(internal,'AI observation analysis: unexpected abstract state ~w\n',[CP]).
9390 %------------------------------------------------------------------------------%
9391 % Auxiliary Predicates
9392 %------------------------------------------------------------------------------%
9394 ai_observation_lub(odom(AG,S1),odom(AG,S2),odom(AG,S3)) :-
9395 ord_intersection(S1,S2,S3).
9397 ai_observation_bot(AG,AS,odom(AG,AS)).
9399 ai_observation_top(AG,odom(AG,EmptyS)) :-
9402 ai_observation_leq(odom(AG,S1),odom(AG,S2)) :-
9405 ai_observation_observe_set(S,ACSet,NS) :-
9406 ord_subtract(S,ACSet,NS).
9408 ai_observation_abstract_constraint(C,ACs,AC) :-
9413 ai_observation_abstract_constraints(Cs,ACs,NACs) :-
9414 findall(NAC,(member(C,Cs),ai_observation_abstract_constraint(C,ACs,NAC)),NACs).
9416 %------------------------------------------------------------------------------%
9417 % Abstraction of Rule Bodies
9418 %------------------------------------------------------------------------------%
9421 ai_observation_memoed_abstract_goal/2,
9422 ai_observation_memo_abstract_goal/2.
9424 :- chr_option(mode,ai_observation_memoed_abstract_goal(+,+)).
9425 :- chr_option(mode,ai_observation_memo_abstract_goal(+,?)).
9427 ai_observation_memoed_abstract_goal(RuleNb,AG) # ID1 \ ai_observation_memo_abstract_goal(RuleNb,QAG)
9433 rule(RuleNb,Rule) # ID1, abstract_constraints(ACs) # ID2 \ ai_observation_memo_abstract_goal(RuleNb,QAG)
9435 Rule = pragma(rule(H1,H2,Guard,Body),_,_,_,_),
9436 ai_observation_abstract_goal_(H1,H2,Guard,Body,ACs,AG),
9438 ai_observation_memoed_abstract_goal(RuleNb,AG)
9443 ai_observation_abstract_goal_(H1,H2,Guard,G,ACs,AG) :-
9444 % also guard: e.g. b, c(X) ==> Y=X | p(Y).
9445 term_variables((H1,H2,Guard),HVars),
9446 append(H1,H2,Heads),
9447 % variables that are declared to be ground are safe,
9448 ground_vars(Heads,GroundVars),
9449 % so we remove them from the list of 'dangerous' head variables
9450 list_difference_eq(HVars,GroundVars,HV),
9451 ai_observation_abstract_goal(G,ACs,AG,[],HV),!.
9452 % writeln(ai_observation_abstract_goal(G,ACs,AG,[],HV)).
9453 % HV are 'dangerous' variables, all others are fresh and safe
9456 ground_vars([H|Hs],GroundVars) :-
9458 get_constraint_mode(F/A,Mode),
9459 % TOM: fix this code!
9460 head_info(H,A,_Vars,_Susp,_HeadVars,HeadPairs),
9461 head_arg_matches(HeadPairs,Mode,[],_FirstMatching,_VarDict1,[],GroundVars1),
9462 ground_vars(Hs,GroundVars2),
9463 append(GroundVars1,GroundVars2,GroundVars).
9465 ai_observation_abstract_goal((G1,G2),ACs,List,Tail,HV) :- !, % conjunction
9466 ai_observation_abstract_goal(G1,ACs,List,IntermediateList,HV),
9467 ai_observation_abstract_goal(G2,ACs,IntermediateList,Tail,HV).
9468 ai_observation_abstract_goal((G1;G2),ACs,[(ABranch1;ABranch2)|Tail],Tail,HV) :- !, % disjunction
9469 ai_observation_abstract_goal(G1,ACs,ABranch1,[],HV),
9470 ai_observation_abstract_goal(G2,ACs,ABranch2,[],HV).
9471 ai_observation_abstract_goal((G1->G2),ACs,List,Tail,HV) :- !, % if-then
9472 ai_observation_abstract_goal(G1,ACs,List,IntermediateList,HV),
9473 ai_observation_abstract_goal(G2,ACs,IntermediateList,Tail,HV).
9474 ai_observation_abstract_goal(C,ACs,[AC|Tail],Tail,HV) :-
9475 ai_observation_abstract_constraint(C,ACs,AC), !. % CHR constraint
9476 ai_observation_abstract_goal(true,_,Tail,Tail,_) :- !.
9477 ai_observation_abstract_goal(writeln(_),_,Tail,Tail,_) :- !.
9478 % non-CHR constraint is safe if it only binds fresh variables
9479 ai_observation_abstract_goal(G,_,Tail,Tail,HV) :-
9480 builtin_binds_b(G,Vars),
9481 intersect_eq(Vars,HV,[]),
9483 ai_observation_abstract_goal(G,_,[AG|Tail],Tail,_) :-
9484 AG = builtin. % default case if goal is not recognized/safe
9486 ai_observation_is_observed(odom(_,ACSet),AC) :-
9487 \+ ord_memberchk(AC,ACSet).
9489 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9490 unconditional_occurrence(C,O) :-
9491 get_occurrence(C,O,RuleNb,ID),
9492 get_rule(RuleNb,PRule),
9493 PRule = pragma(ORule,_,_,_,_),
9494 copy_term_nat(ORule,Rule),
9495 Rule = rule(H1,H2,Guard,_),
9496 guard_entailment:entails_guard([chr_pp_headvariables(H1,H2)],Guard),
9498 H1 = [Head], H2 == []
9500 H2 = [Head], H1 == [], \+ may_trigger(C)
9502 all_distinct_var_args(Head).
9504 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9506 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9507 % Partial wake analysis
9509 % In a Var = Var unification do not wake up constraints of both variables,
9510 % but rather only those of one variable.
9511 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9513 :- chr_constraint partial_wake_analysis/0.
9514 :- chr_constraint no_partial_wake/1.
9515 :- chr_option(mode,no_partial_wake(+)).
9516 :- chr_constraint wakes_partially/1.
9517 :- chr_option(mode,wakes_partially(+)).
9519 partial_wake_analysis, occurrence(FA,O,RuleNb,ID,Type), rule(RuleNb,Rule), constraint_mode(FA,ArgModes)
9521 Rule = pragma(rule(H1,H2,Guard,Body),_,_,_,_),
9522 ( is_passive(RuleNb,ID) ->
9524 ; Type == simplification ->
9525 select(H,H1,RestH1),
9527 term_variables(Guard,Vars),
9528 partial_wake_args(Args,ArgModes,Vars,FA)
9529 ; % Type == propagation ->
9530 select(H,H2,RestH2),
9532 term_variables(Guard,Vars),
9533 partial_wake_args(Args,ArgModes,Vars,FA)
9536 partial_wake_args([],_,_,_).
9537 partial_wake_args([Arg|Args],[Mode|Modes],Vars,C) :-
9541 ; memberchk_eq(Arg,Vars) ->
9549 partial_wake_args(Args,Modes,Vars,C).
9551 no_partial_wake(C) \ no_partial_wake(C) <=> true.
9553 no_partial_wake(C) \ wakes_partially(C) <=> fail.
9555 wakes_partially(C) <=> true.
9558 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9559 % Generate rules that implement chr_show_store/1 functionality.
9565 % Generates additional rules:
9567 % $show, C1 # ID ==> writeln(C1) pragma passive(ID).
9569 % $show, Cn # ID ==> writeln(Cn) pragma passive(ID).
9572 generate_show_constraint(Constraints0,Constraints,Rules0,Rules) :-
9573 ( chr_pp_flag(show,on) ->
9574 Constraints = ['$show'/0|Constraints0],
9575 generate_show_rules(Constraints0,Rules,[Rule|Rules0]),
9576 inc_rule_count(RuleNb),
9578 rule(['$show'],[],true,true),
9585 Constraints = Constraints0,
9589 generate_show_rules([],Rules,Rules).
9590 generate_show_rules([F/A|Rest],[Rule|Tail],Rules) :-
9592 inc_rule_count(RuleNb),
9594 rule([],['$show',C],true,writeln(C)),
9600 generate_show_rules(Rest,Tail,Rules).
9602 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9603 % Custom supension term layout
9605 static_suspension_term(F/A,Suspension) :-
9606 suspension_term_base(F/A,Base),
9608 functor(Suspension,suspension,Arity).
9610 has_suspension_field(FA,Field) :-
9611 suspension_term_base_fields(FA,Fields),
9612 memberchk(Field,Fields).
9614 suspension_term_base(FA,Base) :-
9615 suspension_term_base_fields(FA,Fields),
9616 length(Fields,Base).
9618 suspension_term_base_fields(FA,Fields) :-
9619 ( chr_pp_flag(debugable,on) ->
9622 % 3. Propagation History
9623 % 4. Generation Number
9624 % 5. Continuation Goal
9626 Fields = [id,state,history,generation,continuation,functor]
9628 ( uses_history(FA) ->
9629 Fields = [id,state,history|Fields2]
9630 ; only_ground_indexed_arguments(FA), get_functional_dependency(FA,1,_,_) ->
9631 Fields = [state|Fields2]
9633 Fields = [id,state|Fields2]
9635 ( only_ground_indexed_arguments(FA) ->
9636 get_store_type(FA,StoreType),
9637 basic_store_types(StoreType,BasicStoreTypes),
9638 ( memberchk(global_ground,BasicStoreTypes) ->
9641 % 3. Propagation History
9642 % 4. Global List Prev
9643 Fields2 = [global_list_prev|Fields3]
9647 % 3. Propagation History
9650 ( chr_pp_flag(ht_removal,on)
9651 -> ht_prev_fields(BasicStoreTypes,Fields3)
9654 ; may_trigger(FA) ->
9657 % 3. Propagation History
9658 ( uses_field(FA,generation) ->
9659 % 4. Generation Number
9660 % 5. Global List Prev
9661 Fields2 = [generation,global_list_prev|Fields3]
9663 Fields2 = [global_list_prev|Fields3]
9665 ( chr_pp_flag(mixed_stores,on),
9666 chr_pp_flag(ht_removal,on)
9667 -> get_store_type(FA,StoreType),
9668 basic_store_types(StoreType,BasicStoreTypes),
9669 ht_prev_fields(BasicStoreTypes,Fields3)
9675 % 3. Propagation History
9676 % 4. Global List Prev
9677 Fields2 = [global_list_prev|Fields3],
9678 ( chr_pp_flag(mixed_stores,on),
9679 chr_pp_flag(ht_removal,on)
9680 -> get_store_type(FA,StoreType),
9681 basic_store_types(StoreType,BasicStoreTypes),
9682 ht_prev_fields(BasicStoreTypes,Fields3)
9688 ht_prev_fields(Stores,Prevs) :-
9689 ht_prev_fields_int(Stores,PrevsList),
9690 append(PrevsList,Prevs).
9691 ht_prev_fields_int([],[]).
9692 ht_prev_fields_int([H|T],Fields) :-
9693 ( H = multi_hash(Indexes)
9694 -> maplist(ht_prev_field,Indexes,FH),
9698 ht_prev_fields_int(T,FT).
9700 ht_prev_field(Index,Field) :-
9701 concat_atom(['multi_hash_prev-'|Index],Field).
9703 get_static_suspension_term_field(FieldName,FA,StaticSuspension,Field) :-
9704 suspension_term_base_fields(FA,Fields),
9705 nth1(Index,Fields,FieldName), !,
9706 arg(Index,StaticSuspension,Field).
9707 get_static_suspension_term_field(arguments,FA,StaticSuspension,Field) :- !,
9708 suspension_term_base(FA,Base),
9709 StaticSuspension =.. [_|Args],
9710 drop(Base,Args,Field).
9711 get_static_suspension_term_field(FieldName,FA,_StaticSuspension,_Field) :-
9712 chr_error(internal,'Trying to obtain field ~w of ~w, wich does not have it!',[FieldName,FA]).
9715 get_dynamic_suspension_term_field(FieldName,FA,DynamicSuspension,Field,Goal) :-
9716 suspension_term_base_fields(FA,Fields),
9717 nth1(Index,Fields,FieldName), !,
9718 Goal = arg(Index,DynamicSuspension,Field).
9719 get_dynamic_suspension_term_field(arguments,FA,DynamicSuspension,Field,Goal) :- !,
9720 static_suspension_term(FA,StaticSuspension),
9721 get_static_suspension_term_field(arguments,FA,StaticSuspension,Field),
9722 Goal = (DynamicSuspension = StaticSuspension).
9723 get_dynamic_suspension_term_field(argument(I),FA,DynamicSuspension,Field,Goal) :- !,
9724 suspension_term_base(FA,Base),
9726 Goal = arg(Index,DynamicSuspension,Field).
9727 get_dynamic_suspension_term_field(FieldName,FA,_DynamicSuspension,_Field,_Goal) :-
9728 chr_error(internal,'Dynamic goal to get ~w of ~w, which does not have this field!',[FieldName,FA]).
9731 set_dynamic_suspension_term_field(FieldName,FA,DynamicSuspension,Field,Goal) :-
9732 suspension_term_base_fields(FA,Fields),
9733 nth1(Index,Fields,FieldName), !,
9734 Goal = setarg(Index,DynamicSuspension,Field).
9735 set_dynamic_suspension_term_field(FieldName,FA,_DynamicSuspension,_Field,_Goal) :-
9736 chr_error(internal,'Dynamic goal to set ~w of ~w, which does not have this field!',[FieldName,FA]).
9738 basic_store_types(multi_store(Types),Types) :- !.
9739 basic_store_types(Type,[Type]).
9741 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9748 :- chr_option(mode,phase_end(+)).
9749 :- chr_option(mode,delay_phase_end(+,?)).
9751 phase_end(Phase) \ delay_phase_end(Phase,Goal) <=> call(Goal).
9752 % phase_end(Phase) <=> true.
9755 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9759 novel_production_call/4.
9761 :- chr_option(mode,uses_history(+)).
9762 :- chr_option(mode,does_use_history(+,+)).
9763 :- chr_option(mode,novel_production_call(+,+,?,?)).
9765 does_use_history(FA,Occ) \ does_use_history(FA,Occ) <=> true.
9766 does_use_history(FA,_) \ uses_history(FA) <=> true.
9767 uses_history(_FA) <=> fail.
9769 does_use_history(FA,Occ) \ novel_production_call(FA,Occ,PossibleGoal,Goal) <=> Goal = PossibleGoal.
9770 novel_production_call(FA,_,_PossibleGoal,Goal) <=> Goal = true.
9776 :- chr_option(mode,uses_field(+,+)).
9777 :- chr_option(mode,does_use_field(+,+)).
9779 does_use_field(FA,Field) \ does_use_field(FA,Field) <=> true.
9780 does_use_field(FA,Field) \ uses_field(FA,Field) <=> true.
9781 uses_field(_FA,_Field) <=> fail.
9786 used_states_known/0.
9788 :- chr_option(mode,uses_state(+,+)).
9789 :- chr_option(mode,if_used_state(+,+,?,?,?)).
9792 % states ::= not_stored_yet | passive | active | triggered | removed
9794 % allocate CREATES not_stored_yet
9795 % remove CHECKS not_stored_yet
9796 % activate CHECKS not_stored_yet
9798 % ==> no allocate THEN no not_stored_yet
9800 % recurs CREATES inactive
9801 % lookup CHECKS inactive
9803 % insert CREATES active
9804 % activate CREATES active
9805 % lookup CHECKS active
9806 % recurs CHECKS active
9808 % runsusp CREATES triggered
9809 % lookup CHECKS triggered
9811 % ==> no runsusp THEN no triggered
9813 % remove CREATES removed
9814 % runsusp CHECKS removed
9815 % lookup CHECKS removed
9816 % recurs CHECKS removed
9818 % ==> no remove THEN no removed
9820 % ==> no allocate, no remove, no active/inactive distinction THEN no state at all...
9822 uses_state(Constraint,State) \ uses_state(Constraint,State) <=> true.
9824 used_states_known, uses_state(Constraint,State) \ if_used_state(Constraint,State,Used,NotUsed,ResultGoal)
9825 <=> ResultGoal = Used.
9826 used_states_known \ if_used_state(Constraint,State,Used,NotUsed,ResultGoal)
9827 <=> ResultGoal = NotUsed.
9829 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9830 % CHECK STOREDNESS ANNOTATIONS AND GENERATE DEFAULT SIMPLIFICATION RULES
9836 % When the programmer enables the `declare_stored_constraints' option, i.e. writes
9838 % :- chr_option(declare_stored_constraints,on).
9840 % the compiler will check for the storedness of constraints.
9842 % By default, the compiler assumes that the programmer wants his constraints to
9843 % be never-stored. Hence, a warning will be issues when a constraint is actually
9846 % Such warnings are suppressed, if the programmer adds the `# stored' modifier
9847 % to a constraint declaration, i.e. writes
9849 % :- chr_constraint c(...) # stored.
9851 % In that case a warning is issued when the constraint is never-stored.
9853 % NOTE: Checking is only performed if `storage_analysis' is on. Otherwise, all
9854 % constraints are stored anyway.
9857 % 2. Rule Generation
9858 % ~~~~~~~~~~~~~~~~~~
9860 % When the programmer enables the `declare_stored_constraints' option, i.e. writes
9862 % :- chr_option(declare_stored_constraints,on).
9864 % the compiler will generate default simplification rules for constraints.
9866 % By default, no default rule is generated for a constraint. However, if the
9867 % programmer writes a default/1 annotation in the constraint declaration, i.e. writes
9869 % :- chr_constraint c(...) # default(Goal).
9871 % where `Goal' is a ground and callable goal (e.g. `true', `fail' or `throw(error)'),
9872 % the compiler generates a rule:
9874 % c(_,...,_) <=> Goal.
9876 % at the end of the program. If multiple default rules are generated, for several constraints,
9877 % then the order of the default rules is not specified.
9880 :- chr_constraint stored_assertion/1.
9881 :- chr_option(mode,stored_assertion(+)).
9882 :- chr_option(type_declaration,stored_assertion(constraint)).
9884 :- chr_constraint never_stored_default/2.
9885 :- chr_option(mode,never_stored_default(+,?)).
9886 :- chr_option(type_declaration,never_stored_default(constraint,any)).
9891 generate_never_stored_rules(Constraints,Rules) :-
9892 ( chr_pp_flag(declare_stored_constraints,on) ->
9893 never_stored_rules(Constraints,Rules)
9898 :- chr_constraint never_stored_rules/2.
9899 :- chr_option(mode,never_stored_rules(+,?)).
9900 :- chr_option(type_declaration,never_stored_rules(list(constraint),any)).
9902 never_stored_rules([],Rules) <=> Rules = [].
9903 never_stored_default(Constraint,Goal) \ never_stored_rules([Constraint|Constraints],Rules) <=>
9906 inc_rule_count(RuleNb),
9908 rule([Head],[],true,Goal),
9914 Rules = [Rule|Tail],
9915 never_stored_rules(Constraints,Tail).
9916 never_stored_rules([_|Constraints],Rules) <=>
9917 never_stored_rules(Constraints,Rules).
9922 check_storedness_assertions(Constraints) :-
9923 ( chr_pp_flag(storage_analysis,on), chr_pp_flag(declare_stored_constraints,on) ->
9924 forall(Constraint,Constraints,check_storedness_assertion(Constraint))
9930 :- chr_constraint check_storedness_assertion/1.
9931 :- chr_option(mode,check_storedness_assertion(+)).
9932 :- chr_option(type_declaration,check_storedness_assertion(constraint)).
9934 check_storedness_assertion(Constraint), stored_assertion(Constraint)
9935 <=> ( is_stored(Constraint) ->
9938 chr_warning(assertion_failed,'Constraint ~w is not stored. However, it was asserted to be stored.\n',[Constraint])
9940 never_stored_default(Constraint,_) \ check_storedness_assertion(Constraint)
9941 <=> ( is_finally_stored(Constraint) ->
9942 chr_warning(assertion_failed,'Constraint ~w is stored. However, it was asserted not to be stored.\n',[Constraint])
9943 ; is_stored(Constraint) ->
9944 chr_warning(assertion_failed,'Constraint ~w is temporarily stored. However, it was asserted not to be stored.\n',[Constraint])
9948 % never-stored, no default goal
9949 check_storedness_assertion(Constraint)
9950 <=> ( is_finally_stored(Constraint) ->
9951 chr_warning(assertion_failed,'Constraint ~w is stored. However, it was asserted not to be stored.\n',[Constraint])
9952 ; is_stored(Constraint) ->
9953 chr_warning(assertion_failed,'Constraint ~w is temporarily stored. However, it was asserted not to be stored.\n',[Constraint])
9958 %^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
9959 % success continuation analysis
9962 % also use for forward jumping improvement!
9963 % use Prolog indexing for generated code
9967 % should_skip_to_next_id(C,O)
9969 % get_occurrence_code_id(C,O,Id)
9971 %vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
9973 continuation_analysis(ConstraintSymbols) :-
9974 maplist(analyse_continuations,ConstraintSymbols).
9976 analyse_continuations(C) :-
9977 % 1. compute success continuations of the
9978 % occurrences of constraint C
9979 continuation_analysis(C,1),
9980 % 2. determine for which occurrences
9981 % to skip to next code id
9982 get_max_occurrence(C,MO),
9984 bulk_propagation(C,1,LO),
9985 % 3. determine code id for each occurrence
9986 set_occurrence_code_id(C,1,0).
9988 % 1. Compute the success continuations of constrait C
9989 %-------------------------------------------------------------------------------
9991 continuation_analysis(C,O) :-
9992 get_max_occurrence(C,MO),
9997 continuation_occurrence(C,O,NextO)
9999 constraint_continuation(C,O,MO,NextO),
10000 continuation_occurrence(C,O,NextO),
10002 continuation_analysis(C,NO)
10005 constraint_continuation(C,O,MO,NextO) :-
10006 ( get_occurrence_head(C,O,Head) ->
10008 ( between(NO,MO,NextO),
10009 get_occurrence_head(C,NextO,NextHead),
10010 unifiable(Head,NextHead,_) ->
10015 ; % current occurrence is passive
10019 get_occurrence_head(C,O,Head) :-
10020 get_occurrence(C,O,RuleNb,Id),
10021 \+ is_passive(RuleNb,Id),
10022 get_rule(RuleNb,Rule),
10023 Rule = pragma(rule(H1,H2,_,_),ids(Ids1,Ids2),_,_,_),
10024 ( select2(Id,Head,Ids1,H1,_,_) -> true
10025 ; select2(Id,Head,Ids2,H2,_,_)
10028 :- chr_constraint continuation_occurrence/3.
10029 :- chr_option(mode,continuation_occurrence(+,+,+)).
10031 :- chr_constraint get_success_continuation_occurrence/3.
10032 :- chr_option(mode,get_success_continuation_occurrence(+,+,-)).
10034 continuation_occurrence(C,O,NO) \ get_success_continuation_occurrence(C,O,X)
10038 get_success_continuation_occurrence(C,O,X)
10040 chr_error(internal,'Success continuation not found for ~w.\n',[C:O]).
10042 % 2. figure out when to skip to next code id
10043 %-------------------------------------------------------------------------------
10044 % don't go beyond the last occurrence
10045 % we have to go to next id for storage here
10047 :- chr_constraint skip_to_next_id/2.
10048 :- chr_option(mode,skip_to_next_id(+,+)).
10050 :- chr_constraint should_skip_to_next_id/2.
10051 :- chr_option(mode,should_skip_to_next_id(+,+)).
10053 skip_to_next_id(C,O) \ should_skip_to_next_id(C,O)
10057 should_skip_to_next_id(_,_)
10061 :- chr_constraint bulk_propagation/3.
10062 :- chr_option(mode,bulk_propagation(+,+,+)).
10064 max_occurrence(C,MO) \ bulk_propagation(C,O,_)
10068 skip_to_next_id(C,O).
10069 % we have to go to the next id here because
10070 % a predecessor needs it
10071 bulk_propagation(C,O,LO)
10075 skip_to_next_id(C,O),
10076 get_max_occurrence(C,MO),
10078 bulk_propagation(C,LO,NLO).
10079 % we have to go to the next id here because
10080 % we're running into a simplification rule
10081 % IMPROVE: propagate back to propagation predecessor (IF ANY)
10082 occurrence(C,NO,_,_,simplification) \ bulk_propagation(C,O,LO)
10086 skip_to_next_id(C,O),
10087 get_max_occurrence(C,MO),
10089 bulk_propagation(C,NO,NLO).
10090 % we skip the next id here
10091 % and go to the next occurrence
10092 continuation_occurrence(C,O,NextO) \ bulk_propagation(C,O,LO)
10096 NLO is min(LO,NextO),
10098 bulk_propagation(C,NO,NLO).
10100 % err on the safe side
10101 bulk_propagation(C,O,LO)
10103 skip_to_next_id(C,O),
10104 get_max_occurrence(C,MO),
10107 bulk_propagation(C,NO,NLO).
10109 skip_to_next_id(C,O) \ skip_to_next_id(C,O) <=> true.
10111 % if this occurrence is passive, but has to skip,
10112 % then the previous one must skip instead...
10113 % IMPROVE reasoning is conservative
10114 occurrence(C,O,RuleNb,Id,_), passive(RuleNb,Id), skip_to_next_id(C,O)
10119 skip_to_next_id(C,PO).
10121 % 3. determine code id of each occurrence
10122 %-------------------------------------------------------------------------------
10124 :- chr_constraint set_occurrence_code_id/3.
10125 :- chr_option(mode,set_occurrence_code_id(+,+,+)).
10127 :- chr_constraint occurrence_code_id/3.
10128 :- chr_option(mode,occurrence_code_id(+,+,+)).
10131 set_occurrence_code_id(C,O,IdNb)
10133 get_max_occurrence(C,MO),
10136 occurrence_code_id(C,O,IdNb).
10138 % passive occurrences don't change the code id
10139 occurrence(C,O,RuleNb,Id,_), passive(RuleNb,Id) \ set_occurrence_code_id(C,O,IdNb)
10141 occurrence_code_id(C,O,IdNb),
10143 set_occurrence_code_id(C,NO,IdNb).
10145 occurrence(C,O,RuleNb,Id,simplification) \ set_occurrence_code_id(C,O,IdNb)
10147 occurrence_code_id(C,O,IdNb),
10149 set_occurrence_code_id(C,NO,IdNb).
10151 occurrence(C,O,RuleNb,Id,propagation), skip_to_next_id(C,O) \ set_occurrence_code_id(C,O,IdNb)
10153 occurrence_code_id(C,O,IdNb),
10156 set_occurrence_code_id(C,NO,NIdNb).
10158 occurrence(C,O,RuleNb,Id,propagation) \ set_occurrence_code_id(C,O,IdNb)
10160 occurrence_code_id(C,O,IdNb),
10162 set_occurrence_code_id(C,NO,IdNb).
10164 % occurrence_code_id(C,O,IdNb) ==> writeln(occurrence_code_id(C,O,IdNb)).
10166 :- chr_constraint get_occurrence_code_id/3.
10167 :- chr_option(mode,get_occurrence_code_id(+,+,-)).
10169 occurrence_code_id(C,O,IdNb) \ get_occurrence_code_id(C,O,X)
10173 get_occurrence_code_id(C,O,X)
10178 format('no occurrence code for ~w!\n',[C:O])
10181 get_success_continuation_code_id(C,O,NextId) :-
10182 get_success_continuation_occurrence(C,O,NextO),
10183 get_occurrence_code_id(C,NextO,NextId).
10185 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10186 % COLLECT CONSTANTS FOR INLINING
10190 %%% TODO: APPLY NEW DICT FORMAT DOWNWARDS
10192 % collect_constants(+rules,+constraint_symbols,+clauses) {{{
10193 collect_constants(Rules,Constraints,Clauses0) :-
10194 ( not_restarted, chr_pp_flag(experiment,on) ->
10195 ( chr_pp_flag(sss,on) ->
10196 Dictionary = [fep/4-[2,3]-[[a,b]-fep1,[c,d]-fep2]-no],
10197 copy_term_nat(Clauses0,Clauses),
10198 flatten_clauses(Clauses,Dictionary,FlatClauses),
10199 install_new_declarations_and_restart(FlatClauses)
10201 maplist(collect_rule_constants(Constraints),Rules),
10202 ( chr_pp_flag(verbose,on) ->
10203 print_chr_constants
10207 ( chr_pp_flag(experiment,on) ->
10208 flattening_dictionary(Constraints,Dictionary),
10209 copy_term_nat(Clauses0,Clauses),
10210 flatten_clauses(Clauses,Dictionary,FlatClauses),
10211 install_new_declarations_and_restart(FlatClauses)
10220 :- chr_constraint chr_constants/1.
10221 :- chr_option(mode,chr_constants(+)).
10223 :- chr_constraint get_chr_constants/1.
10225 chr_constants(Constants) \ get_chr_constants(Q) <=> Q = Constants.
10227 get_chr_constants(Q) <=> chr_warning(internal,'No constants found for key ~w.\n',[Key]), Q = [].
10229 % collect_rule_constants(+constraint_symbols,+rule) {{{
10230 collect_rule_constants(Constraints,Rule) :-
10231 Rule = pragma(rule(H1,H2,_,B),_,_,_,_),
10232 maplist(collect_head_constants,H1),
10233 maplist(collect_head_constants,H2),
10234 collect_body_constants(B,Constraints).
10236 collect_body_constants(Body,Constraints) :-
10237 conj2list(Body,Goals),
10238 maplist(collect_goal_constants(Constraints),Goals).
10240 collect_goal_constants(Constraints,Goal) :-
10243 memberchk(C/N,Constraints) ->
10244 collect_head_constants(Goal)
10246 Goal = Mod : TheGoal,
10247 get_target_module(Module),
10250 functor(TheGoal,C,N),
10251 memberchk(C/N,Constraints) ->
10252 collect_head_constants(TheGoal)
10257 collect_head_constants(Head) :-
10259 get_constraint_type_det(C/N,Types),
10261 collect_all_arg_constants(Args,Types,[]).
10263 collect_all_arg_constants([],[],Constants) :-
10264 ( Constants \== [] ->
10265 add_chr_constants(Constants)
10269 collect_all_arg_constants([Arg|Args],[Type|Types],Constants0) :-
10270 unalias_type(Type,NormalizedType),
10271 ( is_chr_constants_type(NormalizedType,Key,_) ->
10273 collect_all_arg_constants(Args,Types,[Key-Arg|Constants0])
10274 ; % no useful information here
10278 collect_all_arg_constants(Args,Types,Constants0)
10281 add_chr_constants(Pairs) :-
10282 keysort(Pairs,SortedPairs),
10283 add_chr_constants_(SortedPairs).
10285 :- chr_constraint add_chr_constants_/1.
10286 :- chr_option(mode,add_chr_constants_(+)).
10288 add_chr_constants_(Constants), chr_constants(MoreConstants) <=>
10289 sort([Constants|MoreConstants],NConstants),
10290 chr_constants(NConstants).
10292 add_chr_constants_(Constants) <=>
10293 chr_constants([Constants]).
10297 :- chr_constraint print_chr_constants/0. % {{{
10299 print_chr_constants, chr_constants(Constants) # Id ==>
10300 format('\t* chr_constants : ~w.\n',[Constants])
10301 pragma passive(Id).
10303 print_chr_constants <=>
10308 % flattening_dictionary(+constraint_symbols,-dictionary) {{{
10309 flattening_dictionary([],[]).
10310 flattening_dictionary([CS|CSs],Dictionary) :-
10311 ( flattening_dictionary_entry(CS,Entry) ->
10312 Dictionary = [Entry|Rest]
10316 flattening_dictionary(CSs,Rest).
10318 flattening_dictionary_entry(CS,Entry) :-
10319 get_constraint_type_det(CS,Types),
10320 constant_positions(Types,1,Positions,Keys,Handler),
10321 Positions \== [], % there are chr_constant arguments
10322 pairup(Keys,Constants,Pairs0),
10323 keysort(Pairs0,Pairs),
10324 Entry = CS-Positions-Specs-Handler,
10325 get_chr_constants(ConstantsList),
10327 ( member(Pairs,ConstantsList)
10328 , flat_spec(CS,Positions,Constants,Spec)
10332 constant_positions([],_,[],[],no).
10333 constant_positions([Type|Types],I,Positions,Keys,Handler) :-
10334 unalias_type(Type,NormalizedType),
10335 ( is_chr_constants_type(NormalizedType,Key,ErrorHandler) ->
10336 compose_error_handlers(ErrorHandler,NHandler,Handler),
10337 Positions = [I|NPositions],
10340 NPositions = Positions,
10345 constant_positions(Types,J,NPositions,NKeys,NHandler).
10347 compose_error_handlers(no,Handler,Handler).
10348 compose_error_handlers(yes(Handler),_,yes(Handler)).
10350 flat_spec(C/N,Positions,Terms,Spec) :-
10351 Spec = Terms - Functor,
10352 term_to_atom(Terms,TermsAtom),
10353 term_to_atom(Positions,PositionsAtom),
10354 atom_concat_list(['$flat_',C,'/',N,'___',PositionsAtom,'___',TermsAtom],Functor).
10359 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10360 % RESTART AFTER FLATTENING {{{
10362 restart_after_flattening(Declarations,Declarations) :-
10363 nb_setval('$chr_restart_after_flattening',started).
10364 restart_after_flattening(_,Declarations) :-
10365 nb_getval('$chr_restart_after_flattening',restart(Declarations)),
10366 nb_setval('$chr_restart_after_flattening',restarted).
10369 nb_getval('$chr_restart_after_flattening',started).
10371 install_new_declarations_and_restart(Declarations) :-
10372 nb_setval('$chr_restart_after_flattening',restart(Declarations)),
10373 fail. /* fails to choicepoint of restart_after_flattening */
10375 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10379 % -) generate dictionary from collected chr_constants
10380 % enable with :- chr_option(experiment,on).
10381 % -) issue constraint declarations for constraints not present in
10383 % -) integrate with CHR compiler
10384 % -) pass Mike's test code (full syntactic support for current CHR code)
10385 % -) rewrite the body using the inliner
10388 % -) refined semantics correctness issue
10389 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10391 flatten_clauses(Clauses,Dict,NClauses) :-
10392 flatten_readcontent(Clauses,Rules,Symbols,ModeDecls,_TypeDefs,TypeDecls,RestClauses),
10393 flatten_clauses_(Dict,Rules,RestClauses,Symbols,ModeDecls,TypeDecls,NClauses).
10395 flatten_clauses_(Dict,Clauses,RestClauses,Symbols,ModeDecls,TypeDecls,NClauses) :-
10396 auxiliary_constraints_declarations(Dict,ModeDecls,TypeDecls,NClauses0),
10397 dispatching_rules(Dict,NClauses1),
10398 declarations(Symbols,Dict,ModeDecls,TypeDecls,NClauses2),
10399 flatten_rules(Clauses,Dict,NClauses3),
10400 append([RestClauses,NClauses0,NClauses1,NClauses2,NClauses3],NClauses).
10402 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10403 % Declarations for non-flattened constraints
10405 % declarations(+constraint_symbols,+dict,+mode_decls,+type_decls,-clauses) {{{
10406 declarations(ConstraintSymbols,Dict,ModeDecls,TypeDecls,Declarations) :-
10407 findall(Symbol,(member(Symbol,ConstraintSymbols), \+ memberchk(Symbol-_-_-_,Dict)),Symbols),
10408 maplist(declaration(ModeDecls,TypeDecls),Symbols,DeclarationsList),
10409 flatten(DeclarationsList,Declarations).
10411 declaration(ModeDecls,TypeDecls,ConstraintSymbol,
10412 [(:- chr_constraint ConstraintSymbol),
10413 (:- chr_option(mode,ModeDeclPattern)),
10414 (:- chr_option(type_declaration,TypeDeclPattern))
10416 ConstraintSymbol = Functor / Arity,
10417 % print optional mode declaration
10418 functor(ModeDeclPattern,Functor,Arity),
10419 ( memberchk(ModeDeclPattern,ModeDecls) ->
10422 replicate(Arity,(?),Modes),
10423 ModeDeclPattern =.. [_|Modes]
10425 % print optional type declaration
10426 functor(TypeDeclPattern,Functor,Arity),
10427 ( memberchk(TypeDeclPattern,TypeDecls) ->
10430 replicate(Arity,any,Types),
10431 TypeDeclPattern =.. [_|Types]
10434 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10435 % read clauses from file
10437 % declared constaints are returned
10438 % type definitions are returned and printed
10439 % mode declarations are returned
10440 % other clauses are returned
10442 % flatten_readcontent(+clauses,-rules,-symbols,-mode_decls,-type_defs,-type_decls,-rest_clauses) {{{
10443 flatten_readcontent([],[],[],[],[],[],[]).
10444 flatten_readcontent([Clause|RClauses],Rules,ConstraintSymbols,ModeDecls,TypeDefs,TypeDecls,RestClauses) :-
10446 ( Clause == end_of_file ->
10448 ConstraintSymbols = [],
10453 ; crude_is_rule(Clause) ->
10454 Rules = [Clause|RestRules],
10455 flatten_readcontent(RClauses,RestRules,ConstraintSymbols,ModeDecls,TypeDefs,TypeDecls,RestClauses)
10456 ; pure_is_declaration(Clause,SomeConstraintSymbols,SomeModeDecls,SomeTypeDecls) ->
10457 append(SomeConstraintSymbols,RestConstraintSymbols,ConstraintSymbols),
10458 append(SomeModeDecls,RestModeDecls,ModeDecls),
10459 append(SomeTypeDecls,RestTypeDecls,TypeDecls),
10460 flatten_readcontent(RClauses,Rules,RestConstraintSymbols,RestModeDecls,TypeDefs,RestTypeDecls,RestClauses)
10461 ; is_mode_declaration(Clause,ModeDecl) ->
10462 ModeDecls = [ModeDecl|RestModeDecls],
10463 flatten_readcontent(RClauses,Rules,ConstraintSymbols,RestModeDecls,TypeDefs,TypeDecls,RestClauses)
10464 ; is_type_declaration(Clause,TypeDecl) ->
10465 TypeDecls = [TypeDecl|RestTypeDecls],
10466 flatten_readcontent(RClauses,Rules,ConstraintSymbols,ModeDecls,TypeDefs,RestTypeDecls,RestClauses)
10467 ; is_type_definition(Clause,TypeDef) ->
10468 RestClauses = [Clause|NRestClauses],
10469 TypeDefs = [TypeDef|RestTypeDefs],
10470 flatten_readcontent(RClauses,Rules,ConstraintSymbols,ModeDecls,RestTypeDefs,TypeDecls,NRestClauses)
10471 ; ( Clause = (:- op(A,B,C)) ->
10472 % assert operators in order to read and print them out properly
10477 RestClauses = [Clause|NRestClauses],
10478 flatten_readcontent(RClauses,Rules,ConstraintSymbols,ModeDecls,TypeDefs,TypeDecls,NRestClauses)
10481 crude_is_rule(_ @ _).
10482 crude_is_rule(_ pragma _).
10483 crude_is_rule(_ ==> _).
10484 crude_is_rule(_ <=> _).
10486 pure_is_declaration(D, Constraints,Modes,Types) :- %% constraint declaration
10487 D = (:- Decl), Decl =.. [F,Cs], F == (chr_constraint),
10488 conj2list(Cs,Constraints0),
10489 pure_extract_type_mode(Constraints0,Constraints,Modes,Types).
10491 pure_extract_type_mode([],[],[],[]).
10492 pure_extract_type_mode([F/A|R],[F/A|R2],Modes,Types) :- !,
10493 pure_extract_type_mode(R,R2,Modes,Types).
10494 pure_extract_type_mode([C|R],[ConstraintSymbol|R2],[Mode|Modes],Types) :-
10496 ConstraintSymbol = F/A,
10498 extract_types_and_modes(Args,ArgTypes,ArgModes),
10499 Mode =.. [F|ArgModes],
10500 ( forall(member(ArgType,ArgTypes),ArgType == any) ->
10503 Types = [Type|RTypes],
10504 Type =.. [F|ArgTypes]
10506 pure_extract_type_mode(R,R2,Modes,RTypes).
10508 is_mode_declaration((:- chr_option(mode,ModeDecl)),ModeDecl).
10510 is_type_declaration((:- chr_option(type_declaration,TypeDecl)),TypeDecl).
10512 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10513 % DECLARATIONS FOR FLATTENED CONSTRAINTS
10514 % including mode and type declarations
10516 % auxiliary_constraints_declarations(+dict,+mode_decls,+type_decls,-constraint_specs) {{{
10517 auxiliary_constraints_declarations(Dict,ModeDecls,TypeDecls,ConstraintSpecs) :-
10518 findall(ConstraintSpec,auxiliary_constraints_declaration(Dict,ModeDecls,TypeDecls,ConstraintSpec),ConstraintSpecs0),
10519 flatten(ConstraintSpecs0,ConstraintSpecs).
10521 auxiliary_constraints_declaration(Dict,ModeDecls,TypeDecls,
10522 [(:- chr_constraint ConstraintSpec),
10523 (:- chr_option(mode,NewModeDecl)),
10524 (:- chr_option(type_declaration,NewTypeDecl))]) :-
10525 member(C/N-I-SFs-_,Dict),
10526 arg_modes(C,N,ModeDecls,Modes),
10527 specialize_modes(Modes,I,SpecializedModes),
10528 arg_types(C,N,TypeDecls,Types),
10529 specialize_types(Types,I,SpecializedTypes),
10530 length(I,IndexSize),
10531 AN is N - IndexSize,
10532 member(_Term-F,SFs),
10533 ConstraintSpec = F/AN,
10534 NewModeDecl =.. [F|SpecializedModes],
10535 NewTypeDecl =.. [F|SpecializedTypes].
10537 arg_modes(C,N,ModeDecls,ArgModes) :-
10538 functor(ConstraintPattern,C,N),
10539 ( memberchk(ConstraintPattern,ModeDecls) ->
10540 ConstraintPattern =.. [_|ArgModes]
10542 replicate(N,?,ArgModes)
10545 specialize_modes(Modes,I,SpecializedModes) :-
10546 split_args(I,Modes,_,SpecializedModes).
10548 arg_types(C,N,TypeDecls,ArgTypes) :-
10549 functor(ConstraintPattern,C,N),
10550 ( memberchk(ConstraintPattern,TypeDecls) ->
10551 ConstraintPattern =.. [_|ArgTypes]
10553 replicate(N,any,ArgTypes)
10556 specialize_types(Types,I,SpecializedTypes) :-
10557 split_args(I,Types,_,SpecializedTypes).
10559 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10560 % DISPATCHING RULES
10562 % dispatching_rules(+dict,-newrules)
10567 % This code generates a decision tree for calling the appropriate specialized
10568 % constraint based on the particular value of the argument the constraint
10569 % is being specialized on.
10571 % In case an error handler is provided, the handler is called with the
10572 % unexpected constraint.
10574 dispatching_rules([],[]).
10575 dispatching_rules([CN-I-SFs-MaybeErrorHandler|Dict], DispatchingRules) :-
10576 constraint_dispatching_rule(SFs,CN,I,MaybeErrorHandler,DispatchingRules,RestDispatchingRules),
10577 dispatching_rules(Dict,RestDispatchingRules).
10579 constraint_dispatching_rule(SFs,C/N,I,MaybeErrorHandler,Rules,RestRules) :-
10580 ( increasing_numbers(I,1) ->
10581 /* index on first arguments */
10585 /* reorder arguments for 1st argument indexing */
10588 split_args(I,Args,GroundArgs,OtherArgs),
10589 append(GroundArgs,OtherArgs,ShuffledArgs),
10590 atom_concat(C,'_$shuffled',NC),
10591 Body =.. [NC|ShuffledArgs],
10592 [(Head :- Body)|Rules0] = Rules,
10595 Context = swap(C,I),
10596 dispatching_rule_term_cases(SFs,I,NCN,MaybeErrorHandler,Context,Rules0,RestRules).
10598 increasing_numbers([],_).
10599 increasing_numbers([X|Ys],X) :-
10601 increasing_numbers(Ys,Y).
10603 dispatching_rule_term_cases(SFs,I,NC/N,MaybeErrorHandler,Context,Rules,RestRules) :-
10604 length(I,IndexLength),
10605 once(pairup(TermLists,Functors,SFs)),
10606 maplist(head_tail,TermLists,Heads,Tails),
10607 Payload is N - IndexLength,
10608 maplist(wrap_in_functor(dispatching_action),Functors,Actions),
10609 dispatch_trie_index(Heads,Tails,Payload,MaybeErrorHandler,Context,Actions,NC,Rules,RestRules).
10611 dispatching_action(Functor,PayloadArgs,Goal) :-
10612 Goal =.. [Functor|PayloadArgs].
10614 dispatch_trie_index(Patterns,MorePatterns,Payload,MaybeErrorHandler,Context,Actions,Prefix,Clauses,Tail) :-
10615 dispatch_trie_step(Patterns,Prefix,Prefix,MorePatterns,Payload,MaybeErrorHandler,Context,Actions,Clauses,Tail).
10617 dispatch_trie_step([],_,_,_,[],_,_,[],L,L) :- !.
10618 % length MorePatterns == length Patterns == length Results
10619 dispatch_trie_step(Patterns,Symbol,Prefix,MorePatterns,Payload,MaybeErrorHandler,Context,Actions,Clauses,T) :-
10620 MorePatterns = [List|_],
10622 aggregate_all(set(F/A),
10623 ( member(Pattern,Patterns),
10624 functor(Pattern,F,A)
10628 dispatch_trie_step_cases(FAs,N1,Patterns,MorePatterns,Payload,MaybeErrorHandler,Context,Actions,Symbol,Prefix,Clauses,T).
10630 dispatch_trie_step_cases([],N,_,_,Payload,MaybeErrorHandler,Context,_,Symbol,_,Clauses0,Clauses) :-
10631 ( MaybeErrorHandler = yes(ErrorHandler) ->
10632 Clauses0 = [ErrorClause|Clauses],
10633 ErrorClause = (Head :- Body),
10634 Arity is N + Payload,
10635 functor(Head,Symbol,Arity),
10636 reconstruct_original_term(Context,Head,Term),
10637 Body =.. [ErrorHandler,Term]
10641 dispatch_trie_step_cases([FA|FAs],N,Pattern,MorePatterns,Payload,MaybeErrorHandler,Context,Actions,Symbol,Prefix,Clauses,Tail) :-
10642 dispatch_trie_step_case(FA,N,Pattern,MorePatterns,Payload,MaybeErrorHandler,Context,Actions,Symbol,Prefix,Clauses,Clauses1),
10643 dispatch_trie_step_cases(FAs,N,Pattern,MorePatterns,Payload,MaybeErrorHandler,Context,Actions,Symbol,Prefix,Clauses1,Tail).
10645 dispatch_trie_step_case(F/A,N,Patterns,MorePatterns,Payload,MaybeErrorHandler,Context0,Actions,Symbol,Prefix,[Clause|List],Tail) :-
10646 Clause = (Head :- Cut, Body),
10647 ( MaybeErrorHandler = yes(_) ->
10652 /* Head = Symbol(IndexPattern,V2,...,Vn,Payload) */
10654 functor(Head,Symbol,N1),
10655 arg(1,Head,IndexPattern),
10656 Head =.. [_,_|RestArgs],
10657 length(PayloadArgs,Payload),
10658 once(append(Vs,PayloadArgs,RestArgs)),
10659 /* IndexPattern = F(...) */
10660 functor(IndexPattern,F,A),
10661 Context1 = index_functor(F,A,Context0),
10662 IndexPattern =.. [_|Args],
10663 append(Args,RestArgs,RecArgs),
10664 ( RecArgs == PayloadArgs ->
10665 /* nothing more to match on */
10667 rec_cases(Patterns,_,Actions,F/A,_,_,MoreActions),
10668 MoreActions = [Action],
10669 call(Action,PayloadArgs,Body)
10670 ; /* more things to match on */
10671 rec_cases(Patterns,MorePatterns,Actions,F/A,Cases,MoreCases,MoreActions),
10672 ( MoreActions = [OneMoreAction] ->
10673 /* only one more thing to match on */
10674 MoreCases = [OneMoreCase],
10675 append([Cases,OneMoreCase,PayloadArgs],RecArgs),
10677 call(OneMoreAction,PayloadArgs,Body)
10679 /* more than one thing to match on */
10683 pairup(Cases,MoreCases,CasePairs),
10684 common_pattern(CasePairs,CommonPatternPair,DiffVars,Differences),
10685 append(Args,Vs,[First|Rest]),
10686 First-Rest = CommonPatternPair,
10687 Context2 = gct([First|Rest],Context1),
10688 gensym(Prefix,RSymbol),
10689 append(DiffVars,PayloadArgs,RecCallVars),
10690 Body =.. [RSymbol|RecCallVars],
10691 findall(CH-CT,member([CH|CT],Differences),CPairs),
10692 once(pairup(CHs,CTs,CPairs)),
10693 dispatch_trie_step(CHs,RSymbol,Prefix,CTs,Payload,MaybeErrorHandler,Context2,MoreActions,List,Tail)
10698 % split(list,int,before,at,after).
10700 split([X|Xs],I,Before,At,After) :-
10707 Before = [X|RBefore],
10708 split(Xs,J,RBefore,At,After)
10711 % reconstruct_original_term(Context,CurrentTerm,OriginalTerm)
10713 % context ::= swap(functor,positions)
10714 % | index_functor(functor,arity,context)
10715 % | gct(Pattern,Context)
10717 reconstruct_original_term(swap(Functor,Positions),Term,OriginalTerm) :-
10718 functor(Term,_,Arity),
10719 functor(OriginalTerm,Functor,Arity),
10720 OriginalTerm =.. [_|OriginalArgs],
10721 split_args(Positions,OriginalArgs,IndexArgs,OtherArgs),
10723 append(IndexArgs,OtherArgs,Args).
10724 reconstruct_original_term(index_functor(Functor,Arity,Context),Term0,OriginalTerm) :-
10725 Term0 =.. [Predicate|Args],
10726 split_at(Arity,Args,IndexArgs,RestArgs),
10727 Index =.. [Functor|IndexArgs],
10728 Term1 =.. [Predicate,Index|RestArgs],
10729 reconstruct_original_term(Context,Term1,OriginalTerm).
10730 reconstruct_original_term(gct(PatternList,Context),Term0,OriginalTerm) :-
10731 copy_term_nat(PatternList,IndexTerms),
10732 term_variables(IndexTerms,Variables),
10733 Term0 =.. [Predicate|Args0],
10734 append(Variables,RestArgs,Args0),
10735 append(IndexTerms,RestArgs,Args1),
10736 Term1 =.. [Predicate|Args1],
10737 reconstruct_original_term(Context,Term1,OriginalTerm).
10740 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10741 % SUBSTITUTE CONSTRAINT SYMBOL FUNCTORS
10743 % flatten_rules(+rule_clauses,+dict,-rule_clauses).
10745 % dict :== list(functor/arity-list(int)-list(list(term)-functor)-maybe(error_handler))
10748 flatten_rules(Rules,Dict,FlatRules) :-
10749 flatten_rules1(Rules,Dict,FlatRulesList),
10750 flatten(FlatRulesList,FlatRules).
10752 flatten_rules1([],_,[]).
10753 flatten_rules1([Rule|Rules],Dict,[FlatRules|FlatRulesList]) :-
10754 findall(FlatRule,flatten_rule(Rule,Dict,FlatRule),FlatRules),
10755 flatten_rules1(Rules,Dict,FlatRulesList).
10757 flatten_rule((Name @ Rule),Dict,(Name @ NRule)) :- !,
10758 flatten_rule(Rule,Dict,NRule).
10759 flatten_rule((Rule pragma Pragmas),Dict,(NRule pragma Pragmas)) :- !,
10760 flatten_rule(Rule,Dict,NRule).
10761 flatten_rule((H ==> B),Dict,(NH ==> NB)) :- !,
10762 flatten_heads(H,Dict,NH),
10763 flatten_body(B,Dict,NB).
10764 flatten_rule((H1 \ H2 <=> B),Dict,(NH1 \ NH2 <=> NB)) :- !,
10765 flatten_heads((H1,H2),Dict,(NH1,NH2)),
10766 flatten_body(B,Dict,NB).
10767 flatten_rule((H <=> B),Dict,(NH <=> NB)) :-
10768 flatten_heads(H,Dict,NH),
10769 flatten_body(B,Dict,NB).
10771 flatten_heads((H1,H2),Dict,(NH1,NH2)) :- !,
10772 flatten_heads(H1,Dict,NH1),
10773 flatten_heads(H2,Dict,NH2).
10774 flatten_heads((H # Annotation),Dict,(NH # Annotation)) :- !,
10775 flatten_heads(H,Dict,NH).
10776 flatten_heads(H,Dict,NH) :-
10778 memberchk(C/N-ArgPositions-SFs-_,Dict) ->
10780 split_args(ArgPositions,AllArgs,GroundArgs,OtherArgs),
10781 member(GroundArgs-Name,SFs),
10782 NH =.. [Name|OtherArgs]
10787 flatten_body((Guard | Body),Dict,(NGuard | NBody)) :- !,
10788 conj2list(Guard,Guards),
10789 maplist(flatten_goal(Dict),Guards,NGuards),
10790 list2conj(NGuards,NGuard),
10791 conj2list(Body,Goals),
10792 maplist(flatten_goal(Dict),Goals,NGoals),
10793 list2conj(NGoals,NBody).
10794 flatten_body(Body,Dict,NBody) :-
10795 conj2list(Body,Goals),
10796 maplist(flatten_goal(Dict),Goals,NGoals),
10797 list2conj(NGoals,NBody).
10799 flatten_goal(Dict,Goal,NGoal) :- var(Goal), !, NGoal = Goal.
10800 flatten_goal(Dict,Goal,NGoal) :-
10801 ( is_specializable_goal(Goal,Dict,ArgPositions)
10803 specialize_goal(Goal,ArgPositions,NGoal)
10804 ; Goal = Mod : TheGoal,
10805 get_target_module(Module),
10808 is_specializable_goal(TheGoal,Dict,ArgPositions)
10810 specialize_goal(TheGoal,ArgPositions,NTheGoal),
10811 NGoal = Mod : NTheGoal
10812 ; partial_eval(Goal,NGoal)
10819 %-------------------------------------------------------------------------------%
10820 % Specialize body/guard goal
10821 %-------------------------------------------------------------------------------%
10822 is_specializable_goal(Goal,Dict,ArgPositions) :-
10824 memberchk(C/N-ArgPositions-_-_,Dict),
10825 args(ArgPositions,Goal,Args),
10828 specialize_goal(Goal,ArgPositions,NGoal) :-
10831 split_args(ArgPositions,Args,GroundTerms,Others),
10832 flat_spec(C/N,ArgPositions,GroundTerms,_-Functor),
10833 NGoal =.. [Functor|Others].
10835 %-------------------------------------------------------------------------------%
10836 % Partially evaluate predicates
10837 %-------------------------------------------------------------------------------%
10839 % append([],Y,Z) >--> Y = Z
10840 % append(X,[],Z) >--> X = Z
10841 partial_eval(append(L1,L2,L3),NGoal) :-
10848 % flatten_path(L1,L2) >--> flatten_path(L1',L2)
10849 % where flatten(L1,L1')
10850 partial_eval(flatten_path(L1,L2),NGoal) :-
10852 flatten(L1,FlatterL1),
10853 FlatterL1 \== L1 ->
10854 NGoal = flatten_path(FlatterL1,L2).
10860 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10861 dump_code(Clauses) :-
10862 ( chr_pp_flag(dump,on) ->
10863 maplist(portray_clause,Clauses)
10869 chr_info(banner,'\tThe K.U.Leuven CHR System\t\n\t\tContributors:\tTom Schrijvers, Jon Sneyers, Bart Demoen,\n\t\t\t\tJan Wielemaker\n\t\tCopyright:\tK.U.Leuven, Belgium\n\t\tURL:\t\thttp://www.cs.kuleuven.be/~~toms/CHR/\n',[]).