| 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(partition_detection, [detect_partitions/2, detect_all_partitions_in_predicate/2]). | |
| 6 | ||
| 7 | :- use_module(module_information,[module_info/2]). | |
| 8 | :- module_info(group,typechecker). | |
| 9 | :- module_info(description,'This module detects set partition predicates.'). | |
| 10 | ||
| 11 | :- use_module(library(lists)). | |
| 12 | :- use_module(bsyntaxtree). | |
| 13 | :- use_module(bmachine_structure,[select_section/5]). | |
| 14 | ||
| 15 | detect_partitions(In,Out) :- | |
| 16 | select_section(properties,Old,New,In,Out), | |
| 17 | detect_all_partitions_in_predicate(Old,New). | |
| 18 | ||
| 19 | % detect all set partition predicates at "top-level", not inside inner predicates (bool(.), comprehension_set,...) | |
| 20 | % this is assumed to be checked by b_ast_cleanup during bottom-up construction | |
| 21 | detect_all_partitions_in_predicate(Predicate,NewPredicate) :- | |
| 22 | ( detect_partitions_in_predicate(Predicate,P1) -> | |
| 23 | detect_all_partitions_in_predicate(P1,NewPredicate) | |
| 24 | ; otherwise -> | |
| 25 | Predicate=NewPredicate %, print('detected: '),translate:print_bexpr(NewPredicate),nl | |
| 26 | %detect_partitions_inside_predicate(Predicate,NewPredicate) % now done in b_ast_cleanup | |
| 27 | ). | |
| 28 | ||
| 29 | % detect partitions of set of the type: | |
| 30 | % x /\ y = {} & x \/ y = z | |
| 31 | detect_partitions_in_predicate(Predicate,NewPredicate) :- | |
| 32 | conjunction_to_list(Predicate,PList), | |
| 33 | detect_partitions_in_predicates(PList,PNew), | |
| 34 | conjunct_predicates(PNew,NewPredicate). | |
| 35 | detect_partitions_in_predicates(Predicates,NewPredicates) :- Predicates \= [], | |
| 36 | ? | find_union(Superset,Partitions,Predicates,P1), |
| 37 | create_pairs(Partitions,Pairs), | |
| 38 | get_texpr_type(Superset,Type), | |
| 39 | find_all_intersections(Pairs,Type,RestPairs,P1,P2), | |
| 40 | RestPairs=[], | |
| 41 | !, | |
| 42 | safe_create_texpr(partition(Superset,Partitions),pred,Part), | |
| 43 | NewPredicates=[Part|P2]. | |
| 44 | ||
| 45 | :- use_module(bsyntaxtree,[get_texpr_set_type/2]). | |
| 46 | % should we also find A = {c1,c2,...cn} with all_different(c1,...,cn) ?? | |
| 47 | find_union(Superset,Partitions,In,Out) :- | |
| 48 | ? | create_texpr(equal(A,B),pred,_,Equal), |
| 49 | ? | get_texpr_set_type(A,Type), |
| 50 | ? | get_texpr_set_type(B,Type), |
| 51 | ? | select(Equal,In,Out), |
| 52 | ( is_union(A,Partitions) -> Superset=B | |
| 53 | ; is_union(B,Partitions) -> Superset=A). | |
| 54 | is_union(Expr,Partitions) :- | |
| 55 | get_texpr_expr(Expr,union(_,_)), | |
| 56 | collect_union(Expr,Partitions,[]). | |
| 57 | collect_union(Expr) --> | |
| 58 | {get_texpr_expr(Expr,union(A,B)),!}, | |
| 59 | collect_union(A), | |
| 60 | collect_union(B). | |
| 61 | collect_union(Expr) --> [Expr]. | |
| 62 | ||
| 63 | create_pairs(Parts,Pairs) :- | |
| 64 | create_pairs2(Parts,Pairs,[]). | |
| 65 | create_pairs2([]) --> []. | |
| 66 | create_pairs2([A|Rest]) --> | |
| 67 | create_pairs3(Rest,A), | |
| 68 | create_pairs2(Rest). | |
| 69 | create_pairs3([],_) --> []. | |
| 70 | create_pairs3([B|Rest],A) --> | |
| 71 | [distinct(A,B)], | |
| 72 | create_pairs3(Rest,A). | |
| 73 | ||
| 74 | find_all_intersections(Pairs,Type,RestPairs,In,Out) :- | |
| 75 | find_all_intersections2(In,Pairs,Type,RestPairs,Out). | |
| 76 | find_all_intersections2([],Pairs,_,Pairs,[]). | |
| 77 | find_all_intersections2([Expr|Erest],Pairs,Type,RestPairs,Out) :- | |
| 78 | is_disjoint_pred(Expr,Type,A,B), | |
| 79 | remove_pair(A,B,Pairs,InterPairs),!, | |
| 80 | find_all_intersections2(Erest,InterPairs,Type,RestPairs,Out). | |
| 81 | find_all_intersections2([Expr|Erest],Pairs,Type,RestPairs,[Expr|Out]) :- | |
| 82 | find_all_intersections2(Erest,Pairs,Type,RestPairs,Out). | |
| 83 | ||
| 84 | is_disjoint_pred(b(Expr,_,_),Type,A,B) :- | |
| 85 | is_disjoint_pred2(Expr,Type,A,B). | |
| 86 | is_disjoint_pred2(equal(X,Y),_,A,B) :- % detect A /\ B = {} or {} = A /\ B | |
| 87 | ( get_texpr_expr(X,empty_set) -> Inter=Y | |
| 88 | ; get_texpr_expr(Y,empty_set) -> Inter=X), | |
| 89 | get_texpr_expr(Inter,intersection(A,B)). | |
| 90 | is_disjoint_pred2(not_equal(X,Y),set(Type),A,B) :- get_texpr_type(X,Type), | |
| 91 | A = b(set_extension([X]),set(Type),_), | |
| 92 | B = b(set_extension([Y]),set(Type),_). | |
| 93 | is_disjoint_pred2(negation(NE),Type,A,B) :- | |
| 94 | is_disjoint_neg_pred(NE,Type,A,B). | |
| 95 | ||
| 96 | is_disjoint_neg_pred(b(Expr,_,_),Type,A,B) :- | |
| 97 | is_disjoint_neg_pred2(Expr,Type,A,B). | |
| 98 | is_disjoint_neg_pred2(not_equal(X,Y),_,A,B) :- % detect A /\ B /= {} or {} /= A /\ B | |
| 99 | ( get_texpr_expr(X,empty_set) -> Inter=Y | |
| 100 | ; get_texpr_expr(Y,empty_set) -> Inter=X), | |
| 101 | get_texpr_expr(Inter,intersection(A,B)). | |
| 102 | is_disjoint_neg_pred2(equal(X,Y),set(Type),A,B) :- get_texpr_type(X,Type), | |
| 103 | A = b(set_extension([X]),set(Type),_), | |
| 104 | B = b(set_extension([Y]),set(Type),_). | |
| 105 | is_disjoint_neg_pred2(negation(NE),Type,A,B) :- | |
| 106 | is_disjoint_pred(NE,Type,A,B). | |
| 107 | ||
| 108 | remove_pair(A,B,In,Out) :- | |
| 109 | remove_all_infos(A,FA), | |
| 110 | remove_all_infos(B,FB), | |
| 111 | ? | ( select(distinct(FA,FB),In,Out) |
| 112 | ; select(distinct(FB,FA),In,Out)),!. |