25
26:- module(multivar,
27 [
28 test_case_1/0,
29 test_case_2/0,
30 test_case_3/0,
31 test_case_4/0
32 44 ]). 45
46:- use_module(logicmoo_common). 47:- meta_predicate user:attvar_variant(0,0). 48:- use_module(library(option),[dict_options/2,option/2]). 49
52
54
55mdwq(Q):- format(user_error,'~NMWQ: ~q~n',[Q]).
56
57:- meta_predicate mdwq_call(*). 58mdwq_call(Q):- !, call(Q).
59mdwq_call(Q):- call(Q) *-> mdwq(success:Q); (mdwq(failed:Q),!,fail).
60:- export(mdwq_call/1). 61
62:- if(current_prolog_flag(attr_pre_unify_hook,true)). 63
64:- module_transparent(user:attr_pre_unify_hook/3). 65:- user:export(user:attr_pre_unify_hook/3). 66
67:- '$set_source_module'('$attvar'). 68
69:- module_transparent(system : = /2). 70:- module_transparent(wakeup/2). 71:- module_transparent('$wakeup'/1). 72wakeup(wakeup(Attribute, Value, Rest),M) :- !,
73 begin_call_all_attr_uhooks(Attribute, Value, M),
74 '$wakeup'(Rest).
75wakeup(_,_).
76
77:- import(user:attr_pre_unify_hook/3). 78:- module_transparent(user:attr_pre_unify_hook/3). 80begin_call_all_attr_uhooks(att('$VAR$', IDVar, Attrs),Value, M) :- !,
81 M:attr_pre_unify_hook(IDVar, Value, Attrs).
82begin_call_all_attr_uhooks(Attribute, Value, M) :-
83 call_all_attr_uhooks(Attribute, Value, M).
84
85orig_call_all_attr_uhooks([], _).
86orig_call_all_attr_uhooks(att(Module, AttVal, Rest), Value) :-
87 uhook(Module, AttVal, Value),
88 orig_call_all_attr_uhooks(Rest, Value).
89
90
91:- module_transparent(call_all_attr_uhooks/3). 92call_all_attr_uhooks(att(Module, AttVal, Rest), Value, M) :- !,
93 uhook(Module, AttVal, Value, M),
94 call_all_attr_uhooks(Rest, Value, M).
95call_all_attr_uhooks(_, _, _).
96
97:- module_transparent(uhook/4). 98uhook(freeze, Goal, Y, M) :-
99 M:(
100 !,
101 ( attvar(Y)
102 -> ( get_attr(Y, freeze, G2)
103 -> put_attr(Y, freeze, '$and'(G2, Goal))
104 ; put_attr(Y, freeze, Goal)
105 )
106 ; '$attvar':unfreeze(Goal)
107 )).
108
109uhook(Module, AttVal, Value, M) :-
110 M:(
111 true,
112 Module:attr_unify_hook(AttVal, Value)).
113
114
115:- ((abolish('$wakeup'/1),'$attvar':asserta('$wakeup'(M:G):-wakeup(G,M)))). 116:- meta_predicate('$wakeup'(:)). 117
118:- all_source_file_predicates_are_transparent. 119
120:- '$set_source_module'('multivar'). 121
122:- module_transparent(attr_pre_unify_hook_m/4). 123attr_pre_unify_hook_m(IDVar, Value, _, M):- \+ attvar(IDVar),!, M:(IDVar=Value).
124attr_pre_unify_hook_m(Var,Value,Rest, M):-
125 mdwq_call('$attvar':call_all_attr_uhooks(Rest, Value, M)),
126 nop(M:mv_add1(Var,Value)).
127
128user:attr_pre_unify_hook(Var,Value,Rest):- strip_module(Rest,M,_), attr_pre_unify_hook_m(Var,Value,Rest,M).
129
130:- else. 131
132:- module_transparent(user:meta_unify/3). 133user:meta_unify(Var,Rest,Value):- user:attr_pre_unify_hook(Var,Value,Rest).
134
137
138
139user:attr_pre_unify_hook(IDVar, Value, _):- \+ attvar(IDVar),!, IDVar=Value.
147user:attr_pre_unify_hook(Var,Value,Rest):-
148 mdwq_call('$attvar':call_all_attr_uhooks(Rest, Value)),
149 nop(mv_add1(Var,Value)).
150
151:- endif. 152
153
154
155call_verify_attributes([], _, _) --> [].
156call_verify_attributes(att(Module, _, Rest), Value, IDVar) -->
157 { Module:verify_attributes(IDVar, Value, Goals) },
158 Goals,
159 call_verify_attributes(Rest, Value, IDVar).
160
162use_va(Var):-
163 put_attr(Var,'$VAR$',Var).
164
166
167verify_attributes(Var, _, Goals) :-
168 get_attr(Var, '$VAR$', Info), !,
169 \+ contains_var(Var,Info),
170 Goals=[].
171
172verify_attributes(_, _, []).
173
174
176
177swiu_case_1 :-
178 use_va(Y), put_attr(Y,'$VAR$',Y),
179 Y = 4201.
180
182test_case_1 :- \+ swiu_case_1.
183
184
186
188
189swiu_case_2 :-
190 use_va(Y), put_attr(Y, '$VAR$', al(Y,a(X))),
191 X = 420,
192 Y = 420.
193
195test_case_2 :- \+ swiu_case_2.
196
197
200
201swiu_case_3 :-
202 use_va(Y), put_attr(Y,'$VAR$', a(420)),
203 Y = 420.
204
206test_case_3 :- swiu_case_3.
207
208
209
212
213swiu_case_4 :-
214 use_va(Y), put_attr(Y,'$VAR$', X),
215 X = 420,
216 Y = 420.
217
219test_case_4 :- swiu_case_4.
220
221
225
227
228
231
232xvarx(Var):-
233 get_attr(Var,'$VAR$',MV)-> var(MV) ;
234 (get_attrs(Var,Attrs) -> put_attrs(Var,att('$VAR$',Var,Attrs)) ;
235 (true -> put_attrs(Var,att('$VAR$',Var,[])))).
236
237
238
240is_mv(Var):- attvar(Var),get_attr(Var,'$VAR$',_Waz).
241
245
246'$VAR$':attr_unify_hook(_,_).
247'$VAR$':attribute_goals(Var) --> {is_implied_xvarx(Var)}->[] ; [xvarx(Var)].
248
249is_implied_xvarx(MV):- get_attrs(MV,ATTS),is_implied_xvarx(MV,ATTS).
250is_implied_xvarx(MV,att(M,Val,ATTS)):- ((Val==MV, \+ atom_concat('$',_,M)) -> true ; is_implied_xvarx(MV,ATTS)).
254
255'variant':attr_unify_hook(_,_).
256user:attvar_variant(N,Var):- (N==Var -> true ; mdwq_call( \+ \+ =(N,Var) )).
257
261
262'references':attr_unify_hook(_,_).
263user:attvar_references(N,Var):- (N==Var -> true ; mdwq_call( \+ \+ =(N,Var) )).
264
265
269multivar(Var):- var(Var)->multivar1(Var);(term_variables(Var,Vars),maplist(multivar1,Vars)).
270multivar1(Var):- xvarx(Var),(get_attr(Var,'$value',lst(Var,_))->true; put_attr(Var,'$value',lst(Var,[]))).
271'$value':attr_unify_hook(lst(Was,Values),Becoming):- var(Was),attvar(Becoming),!,mv_add_values(Becoming,Values).
272'$value':attr_unify_hook(lst(Var,_Values),Value):- mv_add1(Var,Value).
273
275'$value':attribute_goals(Var)--> {get_attr(Var,'$value',lst(Var,Values))},[mv_set_values(Var,Values)].
276mv_set_values(Var,Values):- put_attr(Var,'$value',lst(Var,Values)).
277mv_set1(Var,Value):- put_attr(Var,'$value',lst(Var,[Value])).
278mv_add1(Var,NewValue):- Var==NewValue,!.
279mv_add1(Var,NewValue):- mv_prepend1(Var,'$value',NewValue).
280mv_add_values(Becoming,Values):- maplist(mv_add1(Becoming),Values).
281
282
283mv_prepend1(Var,Mod,Value):- get_attr(Var,Mod,lst(Var,Was))->(prepend_val(Value,Was,New)->put_attr(Var,Mod,lst(Var,New)));put_attr(Var,Mod,lst(Var,[Value])).
284mv_prepend_values(Becoming,Mod,Values):- maplist(mv_prepend1(Becoming,Mod),Values).
285
286prepend_val(Value,[],[Value]).
287prepend_val(Value,Was,[Value|NewList]):-delete_identical(Was,Value,NewList).
288
289delete_identical([],_,[]).
290delete_identical([Elem0|NewList],Elem1,NewList):-Elem1==Elem0,!.
291delete_identical([ElemKeep|List],Elem1,[ElemKeep|NewList]):-delete_identical(List,Elem1,NewList).
292
294mv_prepend(Var,Mod,Value):- get_attr(Var,Mod,lst(Var,Was))->
295 put_attr(Var,Mod,lst(Var,[Value|Was]));
296 put_attr(Var,Mod,lst(Var,[Value])).
297
301
302mv_peek_value(Var,Value):- mv_members(Var,'$value',Value).
303mv_peek_value1(Var,Value):- mv_peek_value(Var,Value),!.
304
305
306
310
311mv_members(Var,Mod,Value):- get_attr(Var,Mod,lst(_,Values)),!,member(Value,Values).
313
314
315guard_from_var(V):- nonvar(V),!.
316guard_from_var(V):- attvar(V),!.
317guard_from_var(V):- xvarx(V),!.
318
322
323check_allow(Var,Value):- get_attr(Var,'$allow',lst(Var,Disallow)), memberchk_variant_mv(Value,Disallow).
324mv_allow(Var,Allow):- guard_from_var(Allow),mv_prepend(Var,'$allow',Allow).
325'$allow':attr_unify_hook(lst(Var,Allow),Value):- \+ ((memberchk_variant_mv(Value,Allow)->true;get_attr(Var,ic_text,_))),!,fail.
326'$allow':attr_unify_hook(lst(Was,Values),Becoming):-
327 ignore((var(Was),attvar(Becoming),!,mv_prepend_values(Becoming,'$allow',Values))).
328'$allow':attribute_goals(Var)--> {get_attr(Var,'$allow',Allow)},[mv_allow(Var,Allow)].
329
333
334check_disallow(Var,Value):- (get_attr(Var,'$disallow',lst(Var,Disallow)) -> \+ memberchk_variant_mv(Value,Disallow) ; true).
335mv_disallow(Var,Disallow):- guard_from_var(Disallow),mv_prepend(Var,'$disallow',Disallow).
336'$disallow':attr_unify_hook(lst(_Var,Disallow),Value):- memberchk_variant_mv(Value,Disallow),!,fail.
337'$disallow':attr_unify_hook(lst(Was,Values),Becoming):-
338 ignore((var(Was),attvar(Becoming),!,mv_prepend_values(Becoming,'$disallow',Values))).
339'$disallow':attribute_goals(Var)--> {get_attr(Var,'$disallow',Disallow)},[mv_disallow(Var,Disallow)].
345memberchk_variant_mv(X, List) :- is_list(List),!, \+ atomic(List), C=..[v|List],(var(X)-> (arg(_,C,YY),X==YY) ; (arg(_,C,YY),X =@= YY)),!.
346memberchk_variant_mv(X, Ys) :- nonvar(Ys), var(X)->memberchk_variant0(X, Ys);memberchk_variant1(X,Ys).
347memberchk_variant0(X, [Y|Ys]) :- X==Y ; (nonvar(Ys),memberchk_variant0(X, Ys)).
348memberchk_variant1(X, [Y|Ys]) :- X =@= Y ; (nonvar(Ys),memberchk_variant1(X, Ys)).
349
350
351
355
356un_mv(Var):-del_attr(Var,'$VAR$')->(mv_peek_value(Var,Value)*->Var=Value;true);true.
357un_mv1(Var):-del_attr(Var,'$VAR$')->ignore(mv_peek_value1(Var,Var));true.
358
359
388plvar(Var):- multivar(Var), put_attr(Var,plvar,Var).
389plvar:attr_unify_hook(Var,Value):- mv_peek_value1(Var,Was)->Value=Was;mv_set1(Var,Value).
390'plvar':attribute_goals(Var)--> {get_attr(Var,'plvar',Var)},[plvar(Var)].
391
392
394:- meta_predicate multivar_call(1,0). 395multivar_call(Type,Goal):-term_variables(Goal,Vars),maplist(Type,Vars),call(Goal).
396
397
401nb_var(Var):- gensym(nb_var_,Symbol),nb_var(Symbol, Var).
402nb_var(Symbol, Var):- multivar(Var), put_attr(Var,nb_var,lst(Var,Symbol)), nb_linkval(Symbol,Var).
403
407nb_var:attr_unify_hook(lst(_Var,Symbol),Value):-
408 nb_getval(Symbol,Prev),
409 ( 410 (var(Value),nonvar(Prev)) -> Value=Prev;
411 412 Value==Prev->true;
413 414 Value=Prev->nb_setval(Symbol,Prev)).
415
419
420
421vdict(Var):- multivar(Var), put_attr(Var,vdict,Var).
422vdict(Value,Var):- vdict(Var),Var=Value.
423vdict:attr_unify_hook(Var,OValue):- to_dict(OValue,Value)-> mv_peek_value(Var,Prev), merge_dicts(Prev,Value,Result)-> mv_set1(Var,Result).
424
425
426to_dict(Value,Value):- is_dict(Value),!.
427to_dict(OValue,Value):- is_list(OValue),!,dict_options(Value,OValue).
428to_dict(OValue,Value):- compound(OValue),!,option(OValue,[MValue]),!,dict_options(Value,[MValue]).
429to_dict(OValue,Value):- option('$value'=OValue,[MValue]),!,dict_options(Value,[MValue]).
430
431
432merge_dicts(Value,Value,Value).
433merge_dicts(Prev,Value,Prev):- Value :< Prev.
434merge_dicts(Value,Prev,Prev):- Value :< Prev.
435merge_dicts(Dict1,Dict2,Combined):- dicts_to_same_keys([Dict1,Dict2],dict_fill(_),[Combined,Combined]).
436
437
438
442
443ic_text(Var):- put_attr(Var,ic_text,Var),multivar(Var),!.
444
445ic_text:attr_unify_hook(Var,Value):- check_disallow(Var,Value),
446 ((mv_members(Var,'$allow',One);mv_peek_value1(Var,One))*-> ic_unify(One,Value)).
447
448'ic_text':attribute_goals(Var)--> {get_attr(Var,'ic_text',Var)},[ic_text(Var)].
451
452ic_unify(One,Value):- (One=Value -> true ; (term_upcase(One,UC1),term_upcase(Value,UC2),UC1==UC2)).
453
454term_upcase(Value,UC2):-catch(string_upper(Value,UC2),_,(format(string(UC1),'~w',Value),string_upper(UC1,UC2))).
465
466:- fixup_exports.