ELF> @@Ì:- module(freeze, [freeze/2, frozen/2]). /** Provides the constraint `freeze/2`. */ :- use_module(library(atts)). :- use_module(library(dcgs)). :- meta_predicate(freeze(-, 0)). :- attribute(frozen/1). verify_attributes(Var, Other, Goals) :- get_atts(Var, frozen(Fa)), !, % are we involved? ( var(Other) -> % must be attributed then ( get_atts(Other, frozen(Fb)) % has a pending goal? -> put_atts(Other, frozen((Fb,Fa))) % rescue conjunction ; put_atts(Other, frozen(Fa)) % rescue the pending goal ), Goals = [] ; Goals = [Fa] ). verify_attributes(_, _, []). %% freeze(Var, Goal) % % Schedules Goal to be executed when Var is instantiated. This can % be useful to observe the exact moment a variable becomes bound to a % more concrete term, for example when creating animations of search % processes. Higher-level constructs such as `phrase_from_file/2` can % also be implemented with `freeze/2`, by scheduling a goal that % reads additional data from a file as soon as it is needed. freeze(X, Goal) :- put_atts(Fresh, frozen(Goal)), Fresh = X. attribute_goals(Var) --> { get_atts(Var, frozen(Goals)), put_atts(Var, -frozen(_)) }, [freeze:freeze(Var, Goals)]. %% frozen(Var, Goal) :- use_module(library(lists)). :- help(freeze(-var,+goal), [iso(false)]). :- help(frozen(@term,-goal), [iso(false)]). frozen(Term, Goal) :- term_attributed_variables_(Term, Vs), collect_atts_(Vs, [], AttsList), collect_goals_(Vs, [], Gs), reapply_atts_(Vs, AttsList), ( Gs = [] -> Goal = true ; flatten(Gs, Gs2), list_to_conjunction(Gs2, Fresh), Fresh = Goal ). collect_atts_([], AttsList, AttsList). collect_atts_([X|Tail], AttsList0, AttsList) :- get_atts(X, Atts), collect_atts_(Tail, [Atts|AttsList0], AttsList). reapply_atts_([], _). reapply_atts_([X|Tail], [Atts|Tail2]) :- put_atts(X, Atts), reapply_atts_(Tail, Tail2). GCC: (OpenIndiana 14.3.0-oi-0) 14.3.0ñÿ   Ìfreeze.clibrary_freeze_pl_lenlibrary_freeze_pl.symtab.strtab.shstrtab.text.data.bss.comment@!@ì ',,0,'X`  ¸2 ê5