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 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
53 %% * add groundness info to a.i.-based observation analysis
54 %% * proper fd/index analysis
55 %% * re-add generation checking
56 %% * untangle CHR-level and traget source-level generation & optimization
58 %% AGGRESSIVE OPTIMISATION IDEAS
60 %% * continuation optimization
61 %% * analyze history usage to determine whether/when
62 %% cheaper suspension is possible
63 %% * store constraint unconditionally for unconditional propagation rule,
64 %% if first, i.e. without checking history and set trigger cont to next occ
65 %% * get rid of suspension passing for never triggered constraints,
66 %% up to allocation occurrence
67 %% * get rid of call indirection for never triggered constraints
68 %% up to first allocation occurrence.
69 %% * get rid of unnecessary indirection if last active occurrence
70 %% before unconditional removal is head2, e.g.
73 %% * Eliminate last clause of never stored constraint, if its body
75 %% * Specialize lookup operations and indexes for functional dependencies.
79 %% * generate code to empty all constraint stores of a module (Bart Demoen)
80 %% * variable suspension: only look upto necessary depth and necessary number
81 %% of arguments into term (Thom Fruehwirth: global constraints)
82 %% * ground matching seems to be not optimized for compound terms
83 %% in case of simpagation_head2 and propagation occurrences
84 %% * Do not unnecessarily generate store operations.
85 %% * further specialize runtime predicates for special cases where
86 %% - none of the constraints contain any indexing variables, ...
87 %% - just one constraint requires some runtime predicate
88 %% * analysis for storage delaying (see primes for case)
89 %% * internal constraints declaration + analyses?
90 %% * Do not store in global variable store if not necessary
91 %% NOTE: affects show_store/1
92 %% * multi-level store: variable - ground
93 %% * Do not maintain/check unnecessary propagation history
94 %% for rules that cannot be applied more than once
95 %% for reasons of anti-monotony
96 %% * Strengthen storage analysis for propagation rules
97 %% reason about bodies of rules only containing constraints
98 %% -> fixpoint with overservation analysis
99 %% * SICStus compatibility
103 %% * instantiation declarations
105 %% VARIABLE (never bound)
107 %% * make difference between cheap guards for reordering
108 %% and non-binding guards for lock removal
109 %% * unqiue -> once/[] transformation for propagation
110 %% * cheap guards interleaved with head retrieval + faster
111 %% via-retrieval + non-empty checking for propagation rules
112 %% redo for simpagation_head2 prelude
113 %% * intelligent backtracking for simplification/simpagation rule
114 %% generator_1(X),'_$savecp'(CP_1),
121 %% ('_$cutto'(CP_1), fail)
125 %% or recently developped cascading-supported approach
126 %% * intelligent backtracking for propagation rule
127 %% use additional boolean argument for each possible smart backtracking
128 %% when boolean at end of list true -> no smart backtracking
129 %% false -> smart backtracking
130 %% only works for rules with at least 3 constraints in the head
131 %% * (set semantics + functional dependency) declaration + resolution
134 %% * identify cases where prefixes of partner lookups for subsequent occurrences can be
137 %% * map A \ B <=> true | true rules
138 %% onto efficient code that empties the constraint stores of B
139 %% in O(1) time for ground constraints where A and B do not share
141 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
142 :- module(chr_translate,
143 [ chr_translate/2 % +Decls, -TranslatedDecls
145 :- use_module(library(lists)).
146 :- use_module(hprolog).
147 :- use_module(library(assoc)).
148 :- use_module(pairlist).
149 :- use_module(library(ordsets)).
150 :- use_module(a_star).
151 :- use_module(listmap).
152 :- use_module(clean_code).
153 :- use_module(builtins).
155 :- use_module(guard_entailment).
156 :- use_module(chr_compiler_options).
157 :- use_module(chr_compiler_utility).
158 :- use_module(chr_compiler_errors).
160 :- op(1150, fx, chr_type).
161 :- op(1130, xfx, --->).
165 :- op(1150, fx, constraints).
166 :- op(1150, fx, chr_constraint).
168 :- chr_option(debug,off).
169 :- chr_option(optimize,full).
172 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
174 target_module/1, % target_module(Module)
177 indexed_argument/2, % argument instantiation may enable applicability of rule
178 is_indexed_argument/2,
181 get_constraint_mode/2,
184 only_ground_indexed_arguments/1,
185 none_suspended_on_variables/0,
186 are_none_suspended_on_variables/0,
191 actual_store_types/2,
192 assumed_store_type/2,
193 validate_store_type_assumption/1,
207 get_max_occurrence/2,
209 allocation_occurrence/2,
210 get_allocation_occurrence/2,
214 is_least_occurrence/1
217 :- chr_option(check_guard_bindings,off).
219 :- chr_option(mode,target_module(+)).
220 :- chr_option(mode,indexed_argument(+,+)).
221 :- chr_option(mode,constraint_mode(+,+)).
222 :- chr_option(mode,may_trigger(+)).
223 :- chr_option(mode,store_type(+,+)).
224 :- chr_option(mode,actual_store_types(+,+)).
225 :- chr_option(mode,assumed_store_type(+,+)).
226 :- chr_option(mode,rule_count(+)).
227 :- chr_option(mode,passive(+,+)).
228 :- chr_option(mode,occurrence(+,+,+,+)).
229 :- chr_option(mode,max_occurrence(+,+)).
230 :- chr_option(mode,allocation_occurrence(+,+)).
231 :- chr_option(mode,rule(+,+)).
232 :- chr_option(mode,least_occurrence(+,+)).
233 :- chr_option(mode,is_least_occurrence(+)).
235 :- chr_option(type_definition,type(list,[ [], [any|list] ])).
236 :- chr_option(type_definition,type(constraint,[ any / any ])).
238 :- chr_option(type_declaration,constraint_mode(constraint,list)).
240 target_module(_) \ target_module(_) <=> true.
241 target_module(Mod) \ get_target_module(Query)
243 get_target_module(Query)
246 indexed_argument(FA,I) \ indexed_argument(FA,I) <=> true.
247 indexed_argument(FA,I) \ is_indexed_argument(FA,I) <=> true.
248 is_indexed_argument(_,_) <=> fail.
250 %%% C O N S T R A I N T M O D E %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
252 constraint_mode(FA,_) \ constraint_mode(FA,_) <=> true.
253 constraint_mode(FA,Mode) \ get_constraint_mode(FA,Q) <=>
255 get_constraint_mode(FA,Q) <=>
259 %%% M A Y T R I G G E R %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
261 may_trigger(FA) <=> \+ has_active_occurrence(FA) | fail.
262 constraint_mode(FA,Mode), indexed_argument(FA,I) \ may_trigger(FA) <=>
266 may_trigger(FA) <=> chr_pp_flag(debugable,on). % in debug mode, we assume everything can be triggered
268 constraint_mode(FA,Mode), indexed_argument(FA,I) \ only_ground_indexed_arguments(FA)
274 only_ground_indexed_arguments(_) <=>
277 none_suspended_on_variables \ none_suspended_on_variables <=> true.
278 none_suspended_on_variables \ are_none_suspended_on_variables <=> true.
279 are_none_suspended_on_variables <=> fail.
280 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
282 store_type(FA,atom_hash(Index)) <=> store_type(FA,multi_hash([Index])).
283 store_type(FA,Store) \ get_store_type(FA,Query)
285 assumed_store_type(FA,Store) \ get_store_type(FA,Query)
287 get_store_type(_,Query)
290 actual_store_types(C,STs) \ update_store_type(C,ST)
291 <=> member(ST,STs) | true.
292 update_store_type(C,ST), actual_store_types(C,STs)
294 actual_store_types(C,[ST|STs]).
295 update_store_type(C,ST)
297 actual_store_types(C,[ST]).
299 % refine store type assumption
300 validate_store_type_assumption(C), actual_store_types(C,STs), assumed_store_type(C,_) % automatic assumption
302 store_type(C,multi_store(STs)).
303 validate_store_type_assumption(C), actual_store_types(C,STs), store_type(C,_) % user assumption
305 store_type(C,multi_store(STs)).
306 validate_store_type_assumption(_)
309 rule_count(C), inc_rule_count(NC)
310 <=> NC is C + 1, rule_count(NC).
312 <=> NC = 1, rule_count(NC).
314 %%% P A S S I V E %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
315 passive(R,ID) \ passive(R,ID) <=> true.
317 passive(RuleNb,ID) \ is_passive(RuleNb,ID) <=> true.
318 is_passive(_,_) <=> fail.
320 passive(RuleNb,_) \ any_passive_head(RuleNb)
324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
326 max_occurrence(C,N) \ max_occurrence(C,M)
329 max_occurrence(C,MO), new_occurrence(C,RuleNb,ID) <=>
331 occurrence(C,NO,RuleNb,ID),
332 max_occurrence(C,NO).
333 new_occurrence(C,RuleNb,ID) <=>
334 chr_error(internal,'new_occurrence: missing max_occurrence for ~w in rule ~w\n',[C,RuleNb]).
336 max_occurrence(C,MON) \ get_max_occurrence(C,Q)
338 get_max_occurrence(C,Q)
339 <=> chr_error(internal,'get_max_occurrence: missing max occurrence for ~w\n',[C]).
341 occurrence(C,ON,Rule,ID) \ get_occurrence(C,ON,QRule,QID)
342 <=> Rule = QRule, ID = QID.
343 get_occurrence(C,O,_,_)
344 <=> chr_error(internal,'get_occurrence: missing occurrence ~w:~w\n',[]).
346 % A L L O C C A T I O N O C C U R R E N C E %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
348 % cannot store constraint at passive occurrence
349 occurrence(C,O,RuleNb,ID), passive(RuleNb,ID) \ allocation_occurrence(C,O)
350 <=> NO is O + 1, allocation_occurrence(C,NO).
351 % need not store constraint that is removed
352 rule(RuleNb,Rule), occurrence(C,O,RuleNb,ID) \ allocation_occurrence(C,O)
353 <=> Rule = pragma(_,ids(IDs1,_),_,_,_), member(ID,IDs1)
354 | NO is O + 1, allocation_occurrence(C,NO).
355 % need not store constraint when body is true
356 rule(RuleNb,Rule), occurrence(C,O,RuleNb,_) \ allocation_occurrence(C,O)
357 <=> Rule = pragma(rule(_,_,_,true),_,_,_,_)
358 | NO is O + 1, allocation_occurrence(C,NO).
359 % need not store constraint if does not observe itself
360 rule(RuleNb,Rule), occurrence(C,O,RuleNb,_) \ allocation_occurrence(C,O)
361 <=> Rule = pragma(rule([_|_],_,_,_),_,_,_,_), \+ is_observed(C,O)
362 | NO is O + 1, allocation_occurrence(C,NO).
363 % need not store constraint if does not observe itself and cannot trigger
364 rule(RuleNb,Rule), occurrence(C,O,RuleNb,_), least_occurrence(RuleNb,[])
365 \ allocation_occurrence(C,O)
366 <=> Rule = pragma(rule([],Heads,_,_),_,_,_,_), \+ is_observed(C,O)
367 | NO is O + 1, allocation_occurrence(C,NO).
369 rule(RuleNb,Rule), occurrence(C,O,RuleNb,ID), allocation_occurrence(C,AO)
370 \ least_occurrence(RuleNb,[ID|IDs])
371 <=> AO >= O, \+ may_trigger(C) |
372 least_occurrence(RuleNb,IDs).
373 rule(RuleNb,Rule), passive(RuleNb,ID)
374 \ least_occurrence(RuleNb,[ID|IDs])
375 <=> least_occurrence(RuleNb,IDs).
378 ==> Rule = pragma(rule([],_,_,_),ids([],IDs),_,_,_) |
379 least_occurrence(RuleNb,IDs).
381 least_occurrence(RuleNb,[]) \ is_least_occurrence(RuleNb)
383 is_least_occurrence(_)
386 allocation_occurrence(C,O) \ get_allocation_occurrence(C,Q)
388 get_allocation_occurrence(_,Q)
389 <=> chr_pp_flag(late_allocation,off), Q=0.
390 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
392 rule(RuleNb,Rule) \ get_rule(RuleNb,Q)
397 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
399 %%% C O N S T R A I N T I N D E X %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
401 constraint_index/2, % constraint_index(F/A,DefaultStoreAndAttachedIndex)
402 get_constraint_index/2,
403 max_constraint_index/1, % max_constraint_index(MaxDefaultStoreAndAttachedIndex)
404 get_max_constraint_index/1.
406 :- chr_option(mode,constraint_index(+,+)).
407 :- chr_option(mode,max_constraint_index(+)).
409 constraint_index(C,Index) \ get_constraint_index(C,Query)
411 get_constraint_index(C,Query)
414 max_constraint_index(Index) \ get_max_constraint_index(Query)
416 get_max_constraint_index(Query)
419 set_constraint_indices(Constraints) :-
420 set_constraint_indices(Constraints,1).
421 set_constraint_indices([],M) :-
423 max_constraint_index(N).
424 set_constraint_indices([C|Cs],N) :-
425 ( ( chr_pp_flag(debugable, on) ; \+ only_ground_indexed_arguments(C) ; is_stored(C), get_store_type(C,default)) ->
426 constraint_index(C,N),
428 set_constraint_indices(Cs,M)
430 set_constraint_indices(Cs,N)
433 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
438 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
442 chr_translate(Declarations,NewDeclarations) :-
443 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',[]),
445 partition_clauses(Declarations,Constraints0,Rules0,OtherClauses),
446 check_declared_constraints(Constraints0),
447 ( Constraints0 == [] ->
448 insert_declarations(OtherClauses, NewDeclarations)
450 generate_show_constraint(Constraints0,Constraints,Rules0,Rules),
451 add_constraints(Constraints),
454 check_rules(Rules,Constraints),
455 add_occurrences(Rules),
456 functional_dependency_analysis(Rules),
457 set_semantics_rules(Rules),
458 symmetry_analysis(Rules),
459 guard_simplification,
460 storage_analysis(Constraints),
461 observation_analysis(Constraints),
462 ai_observation_analysis(Constraints),
463 late_allocation_analysis(Constraints),
464 assume_constraint_stores(Constraints),
465 set_constraint_indices(Constraints),
467 constraints_code(Constraints,ConstraintClauses),
468 validate_store_type_assumptions(Constraints),
469 store_management_preds(Constraints,StoreClauses), % depends on actual code used
470 insert_declarations(OtherClauses, Clauses0),
471 chr_module_declaration(CHRModuleDeclaration),
472 append_lists([Clauses0,
475 CHRModuleDeclaration,
481 store_management_preds(Constraints,Clauses) :-
482 generate_attach_detach_a_constraint_all(Constraints,AttachAConstraintClauses),
483 generate_indexed_variables_clauses(Constraints,IndexedClauses),
484 generate_attach_increment(AttachIncrementClauses),
485 generate_attr_unify_hook(AttrUnifyHookClauses),
486 generate_extra_clauses(Constraints,ExtraClauses),
487 generate_insert_delete_constraints(Constraints,DeleteClauses),
488 generate_attach_code(Constraints,StoreClauses),
489 generate_counter_code(CounterClauses),
490 append_lists([AttachAConstraintClauses
492 ,AttachIncrementClauses
493 ,AttrUnifyHookClauses
502 extra_declaration([ :- use_module(chr(chr_runtime))
503 , :- use_module(chr(chr_hashtable_store))
504 , :- use_module(library('clp/clp_events'))
509 %% extra_declaration([ (:- use_module(library('chr/chr_runtime')))
510 %% , (:- use_module(library('chr/chr_hashtable_store')))
511 %% , (:- use_module(library('chr/hprolog')))
517 insert_declarations(Clauses0, Clauses) :-
518 extra_declaration(Decls),
519 append(Clauses0, Decls, Clauses).
521 generate_counter_code(Clauses) :-
522 ( chr_pp_flag(store_counter,on) ->
524 ('$counter_init'(N1) :- nb_setval(N1,0)) ,
525 ('$counter'(N2,X1) :- nb_getval(N2,X1)),
526 ('$counter_inc'(N) :- nb_getval(N,X), Y is X + 1, nb_setval(N,Y)),
527 (:- '$counter_init'('$insert_counter')),
528 (:- '$counter_init'('$delete_counter')),
529 ('$insert_counter_inc' :- '$counter_inc'('$insert_counter')),
530 ('$delete_counter_inc' :- '$counter_inc'('$delete_counter')),
531 ( counter_stats(I,D) :- '$counter'('$insert_counter',I),'$counter'('$delete_counter',D))
537 % for systems with multifile declaration
538 chr_module_declaration(CHRModuleDeclaration) :-
539 get_target_module(Mod),
540 ( Mod \== chr_translate, chr_pp_flag(toplevel_show_store,on) ->
541 CHRModuleDeclaration = [
542 (:- multifile chr:'$chr_module'/1),
543 chr:'$chr_module'(Mod)
546 CHRModuleDeclaration = []
550 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
552 %% Partitioning of clauses into constraint declarations, chr rules and other
555 partition_clauses([],[],[],[]).
556 partition_clauses([C|Cs],Ds,Rs,OCs) :-
561 ; is_declaration(C,D) ->
565 ; is_module_declaration(C,Mod) ->
570 ; is_type_definition(C) ->
575 chr_warning(deprecated(C),'SICStus compatibility: ignoring handler/1 declaration.\n',[]),
580 chr_warning(deprecated(C),'SICStus compatibility: ignoring rules/1 declaration.\n',[]),
584 ; C = option(OptionName,OptionValue) ->
585 chr_warning(deprecated(C),'Instead use :- chr_option(~w,~w).\n',[OptionName,OptionValue]),
586 handle_option(OptionName,OptionValue),
590 ; C = (:- chr_option(OptionName,OptionValue)) ->
591 handle_option(OptionName,OptionValue),
599 partition_clauses(Cs,RDs,RRs,ROCs).
601 is_declaration(D, Constraints) :- %% constraint declaration
602 ( D = (:- Decl), Decl =.. [F,Cs], F == (chr_constraint) ->
603 conj2list(Cs,Constraints0)
606 Decl =.. [constraints,Cs]
608 D =.. [constraints,Cs]
610 conj2list(Cs,Constraints0),
611 ( length(Constraints0,1) ->
612 chr_warning(deprecated(D),'Instead use :- chr_constraint ~w.\n',[Cs])
614 chr_warning(deprecated(D),'Instead use :- chr_constraint ~w.\n',[Cs])
617 extract_type_mode(Constraints0,Constraints).
619 extract_type_mode([],[]).
620 extract_type_mode([F/A|R],[F/A|R2]) :- !,extract_type_mode(R,R2).
621 extract_type_mode([C|R],[C2|R2]) :-
622 functor(C,F,A),C2=F/A,
624 extract_types_and_modes(Args,ArgTypes,ArgModes),
625 constraint_type(F/A,ArgTypes),
626 constraint_mode(F/A,ArgModes),
627 extract_type_mode(R,R2).
629 extract_types_and_modes([],[],[]).
630 extract_types_and_modes([+(T)|R],[T|R2],[(+)|R3]) :- !,extract_types_and_modes(R,R2,R3).
631 extract_types_and_modes([?(T)|R],[T|R2],[(?)|R3]) :- !,extract_types_and_modes(R,R2,R3).
632 extract_types_and_modes([-(T)|R],[T|R2],[(?)|R3]) :- !,extract_types_and_modes(R,R2,R3).
633 extract_types_and_modes([(+)|R],[any|R2],[(+)|R3]) :- !,extract_types_and_modes(R,R2,R3).
634 extract_types_and_modes([(?)|R],[any|R2],[(?)|R3]) :- !,extract_types_and_modes(R,R2,R3).
635 extract_types_and_modes([(-)|R],[any|R2],[(?)|R3]) :- !,extract_types_and_modes(R,R2,R3).
636 extract_types_and_modes([Illegal|R],_,_) :-
637 chr_error(syntax(Illegal),'Illegal mode/type declaration.\n\tCorrect syntax is +type, -type or ?type\n\tor +, - or ?.\n',[]).
639 is_type_definition(D) :-
645 TDef =.. [chr_type,TypeDef],
646 ( TypeDef = (Name ---> Def) ->
647 tdisj2list(Def,DefList),
648 type_definition(Name,DefList)
650 chr_warning(syntax,'Illegal type definition "~w".\n\tIgnoring this malformed type definition.\n',[TypeDef])
653 % no removal of fails, e.g. :- type bool ---> true ; fail.
654 tdisj2list(Conj,L) :-
655 tdisj2list(Conj,L,[]).
656 tdisj2list(Conj,L,T) :-
660 tdisj2list(G,[G | T],T).
670 %% yesno(string), :: maybe rule nane
671 %% int :: rule number
680 %% list(constraint), :: constraints to be removed
681 %% list(constraint), :: surviving constraints
686 parse_rule(RI,R) :- %% name @ rule
687 RI = (Name @ RI2), !,
688 rule(RI2,yes(Name),R).
693 RI = (RI2 pragma P), !, %% pragmas
696 inc_rule_count(RuleCount),
697 R = pragma(R1,IDs,Ps,Name,RuleCount).
700 inc_rule_count(RuleCount),
701 R = pragma(R1,IDs,[],Name,RuleCount).
703 is_rule(RI,R,IDs) :- %% propagation rule
706 get_ids(Head2i,IDs2,Head2),
709 R = rule([],Head2,G,RB)
711 R = rule([],Head2,true,B)
713 is_rule(RI,R,IDs) :- %% simplification/simpagation rule
722 conj2list(H1,Head2i),
723 conj2list(H2,Head1i),
724 get_ids(Head2i,IDs2,Head2,0,N),
725 get_ids(Head1i,IDs1,Head1,N,_),
727 ; conj2list(H,Head1i),
729 get_ids(Head1i,IDs1,Head1),
732 R = rule(Head1,Head2,Guard,Body).
734 get_ids(Cs,IDs,NCs) :-
735 get_ids(Cs,IDs,NCs,0,_).
737 get_ids([],[],[],N,N).
738 get_ids([C|Cs],[N|IDs],[NC|NCs],N,NN) :-
745 get_ids(Cs,IDs,NCs, M,NN).
747 is_module_declaration((:- module(Mod)),Mod).
748 is_module_declaration((:- module(Mod,_)),Mod).
750 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
752 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
755 add_constraints([C|Cs]) :-
760 constraint_mode(C,Mode),
765 add_rules([Rule|Rules]) :-
766 Rule = pragma(_,_,_,_,RuleNb),
770 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
772 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
773 %% Some input verification:
775 check_declared_constraints(Constraints) :-
776 check_declared_constraints(Constraints,[]).
778 check_declared_constraints([],_).
779 check_declared_constraints([C|Cs],Acc) :-
780 ( memberchk_eq(C,Acc) ->
781 chr_error(syntax(C),'Constraint ~w multiply defined.\n\tRemove redundant declaration!\n',[C])
785 check_declared_constraints(Cs,[C|Acc]).
787 %% - all constraints in heads are declared constraints
788 %% - all passive pragmas refer to actual head constraints
791 check_rules([PragmaRule|Rest],Decls) :-
792 check_rule(PragmaRule,Decls),
793 check_rules(Rest,Decls).
795 check_rule(PragmaRule,Decls) :-
796 check_rule_indexing(PragmaRule),
797 PragmaRule = pragma(Rule,_IDs,Pragmas,_Name,_N),
798 Rule = rule(H1,H2,_,_),
799 append(H1,H2,HeadConstraints),
800 check_head_constraints(HeadConstraints,Decls,PragmaRule),
801 check_pragmas(Pragmas,PragmaRule).
803 check_head_constraints([],_,_).
804 check_head_constraints([Constr|Rest],Decls,PragmaRule) :-
806 ( member(F/A,Decls) ->
807 check_head_constraints(Rest,Decls,PragmaRule)
809 chr_error(syntax(Constr),'Undeclared constraint ~w in head of ~@.\n\tConstraint should be one of ~w.\n', [F/A,format_rule(PragmaRule),Decls]) ).
812 check_pragmas([Pragma|Pragmas],PragmaRule) :-
813 check_pragma(Pragma,PragmaRule),
814 check_pragmas(Pragmas,PragmaRule).
816 check_pragma(Pragma,PragmaRule) :-
818 chr_error(syntax(Pragma),'Invalid pragma ~w in ~@.\n\tPragma should not be a variable!\n',[Pragma,format_rule(PragmaRule)]).
819 check_pragma(passive(ID), PragmaRule) :-
821 PragmaRule = pragma(_,ids(IDs1,IDs2),_,_,RuleNb),
822 ( memberchk_eq(ID,IDs1) ->
824 ; memberchk_eq(ID,IDs2) ->
827 chr_error(syntax(ID),'Invalid identifier ~w in pragma passive in ~@.\n', [ID,format_rule(PragmaRule)])
831 check_pragma(Pragma, PragmaRule) :-
832 Pragma = already_in_heads,
834 chr_warning(unsupported_pragma(Pragma,PragmaRule),'Termination and correctness may be affected.\n',[]).
836 check_pragma(Pragma, PragmaRule) :-
837 Pragma = already_in_head(_),
839 chr_warning(unsupported_pragma(Pragma,PragmaRule),'Termination and correctness may be affected.\n',[]).
841 check_pragma(Pragma,PragmaRule) :-
842 chr_error(syntax(Pragma),'Invalid pragma ~w in ~@.\n', [Pragma,format_rule(PragmaRule)]).
844 format_rule(PragmaRule) :-
845 PragmaRule = pragma(_,_,_,MaybeName,N),
846 ( MaybeName = yes(Name) ->
847 write('rule '), write(Name)
849 write('rule number '), write(N)
852 check_rule_indexing(PragmaRule) :-
853 PragmaRule = pragma(Rule,_,_,_,_),
854 Rule = rule(H1,H2,G,_),
855 term_variables(H1-H2,HeadVars),
856 remove_anti_monotonic_guards(G,HeadVars,NG),
857 check_indexing(H1,NG-H2),
858 check_indexing(H2,NG-H1).
860 remove_anti_monotonic_guards(G,Vars,NG) :-
862 remove_anti_monotonic_guard_list(GL,Vars,NGL),
865 remove_anti_monotonic_guard_list([],_,[]).
866 remove_anti_monotonic_guard_list([G|Gs],Vars,NGs) :-
868 memberchk_eq(X,Vars) ->
873 remove_anti_monotonic_guard_list(Gs,Vars,RGs).
875 check_indexing([],_).
876 check_indexing([Head|Heads],Other) :-
879 term_variables(Heads-Other,OtherVars),
880 check_indexing(Args,1,F/A,OtherVars),
881 check_indexing(Heads,[Head|Other]).
883 check_indexing([],_,_,_).
884 check_indexing([Arg|Args],I,FA,OtherVars) :-
885 ( is_indexed_argument(FA,I) ->
888 indexed_argument(FA,I)
890 term_variables(Args,ArgsVars),
891 append(ArgsVars,OtherVars,RestVars),
892 ( memberchk_eq(Arg,RestVars) ->
893 indexed_argument(FA,I)
899 term_variables(Arg,NVars),
900 append(NVars,OtherVars,NOtherVars),
901 check_indexing(Args,J,FA,NOtherVars).
903 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
905 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
909 add_occurrences([Rule|Rules]) :-
910 Rule = pragma(rule(H1,H2,_,_),ids(IDs1,IDs2),_,_,Nb),
911 add_occurrences(H1,IDs1,Nb),
912 add_occurrences(H2,IDs2,Nb),
913 add_occurrences(Rules).
915 add_occurrences([],[],_).
916 add_occurrences([H|Hs],[ID|IDs],RuleNb) :-
919 new_occurrence(FA,RuleNb,ID),
920 add_occurrences(Hs,IDs,RuleNb).
922 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
924 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
925 % Observation Analysis
930 % - approximative: should make decision in late allocation analysis per body
941 observes_indirectly/2,
945 :- chr_option(mode,observes(+,+)).
946 :- chr_option(mode,spawns_observer(+,+)).
947 :- chr_option(mode,observes_indirectly(+,+)).
949 spawns_observer(C1,C2) \ spawns_observer(C1,C2) <=> true.
950 observes(C1,C2) \ observes(C1,C2) <=> true.
952 observes_indirectly(C1,C2) \ observes_indirectly(C1,C2) <=> true.
954 spawns_observer(C1,C2), observes(C2,C3) ==> observes_indirectly(C1,C3).
955 spawns_observer(C1,C2), observes_indirectly(C2,C3) ==> observes_indirectly(C1,C3).
957 observes_indirectly(C,C) \ is_self_observer(C) <=> true.
958 is_self_observer(_) <=> chr_pp_flag(observation_analysis,off).
959 % true if analysis has not been run,
960 % false if analysis has been run
962 observation_analysis(Cs) :-
963 ( chr_pp_flag(observation_analysis,on) ->
964 observation_analysis(Cs,Cs)
969 observation_analysis([],_).
970 observation_analysis([C|Cs],Constraints) :-
971 get_max_occurrence(C,MO),
972 observation_analysis_occurrences(C,1,MO,Constraints),
973 observation_analysis(Cs,Constraints).
975 observation_analysis_occurrences(C,O,MO,Cs) :-
979 observation_analysis_occurrence(C,O,Cs),
981 observation_analysis_occurrences(C,NO,MO,Cs)
984 observation_analysis_occurrence(C,O,Cs) :-
985 get_occurrence(C,O,RuleNb,ID),
986 ( is_passive(RuleNb,ID) ->
989 get_rule(RuleNb,PragmaRule),
990 PragmaRule = pragma(rule(Heads1,Heads2,_,Body),ids(IDs1,IDs2),_,_,_),
991 ( select2(ID,_Head,IDs1,Heads1,_RIDs1,RHeads1) ->
992 append(RHeads1,Heads2,OtherHeads)
993 ; select2(ID,_Head,IDs2,Heads2,_RIDs2,RHeads2) ->
994 append(RHeads2,Heads1,OtherHeads)
996 observe_heads(C,OtherHeads),
997 observe_body(C,Body,Cs)
1000 observe_heads(C,Heads) :-
1001 findall(F/A,(member(H,Heads),functor(H,F,A)),Cs),
1004 observe_all(C,Cs) :-
1014 spawns_observer(C,C1),
1019 spawn_all_triggers(C,Cs) :-
1021 ( may_trigger(C1) ->
1022 spawns_observer(C,C1)
1026 spawn_all_triggers(C,Cr)
1031 observe_body(C,Body,Cs) :-
1039 observe_body(C,B1,Cs),
1040 observe_body(C,B2,Cs)
1042 observe_body(C,B1,Cs),
1043 observe_body(C,B2,Cs)
1044 ; Body = (B1->B2) ->
1045 observe_body(C,B1,Cs),
1046 observe_body(C,B2,Cs)
1047 ; functor(Body,F,A), member(F/A,Cs) ->
1048 spawns_observer(C,F/A)
1050 spawn_all_triggers(C,Cs)
1051 ; Body = (_ is _) ->
1052 spawn_all_triggers(C,Cs)
1053 ; binds_b(Body,Vars) ->
1057 spawn_all_triggers(C,Cs)
1063 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1065 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1068 late_allocation_analysis(Cs) :-
1069 ( chr_pp_flag(late_allocation,on) ->
1075 late_allocation([]).
1076 late_allocation([C|Cs]) :-
1077 allocation_occurrence(C,1),
1078 late_allocation(Cs).
1079 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1081 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1083 %% Generated predicates
1084 %% attach_$CONSTRAINT
1086 %% detach_$CONSTRAINT
1089 %% attach_$CONSTRAINT
1090 generate_attach_detach_a_constraint_all([],[]).
1091 generate_attach_detach_a_constraint_all([Constraint|Constraints],Clauses) :-
1092 ( ( chr_pp_flag(debugable,on) ; is_stored(Constraint), \+ only_ground_indexed_arguments(Constraint)) ->
1093 generate_attach_a_constraint(Constraint,Clauses1),
1094 generate_detach_a_constraint(Constraint,Clauses2)
1099 generate_attach_detach_a_constraint_all(Constraints,Clauses3),
1100 append_lists([Clauses1,Clauses2,Clauses3],Clauses).
1102 generate_attach_a_constraint(Constraint,[Clause1,Clause2]) :-
1103 generate_attach_a_constraint_empty_list(Constraint,Clause1),
1104 get_max_constraint_index(N),
1106 generate_attach_a_constraint_1_1(Constraint,Clause2)
1108 generate_attach_a_constraint_t_p(Constraint,Clause2)
1111 generate_attach_a_constraint_skeleton(FA,Args,Body,Clause) :-
1112 make_name('attach_',FA,Fct),
1113 Head =.. [Fct | Args],
1114 Clause = ( Head :- Body).
1116 generate_attach_a_constraint_empty_list(FA,Clause) :-
1117 generate_attach_a_constraint_skeleton(FA,[[],_],true,Clause).
1119 generate_attach_a_constraint_1_1(FA,Clause) :-
1120 Args = [[Var|Vars],Susp],
1121 generate_attach_a_constraint_skeleton(FA,Args,Body,Clause),
1122 generate_attach_body_1(FA,Var,Susp,AttachBody),
1123 make_name('attach_',FA,Fct),
1124 RecursiveCall =.. [Fct,Vars,Susp],
1125 % SWI-Prolog specific code
1126 chr_pp_flag(solver_events,NMod),
1128 Args = [[Var|_],Susp],
1129 get_target_module(Mod),
1130 Subscribe = clp_events:subscribe(Var,NMod,Mod,chr_runtime:'chr run_suspensions'([Susp]))
1141 generate_attach_body_1(FA,Var,Susp,Body) :-
1142 get_target_module(Mod),
1144 ( get_attr(Var, Mod, Susps) ->
1145 NewSusps=[Susp|Susps],
1146 put_attr(Var, Mod, NewSusps)
1148 put_attr(Var, Mod, [Susp])
1151 generate_attach_a_constraint_t_p(FA,Clause) :-
1152 Args = [[Var|Vars],Susp],
1153 generate_attach_a_constraint_skeleton(FA,Args,Body,Clause),
1154 make_name('attach_',FA,Fct),
1155 RecursiveCall =.. [Fct,Vars,Susp],
1156 generate_attach_body_n(FA,Var,Susp,AttachBody),
1157 % SWI-Prolog specific code
1158 chr_pp_flag(solver_events,NMod),
1160 Args = [[Var|_],Susp],
1161 get_target_module(Mod),
1162 Subscribe = clp_events:subscribe(Var,NMod,Mod,chr_runtime:'chr run_suspensions'([Susp]))
1173 generate_attach_body_n(F/A,Var,Susp,Body) :-
1174 get_constraint_index(F/A,Position),
1175 or_pattern(Position,Pattern),
1176 get_max_constraint_index(Total),
1177 make_attr(Total,Mask,SuspsList,Attr),
1178 nth(Position,SuspsList,Susps),
1179 substitute(Susps,SuspsList,[Susp|Susps],SuspsList1),
1180 make_attr(Total,Mask,SuspsList1,NewAttr1),
1181 substitute(Susps,SuspsList,[Susp],SuspsList2),
1182 make_attr(Total,NewMask,SuspsList2,NewAttr2),
1183 copy_term(SuspsList,SuspsList3),
1184 nth(Position,SuspsList3,[Susp]),
1185 chr_delete(SuspsList3,[Susp],RestSuspsList),
1186 set_elems(RestSuspsList,[]),
1187 make_attr(Total,Pattern,SuspsList3,NewAttr3),
1188 get_target_module(Mod),
1190 ( get_attr(Var,Mod,TAttr) ->
1192 ( Mask /\ Pattern =:= Pattern ->
1193 put_attr(Var, Mod, NewAttr1)
1195 NewMask is Mask \/ Pattern,
1196 put_attr(Var, Mod, NewAttr2)
1199 put_attr(Var,Mod,NewAttr3)
1202 %% detach_$CONSTRAINT
1203 generate_detach_a_constraint(Constraint,[Clause1,Clause2]) :-
1204 generate_detach_a_constraint_empty_list(Constraint,Clause1),
1205 get_max_constraint_index(N),
1207 generate_detach_a_constraint_1_1(Constraint,Clause2)
1209 generate_detach_a_constraint_t_p(Constraint,Clause2)
1212 generate_detach_a_constraint_empty_list(FA,Clause) :-
1213 make_name('detach_',FA,Fct),
1215 Head =.. [Fct | Args],
1216 Clause = ( Head :- true).
1218 generate_detach_a_constraint_1_1(FA,Clause) :-
1219 make_name('detach_',FA,Fct),
1220 Args = [[Var|Vars],Susp],
1221 Head =.. [Fct | Args],
1222 RecursiveCall =.. [Fct,Vars,Susp],
1223 generate_detach_body_1(FA,Var,Susp,DetachBody),
1229 Clause = (Head :- Body).
1231 generate_detach_body_1(FA,Var,Susp,Body) :-
1232 get_target_module(Mod),
1234 ( get_attr(Var,Mod,Susps) ->
1235 'chr sbag_del_element'(Susps,Susp,NewSusps),
1239 put_attr(Var,Mod,NewSusps)
1245 generate_detach_a_constraint_t_p(FA,Clause) :-
1246 make_name('detach_',FA,Fct),
1247 Args = [[Var|Vars],Susp],
1248 Head =.. [Fct | Args],
1249 RecursiveCall =.. [Fct,Vars,Susp],
1250 generate_detach_body_n(FA,Var,Susp,DetachBody),
1256 Clause = (Head :- Body).
1258 generate_detach_body_n(F/A,Var,Susp,Body) :-
1259 get_constraint_index(F/A,Position),
1260 or_pattern(Position,Pattern),
1261 and_pattern(Position,DelPattern),
1262 get_max_constraint_index(Total),
1263 make_attr(Total,Mask,SuspsList,Attr),
1264 nth(Position,SuspsList,Susps),
1265 substitute(Susps,SuspsList,[],SuspsList1),
1266 make_attr(Total,NewMask,SuspsList1,Attr1),
1267 substitute(Susps,SuspsList,NewSusps,SuspsList2),
1268 make_attr(Total,Mask,SuspsList2,Attr2),
1269 get_target_module(Mod),
1271 ( get_attr(Var,Mod,TAttr) ->
1273 ( Mask /\ Pattern =:= Pattern ->
1274 'chr sbag_del_element'(Susps,Susp,NewSusps),
1276 NewMask is Mask /\ DelPattern,
1280 put_attr(Var,Mod,Attr1)
1283 put_attr(Var,Mod,Attr2)
1292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1293 generate_indexed_variables_clauses(Constraints,Clauses) :-
1294 ( are_none_suspended_on_variables ->
1297 generate_indexed_variables_clauses_(Constraints,Clauses)
1300 generate_indexed_variables_clauses_([],[]).
1301 generate_indexed_variables_clauses_([C|Cs],Clauses) :-
1303 Clauses = [Clause|RestClauses],
1304 generate_indexed_variables_clause(C,Clause)
1306 Clauses = RestClauses
1308 generate_indexed_variables_clauses_(Cs,RestClauses).
1310 %===============================================================================
1311 :- chr_constraint generate_indexed_variables_clause/2.
1312 :- chr_option(mode,generate_indexed_variables_clause(+,+)).
1313 %-------------------------------------------------------------------------------
1314 constraint_mode(F/A,ArgModes) \ generate_indexed_variables_clause(F/A,Clause) <=>
1317 create_indexed_variables_body(Args,ArgModes,Vars,1,F/A,MaybeBody,N),
1318 ( MaybeBody == empty ->
1322 Body = term_variables(Susp,Vars)
1327 ( '$indexed_variables'(Susp,Vars) :-
1331 generate_indexed_variables_clause(FA,_) <=>
1332 chr_error(internal,'generate_indexed_variables_clause: missing mode info for ~w.\n',[FA]).
1333 %===============================================================================
1335 create_indexed_variables_body([],[],_,_,_,empty,0).
1336 create_indexed_variables_body([V|Vs],[Mode|Modes],Vars,I,FA,Body,N) :-
1338 create_indexed_variables_body(Vs,Modes,Tail,J,FA,RBody,M),
1340 is_indexed_argument(FA,I) ->
1342 Body = term_variables(V,Vars)
1344 Body = (term_variables(V,Vars,Tail),RBody)
1353 generate_extra_clauses(Constraints,List) :-
1354 generate_activate_clause(List,Tail0),
1355 generate_remove_clause(Tail0,Tail1),
1356 generate_allocate_clause(Tail1,Tail2),
1357 generate_insert_constraint_internal(Tail2,Tail3),
1358 global_indexed_variables_clause(Constraints,Tail3,[]).
1360 generate_remove_clause(List,Tail) :-
1361 ( is_used_auxiliary_predicate(remove_constraint_internal) ->
1362 List = [RemoveClause|Tail],
1363 use_auxiliary_predicate(chr_indexed_variables),
1364 ( are_none_suspended_on_variables ->
1367 remove_constraint_internal(Susp) :-
1368 arg( 2, Susp, Mref),
1369 'chr update_mutable'( removed, Mref)
1374 remove_constraint_internal(Susp, Agenda, Delete) :-
1375 arg( 2, Susp, Mref),
1376 'chr get_mutable'( State, Mref),
1377 'chr update_mutable'( removed, Mref), % mark in any case
1378 ( compound(State) -> % passive/1
1384 %; State==triggered ->
1388 chr_indexed_variables(Susp,Agenda)
1396 generate_activate_clause(List,Tail) :-
1397 ( is_used_auxiliary_predicate(activate_constraint) ->
1398 List = [ActivateClause|Tail],
1399 use_auxiliary_predicate(chr_indexed_variables),
1402 activate_constraint(Store, Vars, Susp, Generation) :-
1403 arg( 2, Susp, Mref),
1404 'chr get_mutable'( State, Mref),
1405 'chr update_mutable'( active, Mref),
1406 ( nonvar(Generation) -> % aih
1409 arg( 4, Susp, Gref),
1410 'chr get_mutable'( Gen, Gref),
1411 Generation is Gen+1,
1412 'chr update_mutable'( Generation, Gref)
1414 ( compound(State) -> % passive/1
1415 term_variables( State, Vars),
1416 'chr none_locked'( Vars),
1418 ; State == removed -> % the price for eager removal ...
1419 chr_indexed_variables(Susp,Vars),
1430 generate_allocate_clause(List,Tail) :-
1431 ( is_used_auxiliary_predicate(allocate_constraint) ->
1432 List = [AllocateClause|Tail],
1433 use_auxiliary_predicate(chr_indexed_variables),
1436 allocate_constraint( Closure, Self, F, Args) :-
1437 Self =.. [suspension,Id,Mref,Closure,Gref,Href,F|Args],
1438 'chr create_mutable'(0,Gref), % Gref = mutable(0),
1439 'chr empty_history'(History),
1440 'chr create_mutable'(History,Href), % Href = mutable(History),
1441 chr_indexed_variables(Self,Vars),
1442 'chr create_mutable'(passive(Vars),Mref), % Mref = mutable(passive(Vars)),
1449 generate_insert_constraint_internal(List,Tail) :-
1450 ( is_used_auxiliary_predicate(insert_constraint_internal) ->
1451 ( are_none_suspended_on_variables ->
1452 List = [Clause1,Clause2|Tail],
1453 % is clause1 needed????
1456 insert_constraint_internal(yes, [], Self, Closure, F, Args) :-
1457 'chr create_mutable'(active,Active),
1458 'chr create_mutable'(0,Zero),
1459 'chr create_mutable'(t,Tee),
1460 Self =.. [suspension,Id,Active,Closure,Zero,Tee,F|Args],
1465 insert_constraint_internal(Self, F, Args) :-
1466 'chr create_mutable'(active,Active),
1467 'chr create_mutable'(0,Zero),
1468 'chr create_mutable'(t,Tee),
1469 Self =.. [suspension,Id,Active,true,Zero,Tee,F|Args],
1473 List = [Clause|Tail],
1474 use_auxiliary_predicate(chr_indexed_variables),
1477 insert_constraint_internal(yes, Vars, Self, Closure, F, Args) :-
1478 Self =.. [suspension,Id,Mref,Closure,Gref,Href,F|Args],
1479 chr_indexed_variables(Self,Vars),
1480 'chr none_locked'(Vars),
1481 'chr create_mutable'(active,Mref), % Mref = mutable(active),
1482 'chr create_mutable'(0,Gref), % Gref = mutable(0),
1483 'chr empty_history'(History),
1484 'chr create_mutable'(History,Href), % Href = mutable(History),
1492 global_indexed_variables_clause(Constraints,List,Tail) :-
1493 ( is_used_auxiliary_predicate(chr_indexed_variables) ->
1494 List = [Clause|Tail],
1495 ( chr_pp_flag(reduced_indexing,on) ->
1496 ( are_none_suspended_on_variables ->
1500 Body = (Susp =.. [_,_,_,_,_,_,Term|_], '$indexed_variables'(Term,Vars))
1502 Clause = ( chr_indexed_variables(Susp,Vars) :- Body )
1505 ( chr_indexed_variables(Susp,Vars) :-
1506 'chr chr_indexed_variables'(Susp,Vars)
1513 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1514 generate_attach_increment(Clauses) :-
1515 get_max_constraint_index(N),
1517 Clauses = [Clause1,Clause2],
1518 generate_attach_increment_empty(Clause1),
1520 generate_attach_increment_one(Clause2)
1522 generate_attach_increment_many(N,Clause2)
1528 generate_attach_increment_empty((attach_increment([],_) :- true)).
1530 generate_attach_increment_one(Clause) :-
1531 Head = attach_increment([Var|Vars],Susps),
1532 get_target_module(Mod),
1535 'chr not_locked'(Var),
1536 ( get_attr(Var,Mod,VarSusps) ->
1537 sort(VarSusps,SortedVarSusps),
1538 'chr merge_attributes'(Susps,SortedVarSusps,MergedSusps),
1539 put_attr(Var,Mod,MergedSusps)
1541 put_attr(Var,Mod,Susps)
1543 attach_increment(Vars,Susps)
1545 Clause = (Head :- Body).
1547 generate_attach_increment_many(N,Clause) :-
1548 make_attr(N,Mask,SuspsList,Attr),
1549 make_attr(N,OtherMask,OtherSuspsList,OtherAttr),
1550 Head = attach_increment([Var|Vars],Attr),
1551 bagof(G,X ^ Y ^ SY ^ M ^ (member2(SuspsList,OtherSuspsList,X-Y),G = (sort(Y,SY),'chr merge_attributes'(X,SY,M))),Gs),
1552 list2conj(Gs,SortGoals),
1553 bagof(MS,A ^ B ^ C ^ member((A,'chr merge_attributes'(B,C,MS)),Gs), MergedSuspsList),
1554 make_attr(N,MergedMask,MergedSuspsList,NewAttr),
1555 get_target_module(Mod),
1558 'chr not_locked'(Var),
1559 ( get_attr(Var,Mod,TOtherAttr) ->
1560 TOtherAttr = OtherAttr,
1562 MergedMask is Mask \/ OtherMask,
1563 put_attr(Var,Mod,NewAttr)
1565 put_attr(Var,Mod,Attr)
1567 attach_increment(Vars,Attr)
1569 Clause = (Head :- Body).
1572 generate_attr_unify_hook(Clauses) :-
1573 get_max_constraint_index(N),
1579 generate_attr_unify_hook_one(Clause)
1581 generate_attr_unify_hook_many(N,Clause)
1585 generate_attr_unify_hook_one(Clause) :-
1586 Head = attr_unify_hook(Susps,Other),
1587 get_target_module(Mod),
1588 make_run_suspensions(NewSusps,WakeNewSusps),
1589 make_run_suspensions(Susps,WakeSusps),
1592 sort(Susps, SortedSusps),
1594 ( get_attr(Other,Mod,OtherSusps) ->
1599 sort(OtherSusps,SortedOtherSusps),
1600 'chr merge_attributes'(SortedSusps,SortedOtherSusps,NewSusps),
1601 put_attr(Other,Mod,NewSusps),
1604 ( compound(Other) ->
1605 term_variables(Other,OtherVars),
1606 attach_increment(OtherVars, SortedSusps)
1613 Clause = (Head :- Body).
1615 generate_attr_unify_hook_many(N,Clause) :-
1616 make_attr(N,Mask,SuspsList,Attr),
1617 make_attr(N,OtherMask,OtherSuspsList,OtherAttr),
1618 bagof(Sort,A ^ B ^ ( member(A,SuspsList) , Sort = sort(A,B) ) , SortGoalList),
1619 list2conj(SortGoalList,SortGoals),
1620 bagof(B, A ^ member(sort(A,B),SortGoalList), SortedSuspsList),
1621 bagof(C, D ^ E ^ F ^ G ^ (member2(SortedSuspsList,OtherSuspsList,D-E),
1623 'chr merge_attributes'(D,F,G)) ),
1625 bagof(G, D ^ F ^ H ^ member((H,'chr merge_attributes'(D,F,G)),SortMergeGoalList) , MergedSuspsList),
1626 list2conj(SortMergeGoalList,SortMergeGoals),
1627 make_attr(N,MergedMask,MergedSuspsList,MergedAttr),
1628 make_attr(N,Mask,SortedSuspsList,SortedAttr),
1629 Head = attr_unify_hook(Attr,Other),
1630 get_target_module(Mod),
1631 make_run_suspensions_loop(MergedSuspsList,WakeMergedSusps),
1632 make_run_suspensions_loop(SortedSuspsList,WakeSortedSusps),
1637 ( get_attr(Other,Mod,TOtherAttr) ->
1638 TOtherAttr = OtherAttr,
1640 MergedMask is Mask \/ OtherMask,
1641 put_attr(Other,Mod,MergedAttr),
1644 put_attr(Other,Mod,SortedAttr),
1648 ( compound(Other) ->
1649 term_variables(Other,OtherVars),
1650 attach_increment(OtherVars,SortedAttr)
1657 Clause = (Head :- Body).
1659 make_run_suspensions(Susps,Goal) :-
1660 ( chr_pp_flag(debugable,on) ->
1661 Goal = 'chr run_suspensions_d'(Susps)
1663 Goal = 'chr run_suspensions'(Susps)
1666 make_run_suspensions_loop(SuspsList,Goal) :-
1667 ( chr_pp_flag(debugable,on) ->
1668 Goal = 'chr run_suspensions_loop_d'(SuspsList)
1670 Goal = 'chr run_suspensions_loop'(SuspsList)
1673 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1674 % $insert_in_store_F/A
1675 % $delete_from_store_F/A
1677 generate_insert_delete_constraints([],[]).
1678 generate_insert_delete_constraints([FA|Rest],Clauses) :-
1680 Clauses = [IClause,DClause|RestClauses],
1681 generate_insert_delete_constraint(FA,IClause,DClause)
1683 Clauses = RestClauses
1685 generate_insert_delete_constraints(Rest,RestClauses).
1687 generate_insert_delete_constraint(FA,IClause,DClause) :-
1688 get_store_type(FA,StoreType),
1689 generate_insert_constraint(StoreType,FA,IClause),
1690 generate_delete_constraint(StoreType,FA,DClause).
1692 generate_insert_constraint(StoreType,C,Clause) :-
1693 make_name('$insert_in_store_',C,ClauseName),
1694 Head =.. [ClauseName,Susp],
1695 generate_insert_constraint_body(StoreType,C,Susp,Body),
1696 ( chr_pp_flag(store_counter,on) ->
1697 InsertCounterInc = '$insert_counter_inc'
1699 InsertCounterInc = true
1701 Clause = (Head :- InsertCounterInc,Body).
1703 generate_insert_constraint_body(default,C,Susp,Body) :-
1704 get_target_module(Mod),
1705 get_max_constraint_index(Total),
1707 generate_attach_body_1(C,Store,Susp,AttachBody)
1709 generate_attach_body_n(C,Store,Susp,AttachBody)
1713 'chr default_store'(Store),
1716 generate_insert_constraint_body(multi_hash(Indexes),C,Susp,Body) :-
1717 generate_multi_hash_insert_constraint_bodies(Indexes,C,Susp,Body).
1718 generate_insert_constraint_body(global_ground,C,Susp,Body) :-
1719 global_ground_store_name(C,StoreName),
1720 make_get_store_goal(StoreName,Store,GetStoreGoal),
1721 make_update_store_goal(StoreName,[Susp|Store],UpdateStoreGoal),
1724 GetStoreGoal, % nb_getval(StoreName,Store),
1725 UpdateStoreGoal % b_setval(StoreName,[Susp|Store])
1727 generate_insert_constraint_body(global_singleton,C,Susp,Body) :-
1728 global_singleton_store_name(C,StoreName),
1729 make_update_store_goal(StoreName,Susp,UpdateStoreGoal),
1732 UpdateStoreGoal % b_setval(StoreName,Susp)
1734 generate_insert_constraint_body(multi_store(StoreTypes),C,Susp,Body) :-
1735 find_with_var_identity(
1739 member(ST,StoreTypes),
1740 chr_translate:generate_insert_constraint_body(ST,C,Susp,B)
1744 list2conj(Bodies,Body).
1746 generate_multi_hash_insert_constraint_bodies([],_,_,true).
1747 generate_multi_hash_insert_constraint_bodies([Index|Indexes],FA,Susp,(Body,Bodies)) :-
1748 multi_hash_store_name(FA,Index,StoreName),
1749 multi_hash_key(FA,Index,Susp,KeyBody,Key),
1750 make_get_store_goal(StoreName,Store,GetStoreGoal),
1754 GetStoreGoal, % nb_getval(StoreName,Store),
1755 insert_ht(Store,Key,Susp)
1757 generate_multi_hash_insert_constraint_bodies(Indexes,FA,Susp,Bodies).
1759 generate_delete_constraint(StoreType,FA,Clause) :-
1760 make_name('$delete_from_store_',FA,ClauseName),
1761 Head =.. [ClauseName,Susp],
1762 generate_delete_constraint_body(StoreType,FA,Susp,Body),
1763 ( chr_pp_flag(store_counter,on) ->
1764 DeleteCounterInc = '$delete_counter_inc'
1766 DeleteCounterInc = true
1768 Clause = (Head :- DeleteCounterInc, Body).
1770 generate_delete_constraint_body(default,C,Susp,Body) :-
1771 get_target_module(Mod),
1772 get_max_constraint_index(Total),
1774 generate_detach_body_1(C,Store,Susp,DetachBody),
1777 'chr default_store'(Store),
1781 generate_detach_body_n(C,Store,Susp,DetachBody),
1784 'chr default_store'(Store),
1788 generate_delete_constraint_body(multi_hash(Indexes),C,Susp,Body) :-
1789 generate_multi_hash_delete_constraint_bodies(Indexes,C,Susp,Body).
1790 generate_delete_constraint_body(global_ground,C,Susp,Body) :-
1791 global_ground_store_name(C,StoreName),
1792 make_get_store_goal(StoreName,Store,GetStoreGoal),
1793 make_update_store_goal(StoreName,NStore,UpdateStoreGoal),
1796 GetStoreGoal, % nb_getval(StoreName,Store),
1797 'chr sbag_del_element'(Store,Susp,NStore),
1798 UpdateStoreGoal % b_setval(StoreName,NStore)
1800 generate_delete_constraint_body(global_singleton,C,_Susp,Body) :-
1801 global_singleton_store_name(C,StoreName),
1802 make_update_store_goal(StoreName,[],UpdateStoreGoal),
1805 UpdateStoreGoal % b_setval(StoreName,[])
1807 generate_delete_constraint_body(multi_store(StoreTypes),C,Susp,Body) :-
1808 find_with_var_identity(
1812 member(ST,StoreTypes),
1813 chr_translate:generate_delete_constraint_body(ST,C,Susp,B)
1817 list2conj(Bodies,Body).
1819 generate_multi_hash_delete_constraint_bodies([],_,_,true).
1820 generate_multi_hash_delete_constraint_bodies([Index|Indexes],FA,Susp,(Body,Bodies)) :-
1821 multi_hash_store_name(FA,Index,StoreName),
1822 multi_hash_key(FA,Index,Susp,KeyBody,Key),
1823 make_get_store_goal(StoreName,Store,GetStoreGoal),
1827 GetStoreGoal, % nb_getval(StoreName,Store),
1828 delete_ht(Store,Key,Susp)
1830 generate_multi_hash_delete_constraint_bodies(Indexes,FA,Susp,Bodies).
1832 generate_delete_constraint_call(FA,Susp,Call) :-
1833 make_name('$delete_from_store_',FA,Functor),
1834 Call =.. [Functor,Susp].
1836 generate_insert_constraint_call(FA,Susp,Call) :-
1837 make_name('$insert_in_store_',FA,Functor),
1838 Call =.. [Functor,Susp].
1840 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1843 module_initializer/1,
1844 module_initializers/1.
1846 module_initializers(G), module_initializer(Initializer) <=>
1847 G = (Initializer,Initializers),
1848 module_initializers(Initializers).
1850 module_initializers(G) <=>
1853 generate_attach_code(Constraints,[Enumerate|L]) :-
1854 enumerate_stores_code(Constraints,Enumerate),
1855 generate_attach_code(Constraints,L,T),
1856 module_initializers(Initializers),
1857 T = [('$chr_initialization' :- Initializers),(:- '$chr_initialization')].
1859 generate_attach_code([],L,L).
1860 generate_attach_code([C|Cs],L,T) :-
1861 get_store_type(C,StoreType),
1862 generate_attach_code(StoreType,C,L,L1),
1863 generate_attach_code(Cs,L1,T).
1865 generate_attach_code(default,_,L,L).
1866 generate_attach_code(multi_hash(Indexes),C,L,T) :-
1867 multi_hash_store_initialisations(Indexes,C,L,L1),
1868 multi_hash_via_lookups(Indexes,C,L1,T).
1869 generate_attach_code(global_ground,C,L,T) :-
1870 global_ground_store_initialisation(C,L,T).
1871 generate_attach_code(global_singleton,C,L,T) :-
1872 global_singleton_store_initialisation(C,L,T).
1873 generate_attach_code(multi_store(StoreTypes),C,L,T) :-
1874 multi_store_generate_attach_code(StoreTypes,C,L,T).
1876 multi_store_generate_attach_code([],_,L,L).
1877 multi_store_generate_attach_code([ST|STs],C,L,T) :-
1878 generate_attach_code(ST,C,L,L1),
1879 multi_store_generate_attach_code(STs,C,L1,T).
1881 multi_hash_store_initialisations([],_,L,L).
1882 multi_hash_store_initialisations([Index|Indexes],FA,L,T) :-
1883 multi_hash_store_name(FA,Index,StoreName),
1884 make_init_store_goal(StoreName,HT,InitStoreGoal),
1885 module_initializer((new_ht(HT),InitStoreGoal)),
1886 %% module_initializer((new_ht(HT),nb_setval(StoreName,HT))),
1888 multi_hash_store_initialisations(Indexes,FA,L1,T).
1890 global_ground_store_initialisation(C,L,T) :-
1891 global_ground_store_name(C,StoreName),
1892 make_init_store_goal(StoreName,[],InitStoreGoal),
1893 module_initializer(InitStoreGoal),
1894 %% module_initializer(nb_setval(StoreName,[])),
1896 global_singleton_store_initialisation(C,L,T) :-
1897 global_singleton_store_name(C,StoreName),
1898 make_init_store_goal(StoreName,[],InitStoreGoal),
1899 module_initializer(InitStoreGoal),
1900 %% module_initializer(nb_setval(StoreName,[])),
1903 multi_hash_via_lookups([],_,L,L).
1904 multi_hash_via_lookups([Index|Indexes],C,L,T) :-
1905 multi_hash_via_lookup_name(C,Index,PredName),
1906 Head =.. [PredName,Key,SuspsList],
1907 multi_hash_store_name(C,Index,StoreName),
1908 make_get_store_goal(StoreName,HT,GetStoreGoal),
1911 GetStoreGoal, % nb_getval(StoreName,HT),
1912 lookup_ht(HT,Key,SuspsList)
1914 L = [(Head :- Body)|L1],
1915 multi_hash_via_lookups(Indexes,C,L1,T).
1917 multi_hash_via_lookup_name(F/A,Index,Name) :-
1921 atom_concat_list(Index,IndexName)
1923 atom_concat_list(['$via1_multi_hash_',F,(/),A,'-',IndexName],Name).
1925 multi_hash_store_name(F/A,Index,Name) :-
1926 get_target_module(Mod),
1930 atom_concat_list(Index,IndexName)
1932 atom_concat_list(['$chr_store_multi_hash_',Mod,(:),F,(/),A,'-',IndexName],Name).
1934 multi_hash_key(F/A,Index,Susp,KeyBody,Key) :-
1935 ( ( integer(Index) ->
1941 KeyBody = arg(SuspIndex,Susp,Key)
1943 sort(Index,Indexes),
1944 find_with_var_identity(arg(J,Susp,KeyI)-KeyI,[Susp],(member(I,Indexes),J is I + 6),ArgKeyPairs),
1945 pairup(Bodies,Keys,ArgKeyPairs),
1947 list2conj(Bodies,KeyBody)
1950 multi_hash_key_args(Index,Head,KeyArgs) :-
1952 arg(Index,Head,Arg),
1955 sort(Index,Indexes),
1956 term_variables(Head,Vars),
1957 find_with_var_identity(Arg,Vars,(member(I,Indexes), arg(I,Head,Arg)),KeyArgs)
1960 global_ground_store_name(F/A,Name) :-
1961 get_target_module(Mod),
1962 atom_concat_list(['$chr_store_global_ground_',Mod,(:),F,(/),A],Name).
1963 global_singleton_store_name(F/A,Name) :-
1964 get_target_module(Mod),
1965 atom_concat_list(['$chr_store_global_singleton_',Mod,(:),F,(/),A],Name).
1966 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1967 enumerate_stores_code(Constraints,Clause) :-
1968 Head = '$enumerate_suspensions'(Susp),
1969 enumerate_store_bodies(Constraints,Susp,Bodies),
1970 list2disj(Bodies,Body),
1971 Clause = (Head :- Body).
1973 enumerate_store_bodies([],_,[]).
1974 enumerate_store_bodies([C|Cs],Susp,L) :-
1976 get_store_type(C,StoreType),
1977 enumerate_store_body(StoreType,C,Susp,B),
1982 enumerate_store_bodies(Cs,Susp,T).
1984 enumerate_store_body(default,C,Susp,Body) :-
1985 get_constraint_index(C,Index),
1986 get_target_module(Mod),
1987 get_max_constraint_index(MaxIndex),
1990 'chr default_store'(GlobalStore),
1991 get_attr(GlobalStore,Mod,Attr)
1994 NIndex is Index + 1,
1997 arg(NIndex,Attr,List),
1998 'chr sbag_member'(Susp,List)
2001 Body2 = 'chr sbag_member'(Susp,Attr)
2003 Body = (Body1,Body2).
2004 enumerate_store_body(multi_hash([Index|_]),C,Susp,Body) :-
2005 multi_hash_enumerate_store_body(Index,C,Susp,Body).
2006 enumerate_store_body(global_ground,C,Susp,Body) :-
2007 global_ground_store_name(C,StoreName),
2008 make_get_store_goal(StoreName,List,GetStoreGoal),
2011 GetStoreGoal, % nb_getval(StoreName,List),
2012 'chr sbag_member'(Susp,List)
2014 enumerate_store_body(global_singleton,C,Susp,Body) :-
2015 global_singleton_store_name(C,StoreName),
2016 make_get_store_goal(StoreName,Susp,GetStoreGoal),
2019 GetStoreGoal, % nb_getval(StoreName,Susp),
2022 enumerate_store_body(multi_store(STs),C,Susp,Body) :-
2025 enumerate_store_body(ST,C,Susp,Body)
2028 multi_hash_enumerate_store_body(I,C,Susp,B) :-
2029 multi_hash_store_name(C,I,StoreName),
2030 make_get_store_goal(StoreName,HT,GetStoreGoal),
2033 GetStoreGoal, % nb_getval(StoreName,HT),
2037 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2045 :- chr_option(mode,prev_guard_list(+,+,+,+,+,+,+)).
2046 :- chr_option(mode,simplify_guards(+)).
2047 :- chr_option(mode,set_all_passive(+)).
2049 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2050 % GUARD SIMPLIFICATION
2051 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2052 % If the negation of the guards of earlier rules entails (part of)
2053 % the current guard, the current guard can be simplified. We can only
2054 % use earlier rules with a head that matches if the head of the current
2055 % rule does, and which make it impossible for the current rule to match
2056 % if they fire (i.e. they shouldn't be propagation rules and their
2057 % head constraints must be subsets of those of the current rule).
2058 % At this point, we know for sure that the negation of the guard
2059 % of such a rule has to be true (otherwise the earlier rule would have
2060 % fired, because of the refined operational semantics), so we can use
2061 % that information to simplify the guard by replacing all entailed
2062 % conditions by true/0. As a consequence, the never-stored analysis
2063 % (in a further phase) will detect more cases of never-stored constraints.
2065 % e.g. c(X),d(Y) <=> X > 0 | ...
2066 % e(X) <=> X < 0 | ...
2067 % c(X) \ d(Y),e(Z) <=> X =< 0, Z >= 0, ... | ...
2071 guard_simplification :-
2072 ( chr_pp_flag(guard_simplification,on) ->
2073 multiple_occ_constraints_checked([]),
2079 % for every rule, we create a prev_guard_list where the last argument
2080 % eventually is a list of the negations of earlier guards
2081 rule(RuleNb,Rule) \ simplify_guards(RuleNb) <=>
2082 Rule = pragma(rule(Head1,Head2,G,_B),_Ids,_Pragmas,_Name,RuleNb),
2083 append(Head1,Head2,Heads),
2084 make_head_matchings_explicit_not_negated(Heads,UniqueVarsHeads,Matchings),
2085 add_guard_to_head(Heads,G,GHeads),
2086 PrevRule is RuleNb-1,
2087 prev_guard_list(RuleNb,PrevRule,UniqueVarsHeads,G,[],Matchings,[GHeads]),
2088 multiple_occ_constraints_checked([]),
2089 NextRule is RuleNb+1, simplify_guards(NextRule).
2091 simplify_guards(_) <=> true.
2093 % the negation of the guard of a non-propagation rule is added
2094 % if its kept head constraints are a subset of the kept constraints of
2095 % the rule we're working on, and its removed head constraints (at least one)
2096 % are a subset of the removed constraints
2097 rule(N,Rule) \ prev_guard_list(RuleNb,N,H,G,GuardList,M,GH) <=>
2098 Rule = pragma(rule(H1,H2,G2,_B),_Ids,_Pragmas,_Name,N),
2100 append(H1,H2,Heads),
2101 make_head_matchings_explicit(Heads,UniqueVarsHeads,Matchings),
2102 setof(Renaming,chr_translate:head_subset(UniqueVarsHeads,H,Renaming),Renamings),
2105 compute_derived_info(Matchings,Renamings,UniqueVarsHeads,Heads,G2,M,H,GH,DerivedInfo,GH_New1),
2106 append(GuardList,DerivedInfo,GL1),
2109 append(GH_New1,GH,GH1),
2111 conj2list(GH_,GH_New),
2113 prev_guard_list(RuleNb,N1,H,G,GL,M,GH_New).
2116 % if this isn't the case, we skip this one and try the next rule
2117 prev_guard_list(RuleNb,N,H,G,GuardList,M,GH) <=> N > 0 |
2118 N1 is N-1, prev_guard_list(RuleNb,N1,H,G,GuardList,M,GH).
2120 prev_guard_list(RuleNb,0,H,G,GuardList,M,GH) <=>
2122 add_type_information_(H,GH,TypeInfo),
2123 conj2list(TypeInfo,TI),
2124 term_variables(H,HeadVars),
2125 append([chr_pp_headvariables(HeadVars)|TI],GuardList,Info),
2126 list2conj(Info,InfoC),
2127 conj2list(InfoC,InfoL),
2128 prev_guard_list(RuleNb,0,H,G,InfoL,M,[]).
2130 add_type_information_(H,[],true) :- !.
2131 add_type_information_(H,[GH|GHs],TI) :- !,
2132 add_type_information(H,GH,TI1),
2134 add_type_information_(H,GHs,TI2).
2136 % when all earlier guards are added or skipped, we simplify the guard.
2137 % if it's different from the original one, we change the rule
2138 prev_guard_list(RuleNb,0,H,G,GuardList,M,[]), rule(RuleNb,Rule) <=>
2139 Rule = pragma(rule(Head1,Head2,G,B),Ids,Pragmas,Name,RuleNb),
2140 G \== true, % let's not try to simplify this ;)
2141 append(M,GuardList,Info),
2142 simplify_guard(G,B,Info,SimpleGuard,NB),
2144 % ( prolog_flag(verbose,V), V == yes ->
2145 % format(' * Guard simplification in ~@\n',[format_rule(Rule)]),
2146 % format(' was: ~w\n',[G]),
2147 % format(' now: ~w\n',[SimpleGuard]),
2148 % (NB\==B -> format(' new body: ~w\n',[NB]) ; true)
2152 rule(RuleNb,pragma(rule(Head1,Head2,SimpleGuard,NB),Ids,Pragmas,Name,RuleNb)),
2153 prev_guard_list(RuleNb,0,H,SimpleGuard,GuardList,M,[]).
2156 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2157 % AUXILIARY PREDICATES (GUARD SIMPLIFICATION)
2158 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2160 compute_derived_info(Matchings,[],UniqueVarsHeads,Heads,G2,M,H,GH,[],[]) :- !.
2162 compute_derived_info(Matchings,[Renaming1|RR],UniqueVarsHeads,Heads,G2,M,H,GH,DerivedInfo,GH_New) :- !,
2163 copy_term(Matchings-G2,FreshMatchings),
2164 variable_replacement(Matchings-G2,FreshMatchings,ExtraRenaming),
2165 append(Renaming1,ExtraRenaming,Renaming2),
2166 list2conj(Matchings,Match),
2167 negate_b(Match,HeadsDontMatch),
2168 make_head_matchings_explicit_not_negated2(Heads,UniqueVarsHeads,HeadsMatch),
2169 list2conj(HeadsMatch,HeadsMatchBut),
2170 term_variables(Renaming2,RenVars),
2171 term_variables(Matchings-G2-HeadsMatch,MGVars),
2172 new_vars(MGVars,RenVars,ExtraRenaming2),
2173 append(Renaming2,ExtraRenaming2,Renaming),
2174 negate_b(G2,TheGuardFailed),
2175 ( G2 == true -> % true can't fail
2176 Info_ = HeadsDontMatch
2178 Info_ = (HeadsDontMatch ; (HeadsMatchBut, TheGuardFailed))
2180 copy_with_variable_replacement(Info_,DerivedInfo1,Renaming),
2181 copy_with_variable_replacement(G2,RenamedG2,Renaming),
2182 copy_with_variable_replacement(Matchings,RenamedMatchings_,Renaming),
2183 list2conj(RenamedMatchings_,RenamedMatchings),
2184 add_guard_to_head(H,RenamedG2,GH2),
2185 add_guard_to_head(GH2,RenamedMatchings,GH3),
2186 compute_derived_info(Matchings,RR,UniqueVarsHeads,Heads,G2,M,H,GH,DerivedInfo2,GH_New2),
2187 append([DerivedInfo1],DerivedInfo2,DerivedInfo),
2188 append([GH3],GH_New2,GH_New).
2191 simplify_guard(G,B,Info,SG,NB) :-
2193 guard_entailment:simplify_guards(Info,B,LG,SGL,NB),
2198 new_vars([A|As],RV,ER) :-
2199 ( memberchk_eq(A,RV) ->
2202 ER = [A-NewA,NewA-A|ER2],
2206 % check if a list of constraints is a subset of another list of constraints
2207 % (multiset-subset), meanwhile computing a variable renaming to convert
2208 % one into the other.
2209 head_subset(H,Head,Renaming) :-
2210 head_subset(H,Head,Renaming,[],_).
2212 % empty list is a subset of everything
2213 head_subset([],Head,Renaming,Cumul,Headleft) :- !,
2217 % first constraint has to be in the list, the rest has to be a subset
2218 % of the list with one occurrence of the first constraint removed
2219 % (has to be multiset-subset)
2220 head_subset([A|B],Head,Renaming,Cumul,Headleft) :- !,
2221 head_subset(A,Head,R1,Cumul,Headleft1),
2222 head_subset(B,Headleft1,R2,R1,Headleft2),
2224 Headleft = Headleft2.
2226 % check if A is in the list, remove it from Headleft
2227 head_subset(A,[X|Y],Renaming,Cumul,Headleft) :- !,
2228 ( head_subset(A,X,R1,Cumul,HL1),
2232 head_subset(A,Y,R2,Cumul,HL2),
2237 % A is X if there's a variable renaming to make them identical
2238 head_subset(A,X,Renaming,Cumul,Headleft) :-
2239 variable_replacement(A,X,Cumul,Renaming),
2242 make_head_matchings_explicit(Heads,UniqueVarsHeads,Matchings) :-
2243 extract_variables(Heads,VH1),
2244 make_matchings_explicit(VH1,H1_,[],[],_,Matchings),
2245 insert_variables(H1_,Heads,UniqueVarsHeads).
2247 make_head_matchings_explicit_not_negated(Heads,UniqueVarsHeads,Matchings) :-
2248 extract_variables(Heads,VH1),
2249 make_matchings_explicit_not_negated(VH1,H1_,[],Matchings),
2250 insert_variables(H1_,Heads,UniqueVarsHeads).
2252 make_head_matchings_explicit_not_negated2(Heads,UniqueVarsHeads,Matchings) :-
2253 extract_variables(Heads,VH1),
2254 extract_variables(UniqueVarsHeads,UV),
2255 make_matchings_explicit_not_negated(VH1,UV,[],Matchings).
2258 extract_variables([],[]).
2259 extract_variables([X|R],V) :-
2261 extract_variables(R,V2),
2264 insert_variables([],[],[]) :- !.
2265 insert_variables(Vars,[C|R],[C2|R2]) :-
2268 take_first_N(Vars,N,Args2,RestVars),
2270 insert_variables(RestVars,R,R2).
2272 take_first_N(Vars,0,[],Vars) :- !.
2273 take_first_N([X|R],N,[X|R2],RestVars) :-
2275 take_first_N(R,N1,R2,RestVars).
2277 make_matchings_explicit([],[],_,MC,MC,[]).
2278 make_matchings_explicit([X|R],[NewVar|R2],C,MC,MCO,M) :-
2280 ( memberchk_eq(X,C) ->
2281 list2disj(MC,MC_disj),
2282 M = [(MC_disj ; NewVar == X)|M2], % or only = ??
2293 make_matchings_explicit(Args,NewArgs,C,MC,MC_,ArgM),
2296 M = [functor(NewVar,F,A) |M2]
2298 list2conj(ArgM,ArgM_conj),
2299 list2disj(MC,MC_disj),
2300 ArgM_ = (NewVar \= X_ ; MC_disj ; ArgM_conj),
2301 M = [ functor(NewVar,F,A) , ArgM_|M2]
2303 MC2 = [ NewVar \= X_ |MC_],
2304 term_variables(Args,ArgVars),
2305 append(C,ArgVars,C2)
2307 make_matchings_explicit(R,R2,C2,MC2,MCO,M2).
2310 make_matchings_explicit_not_negated([],[],_,[]).
2311 make_matchings_explicit_not_negated([X|R],[NewVar|R2],C,M) :-
2312 M = [NewVar = X|M2],
2314 make_matchings_explicit_not_negated(R,R2,C2,M2).
2317 add_guard_to_head([],G,[]).
2318 add_guard_to_head([H|RH],G,[GH|RGH]) :-
2320 find_guard_info_for_var(H,G,GH)
2324 add_guard_to_head(HArgs,G,NewHArgs),
2327 add_guard_to_head(RH,G,RGH).
2329 find_guard_info_for_var(H,(G1,G2),GH) :- !,
2330 find_guard_info_for_var(H,G1,GH1),
2331 find_guard_info_for_var(GH1,G2,GH).
2333 find_guard_info_for_var(H,G,GH) :-
2334 (G = (H1 = A), H == H1 ->
2337 (G = functor(H2,HF,HA), H == H2, ground(HF), ground(HA) ->
2345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2346 % ALWAYS FAILING HEADS
2347 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2349 rule(RuleNb,Rule) \ prev_guard_list(RuleNb,0,H,G,GuardList,M,[]) <=>
2350 chr_pp_flag(check_impossible_rules,on),
2351 Rule = pragma(rule(Head1,Head2,G,B),Ids,Pragmas,Name,RuleNb),
2352 append(M,GuardList,Info),
2353 guard_entailment:entails_guard(Info,fail) |
2354 chr_warning(weird_program,'Heads will never match in ~@.\n\tThis rule will never fire!\n',[format_rule(Rule)]),
2355 set_all_passive(RuleNb).
2357 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2358 % HEAD SIMPLIFICATION
2359 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2361 % now we check the head matchings (guard may have been simplified meanwhile)
2362 prev_guard_list(RuleNb,0,H,G,GuardList,M,[]) \ rule(RuleNb,Rule) <=>
2363 Rule = pragma(rule(Head1,Head2,G,B),Ids,Pragmas,Name,RuleNb),
2364 simplify_heads(M,GuardList,G,B,NewM,NewB),
2366 extract_variables(Head1,VH1),
2367 extract_variables(Head2,VH2),
2368 extract_variables(H,VH),
2369 replace_some_heads(VH1,VH2,VH,NewM,H1,H2,G,B,NewB_),
2370 insert_variables(H1,Head1,NewH1),
2371 insert_variables(H2,Head2,NewH2),
2372 append(NewB,NewB_,NewBody),
2373 list2conj(NewBody,BodyMatchings),
2374 NewRule = pragma(rule(NewH1,NewH2,G,(BodyMatchings,B)),Ids,Pragmas,Name,RuleNb),
2375 (Head1 \== NewH1 ; Head2 \== NewH2 )
2377 % ( prolog_flag(verbose,V), V == yes ->
2378 % format(' * Head simplification in ~@\n',[format_rule(Rule)]),
2379 % format(' was: ~w \\ ~w \n',[Head2,Head1]),
2380 % format(' now: ~w \\ ~w \n',[NewH2,NewH1]),
2381 % format(' extra body: ~w \n',[BodyMatchings])
2385 rule(RuleNb,NewRule).
2389 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2390 % AUXILIARY PREDICATES (HEAD SIMPLIFICATION)
2391 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2393 replace_some_heads(H1,H2,NH,[],H1,H2,G,Body,[]) :- !.
2394 replace_some_heads([],[H2|RH2],[NH|RNH],[M|RM],[],[H2_|RH2_],G,Body,NewB) :- !,
2397 replace_some_heads([],RH2,RNH,RM,[],RH2_,G,Body,NewB)
2399 (M = functor(X,F,A), NH == X ->
2405 H2 =.. [F|OrigArgs],
2406 use_same_args(OrigArgs,A_args,A_args_,G,Body,NewB1),
2409 replace_some_heads([],RH2,RNH,RM,[],RH2_,G,Body,NewB2),
2410 append(NewB1,NewB2,NewB)
2413 replace_some_heads([],RH2,RNH,[M|RM],[],RH2_,G,Body,NewB)
2417 replace_some_heads([H1|RH1],H2,[NH|RNH],[M|RM],[H1_|RH1_],H2_,G,Body,NewB) :- !,
2420 replace_some_heads(RH1,H2,RNH,RM,RH1_,H2_,G,Body,NewB)
2422 (M = functor(X,F,A), NH == X ->
2428 H1 =.. [F|OrigArgs],
2429 use_same_args(OrigArgs,A_args,A_args_,G,Body,NewB1),
2432 replace_some_heads(RH1,H2,RNH,RM,RH1_,H2_,G,Body,NewB2),
2433 append(NewB1,NewB2,NewB)
2436 replace_some_heads(RH1,H2,RNH,[M|RM],RH1_,H2_,G,Body,NewB)
2440 use_same_args([],[],[],_,_,[]).
2441 use_same_args([OA|ROA],[NA|RNA],[Out|ROut],G,Body,NewB) :-
2444 use_same_args(ROA,RNA,ROut,G,Body,NewB).
2445 use_same_args([OA|ROA],[NA|RNA],[Out|ROut],G,Body,NewB) :-
2447 ( vars_occur_in(OA,Body) ->
2448 NewB = [NA = OA|NextB]
2453 use_same_args(ROA,RNA,ROut,G,Body,NextB).
2456 simplify_heads([],_GuardList,_G,_Body,[],[]).
2457 simplify_heads([M|RM],GuardList,G,Body,NewM,NewB) :-
2459 ( (nonvar(B) ; vars_occur_in(B,RM-GuardList)),
2460 guard_entailment:entails_guard(GuardList,(A=B)) ->
2461 ( vars_occur_in(B,G-RM-GuardList) ->
2465 ( vars_occur_in(B,Body) ->
2466 NewB = [A = B|NextB]
2473 ( nonvar(B), functor(B,BFu,BAr),
2474 guard_entailment:entails_guard([functor(A,BFu,BAr)|GuardList],(A=B)) ->
2476 ( vars_occur_in(B,G-RM-GuardList) ->
2479 NewM = [functor(A,BFu,BAr)|NextM]
2486 simplify_heads(RM,[M|GuardList],G,Body,NextM,NextB).
2488 vars_occur_in(B,G) :-
2489 term_variables(B,BVars),
2490 term_variables(G,GVars),
2491 intersect_eq(BVars,GVars,L),
2495 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2496 % ALWAYS FAILING GUARDS
2497 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2499 set_all_passive(RuleNb), occurrence(_,_,RuleNb,ID) ==> passive(RuleNb,ID).
2500 set_all_passive(_) <=> true.
2502 prev_guard_list(RuleNb,0,H,G,GuardList,M,[]),rule(RuleNb,Rule) ==>
2503 chr_pp_flag(check_impossible_rules,on),
2504 Rule = pragma(rule(_,_,G,_),_Ids,_Pragmas,_Name,RuleNb),
2506 guard_entailment:entails_guard(GL,fail) |
2507 chr_warning(weird_program,'Guard will always fail in ~@.\n\tThis rule will never fire!\n',[format_rule(Rule)]),
2508 set_all_passive(RuleNb).
2512 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2513 % OCCURRENCE SUBSUMPTION
2514 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2517 first_occ_in_rule/4,
2519 multiple_occ_constraints_checked/1.
2521 :- chr_option(mode,first_occ_in_rule(+,+,+,+)).
2522 :- chr_option(mode,next_occ_in_rule(+,+,+,+,+,+)).
2523 :- chr_option(mode,multiple_occ_constraints_checked(+)).
2527 prev_guard_list(RuleNb,0,H,G,GuardList,M,[]),
2528 occurrence(C,O,RuleNb,ID), occurrence(C,O2,RuleNb,ID2), rule(RuleNb,Rule)
2529 \ multiple_occ_constraints_checked(Done) <=>
2531 chr_pp_flag(occurrence_subsumption,on),
2532 Rule = pragma(rule(H1,H2,_G,_B),_Ids,_Pragmas,_Name,RuleNb),
2534 \+ memberchk_eq(C,Done) |
2535 first_occ_in_rule(RuleNb,C,O,ID),
2536 multiple_occ_constraints_checked([C|Done]).
2539 occurrence(C,O,RuleNb,ID) \ first_occ_in_rule(RuleNb,C,O2,_) <=> O < O2 |
2540 first_occ_in_rule(RuleNb,C,O,ID).
2542 first_occ_in_rule(RuleNb,C,O,ID_o1) <=>
2544 functor(FreshHead,F,A),
2545 next_occ_in_rule(RuleNb,C,O,ID_o1,[],FreshHead).
2547 passive(RuleNb,ID_o2), occurrence(C,O2,RuleNb,ID_o2)
2548 \ next_occ_in_rule(RuleNb,C,O,ID_o1,Cond,FH) <=> O2 is O+1 |
2549 next_occ_in_rule(RuleNb,C,O2,ID_o1,NewCond,FH).
2552 prev_guard_list(RuleNb,0,H,G,GuardList,M,[]),
2553 occurrence(C,O2,RuleNb,ID_o2), rule(RuleNb,Rule) \
2554 next_occ_in_rule(RuleNb,C,O,ID_o1,Cond,FH) <=>
2556 Rule = pragma(rule(H1,H2,G,B),ids(ID1,ID2),_Pragmas,_Name,RuleNb)
2558 append(H1,H2,Heads),
2559 add_failing_occ(Rule,Heads,H,ID_o1,ExtraCond,FH,M,C,Repl),
2560 ( ExtraCond == [chr_pp_void_info] ->
2561 next_occ_in_rule(RuleNb,C,O2,ID_o2,Cond,FH)
2563 append(ExtraCond,Cond,NewCond),
2564 add_failing_occ(Rule,Heads,H,ID_o2,CheckCond,FH,M,C,Repl2),
2565 copy_term(GuardList,FGuardList),
2566 variable_replacement(GuardList,FGuardList,GLRepl),
2567 copy_with_variable_replacement(GuardList,GuardList2,Repl),
2568 copy_with_variable_replacement(GuardList,GuardList3_,Repl2),
2569 copy_with_variable_replacement(GuardList3_,GuardList3,GLRepl),
2570 append(NewCond,GuardList2,BigCond),
2571 append(BigCond,GuardList3,BigCond2),
2572 copy_with_variable_replacement(M,M2,Repl),
2573 copy_with_variable_replacement(M,M3,Repl2),
2574 append(M3,BigCond2,BigCond3),
2575 append([chr_pp_active_constraint(FH)|M2],BigCond3,Info),
2576 list2conj(CheckCond,OccSubsum),
2577 copy_term((NewCond,BigCond2,Info,OccSubsum,FH),(NewCond2,BigCond2_,Info2,OccSubsum2,FH2)),
2578 term_variables(NewCond2-FH2,InfoVars),
2579 flatten_stuff(Info2,Info3),
2580 flatten_stuff(OccSubsum2,OccSubsum3),
2581 ( OccSubsum \= chr_pp_void_info,
2582 unify_stuff(InfoVars,Info3,OccSubsum3), !,
2583 ( guard_entailment:entails_guard(Info2,OccSubsum2) ->
2584 % ( prolog_flag(verbose,V), V == yes ->
2585 % format(' * Occurrence subsumption detected in ~@\n',[format_rule(Rule)]),
2586 % format(' passive: constraint ~w, occurrence number ~w (id ~w)\n',[C,O2,ID_o2]),
2590 passive(RuleNb,ID_o2)
2596 next_occ_in_rule(RuleNb,C,O2,ID_o2,NewCond,FH)
2600 next_occ_in_rule(RuleNb,C,O,ID,Cond,Args) <=> true.
2601 prev_guard_list(RuleNb,0,H,G,GuardList,M,[]),
2602 multiple_occ_constraints_checked(Done) <=> true.
2604 flatten_stuff([A|B],C) :- !,
2605 flatten_stuff(A,C1),
2606 flatten_stuff(B,C2),
2608 flatten_stuff((A;B),C) :- !,
2609 flatten_stuff(A,C1),
2610 flatten_stuff(B,C2),
2612 flatten_stuff((A,B),C) :- !,
2613 flatten_stuff(A,C1),
2614 flatten_stuff(B,C2),
2617 flatten_stuff(chr_pp_not_in_store(A),[A]) :- !.
2618 flatten_stuff(X,[]).
2620 unify_stuff(AllInfo,[],[]).
2622 unify_stuff(AllInfo,[H|RInfo],[I|ROS]) :-
2624 term_variables(H,HVars),
2625 term_variables(I,IVars),
2626 intersect_eq(HVars,IVars,SharedVars),
2627 check_safe_unif(H,I,SharedVars),
2628 variable_replacement(H,I,Repl),
2629 check_replacement(Repl),
2630 term_variables(Repl,ReplVars),
2631 list_difference_eq(ReplVars,HVars,LDiff),
2632 intersect_eq(AllInfo,LDiff,LDiff2),
2635 unify_stuff(AllInfo,RInfo,ROS),!.
2637 unify_stuff(AllInfo,X,[Y|ROS]) :-
2638 unify_stuff(AllInfo,X,ROS).
2640 unify_stuff(AllInfo,[Y|RInfo],X) :-
2641 unify_stuff(AllInfo,RInfo,X).
2643 check_safe_unif(H,I,SV) :- var(H), !, var(I),
2644 ( (memberchk_eq(H,SV);memberchk_eq(I,SV)) ->
2650 check_safe_unif([],[],SV) :- !.
2651 check_safe_unif([H|Hs],[I|Is],SV) :- !,
2652 check_safe_unif(H,I,SV),!,
2653 check_safe_unif(Hs,Is,SV).
2655 check_safe_unif(H,I,SV) :-
2656 nonvar(H),!,nonvar(I),
2659 check_safe_unif(HA,IA,SV).
2661 check_safe_unif2(H,I) :- var(H), !.
2663 check_safe_unif2([],[]) :- !.
2664 check_safe_unif2([H|Hs],[I|Is]) :- !,
2665 check_safe_unif2(H,I),!,
2666 check_safe_unif2(Hs,Is).
2668 check_safe_unif2(H,I) :-
2669 nonvar(H),!,nonvar(I),
2672 check_safe_unif2(HA,IA).
2675 check_replacement(Repl) :-
2676 check_replacement(Repl,FirstVars),
2677 sort(FirstVars,Sorted),
2679 length(FirstVars,L).
2681 check_replacement([],[]).
2682 check_replacement([A-B|R],[A|RC]) :- check_replacement(R,RC).
2685 add_failing_occ(Rule,Heads,NH,ID_o1,FailCond,FH,M,C,Repl) :-
2686 Rule = pragma(rule(H1,H2,G,B),ids(ID1,ID2),_Pragmas,_Name,RuleNb),
2687 append(ID2,ID1,IDs),
2688 missing_partner_cond(Heads,NH,IDs,ID_o1,MPCond,H,C),
2689 copy_term((H,Heads,NH),(FH2,FHeads,NH2)),
2690 variable_replacement((H,Heads,NH),(FH2,FHeads,NH2),Repl),
2691 copy_with_variable_replacement(G,FG,Repl),
2692 extract_explicit_matchings(FG,FG2),
2693 negate_b(FG2,NotFG),
2694 copy_with_variable_replacement(MPCond,FMPCond,Repl),
2695 ( check_safe_unif2(FH,FH2), FH=FH2 ->
2696 FailCond = [(NotFG;FMPCond)]
2698 % in this case, not much can be done
2699 % e.g. c(f(...)), c(g(...)) <=> ...
2700 FailCond = [chr_pp_void_info]
2705 missing_partner_cond([],[],[],ID_o1,fail,H2,C).
2706 missing_partner_cond([H|Hs],[H2|H2s],[ID_o1|IDs],ID_o1,Cond,H,C) :- !,
2707 missing_partner_cond(Hs,H2s,IDs,ID_o1,Cond,H,C).
2708 missing_partner_cond([H|Hs],[NH|NHs],[ID|IDs],ID_o1,Cond,H2,F/A) :-
2709 Cond = (chr_pp_not_in_store(H);Cond1),
2710 missing_partner_cond(Hs,NHs,IDs,ID_o1,Cond1,H2,F/A).
2713 extract_explicit_matchings(A=B) :-
2714 var(A), var(B), !, A=B.
2715 extract_explicit_matchings(A==B) :-
2716 var(A), var(B), !, A=B.
2718 extract_explicit_matchings((A,B),D) :- !,
2719 ( extract_explicit_matchings(A) ->
2720 extract_explicit_matchings(B,D)
2723 extract_explicit_matchings(B,E)
2725 extract_explicit_matchings(A,D) :- !,
2726 ( extract_explicit_matchings(A) ->
2735 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2737 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2742 get_type_definition/2,
2743 get_constraint_type/2,
2744 add_type_information/3.
2747 :- chr_option(mode,type_definition(?,?)).
2748 :- chr_option(mode,constraint_type(+,+)).
2749 :- chr_option(mode,add_type_information(+,+,?)).
2750 :- chr_option(type_declaration,add_type_information(list,list,any)).
2752 type_definition(T,D) \ get_type_definition(T2,Def) <=>
2753 nonvar(T),nonvar(T2),functor(T,F,A),functor(T2,F,A) |
2754 copy_term((T,D),(T1,D1)),T1=T2,Def = D1.
2755 get_type_definition(_,_) <=> fail.
2756 constraint_type(C,T) \ get_constraint_type(C,Type) <=> Type = T.
2757 get_constraint_type(_,_) <=> fail.
2759 add_type_information([],[],T) <=> T=true.
2761 constraint_mode(F/A,Modes)
2762 \ add_type_information([Head|R],[RealHead|RRH],TypeInfo) <=>
2765 RealHead =.. [_|RealArgs],
2766 add_mode_info(Modes,Args,ModeInfo),
2767 TypeInfo = (ModeInfo, TI),
2768 (get_constraint_type(F/A,Types) ->
2769 types2condition(Types,Args,RealArgs,Modes,TI2),
2770 list2conj(TI2,ConjTI),
2772 add_type_information(R,RRH,RTI)
2774 add_type_information(R,RRH,TI)
2778 add_type_information([Head|R],_,TypeInfo) <=>
2780 chr_error(internal,'Mode information missing for ~w.\n',[F/A]).
2783 add_mode_info([],[],true).
2784 add_mode_info([(+)|Modes],[A|Args],MI) :- !,
2785 MI = (ground(A), ModeInfo),
2786 add_mode_info(Modes,Args,ModeInfo).
2787 add_mode_info([M|Modes],[A|Args],MI) :-
2788 add_mode_info(Modes,Args,MI).
2791 types2condition([],[],[],[],[]).
2792 types2condition([Type|Types],[Arg|Args],[RealArg|RAs],[Mode|Modes],TI) :-
2793 (get_type_definition(Type,Def) ->
2794 type2condition(Def,Arg,RealArg,TC),
2796 TC_ = [(\+ ground(Arg))|TC]
2800 list2disj(TC_,DisjTC),
2802 types2condition(Types,Args,RAs,Modes,RTI)
2804 ( builtin_type(Type,Arg,C) ->
2806 types2condition(Types,Args,RAs,Modes,RTI)
2808 chr_error(internal,'Undefined type ~w.\n',[Type])
2812 type2condition([],Arg,_,[]).
2813 type2condition([Def|Defs],Arg,RealArg,TC) :-
2814 ( builtin_type(Def,Arg,C) ->
2817 real_type(Def,Arg,RealArg,C)
2820 type2condition(Defs,Arg,RealArg,RTC),
2823 item2list([],[]) :- !.
2824 item2list([X|Y],[X|Y]) :- !.
2825 item2list(N,L) :- L = [N].
2827 builtin_type(X,Arg,true) :- var(X),!.
2828 builtin_type(any,Arg,true).
2829 builtin_type(int,Arg,integer(Arg)).
2830 builtin_type(number,Arg,number(Arg)).
2831 builtin_type(float,Arg,float(Arg)).
2832 builtin_type(natural,Arg,(integer(Arg),Arg>=0)).
2834 real_type(Def,Arg,RealArg,C) :-
2844 C = functor(Arg,F,A)
2846 ( functor(RealArg,F,A) ->
2847 RealArg =.. [_|RAArgs],
2848 nested_types(TArgs,AA,RAArgs,ACond),
2849 C = (functor(Arg,F,A),Arg=Def2,ACond)
2851 C = functor(Arg,F,A)
2856 chr_error(internal,'Illegal type definition (must be nonvar).\n',[])
2858 nested_types([],[],[],true).
2859 nested_types([T|RT],[A|RA],[RealA|RRA],C) :-
2860 (get_type_definition(T,Def) ->
2861 type2condition(Def,A,RealA,TC),
2862 list2disj(TC,DisjTC),
2864 nested_types(RT,RA,RRA,RC)
2866 ( builtin_type(T,A,Cond) ->
2868 nested_types(RT,RA,RRA,RC)
2870 chr_error(internal,'Undefined type ~w inside type definition.\n',[T])
2875 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2878 stored/3, % constraint,occurrence,(yes/no/maybe)
2879 stored_completing/3,
2882 is_finally_stored/1,
2883 check_all_passive/2.
2885 :- chr_option(mode,stored(+,+,+)).
2886 :- chr_option(type_declaration,stored(any,int,storedinfo)).
2887 :- chr_option(type_definition,type(storedinfo,[yes,no,maybe])).
2888 :- chr_option(mode,stored_complete(+,+,+)).
2889 :- chr_option(mode,maybe_complementary_guards(+,+,?,?)).
2890 :- chr_option(mode,guard_list(+,+,+,+)).
2891 :- chr_option(mode,check_all_passive(+,+)).
2893 % change yes in maybe when yes becomes passive
2894 passive(RuleNb,ID), occurrence(C,O,RuleNb,ID) \
2895 stored(C,O,yes), stored_complete(C,RO,Yesses)
2896 <=> O < RO | NYesses is Yesses - 1,
2897 stored(C,O,maybe), stored_complete(C,RO,NYesses).
2898 % change yes in maybe when not observed
2899 ai_not_observed(C,O) \ stored(C,O,yes), stored_complete(C,RO,Yesses)
2901 NYesses is Yesses - 1,
2902 stored(C,O,maybe), stored_complete(C,RO,NYesses).
2904 occurrence(_,_,RuleNb,ID), occurrence(C2,_,RuleNb,_), stored_complete(C2,RO,0), max_occurrence(C2,MO2)
2905 ==> RO =< MO2 | % C2 is never stored
2911 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2913 rule(RuleNb,Rule),passive(RuleNb,Id) ==>
2914 Rule = pragma(rule(Head1,Head2,G,B),ids([Id|IDs1],IDs2),Pragmas,Name,RuleNb) |
2915 append(IDs1,IDs2,I), check_all_passive(RuleNb,I).
2917 rule(RuleNb,Rule),passive(RuleNb,Id) ==>
2918 Rule = pragma(rule(Head1,Head2,G,B),ids([],[Id|IDs2]),Pragmas,Name,RuleNb) |
2919 check_all_passive(RuleNb,IDs2).
2921 passive(RuleNb,Id) \ check_all_passive(RuleNb,[Id|IDs]) <=>
2922 check_all_passive(RuleNb,IDs).
2924 rule(RuleNb,Rule) \ check_all_passive(RuleNb,[]) <=>
2925 chr_warning(weird_program,'All heads passive in ~@.\n\tThis rule never fires. Please check your program.\n',[format_rule(Rule)]).
2927 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2929 % collect the storage information
2930 stored(C,O,yes) \ stored_completing(C,O,Yesses)
2931 <=> NO is O + 1, NYesses is Yesses + 1,
2932 stored_completing(C,NO,NYesses).
2933 stored(C,O,maybe) \ stored_completing(C,O,Yesses)
2935 stored_completing(C,NO,Yesses).
2937 stored(C,O,no) \ stored_completing(C,O,Yesses)
2938 <=> stored_complete(C,O,Yesses).
2939 stored_completing(C,O,Yesses)
2940 <=> stored_complete(C,O,Yesses).
2942 stored_complete(C,O,Yesses), occurrence(C,O2,RuleNb,Id) ==>
2943 O2 > O | passive(RuleNb,Id).
2945 % decide whether a constraint is stored
2946 max_occurrence(C,MO), stored_complete(C,RO,0) \ is_stored(C)
2947 <=> RO =< MO | fail.
2948 is_stored(C) <=> true.
2950 % decide whether a constraint is suspends after occurrences
2951 max_occurrence(C,MO), stored_complete(C,RO,_) \ is_finally_stored(C)
2952 <=> RO =< MO | fail.
2953 is_finally_stored(C) <=> true.
2955 storage_analysis(Constraints) :-
2956 ( chr_pp_flag(storage_analysis,on) ->
2957 check_constraint_storages(Constraints)
2962 check_constraint_storages([]).
2963 check_constraint_storages([C|Cs]) :-
2964 check_constraint_storage(C),
2965 check_constraint_storages(Cs).
2967 check_constraint_storage(C) :-
2968 get_max_occurrence(C,MO),
2969 check_occurrences_storage(C,1,MO).
2971 check_occurrences_storage(C,O,MO) :-
2973 stored_completing(C,1,0)
2975 check_occurrence_storage(C,O),
2977 check_occurrences_storage(C,NO,MO)
2980 check_occurrence_storage(C,O) :-
2981 get_occurrence(C,O,RuleNb,ID),
2982 ( is_passive(RuleNb,ID) ->
2985 get_rule(RuleNb,PragmaRule),
2986 PragmaRule = pragma(rule(Heads1,Heads2,Guard,Body),ids(IDs1,IDs2),_,_,_),
2987 ( select2(ID,Head1,IDs1,Heads1,RIDs1,RHeads1) ->
2988 check_storage_head1(Head1,O,Heads1,Heads2,Guard)
2989 ; select2(ID,Head2,IDs2,Heads2,RIDs2,RHeads2) ->
2990 check_storage_head2(Head2,O,Heads1,Body)
2994 check_storage_head1(Head,O,H1,H2,G) :-
2999 guard_entailment:entails_guard([chr_pp_headvariables(Head)],G),
3001 no_matching(L,[]) ->
3008 no_matching([X|Xs],Prev) :-
3010 \+ memberchk_eq(X,Prev),
3011 no_matching(Xs,[X|Prev]).
3013 check_storage_head2(Head,O,H1,B) :-
3016 ( ( (H1 \== [], B == true ) ;
3017 \+ is_observed(F/A,O) ) ->
3023 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3025 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3026 %% ____ _ ____ _ _ _ _
3027 %% | _ \ _ _| | ___ / ___|___ _ __ ___ _ __ (_) | __ _| |_(_) ___ _ __
3028 %% | |_) | | | | |/ _ \ | | / _ \| '_ ` _ \| '_ \| | |/ _` | __| |/ _ \| '_ \
3029 %% | _ <| |_| | | __/ | |__| (_) | | | | | | |_) | | | (_| | |_| | (_) | | | |
3030 %% |_| \_\\__,_|_|\___| \____\___/|_| |_| |_| .__/|_|_|\__,_|\__|_|\___/|_| |_|
3033 constraints_code(Constraints,Clauses) :-
3034 (chr_pp_flag(reduced_indexing,on),
3035 \+ forsome(C,Constraints,\+ chr_translate:only_ground_indexed_arguments(C)) ->
3036 none_suspended_on_variables
3040 constraints_code1(Constraints,L,[]),
3041 clean_clauses(L,Clauses).
3043 %===============================================================================
3044 :- chr_constraint constraints_code1/3.
3045 :- chr_option(mode,constraints_code1(+,+,+)).
3046 %-------------------------------------------------------------------------------
3047 constraints_code1([],L,T) <=> L = T.
3048 constraints_code1([C|RCs],L,T)
3050 constraint_code(C,L,T1),
3051 constraints_code1(RCs,T1,T).
3052 %===============================================================================
3053 :- chr_constraint constraint_code/3.
3054 :- chr_option(mode,constraint_code(+,+,+)).
3055 %-------------------------------------------------------------------------------
3056 %% Generate code for a single CHR constraint
3057 constraint_code(Constraint, L, T)
3059 | ( (chr_pp_flag(debugable,on) ;
3060 is_stored(Constraint), ( has_active_occurrence(Constraint); chr_pp_flag(late_allocation,off)),
3061 ( may_trigger(Constraint) ;
3062 get_allocation_occurrence(Constraint,AO),
3063 get_max_occurrence(Constraint,MO), MO >= AO ) )
3065 constraint_prelude(Constraint,Clause),
3071 occurrences_code(Constraint,1,Id,NId,L1,L2),
3072 gen_cond_attach_clause(Constraint,NId,L2,T).
3074 %===============================================================================
3075 %% Generate prelude predicate for a constraint.
3076 %% f(...) :- f/a_0(...,Susp).
3077 constraint_prelude(F/A, Clause) :-
3078 vars_susp(A,Vars,Susp,VarsSusp),
3079 Head =.. [ F | Vars],
3080 make_suspension_continuation_goal(F/A,VarsSusp,Continuation),
3081 build_head(F,A,[0],VarsSusp,Delegate),
3083 ( chr_pp_flag(debugable,on) ->
3084 use_auxiliary_predicate(insert_constraint_internal),
3085 generate_insert_constraint_call(F/A,Susp,InsertCall),
3086 make_name('attach_',F/A,AttachF),
3087 AttachCall =.. [AttachF,Vars2,Susp],
3088 Inactive = (arg(2,Susp,Mutable), 'chr update_mutable'(inactive,Mutable)),
3091 insert_constraint_internal(Stored,Vars2,Susp,Continuation,FTerm,Vars),
3096 'chr debug_event'(call(Susp)),
3099 'chr debug_event'(fail(Susp)), !,
3103 'chr debug_event'(exit(Susp))
3105 'chr debug_event'(redo(Susp)),
3109 ; get_allocation_occurrence(F/A,0) ->
3110 gen_insert_constraint_internal_goal(F/A,Goal,VarsSusp,Vars,Susp),
3111 Inactive = (arg(2,Susp,Mutable), 'chr update_mutable'(inactive,Mutable)),
3112 Clause = ( Head :- Goal, Inactive, Delegate )
3114 Clause = ( Head :- Delegate )
3117 make_suspension_continuation_goal(F/A,VarsSusp,Goal) :-
3118 ( may_trigger(F/A) ->
3119 get_target_module(Mod),
3120 build_head(F,A,[0],VarsSusp,Delegate),
3126 %===============================================================================
3127 :- chr_constraint has_active_occurrence/1, has_active_occurrence/2.
3128 %-------------------------------------------------------------------------------
3129 has_active_occurrence(C) <=> has_active_occurrence(C,1).
3131 max_occurrence(C,MO) \ has_active_occurrence(C,O) <=>
3133 passive(RuleNb,ID),occurrence(C,O,RuleNb,ID) \
3134 has_active_occurrence(C,O) <=>
3136 has_active_occurrence(C,NO).
3137 has_active_occurrence(C,O) <=> true.
3138 %===============================================================================
3140 gen_cond_attach_clause(F/A,Id,L,T) :-
3141 ( is_finally_stored(F/A) ->
3142 get_allocation_occurrence(F/A,AllocationOccurrence),
3143 get_max_occurrence(F/A,MaxOccurrence),
3144 ( chr_pp_flag(debugable,off), MaxOccurrence < AllocationOccurrence ->
3145 ( only_ground_indexed_arguments(F/A) ->
3146 gen_insert_constraint_internal_goal(F/A,Body,AllArgs,Args,Susp)
3148 gen_cond_attach_goal(F/A,Body,AllArgs,Args,Susp)
3150 ; vars_susp(A,Args,Susp,AllArgs),
3151 gen_uncond_attach_goal(F/A,Susp,Body,_)
3153 ( chr_pp_flag(debugable,on) ->
3154 Constraint =.. [F|Args],
3155 DebugEvent = 'chr debug_event'(insert(Constraint#Susp))
3159 build_head(F,A,Id,AllArgs,Head),
3160 Clause = ( Head :- DebugEvent,Body ),
3167 use_auxiliary_predicate/1,
3168 is_used_auxiliary_predicate/1.
3170 :- chr_option(mode,use_auxiliary_predicate(+)).
3172 use_auxiliary_predicate(P) \ use_auxiliary_predicate(P) <=> true.
3174 use_auxiliary_predicate(P) \ is_used_auxiliary_predicate(P) <=> true.
3176 is_used_auxiliary_predicate(P) <=> fail.
3178 % only called for constraints with
3180 % non-ground indexed argument
3181 gen_cond_attach_goal(F/A,Goal,AllArgs,Args,Susp) :-
3182 vars_susp(A,Args,Susp,AllArgs),
3183 make_suspension_continuation_goal(F/A,AllArgs,Closure),
3184 make_name('attach_',F/A,AttachF),
3185 Attach =.. [AttachF,Vars,Susp],
3187 generate_insert_constraint_call(F/A,Susp,InsertCall),
3188 use_auxiliary_predicate(insert_constraint_internal),
3189 use_auxiliary_predicate(activate_constraint),
3190 ( may_trigger(F/A) ->
3194 insert_constraint_internal(Stored,Vars,Susp,Closure,FTerm,Args)
3196 activate_constraint(Stored,Vars,Susp,_)
3208 insert_constraint_internal(Stored,Vars,Susp,Closure,FTerm,Args),
3214 gen_insert_constraint_internal_goal(F/A,Goal,AllArgs,Args,Susp) :-
3215 vars_susp(A,Args,Susp,AllArgs),
3216 make_suspension_continuation_goal(F/A,AllArgs,Cont),
3217 ( \+ only_ground_indexed_arguments(F/A) ->
3218 make_name('attach_',F/A,AttachF),
3219 Attach =.. [AttachF,Vars,Susp]
3224 generate_insert_constraint_call(F/A,Susp,InsertCall),
3225 use_auxiliary_predicate(insert_constraint_internal),
3226 ( are_none_suspended_on_variables ->
3229 insert_constraint_internal(Susp,FTerm,Args),
3235 insert_constraint_internal(_,Vars,Susp,Cont,FTerm,Args),
3241 gen_uncond_attach_goal(FA,Susp,AttachGoal,Generation) :-
3242 ( \+ only_ground_indexed_arguments(FA) ->
3243 make_name('attach_',FA,AttachF),
3244 Attach =.. [AttachF,Vars,Susp]
3248 generate_insert_constraint_call(FA,Susp,InsertCall),
3249 ( chr_pp_flag(late_allocation,on) ->
3250 use_auxiliary_predicate(activate_constraint),
3253 activate_constraint(Stored,Vars, Susp, Generation),
3262 use_auxiliary_predicate(activate_constraint),
3265 activate_constraint(Stored,Vars, Susp, Generation)
3269 %-------------------------------------------------------------------------------
3270 :- chr_constraint occurrences_code/6.
3271 :- chr_option(mode,occurrences_code(+,+,+,+,+,+)).
3272 %-------------------------------------------------------------------------------
3273 max_occurrence(C,MO) \ occurrences_code(C,O,Id,NId,L,T)
3276 occurrences_code(C,O,Id,NId,L,T)
3278 occurrence_code(C,O,Id,Id1,L,L1),
3280 occurrences_code(C,NO,Id1,NId,L1,T).
3281 %-------------------------------------------------------------------------------
3282 :- chr_constraint occurrence_code/6.
3283 :- chr_option(mode,occurrence_code(+,+,+,+,+,+)).
3284 %-------------------------------------------------------------------------------
3285 occurrence(C,O,RuleNb,ID), passive(RuleNb,ID) \ occurrence_code(C,O,Id,NId,L,T)
3286 <=> NId = Id, L = T.
3287 occurrence(C,O,RuleNb,ID), rule(RuleNb,PragmaRule) \ occurrence_code(C,O,Id,NId,L,T)
3289 PragmaRule = pragma(rule(Heads1,Heads2,_,_),ids(IDs1,IDs2),_,_,_),
3290 ( select2(ID,Head1,IDs1,Heads1,RIDs1,RHeads1) ->
3292 head1_code(Head1,RHeads1,RIDs1,PragmaRule,C,O,Id,L,T)
3293 ; select2(ID,Head2,IDs2,Heads2,RIDs2,RHeads2) ->
3294 head2_code(Head2,RHeads2,RIDs2,PragmaRule,C,O,Id,L,L1),
3296 ( unconditional_occurrence(C,O) ->
3299 gen_alloc_inc_clause(C,O,Id,L1,T)
3303 occurrence_code(C,O,_,_,_,_)
3305 chr_error(internal,'occurrence_code/6: missing information to compile ~w:~w\n',[C,O]).
3306 %-------------------------------------------------------------------------------
3308 %% Generate code based on one removed head of a CHR rule
3309 head1_code(Head,OtherHeads,OtherIDs,PragmaRule,FA,O,Id,L,T) :-
3310 PragmaRule = pragma(Rule,_,_,_Name,RuleNb),
3311 Rule = rule(_,Head2,_,_),
3313 reorder_heads(RuleNb,Head,OtherHeads,OtherIDs,NOtherHeads,NOtherIDs),
3314 simplification_code(Head,NOtherHeads,NOtherIDs,PragmaRule,FA,O,Id,L,T)
3316 simpagation_head1_code(Head,OtherHeads,OtherIDs,PragmaRule,FA,Id,L,T)
3319 %% Generate code based on one persistent head of a CHR rule
3320 head2_code(Head,OtherHeads,OtherIDs,PragmaRule,FA,O,Id,L,T) :-
3321 PragmaRule = pragma(Rule,_,_,_Name,RuleNb),
3322 Rule = rule(Head1,_,_,_),
3324 reorder_heads(RuleNb,Head,OtherHeads,OtherIDs,NOtherHeads,NOtherIDs),
3325 propagation_code(Head,NOtherHeads,NOtherIDs,Rule,RuleNb,FA,O,Id,L,T)
3327 simpagation_head2_code(Head,OtherHeads,OtherIDs,PragmaRule,FA,O,Id,L,T)
3330 gen_alloc_inc_clause(F/A,O,Id,L,T) :-
3331 vars_susp(A,Vars,Susp,VarsSusp),
3332 build_head(F,A,Id,VarsSusp,Head),
3334 build_head(F,A,IncId,VarsSusp,CallHead),
3335 gen_occ_allocation(F/A,O,Vars,Susp,VarsSusp,ConditionalAlloc),
3344 gen_cond_allocation(Vars,Susp,FA,VarsSusp,ConstraintAllocationGoal) :-
3345 gen_allocation(Vars,Susp,FA,VarsSusp,UncondConstraintAllocationGoal),
3346 ConstraintAllocationGoal =
3348 UncondConstraintAllocationGoal
3352 gen_allocation(Vars,Susp,F/A,VarsSusp,ConstraintAllocationGoal) :-
3353 ( may_trigger(F/A) ->
3354 build_head(F,A,[0],VarsSusp,Term),
3355 get_target_module(Mod),
3361 use_auxiliary_predicate(allocate_constraint),
3362 ConstraintAllocationGoal = allocate_constraint(Cont, Susp, FTerm, Vars).
3364 gen_occ_allocation(FA,O,Vars,Susp,VarsSusp,ConstraintAllocationGoal) :-
3365 get_allocation_occurrence(FA,AO),
3366 ( chr_pp_flag(debugable,off), O == AO ->
3367 ( may_trigger(FA) ->
3368 gen_cond_allocation(Vars,Susp,FA,VarsSusp,ConstraintAllocationGoal)
3370 gen_allocation(Vars,Susp,FA,VarsSusp,ConstraintAllocationGoal)
3373 ConstraintAllocationGoal = true
3375 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3378 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3380 guard_via_reschedule(Retrievals,GuardList,Prelude,Goal) :-
3381 ( chr_pp_flag(guard_via_reschedule,on) ->
3382 guard_via_reschedule_main(Retrievals,GuardList,Prelude,Goal)
3384 append(Retrievals,GuardList,GoalList),
3385 list2conj(GoalList,Goal)
3388 guard_via_reschedule_main(Retrievals,GuardList,Prelude,Goal) :-
3389 initialize_unit_dictionary(Prelude,Dict),
3390 build_units(Retrievals,GuardList,Dict,Units),
3391 dependency_reorder(Units,NUnits),
3392 units2goal(NUnits,Goal).
3394 units2goal([],true).
3395 units2goal([unit(_,Goal,_,_)|Units],(Goal,Goals)) :-
3396 units2goal(Units,Goals).
3398 dependency_reorder(Units,NUnits) :-
3399 dependency_reorder(Units,[],NUnits).
3401 dependency_reorder([],Acc,Result) :-
3402 reverse(Acc,Result).
3404 dependency_reorder([Unit|Units],Acc,Result) :-
3405 Unit = unit(_GID,_Goal,Type,GIDs),
3409 dependency_insert(Acc,Unit,GIDs,NAcc)
3411 dependency_reorder(Units,NAcc,Result).
3413 dependency_insert([],Unit,_,[Unit]).
3414 dependency_insert([X|Xs],Unit,GIDs,L) :-
3415 X = unit(GID,_,_,_),
3416 ( memberchk(GID,GIDs) ->
3420 dependency_insert(Xs,Unit,GIDs,T)
3423 build_units(Retrievals,Guard,InitialDict,Units) :-
3424 build_retrieval_units(Retrievals,1,N,InitialDict,Dict,Units,Tail),
3425 build_guard_units(Guard,N,Dict,Tail).
3427 build_retrieval_units([],N,N,Dict,Dict,L,L).
3428 build_retrieval_units([U|Us],N,M,Dict,NDict,L,T) :-
3429 term_variables(U,Vs),
3430 update_unit_dictionary(Vs,N,Dict,Dict1,[],GIDs),
3431 L = [unit(N,U,movable,GIDs)|L1],
3433 build_retrieval_units2(Us,N1,M,Dict1,NDict,L1,T).
3435 build_retrieval_units2([],N,N,Dict,Dict,L,L).
3436 build_retrieval_units2([U|Us],N,M,Dict,NDict,L,T) :-
3437 term_variables(U,Vs),
3438 update_unit_dictionary(Vs,N,Dict,Dict1,[],GIDs),
3439 L = [unit(N,U,fixed,GIDs)|L1],
3441 build_retrieval_units(Us,N1,M,Dict1,NDict,L1,T).
3443 initialize_unit_dictionary(Term,Dict) :-
3444 term_variables(Term,Vars),
3445 pair_all_with(Vars,0,Dict).
3447 update_unit_dictionary([],_,Dict,Dict,GIDs,GIDs).
3448 update_unit_dictionary([V|Vs],This,Dict,NDict,GIDs,NGIDs) :-
3449 ( lookup_eq(Dict,V,GID) ->
3450 ( (GID == This ; memberchk(GID,GIDs) ) ->
3457 Dict1 = [V - This|Dict],
3460 update_unit_dictionary(Vs,This,Dict1,NDict,GIDs1,NGIDs).
3462 build_guard_units(Guard,N,Dict,Units) :-
3464 Units = [unit(N,Goal,fixed,[])]
3465 ; Guard = [Goal|Goals] ->
3466 term_variables(Goal,Vs),
3467 update_unit_dictionary2(Vs,N,Dict,NDict,[],GIDs),
3468 Units = [unit(N,Goal,movable,GIDs)|RUnits],
3470 build_guard_units(Goals,N1,NDict,RUnits)
3473 update_unit_dictionary2([],_,Dict,Dict,GIDs,GIDs).
3474 update_unit_dictionary2([V|Vs],This,Dict,NDict,GIDs,NGIDs) :-
3475 ( lookup_eq(Dict,V,GID) ->
3476 ( (GID == This ; memberchk(GID,GIDs) ) ->
3481 Dict1 = [V - This|Dict]
3483 Dict1 = [V - This|Dict],
3486 update_unit_dictionary2(Vs,This,Dict1,NDict,GIDs1,NGIDs).
3488 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3490 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3492 %% / ___| ___| |_ / ___| ___ _ __ ___ __ _ _ __ | |_(_) ___ ___ _
3493 %% \___ \ / _ \ __| \___ \ / _ \ '_ ` _ \ / _` | '_ \| __| |/ __/ __(_)
3494 %% ___) | __/ |_ ___) | __/ | | | | | (_| | | | | |_| | (__\__ \_
3495 %% |____/ \___|\__| |____/ \___|_| |_| |_|\__,_|_| |_|\__|_|\___|___(_)
3498 %% | | | |_ __ (_) __ _ _ _ ___ |_ _|_ __ / _| ___ _ __ ___ _ __ ___ ___
3499 %% | | | | '_ \| |/ _` | | | |/ _ \ | || '_ \| |_ / _ \ '__/ _ \ '_ \ / __/ _ \
3500 %% | |_| | | | | | (_| | |_| | __/ | || | | | _| __/ | | __/ | | | (_| __/
3501 %% \___/|_| |_|_|\__, |\__,_|\___| |___|_| |_|_| \___|_| \___|_| |_|\___\___|
3504 functional_dependency/4,
3505 get_functional_dependency/4.
3507 :- chr_option(mode,functional_dependency(+,+,?,?)).
3509 allocation_occurrence(C,AO), occurrence(C,O,RuleNb,_) \ functional_dependency(C,RuleNb,Pattern,Key)
3513 functional_dependency(C,1,Pattern,Key).
3515 functional_dependency(C,RuleNb1,Pattern,Key) \ get_functional_dependency(C,RuleNb2,QPattern,QKey)
3519 QPattern = Pattern, QKey = Key.
3520 get_functional_dependency(_,_,_,_)
3524 functional_dependency_analysis(Rules) :-
3525 ( chr_pp_flag(functional_dependency_analysis,on) ->
3526 functional_dependency_analysis_main(Rules)
3531 functional_dependency_analysis_main([]).
3532 functional_dependency_analysis_main([PRule|PRules]) :-
3533 ( discover_unique_pattern(PRule,C,RuleNb,Pattern,Key) ->
3534 functional_dependency(C,RuleNb,Pattern,Key)
3538 functional_dependency_analysis_main(PRules).
3540 discover_unique_pattern(PragmaRule,F/A,RuleNb,Pattern,Key) :-
3541 PragmaRule = pragma(Rule,_,_,Name,RuleNb),
3542 Rule = rule(H1,H2,Guard,_),
3550 check_unique_constraints(C1,C2,Guard,RuleNb,List),
3551 term_variables(C1,Vs),
3554 lookup_eq(List,V1,V2),
3557 select_pragma_unique_variables(Vs,List,Key1),
3558 copy_term_nat(C1-Key1,Pattern-Key),
3561 select_pragma_unique_variables([],_,[]).
3562 select_pragma_unique_variables([V|Vs],List,L) :-
3563 ( lookup_eq(List,V,_) ->
3568 select_pragma_unique_variables(Vs,List,T).
3570 % depends on functional dependency analysis
3571 % and shape of rule: C1 \ C2 <=> true.
3572 set_semantics_rules(Rules) :-
3573 ( chr_pp_flag(set_semantics_rule,on) ->
3574 set_semantics_rules_main(Rules)
3579 set_semantics_rules_main([]).
3580 set_semantics_rules_main([R|Rs]) :-
3581 set_semantics_rule_main(R),
3582 set_semantics_rules_main(Rs).
3584 set_semantics_rule_main(PragmaRule) :-
3585 PragmaRule = pragma(Rule,IDs,Pragmas,_,RuleNb),
3586 ( Rule = rule([C1],[C2],true,_),
3587 IDs = ids([ID1],[ID2]),
3588 \+ is_passive(RuleNb,ID1),
3590 get_functional_dependency(F/A,RuleNb,Pattern,Key),
3591 copy_term_nat(Pattern-Key,C1-Key1),
3592 copy_term_nat(Pattern-Key,C2-Key2),
3599 check_unique_constraints(C1,C2,G,RuleNb,List) :-
3600 \+ any_passive_head(RuleNb),
3601 variable_replacement(C1-C2,C2-C1,List),
3602 copy_with_variable_replacement(G,OtherG,List),
3604 once(entails_b(NotG,OtherG)).
3606 % checks for rules of the shape ...,C1,C2... (<|=)==> ...
3607 % where C1 and C2 are symmteric constraints
3608 symmetry_analysis(Rules) :-
3609 ( chr_pp_flag(check_unnecessary_active,off) ->
3612 symmetry_analysis_main(Rules)
3615 symmetry_analysis_main([]).
3616 symmetry_analysis_main([R|Rs]) :-
3617 R = pragma(Rule,ids(IDs1,IDs2),_,_,RuleNb),
3618 Rule = rule(H1,H2,_,_),
3619 ( ( \+ chr_pp_flag(check_unnecessary_active,simplification)
3620 ; H2 == [] ), H1 \== [] ->
3621 symmetry_analysis_heads(H1,IDs1,[],[],Rule,RuleNb),
3622 symmetry_analysis_heads(H2,IDs2,[],[],Rule,RuleNb)
3626 symmetry_analysis_main(Rs).
3628 symmetry_analysis_heads([],[],_,_,_,_).
3629 symmetry_analysis_heads([H|Hs],[ID|IDs],PreHs,PreIDs,Rule,RuleNb) :-
3630 ( \+ is_passive(RuleNb,ID),
3631 member2(PreHs,PreIDs,PreH-PreID),
3632 \+ is_passive(RuleNb,PreID),
3633 variable_replacement(PreH,H,List),
3634 copy_with_variable_replacement(Rule,Rule2,List),
3635 identical_rules(Rule,Rule2) ->
3640 symmetry_analysis_heads(Hs,IDs,[H|PreHs],[ID|PreIDs],Rule,RuleNb).
3642 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3644 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3645 %% ____ _ _ _ __ _ _ _
3646 %% / ___|(_)_ __ ___ _ __ | (_)/ _(_) ___ __ _| |_(_) ___ _ __
3647 %% \___ \| | '_ ` _ \| '_ \| | | |_| |/ __/ _` | __| |/ _ \| '_ \
3648 %% ___) | | | | | | | |_) | | | _| | (_| (_| | |_| | (_) | | | |
3649 %% |____/|_|_| |_| |_| .__/|_|_|_| |_|\___\__,_|\__|_|\___/|_| |_|
3652 simplification_code(Head,RestHeads,RestIDs,PragmaRule,F/A,O,Id,L,T) :-
3653 PragmaRule = pragma(Rule,_,Pragmas,_,_RuleNb),
3654 head_info(Head,A,_Vars,Susp,HeadVars,HeadPairs),
3655 build_head(F,A,Id,HeadVars,ClauseHead),
3656 get_constraint_mode(F/A,Mode),
3657 head_arg_matches(HeadPairs,Mode,[],FirstMatching,VarDict1,[],GroundVars),
3659 rest_heads_retrieval_and_matching(RestHeads,RestIDs,Head,GetRestHeads,Susps,VarDict1,VarDict,[],[],[],GroundVars,_),
3661 guard_body_copies2(Rule,VarDict,GuardCopyList,BodyCopy),
3662 guard_via_reschedule(GetRestHeads,GuardCopyList,ClauseHead-FirstMatching,RescheduledTest),
3664 gen_uncond_susps_detachments(Susps,RestHeads,SuspsDetachments),
3665 gen_cond_susp_detachment(Id,Susp,F/A,SuspDetachment),
3667 ( chr_pp_flag(debugable,on) ->
3668 Rule = rule(_,_,Guard,Body),
3669 my_term_copy(Guard - Body, VarDict, DebugGuard - DebugBody),
3670 DebugTry = 'chr debug_event'( try([Susp|RestSusps],[],DebugGuard,DebugBody)),
3671 DebugApply = 'chr debug_event'(apply([Susp|RestSusps],[],DebugGuard,DebugBody)),
3672 instrument_goal(ActualCut,DebugTry,DebugApply,Cut)
3676 ( unconditional_occurrence(F/A,O), chr_pp_flag(late_allocation,on) -> ActualCut = true ; ActualCut = (!) ),
3677 Clause = ( ClauseHead :-
3687 head_arg_matches(Pairs,Modes,VarDict,Goal,NVarDict) :-
3688 head_arg_matches(Pairs,Modes,VarDict,Goal,NVarDict,[],_).
3690 head_arg_matches(Pairs,Modes,VarDict,Goal,NVarDict,GroundVars,NGroundVars) :-
3691 head_arg_matches_(Pairs,Modes,VarDict,GroundVars,GoalList,NVarDict,NGroundVars),
3692 list2conj(GoalList,Goal).
3694 head_arg_matches_([],[],VarDict,GroundVars,[],VarDict,GroundVars).
3695 head_arg_matches_([Arg-Var| Rest],[Mode|Modes],VarDict,GroundVars,GoalList,NVarDict,NGroundVars) :-
3697 ( lookup_eq(VarDict,Arg,OtherVar) ->
3699 ( memberchk_eq(Arg,GroundVars) ->
3700 GoalList = [Var = OtherVar | RestGoalList],
3701 GroundVars1 = GroundVars
3703 GoalList = [Var == OtherVar | RestGoalList],
3704 GroundVars1 = [Arg|GroundVars]
3707 GoalList = [Var == OtherVar | RestGoalList],
3708 GroundVars1 = GroundVars
3711 ; VarDict1 = [Arg-Var | VarDict],
3712 GoalList = RestGoalList,
3714 GroundVars1 = [Arg|GroundVars]
3716 GroundVars1 = GroundVars
3723 GoalList = [ Var = Arg | RestGoalList]
3725 GoalList = [ Var == Arg | RestGoalList]
3728 GroundVars1 = GroundVars,
3731 ; Mode == (+), is_ground(GroundVars,Arg) ->
3732 copy_with_variable_replacement(Arg,ArgCopy,VarDict),
3733 GoalList = [ Var = ArgCopy | RestGoalList],
3735 GroundVars1 = GroundVars,
3740 functor(Term,Fct,N),
3743 GoalList = [ Var = Term | RestGoalList ]
3745 GoalList = [ nonvar(Var), Var = Term | RestGoalList ]
3747 pairup(Args,Vars,NewPairs),
3748 append(NewPairs,Rest,Pairs),
3749 replicate(N,Mode,NewModes),
3750 append(NewModes,Modes,RestModes),
3752 GroundVars1 = GroundVars
3754 head_arg_matches_(Pairs,RestModes,VarDict1,GroundVars1,RestGoalList,NVarDict,NGroundVars).
3756 is_ground(GroundVars,Term) :-
3761 maplist(is_ground(GroundVars),Args)
3763 memberchk_eq(Term,GroundVars)
3766 rest_heads_retrieval_and_matching(Heads,IDs,ActiveHead,GoalList,Susps,VarDict,NVarDict,PrevHs,PrevSusps,AttrDict) :-
3767 rest_heads_retrieval_and_matching(Heads,IDs,ActiveHead,GoalList,Susps,VarDict,NVarDict,PrevHs,PrevSusps,AttrDict,[],_).
3769 rest_heads_retrieval_and_matching(Heads,IDs,ActiveHead,GoalList,Susps,VarDict,NVarDict,PrevHs,PrevSusps,AttrDict,GroundVars,NGroundVars) :-
3771 rest_heads_retrieval_and_matching_n(Heads,IDs,PrevHs,PrevSusps,ActiveHead,GoalList,Susps,VarDict,NVarDict,AttrDict,GroundVars,NGroundVars)
3776 GroundVars = NGroundVars
3779 rest_heads_retrieval_and_matching_n([],_,_,_,_,[],[],VarDict,VarDict,AttrDict,GroundVars,GroundVars) :-
3780 instantiate_pattern_goals(AttrDict).
3781 rest_heads_retrieval_and_matching_n([H|Hs],[ID|IDs],PrevHs,PrevSusps,ActiveHead,[Goal|Goals],[Susp|Susps],VarDict,NVarDict,AttrDict,GroundVars,NGroundVars) :-
3783 head_info(H,A,Vars,_,_,Pairs),
3784 get_store_type(F/A,StoreType),
3785 ( StoreType == default ->
3786 passive_head_via(H,[ActiveHead|PrevHs],AttrDict,VarDict,ViaGoal,Attr,NewAttrDict),
3787 get_max_constraint_index(N),
3791 get_constraint_index(F/A,Pos),
3792 make_attr(N,_Mask,SuspsList,Attr),
3793 nth(Pos,SuspsList,VarSusps)
3795 create_get_mutable_ref(active,State,GetMutable),
3796 get_constraint_mode(F/A,Mode),
3797 head_arg_matches(Pairs,Mode,VarDict,MatchingGoal,VarDict1,GroundVars,GroundVars1),
3798 ExistentialLookup = (
3800 'chr sbag_member'(Susp,VarSusps),
3805 existential_lookup(StoreType,H,[ActiveHead|PrevHs],VarDict,Suspension,State,ExistentialLookup,Susp,Pairs,NPairs),
3806 get_constraint_mode(F/A,Mode),
3807 filter_mode(NPairs,Pairs,Mode,NMode),
3808 head_arg_matches(NPairs,NMode,VarDict,MatchingGoal,VarDict1,GroundVars,GroundVars1),
3809 NewAttrDict = AttrDict
3811 Suspension =.. [suspension,_,State,_,_,_,_|Vars],
3812 different_from_other_susps(H,Susp,PrevHs,PrevSusps,DiffSuspGoals),
3819 rest_heads_retrieval_and_matching_n(Hs,IDs,[H|PrevHs],[Susp|PrevSusps],ActiveHead,Goals,Susps,VarDict1,NVarDict,NewAttrDict,GroundVars1,NGroundVars).
3821 filter_mode([],_,_,[]).
3822 filter_mode([Arg-Var|Rest],[_-V|R],[M|Ms],Modes) :-
3825 filter_mode(Rest,R,Ms,MT)
3827 filter_mode([Arg-Var|Rest],R,Ms,Modes)
3830 instantiate_pattern_goals([]).
3831 instantiate_pattern_goals([_-attr(Attr,Bits,Goal)|Rest]) :-
3832 get_max_constraint_index(N),
3836 make_attr(N,Mask,_,Attr),
3837 or_list(Bits,Pattern), !,
3838 Goal = (Mask /\ Pattern =:= Pattern)
3840 instantiate_pattern_goals(Rest).
3843 check_unique_keys([],_).
3844 check_unique_keys([V|Vs],Dict) :-
3845 lookup_eq(Dict,V,_),
3846 check_unique_keys(Vs,Dict).
3848 % Generates tests to ensure the found constraint differs from previously found constraints
3849 % TODO: detect more cases where constraints need be different
3850 different_from_other_susps(Head,Susp,Heads,Susps,DiffSuspGoals) :-
3851 different_from_other_susps_(Heads,Susps,Head,Susp,DiffSuspGoalList),
3852 list2conj(DiffSuspGoalList,DiffSuspGoals).
3853 % ( bagof(DiffSuspGoal, Pos ^ ( nth(Pos,Heads,PreHead), \+ Head \= PreHead, nth(Pos,Susps,PreSusp), DiffSuspGoal = (Susp \== PreSusp) ),DiffSuspGoalList) ->
3854 % list2conj(DiffSuspGoalList,DiffSuspGoals)
3856 % DiffSuspGoals = true
3859 different_from_other_susps_(_,[],_,_,[]) :- !.
3860 different_from_other_susps_([PreHead|Heads],[PreSusp|Susps],Head,Susp,List) :-
3861 ( functor(Head,F,A), functor(PreHead,F,A),
3862 copy_term_nat(PreHead-Head,PreHeadCopy-HeadCopy),
3863 \+ \+ PreHeadCopy = HeadCopy ->
3865 List = [Susp \== PreSusp | Tail]
3869 different_from_other_susps_(Heads,Susps,Head,Susp,Tail).
3871 passive_head_via(Head,PrevHeads,AttrDict,VarDict,Goal,Attr,NewAttrDict) :-
3873 get_constraint_index(F/A,Pos),
3874 common_variables(Head,PrevHeads,CommonVars),
3875 translate(CommonVars,VarDict,Vars),
3876 or_pattern(Pos,Bit),
3877 ( permutation(Vars,PermutedVars),
3878 lookup_eq(AttrDict,PermutedVars,attr(Attr,Positions,_)) ->
3879 member(Bit,Positions), !,
3880 NewAttrDict = AttrDict,
3883 Goal = (Goal1, PatternGoal),
3884 gen_get_mod_constraints(Vars,Goal1,Attr),
3885 NewAttrDict = [Vars - attr(Attr,[Bit|_],PatternGoal) | AttrDict]
3888 common_variables(T,Ts,Vs) :-
3889 term_variables(T,V1),
3890 term_variables(Ts,V2),
3891 intersect_eq(V1,V2,Vs).
3893 gen_get_mod_constraints(L,Goal,Susps) :-
3894 get_target_module(Mod),
3897 ( 'chr default_store'(Global),
3898 get_attr(Global,Mod,TSusps),
3903 VIA = 'chr via_1'(A,V)
3905 VIA = 'chr via_2'(A,B,V)
3906 ; VIA = 'chr via'(L,V)
3911 get_attr(V,Mod,TSusps),
3916 guard_body_copies(Rule,VarDict,GuardCopy,BodyCopy) :-
3917 guard_body_copies2(Rule,VarDict,GuardCopyList,BodyCopy),
3918 list2conj(GuardCopyList,GuardCopy).
3920 guard_body_copies2(Rule,VarDict,GuardCopyList,BodyCopy) :-
3921 Rule = rule(_,_,Guard,Body),
3922 conj2list(Guard,GuardList),
3923 split_off_simple_guard(GuardList,VarDict,GuardPrefix,RestGuardList),
3924 my_term_copy(GuardPrefix-RestGuardList,VarDict,VarDict2,GuardPrefixCopy-RestGuardListCopyCore),
3926 append(GuardPrefixCopy,[RestGuardCopy],GuardCopyList),
3927 term_variables(RestGuardList,GuardVars),
3928 term_variables(RestGuardListCopyCore,GuardCopyVars),
3929 ( chr_pp_flag(guard_locks,on),
3930 bagof(('chr lock'(Y)) - ('chr unlock'(Y)),
3931 X ^ (lists:member(X,GuardVars), % X is a variable appearing in the original guard
3932 pairlist:lookup_eq(VarDict,X,Y), % translate X into new variable
3933 memberchk_eq(Y,GuardCopyVars) % redundant check? or multiple entries for X possible?
3936 once(pairup(Locks,Unlocks,LocksUnlocks))
3941 list2conj(Locks,LockPhase),
3942 list2conj(Unlocks,UnlockPhase),
3943 list2conj(RestGuardListCopyCore,RestGuardCopyCore),
3944 RestGuardCopy = (LockPhase,(RestGuardCopyCore,UnlockPhase)),
3945 my_term_copy(Body,VarDict2,BodyCopy).
3948 split_off_simple_guard([],_,[],[]).
3949 split_off_simple_guard([G|Gs],VarDict,S,C) :-
3950 ( simple_guard(G,VarDict) ->
3952 split_off_simple_guard(Gs,VarDict,Ss,C)
3958 % simple guard: cheap and benign (does not bind variables)
3959 simple_guard(G,VarDict) :-
3961 \+ (( member(V,Vars),
3962 lookup_eq(VarDict,V,_)
3965 gen_cond_susp_detachment(Id,Susp,FA,SuspDetachment) :-
3968 (get_allocation_occurrence(FA,AO),
3969 get_max_occurrence(FA,MO),
3971 only_ground_indexed_arguments(FA), chr_pp_flag(late_allocation,on) ->
3972 SuspDetachment = true
3974 gen_uncond_susp_detachment(Susp,FA,UnCondSuspDetachment),
3975 ( chr_pp_flag(late_allocation,on) ->
3979 ; UnCondSuspDetachment
3982 SuspDetachment = UnCondSuspDetachment
3986 SuspDetachment = true
3989 gen_uncond_susp_detachment(Susp,FA,SuspDetachment) :-
3991 ( \+ only_ground_indexed_arguments(FA) ->
3992 make_name('detach_',FA,Fct),
3993 Detach =.. [Fct,Vars,Susp]
3997 ( chr_pp_flag(debugable,on) ->
3998 DebugEvent = 'chr debug_event'(remove(Susp))
4002 generate_delete_constraint_call(FA,Susp,DeleteCall),
4003 use_auxiliary_predicate(remove_constraint_internal),
4004 ( are_none_suspended_on_variables ->
4008 remove_constraint_internal(Susp),
4016 remove_constraint_internal(Susp, Vars, Delete),
4026 SuspDetachment = true
4029 gen_uncond_susps_detachments([],[],true).
4030 gen_uncond_susps_detachments([Susp|Susps],[Term|Terms],(SuspDetachment,SuspsDetachments)) :-
4032 gen_uncond_susp_detachment(Susp,F/A,SuspDetachment),
4033 gen_uncond_susps_detachments(Susps,Terms,SuspsDetachments).
4035 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4037 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4039 %% / ___|(_)_ __ ___ _ __ __ _ __ _ __ _| |_(_) ___ _ __ / |
4040 %% \___ \| | '_ ` _ \| '_ \ / _` |/ _` |/ _` | __| |/ _ \| '_ \ | |
4041 %% ___) | | | | | | | |_) | (_| | (_| | (_| | |_| | (_) | | | | | |
4042 %% |____/|_|_| |_| |_| .__/ \__,_|\__, |\__,_|\__|_|\___/|_| |_| |_|
4045 simpagation_head1_code(Head,RestHeads,OtherIDs,PragmaRule,F/A,Id,L,T) :-
4046 PragmaRule = pragma(Rule,ids(_,Heads2IDs),Pragmas,_Name,_RuleNb),
4047 Rule = rule(_Heads,Heads2,Guard,Body),
4049 head_info(Head,A,_Vars,Susp,HeadVars,HeadPairs),
4050 get_constraint_mode(F/A,Mode),
4051 head_arg_matches(HeadPairs,Mode,[],FirstMatching,VarDict1,[],GroundVars),
4053 build_head(F,A,Id,HeadVars,ClauseHead),
4055 append(RestHeads,Heads2,Heads),
4056 append(OtherIDs,Heads2IDs,IDs),
4057 reorder_heads(RuleNb,Head,Heads,IDs,NHeads,NIDs),
4058 rest_heads_retrieval_and_matching(NHeads,NIDs,Head,GetRestHeads,Susps,VarDict1,VarDict,[],[],[],GroundVars,_),
4059 split_by_ids(NIDs,Susps,OtherIDs,Susps1,Susps2),
4061 guard_body_copies2(Rule,VarDict,GuardCopyList,BodyCopy),
4062 guard_via_reschedule(GetRestHeads,GuardCopyList,ClauseHead-FirstMatching,RescheduledTest),
4064 gen_uncond_susps_detachments(Susps1,RestHeads,SuspsDetachments),
4065 gen_cond_susp_detachment(Id,Susp,F/A,SuspDetachment),
4067 ( chr_pp_flag(debugable,on) ->
4068 my_term_copy(Guard - Body, VarDict, DebugGuard - DebugBody),
4069 DebugTry = 'chr debug_event'( try([Susp|Susps1],Susps2,DebugGuard,DebugBody)),
4070 DebugApply = 'chr debug_event'(apply([Susp|Susps1],Susps2,DebugGuard,DebugBody)),
4071 instrument_goal((!),DebugTry,DebugApply,Cut)
4076 Clause = ( ClauseHead :-
4086 split_by_ids([],[],_,[],[]).
4087 split_by_ids([I|Is],[S|Ss],I1s,S1s,S2s) :-
4088 ( memberchk_eq(I,I1s) ->
4095 split_by_ids(Is,Ss,I1s,R1s,R2s).
4097 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4102 %% / ___|(_)_ __ ___ _ __ __ _ __ _ __ _| |_(_) ___ _ __ |___ \
4103 %% \___ \| | '_ ` _ \| '_ \ / _` |/ _` |/ _` | __| |/ _ \| '_ \ __) |
4104 %% ___) | | | | | | | |_) | (_| | (_| | (_| | |_| | (_) | | | | / __/
4105 %% |____/|_|_| |_| |_| .__/ \__,_|\__, |\__,_|\__|_|\___/|_| |_| |_____|
4108 %% Genereate prelude + worker predicate
4109 %% prelude calls worker
4110 %% worker iterates over one type of removed constraints
4111 simpagation_head2_code(Head2,RestHeads2,RestIDs,PragmaRule,FA,O,Id,L,T) :-
4112 PragmaRule = pragma(Rule,ids(IDs1,IDs2),Pragmas,_Name,RuleNb),
4113 Rule = rule(Heads1,_,Guard,Body),
4114 append(Heads1,RestHeads2,Heads),
4115 append(IDs1,RestIDs,IDs),
4116 reorder_heads(RuleNb,Head2,Heads,IDs,[NHead|NHeads],[NID|NIDs]),
4117 simpagation_head2_prelude(Head2,NHead,[NHeads,Guard,Body],FA,O,Id,L,L1),
4119 ( memberchk_eq(NID,IDs2) ->
4120 simpagation_universal_searches(NHeads,NIDs,IDs2,[NHead,Head2],Rule,FA,NextHeads,PreHeads,NextIDs,Id1,Id2,L1,L2)
4122 L1 = L2, Id1 = Id2,NextHeads = NHeads, PreHeads = [NHead,Head2], NextIDs = NIDs
4124 universal_search_iterator_end(PreHeads,NextHeads,Rule,FA,Id2,L2,L3),
4125 simpagation_head2_new_worker(PreHeads,NextHeads,NextIDs,PragmaRule,FA,O,Id2,L3,T).
4127 simpagation_universal_searches([],[],_,PreHeads,_,_,[],PreHeads,[],Id,Id,L,L).
4128 simpagation_universal_searches(Heads,[ID|IDs],IDs2,PreHeads,Rule,C,OutHeads,OutPreHeads,OutIDs,Id,NId,L,T) :-
4129 Heads = [Head|RHeads],
4131 universal_search_iterator_end(PreHeads,Heads,Rule,C,Id,L,L0),
4132 universal_search_iterator(Heads,PreHeads,Rule,C,Id,L0,L1),
4133 ( memberchk_eq(ID,IDs2) ->
4134 simpagation_universal_searches(RHeads,IDs,IDs2,[Head|PreHeads],Rule,C,OutHeads,OutPreHeads,OutIDs,Id1,NId,L1,T)
4136 NId = Id1, L1 = T, OutHeads = RHeads, OutPreHeads = [Head|PreHeads], IDs = OutIDs
4139 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4140 simpagation_head2_prelude(Head,Head1,Rest,F/A,O,Id1,L,T) :-
4141 head_info(Head,A,Vars,Susp,VarsSusp,HeadPairs),
4142 build_head(F,A,Id1,VarsSusp,ClauseHead),
4143 get_constraint_mode(F/A,Mode),
4144 head_arg_matches(HeadPairs,Mode,[],FirstMatching,VarDict),
4146 lookup_passive_head(Head1,[Head],VarDict,ModConstraintsGoal,AllSusps),
4148 gen_occ_allocation(F/A,O,Vars,Susp,VarsSusp,ConstraintAllocationGoal),
4150 extend_id(Id1,DelegateId),
4151 extra_active_delegate_variables(Head,[Head1|Rest],VarDict,ExtraVars),
4152 append([AllSusps|VarsSusp],ExtraVars,DelegateCallVars),
4153 build_head(F,A,DelegateId,DelegateCallVars,Delegate),
4160 ConstraintAllocationGoal,
4163 L = [PreludeClause|T].
4165 extra_active_delegate_variables(Term,Terms,VarDict,Vars) :-
4167 delegate_variables(Term,Terms,VarDict,Args,Vars).
4169 passive_delegate_variables(Term,PrevTerms,NextTerms,VarDict,Vars) :-
4170 term_variables(PrevTerms,PrevVars),
4171 delegate_variables(Term,NextTerms,VarDict,PrevVars,Vars).
4173 delegate_variables(Term,Terms,VarDict,PrevVars,Vars) :-
4174 term_variables(Term,V1),
4175 term_variables(Terms,V2),
4176 intersect_eq(V1,V2,V3),
4177 list_difference_eq(V3,PrevVars,V4),
4178 translate(V4,VarDict,Vars).
4181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4182 simpagation_head2_new_worker([CurrentHead|PreHeads],NextHeads,NextIDs,PragmaRule,F/A,O,Id,L,T) :-
4184 PragmaRule = pragma(Rule,ids(IDs1,_),Pragmas,_,RuleNb),
4185 Rule = rule(_,_,Guard,Body),
4186 get_prop_inner_loop_vars(PreHeads,[CurrentHead,NextHeads,Guard,Body],PreVarsAndSusps,VarDict,Susp,PreSusps),
4189 gen_var(OtherSusps),
4191 functor(CurrentHead,OtherF,OtherA),
4192 gen_vars(OtherA,OtherVars),
4193 head_info(CurrentHead,OtherA,OtherVars,OtherSusp,_VarsSusp,HeadPairs),
4194 get_constraint_mode(OtherF/OtherA,Mode),
4195 head_arg_matches(HeadPairs,Mode,VarDict,FirstMatching,VarDict1),
4197 OtherSuspension =.. [suspension,_,State,_,_,_,_|OtherVars],
4198 different_from_other_susps(CurrentHead,OtherSusp,PreHeads,PreSusps,DiffSuspGoals),
4199 create_get_mutable_ref(active,State,GetMutable),
4201 OtherSusp = OtherSuspension,
4207 ClauseVars = [[OtherSusp|OtherSusps]|PreVarsAndSusps],
4208 build_head(F,A,Id,ClauseVars,ClauseHead),
4210 rest_heads_retrieval_and_matching(NextHeads,NextIDs,[CurrentHead|PreHeads],RestSuspsRetrieval,Susps,VarDict1,VarDict2,[CurrentHead|PreHeads],[OtherSusp|PreSusps],[]),
4211 split_by_ids(NextIDs,Susps,IDs1,Susps1,Susps2),
4212 split_by_ids(NextIDs,NextHeads,IDs1,RestHeads1,_),
4214 gen_uncond_susps_detachments([OtherSusp | Susps1],[CurrentHead|RestHeads1],Susps1Detachments),
4216 RecursiveVars = [OtherSusps|PreVarsAndSusps],
4217 build_head(F,A,Id,RecursiveVars,RecursiveCall),
4218 RecursiveVars2 = [[]|PreVarsAndSusps],
4219 build_head(F,A,Id,RecursiveVars2,RecursiveCall2),
4221 guard_body_copies2(Rule,VarDict2,GuardCopyList,BodyCopy),
4222 guard_via_reschedule(RestSuspsRetrieval,GuardCopyList,v(ClauseHead,CurrentSuspTest),RescheduledTest),
4223 ( BodyCopy \== true, is_observed(F/A,O) ->
4224 gen_uncond_attach_goal(F/A,Susp,Attachment,Generation),
4225 gen_state_cond_call(Susp,A,RecursiveCall,Generation,ConditionalRecursiveCall),
4226 gen_state_cond_call(Susp,A,RecursiveCall2,Generation,ConditionalRecursiveCall2)
4227 ; Attachment = true,
4228 ConditionalRecursiveCall = RecursiveCall,
4229 ConditionalRecursiveCall2 = RecursiveCall2
4232 ( chr_pp_flag(debugable,on) ->
4233 my_term_copy(Guard - Body, VarDict, DebugGuard - DebugBody),
4234 DebugTry = 'chr debug_event'( try([OtherSusp|Susps1],[Susp|Susps2],DebugGuard,DebugBody)),
4235 DebugApply = 'chr debug_event'(apply([OtherSusp|Susps1],[Susp|Susps2],DebugGuard,DebugBody))
4241 ( member(unique(ID1,UniqueKeys), Pragmas),
4242 check_unique_keys(UniqueKeys,VarDict) ->
4245 ( CurrentSuspTest ->
4252 ConditionalRecursiveCall2
4270 ConditionalRecursiveCall
4278 gen_state_cond_call(Susp,N,Call,Generation,ConditionalCall) :-
4280 Suspension =.. [suspension,_,State,_,NewGeneration,_,_|Args],
4281 create_get_mutable_ref(active,State,GetState),
4282 create_get_mutable_ref(Generation,NewGeneration,GetGeneration),
4284 ( Susp = Suspension,
4287 'chr update_mutable'(inactive,State),
4292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4295 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4297 %% | _ \ _ __ ___ _ __ __ _ __ _ __ _| |_(_) ___ _ __
4298 %% | |_) | '__/ _ \| '_ \ / _` |/ _` |/ _` | __| |/ _ \| '_ \
4299 %% | __/| | | (_) | |_) | (_| | (_| | (_| | |_| | (_) | | | |
4300 %% |_| |_| \___/| .__/ \__,_|\__, |\__,_|\__|_|\___/|_| |_|
4303 propagation_code(Head,RestHeads,RestIDs,Rule,RuleNb,FA,O,Id,L,T) :-
4304 ( RestHeads == [] ->
4305 propagation_single_headed(Head,Rule,RuleNb,FA,O,Id,L,T)
4307 propagation_multi_headed(Head,RestHeads,RestIDs,Rule,RuleNb,FA,O,Id,L,T)
4309 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4310 %% Single headed propagation
4311 %% everything in a single clause
4312 propagation_single_headed(Head,Rule,RuleNb,F/A,O,Id,ProgramList,ProgramTail) :-
4313 head_info(Head,A,Vars,Susp,VarsSusp,HeadPairs),
4314 build_head(F,A,Id,VarsSusp,ClauseHead),
4317 build_head(F,A,NextId,VarsSusp,NextHead),
4319 get_constraint_mode(F/A,Mode),
4320 head_arg_matches(HeadPairs,Mode,[],HeadMatching,VarDict),
4321 guard_body_copies(Rule,VarDict,GuardCopy,BodyCopy),
4322 gen_occ_allocation(F/A,O,Vars,Susp,VarsSusp,Allocation),
4324 % - recursive call -
4325 RecursiveCall = NextHead,
4326 ( BodyCopy \== true, is_observed(F/A,O) ->
4327 gen_uncond_attach_goal(F/A,Susp,Attachment,Generation),
4328 gen_state_cond_call(Susp,A,RecursiveCall,Generation,ConditionalRecursiveCall)
4329 ; Attachment = true,
4330 ConditionalRecursiveCall = RecursiveCall
4333 ( unconditional_occurrence(F/A,O), chr_pp_flag(late_allocation,on) ->
4339 ( chr_pp_flag(debugable,on) ->
4340 Rule = rule(_,_,Guard,Body),
4341 my_term_copy(Guard - Body, VarDict, DebugGuard - DebugBody),
4342 DebugTry = 'chr debug_event'( try([],[Susp],DebugGuard,DebugBody)),
4343 DebugApply = 'chr debug_event'(apply([],[Susp],DebugGuard,DebugBody)),
4344 instrument_goal(ActualCut,DebugTry,DebugApply,Cut)
4349 ( may_trigger(F/A) ->
4350 NovelProduction = 'chr novel_production'(Susp,RuleNb), % optimisation of t(RuleNb,Susp)
4351 ExtendHistory = 'chr extend_history'(Susp,RuleNb)
4353 NovelProduction = true,
4354 ExtendHistory = true
4367 ConditionalRecursiveCall
4369 ProgramList = [Clause | ProgramTail].
4371 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4372 %% multi headed propagation
4373 %% prelude + predicates to accumulate the necessary combinations of suspended
4374 %% constraints + predicate to execute the body
4375 propagation_multi_headed(Head,RestHeads,RestIDs,Rule,RuleNb,FA,O,Id,L,T) :-
4376 RestHeads = [First|Rest],
4377 propagation_prelude(Head,RestHeads,Rule,FA,O,Id,L,L1),
4378 extend_id(Id,ExtendedId),
4379 propagation_nested_code(Rest,[First,Head],RestIDs,Rule,RuleNb,FA,O,ExtendedId,L1,T).
4381 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4382 propagation_prelude(Head,[First|Rest],Rule,F/A,O,Id,L,T) :-
4383 head_info(Head,A,Vars,Susp,VarsSusp,HeadPairs),
4384 build_head(F,A,Id,VarsSusp,PreludeHead),
4385 get_constraint_mode(F/A,Mode),
4386 head_arg_matches(HeadPairs,Mode,[],FirstMatching,VarDict),
4387 Rule = rule(_,_,Guard,Body),
4388 extra_active_delegate_variables(Head,[First,Rest,Guard,Body],VarDict,ExtraVars),
4390 lookup_passive_head(First,[Head],VarDict,FirstSuspGoal,Susps),
4392 gen_occ_allocation(F/A,O,Vars,Susp,VarsSusp,CondAllocation),
4394 extend_id(Id,NestedId),
4395 append([Susps|VarsSusp],ExtraVars,NestedVars),
4396 build_head(F,A,NestedId,NestedVars,NestedHead),
4397 NestedCall = NestedHead,
4409 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4410 propagation_nested_code([],[CurrentHead|PreHeads],RestIDs,Rule,RuleNb,FA,O,Id,L,T) :-
4411 universal_search_iterator_end([CurrentHead|PreHeads],[],Rule,FA,Id,L,L1),
4412 propagation_body(CurrentHead,PreHeads,RestIDs,Rule,RuleNb,FA,O,Id,L1,T).
4414 propagation_nested_code([Head|RestHeads],PreHeads,RestIDs,Rule,RuleNb,FA,O,Id,L,T) :-
4415 universal_search_iterator_end(PreHeads,[Head|RestHeads],Rule,FA,Id,L,L1),
4416 universal_search_iterator([Head|RestHeads],PreHeads,Rule,FA,Id,L1,L2),
4418 propagation_nested_code(RestHeads,[Head|PreHeads],RestIDs,Rule,RuleNb,FA,O,IncId,L2,T).
4420 check_fd_lookup_condition(_,_,_,_) :- fail.
4421 %check_fd_lookup_condition(F,A,_,_) :-
4422 % get_store_type(F/A,global_singleton), !.
4423 %check_fd_lookup_condition(F,A,CurrentHead,PreHeads) :-
4424 % get_functional_dependency(F/A,1,P,K),
4425 % copy_term(P-K,CurrentHead-Key),
4426 % term_variables(PreHeads,PreVars),
4427 % intersect_eq(Key,PreVars,Key).
4429 propagation_body(CurrentHead,PreHeads,RestIDs,Rule,RuleNb,F/A,O,Id,L,T) :-
4430 Rule = rule(_,_,Guard,Body),
4431 gen_var_susp_list_for_b(PreHeads,[CurrentHead,Guard,Body],VarDict1,PreVarsAndSuspsList,FirstVarsSusp,AllSusps,PrevIterators),
4432 flatten(PreVarsAndSuspsList,PreVarsAndSusps),
4433 init(AllSusps,RestSusps),
4434 last(AllSusps,Susp),
4436 gen_var(OtherSusps),
4437 functor(CurrentHead,OtherF,OtherA),
4438 gen_vars(OtherA,OtherVars),
4439 Suspension =.. [suspension,_,State,_,_,_,_|OtherVars],
4440 create_get_mutable_ref(active,State,GetMutable),
4442 OtherSusp = Suspension,
4445 ClauseVars = [[OtherSusp|OtherSusps]|PreVarsAndSusps],
4446 build_head(F,A,Id,ClauseVars,ClauseHead),
4447 ( check_fd_lookup_condition(OtherF,OtherA,CurrentHead,PreHeads) -> % iterator (OtherSusps) is empty at runtime
4448 universal_search_iterator_failure_vars(PreHeads,Id,PreVarsAndSuspsList,FirstVarsSusp,PrevIterators,PreVarsAndSusps1,PrevId),
4449 RecursiveVars = PreVarsAndSusps1
4451 RecursiveVars = [OtherSusps|PreVarsAndSusps],
4454 build_head(F,A,PrevId,RecursiveVars,RecursiveHead),
4455 RecursiveCall = RecursiveHead,
4456 CurrentHead =.. [_|OtherArgs],
4457 pairup(OtherArgs,OtherVars,OtherPairs),
4458 get_constraint_mode(OtherF/OtherA,Mode),
4459 head_arg_matches(OtherPairs,Mode,VarDict1,Matching,VarDict),
4461 different_from_other_susps(CurrentHead,OtherSusp,PreHeads,RestSusps,DiffSuspGoals),
4462 guard_body_copies(Rule,VarDict,GuardCopy,BodyCopy),
4464 ( BodyCopy \== true, is_observed(F/A,O) ->
4465 gen_uncond_attach_goal(F/A,Susp,Attach,Generation),
4466 gen_state_cond_call(Susp,A,RecursiveCall,Generation,ConditionalRecursiveCall)
4468 ConditionalRecursiveCall = RecursiveCall
4471 ( is_least_occurrence(RuleNb) ->
4472 NovelProduction = true,
4473 ExtendHistory = true
4475 get_occurrence(F/A,O,_,ID),
4476 history_susps(RestIDs,[OtherSusp|RestSusps],Susp,ID,HistorySusps),
4477 Tuple =.. [t,RuleNb|HistorySusps],
4478 bagof('chr novel_production'(X,Y),( lists:member(X,HistorySusps), Y = TupleVar) ,NovelProductionsList),
4479 list2conj(NovelProductionsList,NovelProductions),
4480 NovelProduction = ( TupleVar = Tuple, NovelProductions),
4481 ExtendHistory = 'chr extend_history'(Susp,TupleVar)
4485 ( chr_pp_flag(debugable,on) ->
4486 Rule = rule(_,_,Guard,Body),
4487 my_term_copy(Guard - Body, VarDict, DebugGuard - DebugBody),
4488 DebugTry = 'chr debug_event'( try([],[Susp,OtherSusp|RestSusps],DebugGuard,DebugBody)),
4489 DebugApply = 'chr debug_event'(apply([],[Susp,OtherSusp|RestSusps],DebugGuard,DebugBody))
4507 ConditionalRecursiveCall
4513 history_susps(RestIDs,ReversedRestSusps,Susp,ID,HistorySusps) :-
4514 reverse(ReversedRestSusps,RestSusps),
4515 pairup([ID|RestIDs],[Susp|RestSusps],IDSusps),
4516 sort(IDSusps,SortedIDSusps),
4517 pairup(_,HistorySusps,SortedIDSusps).
4519 gen_var_susp_list_for([Head],Terms,VarDict,HeadVars,VarsSusp,Susp) :-
4522 head_info(Head,A,_Vars,Susp,VarsSusp,HeadPairs),
4523 get_constraint_mode(F/A,Mode),
4524 head_arg_matches(HeadPairs,Mode,[],_,VarDict),
4525 extra_active_delegate_variables(Head,Terms,VarDict,ExtraVars),
4526 append(VarsSusp,ExtraVars,HeadVars).
4527 gen_var_susp_list_for([Head|Heads],Terms,NVarDict,VarsSusps,Rest,Susps) :-
4528 gen_var_susp_list_for(Heads,[Head|Terms],VarDict,Rest,_,_),
4531 head_info(Head,A,_Vars,Susp,_VarsSusp,HeadPairs),
4532 get_constraint_mode(F/A,Mode),
4533 head_arg_matches(HeadPairs,Mode,VarDict,_,NVarDict),
4534 passive_delegate_variables(Head,Heads,Terms,NVarDict,HeadVars),
4535 append(HeadVars,[Susp,Susps|Rest],VarsSusps).
4538 % VarDict for the copies of variables in the original heads
4539 % VarsSuspsList list of lists of arguments for the successive heads
4540 % FirstVarsSusp top level arguments
4541 % SuspList list of all suspensions
4542 % Iterators list of all iterators
4543 gen_var_susp_list_for_b([Head],NextHeads,VarDict,[HeadVars],VarsSusp,[Susp],[]) :-
4546 head_info(Head,A,_Vars,Susp,VarsSusp,HeadPairs), % make variables for argument positions
4547 get_constraint_mode(F/A,Mode),
4548 head_arg_matches(HeadPairs,Mode,[],_,VarDict), % copy variables inside arguments, build dictionary
4549 extra_active_delegate_variables(Head,NextHeads,VarDict,ExtraVars), % decide what additional variables are needed
4550 append(VarsSusp,ExtraVars,HeadVars). % add additional variables to head variables
4551 gen_var_susp_list_for_b([Head|Heads],NextHeads,NVarDict,[Vars|RestVars],FirstVarsSusp,[Susp|SuspList],[Susps|Iterators]) :-
4552 % gen_var_susp_list_for_b(Heads,[Head|NextHeads],VarDict,RestVars,FirstVarsSusp,[SuspList],Iterators),
4553 gen_var_susp_list_for_b(Heads,[Head|NextHeads],VarDict,RestVars,FirstVarsSusp,SuspList,Iterators), % needed almost an hour to find this nasty typo/bug
4556 head_info(Head,A,_Vars,Susp,_VarsSusp,HeadPairs),
4557 get_constraint_mode(F/A,Mode),
4558 head_arg_matches(HeadPairs,Mode,VarDict,_,NVarDict),
4559 passive_delegate_variables(Head,Heads,NextHeads,NVarDict,HeadVars),
4560 append(HeadVars,[Susp,Susps],Vars).
4562 get_prop_inner_loop_vars([Head],Terms,HeadVars,VarDict,Susp,[]) :-
4565 head_info(Head,A,_Vars,Susp,VarsSusp,Pairs),
4566 get_constraint_mode(F/A,Mode),
4567 head_arg_matches(Pairs,Mode,[],_,VarDict),
4568 extra_active_delegate_variables(Head,Terms,VarDict,ExtraVars),
4569 append(VarsSusp,ExtraVars,HeadVars).
4570 get_prop_inner_loop_vars([Head|Heads],Terms,VarsSusps,NVarDict,MainSusp,[Susp|RestSusps]) :-
4571 get_prop_inner_loop_vars(Heads,[Head|Terms],RestVarsSusp,VarDict,MainSusp,RestSusps),
4574 head_info(Head,A,_Vars,Susp,_VarsSusp,Pairs),
4575 get_constraint_mode(F/A,Mode),
4576 head_arg_matches(Pairs,Mode,VarDict,_,NVarDict),
4577 passive_delegate_variables(Head,Heads,Terms,NVarDict,HeadVars),
4578 append(HeadVars,[Susp,Susps|RestVarsSusp],VarsSusps).
4580 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4582 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4584 %% | _ \ __ _ ___ ___(_)_ _____ | | | | ___ __ _ __| |
4585 %% | |_) / _` / __/ __| \ \ / / _ \ | |_| |/ _ \/ _` |/ _` |
4586 %% | __/ (_| \__ \__ \ |\ V / __/ | _ | __/ (_| | (_| |
4587 %% |_| \__,_|___/___/_| \_/ \___| |_| |_|\___|\__,_|\__,_|
4590 %% | _ \ ___| |_ _ __(_) _____ ____ _| |
4591 %% | |_) / _ \ __| '__| |/ _ \ \ / / _` | |
4592 %% | _ < __/ |_| | | | __/\ V / (_| | |
4593 %% |_| \_\___|\__|_| |_|\___| \_/ \__,_|_|
4596 %% | _ \ ___ ___ _ __ __| | ___ _ __(_)_ __ __ _
4597 %% | |_) / _ \/ _ \| '__/ _` |/ _ \ '__| | '_ \ / _` |
4598 %% | _ < __/ (_) | | | (_| | __/ | | | | | | (_| |
4599 %% |_| \_\___|\___/|_| \__,_|\___|_| |_|_| |_|\__, |
4602 reorder_heads(RuleNb,Head,RestHeads,RestIDs,NRestHeads,NRestIDs) :-
4603 ( chr_pp_flag(reorder_heads,on) ->
4604 reorder_heads_main(RuleNb,Head,RestHeads,RestIDs,NRestHeads,NRestIDs)
4606 NRestHeads = RestHeads,
4610 reorder_heads_main(RuleNb,Head,RestHeads,RestIDs,NRestHeads,NRestIDs) :-
4611 term_variables(Head,Vars),
4612 InitialData = entry([],[],Vars,RestHeads,RestIDs,RuleNb),
4613 copy_term_nat(InitialData,InitialDataCopy),
4614 a_star(InitialDataCopy,FD^(chr_translate:final_data(FD)),N^EN^C^(chr_translate:expand_data(N,EN,C)),FinalData),
4615 InitialDataCopy = InitialData,
4616 FinalData = entry(RNRestHeads,RNRestIDs,_,_,_,_),
4617 reverse(RNRestHeads,NRestHeads),
4618 reverse(RNRestIDs,NRestIDs).
4620 final_data(Entry) :-
4621 Entry = entry(_,_,_,_,[],_).
4623 expand_data(Entry,NEntry,Cost) :-
4624 Entry = entry(Heads,IDs,Vars,NHeads,NIDs,RuleNb),
4625 select2(Head1,ID1,NHeads,NIDs,NHeads1,NIDs1),
4626 term_variables([Head1|Vars],Vars1),
4627 NEntry = entry([Head1|Heads],[ID1|IDs],Vars1,NHeads1,NIDs1,RuleNb),
4628 order_score(Head1,ID1,Vars,NHeads1,RuleNb,Cost).
4630 % Assigns score to head based on known variables and heads to lookup
4631 order_score(Head,ID,KnownVars,RestHeads,RuleNb,Score) :-
4633 get_store_type(F/A,StoreType),
4634 order_score(StoreType,Head,ID,KnownVars,RestHeads,RuleNb,Score).
4636 order_score(default,Head,_ID,KnownVars,RestHeads,RuleNb,Score) :-
4637 term_variables(Head,HeadVars),
4638 term_variables(RestHeads,RestVars),
4639 order_score_vars(HeadVars,KnownVars,RestVars,Score).
4640 order_score(multi_hash(Indexes),Head,_ID,KnownVars,RestHeads,RuleNb,Score) :-
4641 order_score_indexes(Indexes,Head,KnownVars,0,Score).
4642 order_score(global_ground,Head,ID,KnownVars,RestHeads,RuleNb,Score) :-
4643 term_variables(Head,HeadVars),
4644 term_variables(RestHeads,RestVars),
4645 order_score_vars(HeadVars,KnownVars,RestVars,Score_),
4646 Score is Score_ * 2.
4647 order_score(global_singleton,_Head,ID,_KnownVars,_RestHeads,_RuleNb,Score) :-
4648 Score = 1. % guaranteed O(1)
4650 order_score(multi_store(StoreTypes),Head,ID,KnownVars,RestHeads,RuleNb,Score) :-
4651 find_with_var_identity(
4653 t(Head,KnownVars,RestHeads),
4654 ( lists:member(ST,StoreTypes), chr_translate:order_score(ST,Head,ID,KnownVars,RestHeads,RuleNb,S) ),
4657 min_list(Scores,Score).
4660 order_score_indexes([],_,_,Score,NScore) :-
4661 Score > 0, NScore = 100.
4662 order_score_indexes([I|Is],Head,KnownVars,Score,NScore) :-
4663 multi_hash_key_args(I,Head,Args),
4664 ( forall(Arg,Args,memberchk_eq(Arg,KnownVars)) ->
4669 order_score_indexes(Is,Head,KnownVars,Score1,NScore).
4671 order_score_vars(Vars,KnownVars,RestVars,Score) :-
4672 order_score_count_vars(Vars,KnownVars,RestVars,K-R-O),
4676 Score is max(10 - K,0)
4678 Score is max(10 - R,1) * 10
4680 Score is max(10-O,1) * 100
4682 order_score_count_vars([],_,_,0-0-0).
4683 order_score_count_vars([V|Vs],KnownVars,RestVars,NK-NR-NO) :-
4684 order_score_count_vars(Vs,KnownVars,RestVars,K-R-O),
4685 ( memberchk_eq(V,KnownVars) ->
4688 ; memberchk_eq(V,RestVars) ->
4696 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4698 %% |_ _|_ __ | (_)_ __ (_)_ __ __ _
4699 %% | || '_ \| | | '_ \| | '_ \ / _` |
4700 %% | || | | | | | | | | | | | | (_| |
4701 %% |___|_| |_|_|_|_| |_|_|_| |_|\__, |
4705 create_get_mutable_ref(V,M,GM) :- GM = (M = mutable(V)).
4709 %% create_get_mutable_ref(V,M,GM) :- GM = get_mutable(V,M).
4712 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4714 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4716 %% | | | | |_(_) (_) |_ _ _
4717 %% | | | | __| | | | __| | | |
4718 %% | |_| | |_| | | | |_| |_| |
4719 %% \___/ \__|_|_|_|\__|\__, |
4726 head_info(Head,A,Vars,Susp,VarsSusp,HeadPairs) :-
4727 vars_susp(A,Vars,Susp,VarsSusp),
4729 pairup(Args,Vars,HeadPairs).
4731 inc_id([N|Ns],[O|Ns]) :-
4733 dec_id([N|Ns],[M|Ns]) :-
4736 extend_id(Id,[0|Id]).
4738 next_id([_,N|Ns],[O|Ns]) :-
4741 build_head(F,A,Id,Args,Head) :-
4742 buildName(F,A,Id,Name),
4743 ( (chr_pp_flag(debugable,on) ; is_stored(F/A), has_active_occurrence(F/A),
4744 ( may_trigger(F/A) ;
4745 get_allocation_occurrence(F/A,AO),
4746 get_max_occurrence(F/A,MO),
4748 Head =.. [Name|Args]
4750 init(Args,ArgsWOSusp), % XXX not entirely correct!
4751 Head =.. [Name|ArgsWOSusp]
4754 buildName(Fct,Aty,List,Result) :-
4755 ( (chr_pp_flag(debugable,on) ; (once((is_stored(Fct/Aty), ( has_active_occurrence(Fct/Aty) ; chr_pp_flag(late_allocation,off)),
4756 ( may_trigger(Fct/Aty) ; get_allocation_occurrence(Fct/Aty,AO), get_max_occurrence(Fct/Aty,MO),
4757 MO >= AO ) ; List \= [0])) ) ) ->
4758 atom_concat(Fct, (/) ,FctSlash),
4759 atomic_concat(FctSlash,Aty,FctSlashAty),
4760 buildName_(List,FctSlashAty,Result)
4765 buildName_([],Name,Name).
4766 buildName_([N|Ns],Name,Result) :-
4767 buildName_(Ns,Name,Name1),
4768 atom_concat(Name1,'__',NameDash), % '_' is a char :-(
4769 atomic_concat(NameDash,N,Result).
4771 vars_susp(A,Vars,Susp,VarsSusp) :-
4773 append(Vars,[Susp],VarsSusp).
4775 make_attr(N,Mask,SuspsList,Attr) :-
4776 length(SuspsList,N),
4777 Attr =.. [v,Mask|SuspsList].
4779 or_pattern(Pos,Pat) :-
4781 Pat is 1 << Pow. % was 2 ** X
4783 and_pattern(Pos,Pat) :-
4785 Y is 1 << X, % was 2 ** X
4786 Pat is (-1)*(Y + 1).
4788 make_name(Prefix,F/A,Name) :-
4789 atom_concat_list([Prefix,F,(/),A],Name).
4791 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4792 % Storetype dependent lookup
4793 lookup_passive_head(Head,PreJoin,VarDict,Goal,AllSusps) :-
4795 get_store_type(F/A,StoreType),
4796 lookup_passive_head(StoreType,Head,PreJoin,VarDict,Goal,AllSusps).
4798 lookup_passive_head(default,Head,PreJoin,VarDict,Goal,AllSusps) :-
4799 passive_head_via(Head,PreJoin,[],VarDict,Goal,Attr,AttrDict),
4800 instantiate_pattern_goals(AttrDict),
4801 get_max_constraint_index(N),
4806 get_constraint_index(F/A,Pos),
4807 make_attr(N,_,SuspsList,Attr),
4808 nth(Pos,SuspsList,AllSusps)
4810 lookup_passive_head(multi_hash(Indexes),Head,_PreJoin,VarDict,Goal,AllSusps) :-
4812 member(Index,Indexes),
4813 multi_hash_key_args(Index,Head,KeyArgs),
4814 translate(KeyArgs,VarDict,KeyArgCopies)
4816 ( KeyArgCopies = [KeyCopy] ->
4819 KeyCopy =.. [k|KeyArgCopies]
4822 multi_hash_via_lookup_name(F/A,Index,ViaName),
4823 Goal =.. [ViaName,KeyCopy,AllSusps],
4824 update_store_type(F/A,multi_hash([Index])).
4825 lookup_passive_head(global_ground,Head,_PreJoin,_VarDict,Goal,AllSusps) :-
4827 global_ground_store_name(F/A,StoreName),
4828 make_get_store_goal(StoreName,AllSusps,Goal), % Goal = nb_getval(StoreName,AllSusps),
4829 update_store_type(F/A,global_ground).
4830 lookup_passive_head(global_singleton,Head,_PreJoin,_VarDict,Goal,AllSusps) :-
4832 global_singleton_store_name(F/A,StoreName),
4833 make_get_store_goal(StoreName,Susp,GetStoreGoal),
4834 Goal = (GetStoreGoal,Susp \== [],AllSusps = [Susp]),
4835 update_store_type(F/A,global_singleton).
4836 lookup_passive_head(multi_store(StoreTypes),Head,PreJoin,VarDict,Goal,AllSusps) :-
4838 member(ST,StoreTypes),
4839 lookup_passive_head(ST,Head,PreJoin,VarDict,Goal,AllSusps)
4842 existential_lookup(global_singleton,Head,_PreJoin,_VarDict,SuspTerm,State,Goal,Susp,Pairs,Pairs) :- !,
4844 global_singleton_store_name(F/A,StoreName),
4845 make_get_store_goal(StoreName,Susp,GetStoreGoal),
4847 GetStoreGoal, % nb_getval(StoreName,Susp),
4851 update_store_type(F/A,global_singleton).
4852 existential_lookup(multi_store(StoreTypes),Head,PreJoin,VarDict,SuspTerm,State,Goal,Susp,Pairs,NPairs) :- !,
4854 member(ST,StoreTypes),
4855 existential_lookup(ST,Head,PreJoin,VarDict,SuspTerm,State,Goal,Susp,Pairs,NPairs)
4857 existential_lookup(multi_hash(Indexes),Head,_PreJoin,VarDict,SuspTerm,State,Goal,Susp,Pairs,NPairs) :- !,
4859 member(Index,Indexes),
4860 multi_hash_key_args(Index,Head,KeyArgs),
4861 translate(KeyArgs,VarDict,KeyArgCopies)
4863 ( KeyArgCopies = [KeyCopy] ->
4866 KeyCopy =.. [k|KeyArgCopies]
4869 multi_hash_via_lookup_name(F/A,Index,ViaName),
4870 LookupGoal =.. [ViaName,KeyCopy,AllSusps],
4871 create_get_mutable_ref(active,State,GetMutable),
4874 'chr sbag_member'(Susp,AllSusps),
4878 hash_index_filter(Pairs,Index,NPairs),
4879 update_store_type(F/A,multi_hash([Index])).
4880 existential_lookup(StoreType,Head,PreJoin,VarDict,SuspTerm,State,Goal,Susp,Pairs,Pairs) :-
4881 lookup_passive_head(StoreType,Head,PreJoin,VarDict,UGoal,Susps),
4882 create_get_mutable_ref(active,State,GetMutable),
4885 'chr sbag_member'(Susp,Susps),
4890 hash_index_filter(Pairs,Index,NPairs) :-
4896 hash_index_filter(Pairs,NIndex,1,NPairs).
4898 hash_index_filter([],_,_,[]).
4899 hash_index_filter([P|Ps],Index,N,NPairs) :-
4904 hash_index_filter(Ps,[I|Is],NN,NPs)
4907 hash_index_filter(Ps,Is,NN,NPs)
4913 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4914 assume_constraint_stores([]).
4915 assume_constraint_stores([C|Cs]) :-
4916 ( only_ground_indexed_arguments(C),
4918 get_store_type(C,default) ->
4919 get_indexed_arguments(C,IndexedArgs),
4920 findall(Index,(sublist(Index,IndexedArgs), Index \== []),UnsortedIndexes),
4921 predsort(longer_list,UnsortedIndexes,Indexes),
4922 ( get_functional_dependency(C,1,Pattern,Key),
4923 all_distinct_var_args(Pattern), Key == [] ->
4924 assumed_store_type(C,global_singleton)
4926 assumed_store_type(C,multi_store([multi_hash(Indexes),global_ground]))
4931 assume_constraint_stores(Cs).
4933 longer_list(R,L1,L2) :-
4943 all_distinct_var_args(Term) :-
4945 copy_term_nat(Args,NArgs),
4946 all_distinct_var_args_(NArgs).
4948 all_distinct_var_args_([]).
4949 all_distinct_var_args_([X|Xs]) :-
4952 all_distinct_var_args_(Xs).
4954 get_indexed_arguments(C,IndexedArgs) :-
4956 get_indexed_arguments(1,A,C,IndexedArgs).
4958 get_indexed_arguments(I,N,C,L) :-
4961 ; ( is_indexed_argument(C,I) ->
4967 get_indexed_arguments(J,N,C,T)
4970 validate_store_type_assumptions([]).
4971 validate_store_type_assumptions([C|Cs]) :-
4972 validate_store_type_assumption(C),
4973 validate_store_type_assumptions(Cs).
4975 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4976 % new code generation
4977 universal_search_iterator_end([CurrentHead|PrevHeads],NextHeads,Rule,F/A,Id,L,T) :-
4978 Rule = rule(H1,_,Guard,Body),
4980 functor(CurrentHead,CF,CA),
4981 check_fd_lookup_condition(CF,CA,CurrentHead,PrevHeads) ->
4984 gen_var_susp_list_for_b(PrevHeads,[CurrentHead,NextHeads,Guard,Body],_,VarsAndSuspsList,FirstVarsSusp,_,PrevIterators),
4985 universal_search_iterator_failure_vars(PrevHeads,Id,VarsAndSuspsList,FirstVarsSusp,PrevIterators,PrevVarsAndSusps,PrevId),
4986 flatten(VarsAndSuspsList,VarsAndSusps),
4987 Vars = [ [] | VarsAndSusps],
4988 build_head(F,A,Id,Vars,Head),
4989 build_head(F,A,PrevId,PrevVarsAndSusps,PredecessorCall),
4990 Clause = ( Head :- PredecessorCall),
4994 % skips back intelligently over global_singleton lookups
4995 universal_search_iterator_failure_vars(PrevHeads,Id,VarsAndSuspsList,BaseCallArgs,PrevIterators,PrevVarsAndSusps,PrevId) :-
4998 PrevVarsAndSusps = BaseCallArgs
5000 VarsAndSuspsList = [_|AllButFirstList],
5002 ( PrevHeads = [PrevHead|PrevHeads1],
5003 functor(PrevHead,F,A),
5004 check_fd_lookup_condition(F,A,PrevHead,PrevHeads1) ->
5005 PrevIterators = [_|PrevIterators1],
5006 universal_search_iterator_failure_vars(PrevHeads1,PrevId1,AllButFirstList,BaseCallArgs,PrevIterators1,PrevVarsAndSusps,PrevId)
5009 flatten(AllButFirstList,AllButFirst),
5010 PrevIterators = [PrevIterator|_],
5011 PrevVarsAndSusps = [PrevIterator|AllButFirst]
5015 universal_search_iterator([NextHead|RestHeads],[CurrentHead|PreHeads],Rule,F/A,Id,L,T) :-
5016 Rule = rule(_,_,Guard,Body),
5017 gen_var_susp_list_for_b(PreHeads,[CurrentHead,NextHead,RestHeads,Guard,Body],VarDict,PreVarsAndSuspsList,FirstVarsSusp,AllSusps,PrevIterators),
5018 init(AllSusps,PreSusps),
5019 flatten(PreVarsAndSuspsList,PreVarsAndSusps),
5020 gen_var(OtherSusps),
5021 functor(CurrentHead,OtherF,OtherA),
5022 gen_vars(OtherA,OtherVars),
5023 head_info(CurrentHead,OtherA,OtherVars,OtherSusp,_VarsSusp,HeadPairs),
5024 get_constraint_mode(OtherF/OtherA,Mode),
5025 head_arg_matches(HeadPairs,Mode,VarDict,FirstMatching,VarDict1),
5027 OtherSuspension =.. [suspension,_,State,_,_,_,_|OtherVars],
5029 different_from_other_susps(CurrentHead,OtherSusp,PreHeads,PreSusps,DiffSuspGoals),
5030 create_get_mutable_ref(active,State,GetMutable),
5032 OtherSusp = OtherSuspension,
5037 lookup_passive_head(NextHead,[CurrentHead|PreHeads],VarDict1,NextSuspGoal,NextSusps),
5038 inc_id(Id,NestedId),
5039 ClauseVars = [[OtherSusp|OtherSusps]|PreVarsAndSusps],
5040 build_head(F,A,Id,ClauseVars,ClauseHead),
5041 passive_delegate_variables(CurrentHead,PreHeads,[NextHead,RestHeads,Guard,Body],VarDict1,CurrentHeadVars),
5042 append([NextSusps|CurrentHeadVars],[OtherSusp,OtherSusps|PreVarsAndSusps],NestedVars),
5043 build_head(F,A,NestedId,NestedVars,NestedHead),
5045 ( check_fd_lookup_condition(OtherF,OtherA,CurrentHead,PreHeads) -> % iterator (OtherSusps) is empty at runtime
5046 universal_search_iterator_failure_vars(PreHeads,Id,PreVarsAndSuspsList,FirstVarsSusp,PrevIterators,PreVarsAndSusps1,PrevId),
5047 RecursiveVars = PreVarsAndSusps1
5049 RecursiveVars = [OtherSusps|PreVarsAndSusps],
5052 build_head(F,A,PrevId,RecursiveVars,RecursiveHead),
5065 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5068 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5069 % Observation Analysis
5074 % Analysis based on Abstract Interpretation paper.
5077 % stronger analysis domain [research]
5080 initial_call_pattern/1,
5082 final_answer_pattern/2,
5083 abstract_constraints/1,
5092 :- chr_option(mode,initial_call_pattern(+)).
5093 :- chr_option(mode,call_pattern(+)).
5094 :- chr_option(mode,final_answer_pattern(+,+)).
5095 :- chr_option(mode,abstract_constraints(+)).
5096 :- chr_option(mode,depends_on(+,+)).
5097 :- chr_option(mode,depends_on_as(+,+,+)).
5098 :- chr_option(mode,depends_on_ap(+,+,+,+)).
5099 :- chr_option(mode,depends_on_goal(+,+)).
5100 :- chr_option(mode,ai_observed(+,+)).
5101 :- chr_option(mode,ai_is_observed(+,+)).
5102 :- chr_option(mode,ai_not_observed(+,+)).
5104 ai_observed(C,O) \ ai_not_observed(C,O) <=> true.
5105 ai_not_observed(C,O) \ ai_not_observed(C,O) <=> true.
5106 ai_observed(C,O) \ ai_observed(C,O) <=> true.
5108 ai_not_observed(C,O) \ ai_is_observed(C,O) <=> fail.
5109 ai_is_observed(_,_) <=> true.
5111 ai_observation_analysis(ACs) :-
5112 ( chr_pp_flag(ai_observation_analysis,on) ->
5113 list_to_ord_set(ACs,ACSet),
5114 abstract_constraints(ACs),
5115 ai_observation_schedule_initial_calls(ACs)
5120 ai_observation_schedule_initial_calls([]).
5121 ai_observation_schedule_initial_calls([AC|ACs]) :-
5122 ai_observation_schedule_initial_call(AC),
5123 ai_observation_schedule_initial_calls(ACs).
5125 ai_observation_schedule_initial_call(AC) :-
5126 ai_observation_top(AC,CallPattern),
5127 initial_call_pattern(CallPattern).
5129 ai_observation_schedule_new_calls([],AP).
5130 ai_observation_schedule_new_calls([AC|ACs],AP) :-
5132 initial_call_pattern(odom(AC,Set)),
5133 ai_observation_schedule_new_calls(ACs,AP).
5135 final_answer_pattern(CP,AP1) \ final_answer_pattern(CP,AP2)
5137 ai_observation_leq(AP2,AP1)
5141 initial_call_pattern(CP) \ initial_call_pattern(CP) <=> true.
5143 initial_call_pattern(CP) ==> call_pattern(CP).
5145 initial_call_pattern(CP), final_answer_pattern(CP,AP),
5146 abstract_constraints(ACs) ==>
5147 ai_observation_schedule_new_calls(ACs,AP).
5149 call_pattern(CP) \ call_pattern(CP) <=> true.
5151 depends_on(CP1,CP2), final_answer_pattern(CP2,AP) ==>
5152 final_answer_pattern(CP1,AP).
5155 call_pattern(odom([],Set)) ==>
5156 final_answer_pattern(odom([],Set),odom([],Set)).
5159 call_pattern(odom([G|Gs],Set)) ==>
5161 depends_on_goal(odom([G|Gs],Set),CP1),
5164 depends_on_goal(CP1,CP2), final_answer_pattern(CP2,AP2) \ depends_on(CP1,_)
5166 depends_on_goal(CP1,CP2), final_answer_pattern(CP2,AP2)
5168 CP1 = odom([_|Gs],_),
5172 depends_on(CP1,CCP).
5175 call_pattern(odom(builtin,Set)) ==>
5176 % writeln(' - AbstractSolve'),
5177 ord_empty(EmptySet),
5178 final_answer_pattern(odom(builtin,Set),odom([],EmptySet)).
5181 call_pattern(odom(occ(C,O),Set)), max_occurrence(C,MO) ==>
5183 % writeln(' - AbstractDrop'),
5184 final_answer_pattern(odom(occ(C,O),Set),odom([],Set)).
5187 call_pattern(odom(AC,Set)), abstract_constraints(ACs)
5189 memberchk_eq(AC,ACs)
5191 % writeln(' - AbstractActivate'),
5192 CP = odom(occ(AC,1),Set),
5194 depends_on(odom(AC,Set),CP).
5197 call_pattern(odom(occ(C,O),Set)), abstract_constraints(ACs), occurrence(C,O,RuleNb,ID), rule(RuleNb,Rule) ==>
5198 Rule = pragma(rule(H1,H2,G,Body),ids(IDs1,_),_,_,_),
5199 memberchk_eq(ID,IDs1) |
5200 % writeln(' - AbstractSimplify'),
5202 select2(ID,_,IDs1,H1,_,RestH1),
5203 ai_observation_abstract_constraints(RestH1,ACs,ARestHeads),
5204 ai_observation_observe_list(odom([],Set),ARestHeads,odom([],Set1)),
5205 ai_observation_abstract_constraints(H2,ACs,AH2),
5206 ai_observation_observe_list(odom([],Set1),AH2,odom([],Set2)),
5207 ai_observation_abstract_goal(Body,ACs,AG),
5208 call_pattern(odom(AG,Set2)),
5211 DCP = odom(occ(C,NO),Set),
5213 depends_on_as(odom(occ(C,O),Set),odom(AG,Set2),DCP).
5215 depends_on_as(CP,CPS,CPD),
5216 final_answer_pattern(CPS,APS),
5217 final_answer_pattern(CPD,APD) ==>
5218 ai_observation_lub(APS,APD,AP),
5219 final_answer_pattern(CP,AP).
5222 call_pattern(odom(occ(C,O),Set)), abstract_constraints(ACs), occurrence(C,O,RuleNb,ID), rule(RuleNb,Rule) ==>
5223 Rule = pragma(rule(H1,H2,G,Body),ids(_,IDs2),_,_,_),
5224 memberchk_eq(ID,IDs2)
5226 % writeln(' - AbstractPropagate'),
5228 select2(ID,_,IDs2,H2,_,RestH2),
5229 ai_observation_abstract_constraints(RestH2,ACs,ARestHeads),
5230 ai_observation_observe_list(odom([],Set),ARestHeads,odom([],Set1)),
5231 ai_observation_abstract_constraints(H1,ACs,AH1),
5232 ai_observation_observe_list(odom([],Set1),AH1,odom([],Set2)),
5233 ord_add_element(Set2,C,Set3),
5234 ai_observation_abstract_goal(Body,ACs,AG),
5235 call_pattern(odom(AG,Set3)),
5236 ( ord_memberchk(C,Set2) ->
5243 DCP = odom(occ(C,NO),Set),
5245 depends_on_ap(odom(occ(C,O),Set),odom(AG,Set3),DCP,Delete).
5248 depends_on_ap(CP,CPP,CPD,Delete), final_answer_pattern(CPD,APD) ==>
5250 final_answer_pattern(CP,APD).
5251 depends_on_ap(CP,CPP,CPD,Delete), final_answer_pattern(CPP,APP),
5252 final_answer_pattern(CPD,APD) ==>
5254 CP = odom(occ(C,O),_),
5255 ( ai_observation_is_observed(APP,C) ->
5258 ai_not_observed(C,O)
5261 APP = odom([],Set0),
5262 ord_del_element(Set0,C,Set),
5267 ai_observation_lub(NAPP,APD,AP),
5268 final_answer_pattern(CP,AP).
5270 ai_observation_lub(odom(AG,S1),odom(AG,S2),odom(AG,S3)) :-
5271 ord_intersect(S1,S2,S3).
5273 ai_observation_top(AG,odom(AG,EmptyS)) :-
5276 ai_observation_leq(odom(AG,S1),odom(AG,S2)) :-
5279 ai_observation_observe_list(odom(AG,S),ACs,odom(AG,NS)) :-
5280 list_to_ord_set(ACs,ACSet),
5281 ord_subtract(S,ACSet,NS).
5283 ai_observation_abstract_constraint(C,ACs,AC) :-
5288 ai_observation_abstract_constraints(Cs,ACs,NACs) :-
5289 findall(NAC,(member(C,Cs),ai_observation_abstract_constraint(C,ACs,NAC)),NACs).
5291 ai_observation_abstract_goal(G,ACs,AG) :-
5292 ai_observation_abstract_goal(G,ACs,AG,[]).
5294 ai_observation_abstract_goal((G1,G2),ACs,List,Tail) :- !, % conjunction
5295 ai_observation_abstract_goal(G1,ACs,List,IntermediateList),
5296 ai_observation_abstract_goal(G2,ACs,IntermediateList,Tail).
5297 ai_observation_abstract_goal((G1;G2),ACs,List,Tail) :- !, % disjunction
5298 ai_observation_abstract_goal(G1,ACs,List,IntermediateList),
5299 ai_observation_abstract_goal(G2,ACs,IntermediateList,Tail).
5300 ai_observation_abstract_goal((G1->G2),ACs,List,Tail) :- !, % if-then
5301 ai_observation_abstract_goal(G1,ACs,List,IntermediateList),
5302 ai_observation_abstract_goal(G2,ACs,IntermediateList,Tail).
5303 ai_observation_abstract_goal(C,ACs,[AC|Tail],Tail) :-
5304 ai_observation_abstract_constraint(C,ACs,AC), !. % CHR constraint
5305 ai_observation_abstract_goal(true,_,Tail,Tail) :- !.
5306 ai_observation_abstract_goal(writeln(_),_,Tail,Tail) :- !.
5307 ai_observation_abstract_goal(G,_,[AG|Tail],Tail) :-
5308 AG = builtin. % default case if goal is not recognized
5310 ai_observation_is_observed(odom(_,ACSet),AC) :-
5311 \+ ord_memberchk(AC,ACSet).
5313 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5314 unconditional_occurrence(C,O) :-
5315 get_occurrence(C,O,RuleNb,ID),
5316 get_rule(RuleNb,PRule),
5317 PRule = pragma(ORule,_,_,_,_),
5318 copy_term_nat(ORule,Rule),
5319 Rule = rule(H1,H2,Guard,_),
5320 guard_entailment:entails_guard([chr_pp_headvariables(H1,H2)],Guard),
5322 H1 = [Head], H2 == []
5324 H2 = [Head], H1 == [], \+ may_trigger(C)
5328 unconditional_occurrence_args(Args).
5330 unconditional_occurrence_args([]).
5331 unconditional_occurrence_args([X|Xs]) :-
5334 unconditional_occurrence_args(Xs).
5336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5337 % Generate rules that implement chr_show_store/1 functionality.
5343 % Generates additional rules:
5345 % $show, C1 # ID ==> writeln(C1) pragma passive(ID).
5347 % $show, Cn # ID ==> writeln(Cn) pragma passive(ID).
5350 generate_show_constraint(Constraints0,Constraints,Rules0,Rules) :-
5351 ( chr_pp_flag(show,on) ->
5352 Constraints = ['$show'/0|Constraints0],
5353 generate_show_rules(Constraints0,Rules,[Rule|Rules0]),
5354 inc_rule_count(RuleNb),
5356 rule(['$show'],[],true,true),
5363 Constraints = Constraints0,
5367 generate_show_rules([],Rules,Rules).
5368 generate_show_rules([F/A|Rest],[Rule|Tail],Rules) :-
5370 inc_rule_count(RuleNb),
5372 rule([],['$show',C],true,writeln(C)),
5378 generate_show_rules(Rest,Tail,Rules).