1 % (c) 2009-2024 Lehrstuhl fuer Softwaretechnik und Programmiersprachen,
2 % Heinrich Heine Universitaet Duesseldorf
3 % This software is licenced under EPL 1.0 (http://www.eclipse.org/org/documents/epl-v10.html)
4
5 :- module(kodkod_typing,[kodkod_insert_casts/4]).
6
7 :- use_module(library(lists)).
8 :- use_module(library(avl)).
9
10 :- use_module(probsrc(module_information),[module_info/2]).
11 :- use_module(probsrc(tools),[foldl/4]).
12
13 :- use_module(kodkod_tools).
14
15 :- module_info(group,kodkod).
16 :- module_info(description,'This is a small internal type checker for Kodkod expressions. It\'s needed for inserting casts between different integer representations.').
17
18 kodkod_insert_casts(Kin,TypeMap,IdMap,Kout) :-
19 create_refmap(TypeMap,IdMap,Env),
20 type_kodkod(Kin,Env,formula,Kout).
21
22 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
23 % create Kodkod typechecking environment
24 create_refmap(TypeMap,IdMap,ktypenv(Env,StartEnv)) :-
25 empty_avl(StartEnv),
26 create_refmap_types(TypeMap,StartEnv,TypeEnv),
27 create_refmap_ids(IdMap,TypeEnv,Env).
28 lookup_reltypes(Id,ktypenv(Env,_Vars),Types) :-
29 avl_fetch(Id,Env,Types).
30 lookup_vartypes(Id,ktypenv(_Env,Vars),Types) :-
31 avl_fetch(Id,Vars,Types).
32 add_var_to_type_env(Id,Types,ktypenv(E,EnvIn),ktypenv(E,EnvOut)) :-
33 avl_store(Id,EnvIn,Types,EnvOut).
34
35 create_refmap_types(TypeMap,In,Out) :-
36 avl_range(TypeMap,Relations1),
37 maplist(remove_relation_wrapper,Relations1,Relations),
38 foldl(add_to_refmap,Relations,In,Out).
39 remove_relation_wrapper(relation(_,_,Rel),Rel).
40
41 create_refmap_ids(IdMap,In,Out) :-
42 avl_range(IdMap,Relations),
43 foldl(add_to_refmap,Relations,In,Out).
44 add_to_refmap(R,In,Inter) :-
45 get_rel_types(R,Id,Types),
46 avl_store(Id,In,Types,Inter).
47 get_rel_types(reldef(Id,Types,_,_,_),Id,Types).
48 get_rel_types(intsetrel(Id,_,_),Id,[R]) :-
49 intset_relation_kodkod_name(R).
50 get_rel_types(pow2rel(Id,_,_),Id,[R]) :-
51 pow2integer_relation_kodkod_name(R).
52
53 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
54 % typechecking kodkod expressions with inserting type-casts
55
56 type_kodkod(KExpr1, Env, OuterType, OuterExpr) :-
57 ( KExpr1 = KExpr:ExpectedType ->
58 % The expression has an explicit type associated,
59 % first make sure that this expected type matches the type seen
60 % by the caller (insert cast if necessary)
61 unify_kodkod_types(ExpectedType,OuterType,Expr,OuterExpr)
62 ;
63 % If there is no explicit type given, the type seen by the
64 % outside is used as the expected type. No cast is needed
65 KExpr=KExpr1, ExpectedType=OuterType, OuterExpr=Expr
66 ),
67 % Now type-check the expression itself
68 type_kodkod2(KExpr, Env, InnerType, InnerExpr),
69 % and try to match the types (insert cat if necessary)
70 unify_kodkod_types(ExpectedType,InnerType,InnerExpr,Expr).
71
72 :- block unify_kodkod_types(-,-,?,?).
73 unify_kodkod_types(rel(A),rel(B),Expr,NewExpr) :- !,
74 ( A=B -> Expr=NewExpr
75 % both relations can be unified, good
76 ; A=[IS],intset_relation_kodkod_name(IS),
77 B=[P2I],pow2integer_relation_kodkod_name(P2I) ->
78 % expected was a set of integers but given was a set representing
79 % one integer by its bits
80 % TODO: this conversion is not optimal, better try to avoid rel([p2i])
81 NewExpr = int2intset(expr2int(Expr))
82 ; A = [P2I],pow2integer_relation_kodkod_name(P2I),
83 B = [IS],intset_relation_kodkod_name(IS)
84 -> % happens in test 709 when rewriting (x=E or x=F) into x:{E,F}
85 % ((x=y or x=z) => (y=x or z=x)) & ((x=y or x=z) <=> (y=x or z=x))
86 % Test 2197 tests it explicitly
87 NewExpr = int2pow2(expr2int(Expr))
88 ).
89 unify_kodkod_types(int_expression,int_expression,Expr,Expr) :- !.
90 unify_kodkod_types(formula,formula,Expr,Expr) :- !.
91 unify_kodkod_types(rel([R]),int_expression,Expr,int2intset(Expr)) :-
92 intset_relation_kodkod_name(R),!.
93 unify_kodkod_types(rel([R]),int_expression,Expr,int2pow2(Expr)) :-
94 pow2integer_relation_kodkod_name(R),!.
95 unify_kodkod_types(int_expression,rel([_]),Expr,expr2int(Expr)).
96 % intset_relation_kodkod_name(R).
97
98
99
100 type_kodkod2(relref(Id), Env, rel(Types), relref(Id)) :- !,
101 lookup_reltypes(Id,Env,Types).
102 type_kodkod2(varref(Id), Env, VType, K) :- !,
103 lookup_vartypes(Id,Env,Types),
104 ( Types = [p2i] ->
105 VType = int_expression, K=expr2int(varref(Id))
106 ;
107 VType = rel(Types), K=varref(Id)).
108 type_kodkod2(int(I), _Env, int_expression, int(I)) :- !.
109 type_kodkod2(prj(Pos,Arg), Env, rel(P), prj(Pos,NArg)) :-
110 !,type_kodkod(Arg,Env,rel(S),NArg),
111 nth0s(Pos,S,P).
112 type_kodkod2(forall(Decls,Formula), Env, formula, forall(NDecls,NFormula)) :-
113 !,type_quantifier(Decls,Formula,Env,_,NDecls,NFormula).
114 type_kodkod2(exists(Decls,Formula), Env, formula, exists(NDecls,NFormula)) :-
115 !,type_quantifier(Decls,Formula,Env,_,NDecls,NFormula).
116 type_kodkod2(comp(Decls,Expr), Env, rel(Types), comp(NDecls,NExpr)) :-
117 !,type_quantifier(Decls,Expr,Env,rel(Types),NDecls,NExpr).
118 type_kodkod2(Expr, Env, Type, NExpr) :-
119 functor(Expr,F,Arity),
120 functor(Lookup,F,Arity),
121 ktype(Lookup,Type),!,
122 Expr =.. [_|Args], Lookup =.. [_|Types],
123 maplist(type_kodkod3(Env),Args,Types,NArgs),
124 NExpr =.. [F|NArgs].
125 type_kodkod2(Expr, _Env, _Type, _NExpr) :-
126 throw( unsupported_kodkod_expression(Expr) ).
127
128 % just to swap arguments
129 type_kodkod3(Env,Expr,Type,NExpr) :-
130 type_kodkod(Expr,Env,Type,NExpr).
131
132 type_quantifier(Decls,Subexpr,Env,rel(Types),NDecls,NSubexpr) :-
133 type_kodkod_declarations(Decls,Env,Env,NDecls,Subenv,Types),
134 type_kodkod(Subexpr,Subenv,formula,NSubexpr).
135
136 type_kodkod_declarations([],_,Env,[],Env,[]).
137 type_kodkod_declarations([Decl|Drest],Env,EnvIn,[NDecl|Nrest],EnvOut,Types) :-
138 type_kodkod_declaration(Decl,Env,EnvIn,NDecl,EnvInter,Types1),
139 safe_append(Types1,Types2,Types),
140 type_kodkod_declarations(Drest,Env,EnvInter,Nrest,EnvOut,Types2).
141 type_kodkod_declaration(decl(Id,Arity,Mult,Expr),Env,EnvIn,
142 decl(Id,Arity,Mult,NExpr),EnvOut,Types) :-
143 add_var_to_type_env(Id,Types,Env,Subenv),
144 type_kodkod(Expr,Subenv,rel(Types),NExpr),
145 add_var_to_type_env(Id,Types,EnvIn,EnvOut).
146
147
148 ktype(true,formula).
149 ktype(false,formula).
150 ktype(not(formula),formula).
151 ktype(and(formula,formula),formula).
152 ktype(or(formula,formula),formula).
153 ktype(implies(formula,formula),formula).
154 ktype(iff(formula,formula),formula).
155
156 ktype(one(rel(_)), formula).
157 ktype(some(rel(_)), formula).
158 ktype(no(rel(_)), formula).
159 ktype(lone(rel(_)), formula).
160 ktype(set(rel(_)), formula).
161
162 ktype(in(rel(T),rel(T)), formula).
163 ktype(equals(T,T),formula).
164 ktype(pfunc(rel(_),rel(_),rel(_)), formula).
165 ktype(func(rel(_),rel(_),rel(_)), formula).
166
167 ktype(empty,rel(_)).
168 ktype(iden,rel(_)).
169 ktype(univ,rel(_)).
170 ktype(intersection(rel(A),rel(A)), rel(A)).
171 ktype(union(rel(A),rel(A)), rel(A)).
172 ktype(difference(rel(A),rel(A)), rel(A)).
173 ktype(overwrite(rel(A),rel(A)), rel(A)).
174 ktype(closure(rel(A)), rel(A)).
175 ktype(reflexive_closure(rel(A)), rel(A)).
176 ktype(product(rel(A),rel(B)), rel(C)) :- safe_append(A,B,C).
177 ktype(transpose(rel(R)), rel(T)) :- safe_reverse(R,T).
178 ktype(join(rel(A),rel([Bhead|Btail])), rel(C)) :-
179 safe_append(Astart,[Bhead],A),
180 safe_append(Astart,Btail,C).
181 ktype(if(formula,rel(R),rel(R)), rel(R)).
182
183 ktype(gt(int_expression,int_expression), formula).
184 ktype(gte(int_expression,int_expression), formula).
185 ktype(lt(int_expression,int_expression), formula).
186 ktype(lte(int_expression,int_expression), formula).
187
188 ktype(card(rel(_)), int_expression).
189 ktype(add(int_expression,int_expression), int_expression).
190 ktype(sub(int_expression,int_expression), int_expression).
191 ktype(mul(int_expression,int_expression), int_expression).
192 ktype(div(int_expression,int_expression), int_expression).
193 ktype(floored_div(int_expression,int_expression), int_expression).
194 ktype(mod(int_expression,int_expression), int_expression).
195 ktype(sum(rel([_])), int_expression).
196
197 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
198
199 nth0s(Positions,List,Elements) :- maplist(nth0s2(List),Positions,Elements).
200 nth0s2(List,Position,Element) :- nth0(Position,List,Element).
201
202 safe_append(A,B,C) :-
203 complete_list(A,AComplete),
204 complete_list(B,BComplete),
205 complete_list(C,CComplete),
206 safe_append2(A,B,C,AComplete,BComplete,CComplete).
207 :- block safe_append2(?,?,?,-,-,?), safe_append2(?,?,?,-,?,-).
208 safe_append2(A,B,C,1,1,1) :- append(A,B,C),!.
209 :- block complete_list(-,?).
210 complete_list([],1).
211 complete_list([_|T],Trigger) :- complete_list(T,Trigger).
212
213 safe_reverse(A,B) :-
214 safe_reverse2(A,[],B),
215 safe_reverse2(B,[],A).
216 :- block safe_reverse2(-,?,?).
217 safe_reverse2([],Acc,Acc).
218 safe_reverse2([H|T],Acc,Rev) :-
219 safe_reverse2(T,[H|Acc],Rev).