ELF>p @@! /** Provides the predicate `when/2`. */ :- module(when, [when/2]). :- use_module(library(atts)). :- use_module(library(dcgs)). :- use_module(library(lists)). :- use_module(library(lambda)). :- use_module(library(format)). :- use_module(library(debug)). :- attribute when_list/1. :- meta_predicate(when(+, 0)). %% when(Condition, Goal). % % Executes Goal when Condition becomes true. % Condition may consist of `ground(T)`, `nonvar(T)`, `C1,C2`, `C1;C2`. when(Condition, Goal) :- ( when_condition(Condition) -> ( Condition -> Goal ; term_variables(Condition, Vars), maplist( [Goal, Condition]+\Var^( get_atts(Var, when_list(Whens0)) -> Whens = [when(Condition, Goal) | Whens0], put_atts(Var, when_list(Whens)) ; put_atts(Var, when_list([when(Condition, Goal)])) ), Vars ) ) ; throw(error(domain_error(when_condition, Condition),_)) ). when_condition(Cond) :- % Should this be delayed? var(Cond), !, throw(error(instantiation_error,when_condition/1)). when_condition(ground(_)). when_condition(nonvar(_)). when_condition((A, B)) :- when_condition(A), when_condition(B). when_condition((A ; B)) :- when_condition(A), when_condition(B). remove_goal([], _, []). remove_goal([G0|G0s], Goal, Goals) :- ( G0 == Goal -> remove_goal(G0s, Goal, Goals) ; Goals = [G0|Goals1], remove_goal(G0s, Goal, Goals1) ). vars_remove_goal(Vars, Goal) :- maplist( Goal+\Var^( get_atts(Var, when_list(Whens0)) -> remove_goal(Whens0, Goal, Whens), ( Whens = [] -> put_atts(Var, -when_list(_)) ; put_atts(Var, when_list(Whens)) ) ; true ), Vars ). reinforce_goal(Goal0, Goal) :- Goal = ( term_variables(Goal0, Vars), when:vars_remove_goal(Vars, Goal0), Goal0 ). verify_attributes(Var, Value, Goals) :- ( get_atts(Var, when_list(Whens)) -> ( var(Value) -> ( get_atts(Value, when_list(WhensValue)) -> append(Whens, WhensValue, WhensNew), put_atts(Value, when_list(WhensNew)) ; put_atts(Value, when_list(Whens)) ), Goals = [] ; maplist(reinforce_goal, Whens, Goals) ) ; Goals = [] ). gather_when_goals([], _) --> []. gather_when_goals([When|Whens], Var) --> ( { term_variables(When, [V0|_]), Var == V0 } -> [when:When] ; [] ), gather_when_goals(Whens, Var). attribute_goals(Var) --> { get_atts(Var, when_list(Whens)) }, gather_when_goals(Whens, Var), { put_atts(Var, -when_list(_)) }. GCC: (OpenIndiana 14.3.0-oi-0) 14.3.0 ! when.clibrary_when_pl_lenlibrary_when_pl.symtab.strtab.shstrtab.text.data.bss.comment@!@A ' ,0 ' `   , 4 5