| 1 | % (c) 2009-2019 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(typing_tools,[ | |
| 6 | is_infinite_type/1, % check if a type is infinite | |
| 7 | valid_ground_type/1, % check if a type is a valid ground type | |
| 8 | contains_infinite_type/1, | |
| 9 | any_value_for_type/2, | |
| 10 | normalize_type/2 | |
| 11 | ]). | |
| 12 | ||
| 13 | %:- use_module(bsyntaxtree, [get_texpr_types/2, syntaxtraversion/6, find_typed_identifier_uses/3]). | |
| 14 | :- use_module(library(lists), [maplist/3]). | |
| 15 | ||
| 16 | % check if a type is infinite for ProB animation; deferred sets are not counted as infinite here! | |
| 17 | is_infinite_type(integer). | |
| 18 | is_infinite_type(string). | |
| 19 | is_infinite_type(freetype(_)). | |
| 20 | is_infinite_type(set(X)) :- is_infinite_type(X). | |
| 21 | is_infinite_type(seq(_)). | |
| 22 | is_infinite_type(couple(X,Y)) :- (is_infinite_type(X) -> true ; is_infinite_type(Y)). | |
| 23 | is_infinite_type(record(Fields)) :- | |
| 24 | ((member(field(_,Type),Fields), is_infinite_type(Type)) -> true). | |
| 25 | ||
| 26 | contains_infinite_type([H|T]) :- | |
| 27 | (is_infinite_type(H) -> true ; contains_infinite_type(T)). | |
| 28 | ||
| 29 | :- use_module(error_manager). | |
| 30 | ||
| 31 | valid_ground_type(X) :- var(X),!, add_error(valid_ground_type,'Variable as type: ',X),fail. | |
| 32 | valid_ground_type(X) :- valid_ground_type_aux(X),!. | |
| 33 | valid_ground_type(X) :- add_error(valid_ground_type,'Illegal type term: ',X),fail. | |
| 34 | ||
| 35 | %:- use_module(b_global_sets,[b_global_set/1]). | |
| 36 | ||
| 37 | valid_ground_type_aux(any) :- format(user_error,'! Type contains *any*~n',[]). % can happen, e.g., for test 949 due to assertion prj1({{}},BOOL)({}|->TRUE) = {} | |
| 38 | valid_ground_type_aux(integer). | |
| 39 | valid_ground_type_aux(string). | |
| 40 | valid_ground_type_aux(boolean). | |
| 41 | valid_ground_type_aux(global(G)) :- atom(G). | |
| 42 | %bmachine:b_get_machine_set(G). | |
| 43 | %b_global_sets:b_global_set(G). | |
| 44 | valid_ground_type_aux(freetype(FT)) :- ground(FT). | |
| 45 | valid_ground_type_aux(set(X)) :- valid_ground_type(X). | |
| 46 | valid_ground_type_aux(seq(X)) :- valid_ground_type(X). | |
| 47 | valid_ground_type_aux(couple(X,Y)) :- valid_ground_type(X), valid_ground_type(Y). | |
| 48 | valid_ground_type_aux(record(Fields)) :- valid_fields(Fields). | |
| 49 | ||
| 50 | valid_fields([]). | |
| 51 | valid_fields([field(Name,_)|_]) :- \+ atom(Name),!, | |
| 52 | add_error(valid_ground_type,'Illegal record field name: ',Name),fail. | |
| 53 | valid_fields([field(_Name,Type)|T]) :- | |
| 54 | valid_ground_type(Type), | |
| 55 | valid_fields(T). | |
| 56 | ||
| 57 | ||
| 58 | % -------------- | |
| 59 | ||
| 60 | :- use_module(kernel_freetypes,[get_freeval_type/3]). | |
| 61 | :- use_module(b_global_sets,[b_get_fd_type_bounds/3,get_global_type_value/3]). | |
| 62 | any_value_for_type(T,V) :- if(inst2(T,V),true, (nl,print('*** instantiate_to_any_value failed: '), print(T:V),nl,nl %,trace,inst2(T,V) | |
| 63 | )). | |
| 64 | %inst2(_,V) :- ground(V),!. | |
| 65 | %inst2(Type,V) :- print(inst2(Type,V)),nl,trace,fail. | |
| 66 | inst2(boolean,V) :- !, inst3(V,pred_true). | |
| 67 | inst2(pred,V) :- !, inst3(V,pred_true). | |
| 68 | inst2(integer,V) :- !, V=int(X),inst_fd(X,0). | |
| 69 | inst2(set(_),V) :- !, inst3(V,[]). % TO DO: what if V already partially instantiated | |
| 70 | inst2(seq(_),V) :- !, inst3(V,[]). % TO DO: what if V already partially instantiated | |
| 71 | inst2(couple(TA,TB),V) :- !, V=(A,B), inst2(TA,A), inst2(TB,B). | |
| 72 | inst2(string,V) :- !, V=string(X), inst3(X,''). | |
| 73 | inst2(global(T),V) :- !, get_global_type_value(V,T,X), | |
| 74 | b_get_fd_type_bounds(T,LowBnd,_UpBnd), | |
| 75 | inst_fd(X,LowBnd). | |
| 76 | inst2(record(Fields),rec(Vals)) :- !, instantiate_fields(Fields,Vals). | |
| 77 | inst2(constant([A]),V) :- !, V=term(A). | |
| 78 | inst2(freetype(FT),V) :- !, V=freeval(FT,CASE,Val), | |
| 79 | (nonvar(CASE) -> (get_freeval_type(FT,CASE,Type) -> any_value_for_type(Type,Val)) % ensure no backtracking | |
| 80 | ; nonvar(Val) -> print((nonvar_value(V))),nl, get_freeval_type(FT,CASE,Type), any_value_for_type(Type,Val) | |
| 81 | ; (get_freeval_type(FT,C,Type) -> CASE=C, any_value_for_type(Type,Val)) | |
| 82 | ). | |
| 83 | inst2(X,V) :- print(cannot_inst2(X,V)),nl. | |
| 84 | ||
| 85 | inst3(X,V) :- (var(X) -> X=V ; true). | |
| 86 | ||
| 87 | :- use_module(probsrc(clpfd_interface), [clpfd_some_element_in_domain/2]). | |
| 88 | inst_fd(X,_) :- nonvar(X),!. | |
| 89 | inst_fd(X,_Default) :- clpfd_some_element_in_domain(X,El),!, X=El. | |
| 90 | inst_fd(X,X). | |
| 91 | ||
| 92 | instantiate_fields([],[]). | |
| 93 | instantiate_fields([field(Name,Type)|T],[field(Name,Val)|TV]) :- | |
| 94 | any_value_for_type(Type,Val), | |
| 95 | instantiate_fields(T,TV). | |
| 96 | ||
| 97 | % ---------------------- | |
| 98 | ||
| 99 | % replace seq(X) by set(couple(integer,X)) | |
| 100 | ||
| 101 | normalize_type(X,Y) :- | |
| 102 | (normalize_type_aux(X,Y) -> true ; add_internal_error('Illegal type: ',normalize_type(X,Y)),Y=X). | |
| 103 | ||
| 104 | normalize_type_aux(V,R) :- var(V),!,R=V. | |
| 105 | normalize_type_aux(any,any). | |
| 106 | normalize_type_aux(pred,pred). | |
| 107 | normalize_type_aux(subst,subst). | |
| 108 | normalize_type_aux(boolean,boolean). | |
| 109 | normalize_type_aux(integer,integer). | |
| 110 | normalize_type_aux(string,string). | |
| 111 | normalize_type_aux(global(F),global(F)). | |
| 112 | normalize_type_aux(freetype(F),freetype(F)). | |
| 113 | normalize_type_aux(set(X),set(N)) :- normalize_type_aux(X,N). | |
| 114 | normalize_type_aux(seq(X),set(couple(integer,N))) :- normalize_type_aux(X,N). | |
| 115 | normalize_type_aux(couple(X,Y),couple(NX,NY)) :- normalize_type_aux(X,NX),normalize_type_aux(Y,NY). | |
| 116 | normalize_type_aux(record(F),record(NF)) :- normalize_type_fields(F,NF). | |
| 117 | normalize_type_aux(op(A,B),op(NA,NB)) :- maplist(normalize_type_aux,A,NA), maplist(normalize_type_aux,B,NB). | |
| 118 | ||
| 119 | normalize_type_fields([],[]). | |
| 120 | normalize_type_fields([field(N,T)|R],[field(N,NT)|RN]) :- normalize_type_aux(T,NT),normalize_type_fields(R,RN). |