18
19:- module(env,
20 [ init_env//0
21 , key//1
22 , key_val//2
23 , ins_key//1
24 , ins_key//2
25 , get_key//2
26 , get_key//3
27 , set_key//2
28 , upd_key//3
29 , with_key//2
30 , del_key//1
31 , sel_key//2
32 , with_env/1
33 , ins_keys//1
34 , sel_keys//1
35 ]). 36
37:- meta_predicate with_key(+,//,+,-), with_env(:).
47:- use_module(library(dcg_core)). 48:- use_module(library(rbtrees)). 49
50user:goal_expansion(no_fail(K,S,G), (G -> true; check(K,S), throw(failed(G)))).
51user:portray(t(_,_)) :- write('<rbtree/2>').
55init_env --> set_with(rb_empty).
59key(K,S,S) :- rb_in(K,_,S).
63key_val(K,V,S,S) :- rb_in(K,V,S).
67get_key(K,V,D,S,S) :- (rb_lookup(K,V,S) -> true; V=D).
71get_key(K,V,S,S) :- no_fail(K, S, rb_lookup(K,V,S)).
75set_key(K,V,S1,S2) :- no_fail(K, S1, rb_update(S1,K,V,S2)).
79upd_key(K,V1,V2,S1,S2) :- no_fail(K, S1, rb_update(S1,K,V1,V2,S2)).
83del_key(K,S1,S2) :- no_fail(K, S1, rb_delete(S1,K,S2)).
87sel_key(K,V,S1,S2) :- no_fail(K, S1, rb_delete(S1,K,V,S2)).
93ins_key(K,S1,S2) :- ins_key(K,_,S1,S2).
94ins_key(K,V,S1,S2) :-
95 ( var(K) -> throw(instantiation_error('environment key'))
96 ; rb_in(K,_,S1) -> throw(error(key_exists(K)))
97 ; no_fail(K, S1, rb_insert_new(S1,K,V,S2))
98 ).
102with_key(K,P,S1,S2) :- check(K,S1), rb_apply(S1,K,call_dcg(P),S2).
107with_env(G) :- init_env(_,E), call_dcg(G,E,_).
108
109
110check(K,S) :-
111 ( var(K) -> throw(instantiation_error('environment key'))
112 ; rb_in(K,_,S) -> true
113 ; throw(error(key_not_found(K)))
114 ).
115
116prolog:message(error(key_not_found(K))) -->
117 [ 'Key (~w) not found in current environment.'-[K], nl].
118
119prolog:message(error(key_exists(K))) -->
120 [ 'Key (~w) already present in current environment.'-[K], nl].
125
126
127ins_keys([]) --> !.
128ins_keys([(K,V)|KX]) --> ins_key(K,V), ins_keys(KX).
129
130sel_keys([]) --> !.
131sel_keys([(K,V)|KX]) --> sel_key(K,V), sel_keys(KX)
Environments for stateful computations
This module provides DCG compatible rules for managing a state variable which consistists of an environment, which contains a set of key-value mappings. The predicates do a number of checks to ensure safe and consistant use. */