| 1 | % collection of code snippets | |
| 2 | ||
| 3 | set_wd_option(Options, WD) :- | |
| 4 | member(not-well-defined, Options), | |
| 5 | !, | |
| 6 | WD = no. | |
| 7 | set_wd_option(_, yes). | |
| 8 | ||
| 9 | %% insert_identifier_to_ast(+WD, +AST, +Amount, -NewAst). | |
| 10 | % Try to insert a given amount of identifier nodes to an ast, the actual amount can be less. | |
| 11 | % WD is 'yes' or 'no' for considering well-definedness. | |
| 12 | insert_identifier_to_ast(_,AST,0,AST) :- !. | |
| 13 | insert_identifier_to_ast(_,b(Node,Type,_),_,NewAST) :- | |
| 14 | (Node = min_int ; Node = max_int ; Type = boolean ; Node = integer(_) ; Node = string(_)) , | |
| 15 | generate(prob_ast_identifier(Type),NewAST). | |
| 16 | insert_identifier_to_ast(_,b(Node,Type,_),_,NewAST) :- | |
| 17 | Node =.. [_,Temp] , Type \= pred , Type \= record(_) , (Temp =.. [_] ; is_list(Temp)) , | |
| 18 | generate(prob_ast_identifier(Type),NewAST). | |
| 19 | insert_identifier_to_ast(_,b(rec(_),record(Type),_),_,NewAST) :- | |
| 20 | generate(prob_ast_identifier(record(Type)),NewAST). | |
| 21 | insert_identifier_to_ast(WD,b(Node,Type,Info),Amount,NewAST) :- | |
| 22 | Node =.. [Inner,Arg] , | |
| 23 | insert_identifier_to_ast(WD,Arg,Amount,NewArg) , | |
| 24 | NewNode =.. [Inner,NewArg] , | |
| 25 | NewAST = b(NewNode,Type,Info). | |
| 26 | % no identifier for power_of | |
| 27 | insert_identifier_to_ast(_,b(Node,Type,Info),_,NewAst) :- | |
| 28 | Node = power_of(_,_), | |
| 29 | !, | |
| 30 | NewAst = b(Node,Type,Info). | |
| 31 | insert_identifier_to_ast(yes,b(Node,Type,Info),Amount,NewAst) :- | |
| 32 | Node = div(Lhs,Rhs), | |
| 33 | !, | |
| 34 | insert_identifier_to_ast(yes,Lhs,Amount,NewLhs) , | |
| 35 | NewAst = b(div(NewLhs,Rhs),Type,Info). | |
| 36 | insert_identifier_to_ast(WD,b(Node,Type,Info),Amount,NewAST) :- | |
| 37 | Node =.. [Inner,LArg,RArg] , | |
| 38 | LAmount is Amount div 2 , | |
| 39 | RAmount is Amount - LAmount , | |
| 40 | insert_identifier_to_ast(WD,LArg,LAmount,NLArg) , | |
| 41 | insert_identifier_to_ast(WD,RArg,RAmount,NRArg) , | |
| 42 | NewNode =.. [Inner,NLArg,NRArg] , | |
| 43 | NewAST = b(NewNode,Type,Info). | |
| 44 | insert_identifier_to_ast(_,AST,_,AST). | |
| 45 | ||
| 46 | % creates the type to use in generate/2 with prefix 'prob_ast_' or 'prob_value' | |
| 47 | % only atom_concat wouldn't succeed if type is a term like set(integer([])) | |
| 48 | % ASTType is either 'ast' or 'value' | |
| 49 | ||
| 50 | % don't expand fixed values | |
| 51 | gen_type(TypeIn,_,TypeIn) :- | |
| 52 | TypeIn =.. [fixed,_]. | |
| 53 | gen_type(TypeIn,ASTType,NType) :- | |
| 54 | TypeIn =.. [set,In] , | |
| 55 | atom_concat(prob_,ASTType,Temp) , | |
| 56 | atom_concat(Temp,'_',ProBType) , | |
| 57 | atom_concat(ProBType,set,NewPre) , | |
| 58 | NType =.. [NewPre,In,[]]. % no options for ast or value sets | |
| 59 | gen_type(TypeIn,ASTType,NType) :- | |
| 60 | TypeIn =.. [Type,In1,In2] , | |
| 61 | atom_concat(prob_,ASTType,Temp) , | |
| 62 | atom_concat(Temp,'_',ProBType) , | |
| 63 | atom_concat(ProBType,Type,NewPre) , | |
| 64 | NType =.. [NewPre,In1,In2]. | |
| 65 | gen_type(TypeIn,ASTType,NType) :- | |
| 66 | TypeIn =.. [Type,In] , ! , | |
| 67 | atom_concat(prob_,ASTType,Temp) , | |
| 68 | atom_concat(Temp,'_',ProBType) , | |
| 69 | atom_concat(ProBType,Type,NewPre) , | |
| 70 | NType =.. [NewPre,In]. | |
| 71 | gen_type(Type,ASTType,NType) :- | |
| 72 | Type =.. [_] , | |
| 73 | atom_concat(prob_,ASTType,Temp) , | |
| 74 | atom_concat(Temp,'_',ProBType) , | |
| 75 | atom_concat(ProBType,Type,NType). | |
| 76 | ||
| 77 | % detype an ast like the parsers output | |
| 78 | :- multifile generate/2. | |
| 79 | generate(detype(AST),DetypedAST) :- | |
| 80 | detype_ast(AST,1,DetypedAST,_NodeAmount). | |
| 81 | ||
| 82 | detype_ast(AST,DetypedAST) :- | |
| 83 | detype_ast(AST,1,DetypedAST,_NodeAmount). | |
| 84 | % remove index of sequence elements | |
| 85 | detype_ast((_,Node),C,DetypedAST,NC) :- | |
| 86 | detype_ast(Node,C,DetypedAST,NC). | |
| 87 | % ProB-Values | |
| 88 | detype_ast(int(Value),C,integer(C,Value),C). | |
| 89 | detype_ast(string(Value),C,string(C,Value),C). | |
| 90 | detype_ast(Bool,C,DetypedBool,C) :- | |
| 91 | ( Bool = pred_true -> | |
| 92 | DetypedBool = boolean_true(C) | |
| 93 | ; Bool = pred_false -> | |
| 94 | DetypedBool = boolean_false(C)). | |
| 95 | % ProB-AST-Nodes | |
| 96 | detype_ast(b(integer(Value),_,_),C,integer(C,Value),C). | |
| 97 | detype_ast(b(string(Value),_,_),C,string(C,Value),C). | |
| 98 | detype_ast(b(Node,_,_),C,DetypedAST,C) :- | |
| 99 | Node =.. [_] , | |
| 100 | DetypedAST =.. [Node,C]. | |
| 101 | detype_ast(field(Name,ValueNode),C,rec_entry(C,identifier(C1,Name),DetypedValueNode),NC) :- | |
| 102 | C1 is C + 1 , | |
| 103 | C2 is C1 + 1 , | |
| 104 | detype_ast(ValueNode,C2,DetypedValueNode,NC). | |
| 105 | detype_ast(b(identifier(Name),_,_),C,identifier(C,Name),C). | |
| 106 | % sequence_extension or value sequence | |
| 107 | detype_ast(b(Node,_,_),C,DetypedAST,NC) :- | |
| 108 | Node =.. [NodeType,Arg] , | |
| 109 | avl_to_list_set(Arg,NArg) , | |
| 110 | (NodeType = sequence_extension ; (NodeType = value , NArg = [(_,_)|_])) , | |
| 111 | C1 is C + 1 , | |
| 112 | detype_set(NArg,C1,DetypedArg,NC) , | |
| 113 | % use 'sequence_extension' instead of 'value' for detyped ASTs | |
| 114 | DetypedAST =.. [sequence_extension,C,DetypedArg]. | |
| 115 | % set_extension or value set | |
| 116 | detype_ast(b(Node,_,_),C,DetypedAST,NC) :- | |
| 117 | Node =.. [NodeType,Arg] , | |
| 118 | (NodeType = set_extension ; NodeType = value) , | |
| 119 | avl_to_list_set(Arg,NArg) , | |
| 120 | C1 is C + 1 , | |
| 121 | detype_set(NArg,C1,DetypedArg,NC) , | |
| 122 | % use 'set_extension' instead of 'value' for detyped ASTs | |
| 123 | DetypedAST =.. [set_extension,C,DetypedArg]. | |
| 124 | detype_ast(b(rec(FieldList),_,_),C,rec(C,DetypedFieldList),NC) :- | |
| 125 | C1 is C + 1 , | |
| 126 | detype_set(FieldList,C1,DetypedFieldList,NC). | |
| 127 | % quantifier | |
| 128 | detype_ast(b(exists(IDList,Predicate),_,_),C,exists(C,DetypedIDList,DetypedPredicate),NC) :- | |
| 129 | C1 is C + 1 , | |
| 130 | detype_set(IDList,C1,DetypedIDList,TempC) , | |
| 131 | C2 is TempC + 1 , | |
| 132 | detype_ast(Predicate,C2,DetypedPredicate,NC). | |
| 133 | detype_ast(b(forall(IDList,LHS,RHS),_,_),C,forall(C,DetypedIDList,implication(ImpC,DetypedLHS,DetypedRHS)),NC) :- | |
| 134 | C1 is C + 1 , | |
| 135 | detype_set(IDList,C1,DetypedIDList,TempC) , | |
| 136 | ImpC is TempC + 1 , | |
| 137 | C2 is ImpC + 1 , | |
| 138 | detype_ast(LHS,C2,DetypedLHS,TempC2) , | |
| 139 | C3 is TempC2 + 1 , | |
| 140 | detype_ast(RHS,C3,DetypedRHS,NC). | |
| 141 | % one argument nodes | |
| 142 | detype_ast(b(Node,_,_),C,DetypedAST,NC) :- | |
| 143 | Node =.. [NodeType,Arg] , | |
| 144 | C1 is C + 1 , | |
| 145 | detype_ast(Arg,C1,DetypedArg,NC) , | |
| 146 | DetypedAST =.. [NodeType,C,DetypedArg]. | |
| 147 | % two argument nodes | |
| 148 | detype_ast(b(Node,_,_),C,DetypedAST,NC) :- | |
| 149 | Node =.. [NodeType,Arg1,Arg2] , | |
| 150 | C1 is C + 1 , | |
| 151 | detype_ast(Arg1,C1,DetypedArg1,TempC) , | |
| 152 | C2 is TempC + 1 , | |
| 153 | detype_ast(Arg2,C2,DetypedArg2,NC) , | |
| 154 | DetypedAST =.. [NodeType,C,DetypedArg1,DetypedArg2]. | |
| 155 | ||
| 156 | % detype a set of ast or value nodes | |
| 157 | detype_set([],C,[],NC) :- | |
| 158 | NC is C - 1. | |
| 159 | detype_set([Node|R],C,[NewNode|NewR],NC) :- | |
| 160 | detype_ast(Node,C,NewNode,TempC) , | |
| 161 | C1 is TempC + 1 , | |
| 162 | detype_set(R,C1,NewR,NC). | |
| 163 | ||
| 164 | % convert avl set to list set, otherwise just return the list set | |
| 165 | avl_to_list_set(avl_set(AVL),Set) :- | |
| 166 | avl_to_list(AVL,TempSet) , | |
| 167 | findall(Elm,member(Elm-_,TempSet),Set). | |
| 168 | avl_to_list_set(Set,Set). | |
| 169 | ||
| 170 | % get inner type and a list of the surrounding terms of an ast type | |
| 171 | % for input like set(set(integer([]))) inner_type/3 will return | |
| 172 | % [] and [set,set,integer] in its second and third argument | |
| 173 | inner_type(Type,Inner,[H|Outter]) :- | |
| 174 | Type =.. [H,Temp] , ! , | |
| 175 | inner_type(Temp,Inner,Outter). | |
| 176 | inner_type(Inner,Inner,[]). | |
| 177 | ||
| 178 | % surround type with terms from a list | |
| 179 | surround_type(Inner,[],Inner). | |
| 180 | surround_type(Inner,[Outter],New) :- | |
| 181 | New =.. [Outter,Inner]. | |
| 182 | surround_type(Inner,[Outter|T],New) :- | |
| 183 | surround_type(Inner,T,Temp) , | |
| 184 | New =.. [Outter,Temp]. | |
| 185 | surround_type(Inner,_,Inner). | |
| 186 | ||
| 187 | get_type_from_value(field(_,Value),Type) :- | |
| 188 | get_type_from_value(Value,Type). | |
| 189 | get_type_from_value(int(_),integer). | |
| 190 | get_type_from_value(string(_),string). | |
| 191 | get_type_from_value(Bool,boolean) :- | |
| 192 | Bool = pred_true ; Bool = pred_false. | |
| 193 | get_type_from_value(Seq,seq(Type)) :- | |
| 194 | is_list(Seq) , Seq = [Value|_] , | |
| 195 | Value = (_,_) , | |
| 196 | get_type_from_value(Value,Type). | |
| 197 | get_type_from_value(Set,set(Type)) :- | |
| 198 | is_list(Set) , Set = [Value|_] , | |
| 199 | get_type_from_value(Value,Type). | |
| 200 | get_type_from_value(rec(FieldList),record(Type)) :- | |
| 201 | FieldList = [Value|_] , | |
| 202 | get_type_from_value(Value,Type). | |
| 203 | ||
| 204 | value_to_ast(int(Value),b(integer(Value),integer,[])). | |
| 205 | value_to_ast(string(Value),b(string(Value),string,[])). | |
| 206 | value_to_ast(pred_true,b(boolean_true,boolean,[])). | |
| 207 | value_to_ast(pred_false,b(boolean_false,boolean,[])). | |
| 208 | value_to_ast(Seq,b(value(Seq),seq(Type),[])) :- | |
| 209 | is_list(Seq) , Seq = [Value|_] , | |
| 210 | Value = (_,_) , | |
| 211 | get_type_from_value(Value,Type). | |
| 212 | value_to_ast(Set,b(value(Set),set(Type),[])) :- | |
| 213 | is_list(Set) , Set = [Value|_] , | |
| 214 | get_type_from_value(Value,Type). | |
| 215 | value_to_ast(Record,b(Record,record(FieldTypes),[])) :- | |
| 216 | Record = rec(FieldList) , | |
| 217 | findall(field(Name,Type),(member(field(Name,Value),FieldList) , | |
| 218 | get_type_from_value(Value,Type)),FieldTypes). | |
| 219 | ||
| 220 | % add solutions given as a list of bindings to an ast (smt-solver) | |
| 221 | add_solution_to_ast(AST,Bindings,NewAST) :- | |
| 222 | add_solution_to_ast(AST,Bindings,empty_ast,NewAST). | |
| 223 | ||
| 224 | add_solution_to_ast(AST,[],Acc,NewAcc) :- | |
| 225 | NewAcc = b(conjunct(AST,Acc),pred,[]). | |
| 226 | add_solution_to_ast(AST,[binding(Name,Value,_RawValue)|Bindings],Acc,NewAST) :- | |
| 227 | value_to_ast(Value,ASTValue) , | |
| 228 | ASTValue = b(_,Type,_) , | |
| 229 | Node = b(equal(b(identifier(Name),Type,[]),ASTValue),pred,[]) , | |
| 230 | (Acc = empty_ast -> | |
| 231 | NewAcc = Node | |
| 232 | ; NewAcc = b(conjunct(Acc,Node),pred,[])) , | |
| 233 | add_solution_to_ast(AST,Bindings,NewAcc,NewAST). | |
| 234 | ||
| 235 | % check if prob ast node has "ground" value | |
| 236 | % here ground means ast leave, one-element (or empty) set/seq or quantifier | |
| 237 | prob_is_ground(b(Bool,pred,_),true) :- | |
| 238 | Bool = truth ; Bool = falsity. | |
| 239 | prob_is_ground(b(Bool,boolean,_),true) :- | |
| 240 | Bool = boolean_true ; Bool = boolean_false. | |
| 241 | prob_is_ground(b(identifier(_),_,_),true). | |
| 242 | prob_is_ground(b(Int,integer,_),true) :- | |
| 243 | Int = max_int ; Int = min_int. | |
| 244 | prob_is_ground(b(integer(_),integer,_),true). | |
| 245 | prob_is_ground(b(unary_minus(b(integer(_),integer,[])),integer,_),true). | |
| 246 | prob_is_ground(b(string(_),string,_),true). | |
| 247 | prob_is_ground(b(rec([_]),_,_),true). | |
| 248 | % one value or empty sets are ground | |
| 249 | prob_is_ground(b(set_extension([]),set(_),_),true). | |
| 250 | prob_is_ground(b(set_extension([_]),set(_),_),true). | |
| 251 | prob_is_ground(b(sequence_extension([]),seq(_),_),true). | |
| 252 | prob_is_ground(b(sequence_extension([_]),seq(_),_),true). | |
| 253 | % handle exists and forall as "ground" to improve shrinking | |
| 254 | % by allowing to evaluate those nodes | |
| 255 | prob_is_ground(b(exists(_,_),_,_),true). | |
| 256 | prob_is_ground(b(forall(_,_,_),_,_),true). | |
| 257 | prob_is_ground(b(value([]),_,_),true). | |
| 258 | prob_is_ground(b(value([_]),_,_),true). | |
| 259 | prob_is_ground(b(value(avl_set(empty)),_,_),true). | |
| 260 | prob_is_ground(b(value(avl_set(node(_,_,0,empty,empty))),_,_),true). | |
| 261 | % true for small interval, used in shrinking | |
| 262 | prob_is_ground(b(interval(b(integer(Value1),integer,_),b(integer(Value2),integer,_)),set(integer),_),true) :- | |
| 263 | C1 is Value1 + 5 , | |
| 264 | C2 is Value2 - 5 , | |
| 265 | C1 >= C2. | |
| 266 | prob_is_ground(_,false). |