1+ package de .uka .ilkd .key .scripts ;
2+
3+ import org .jspecify .annotations .Nullable ;
4+ import org .key_project .prover .rules .Rule ;
5+ import de .uka .ilkd .key .macros .FilterStrategy ;
6+ import de .uka .ilkd .key .proof .Goal ;
7+ import de .uka .ilkd .key .rule .Taclet ;
8+ import de .uka .ilkd .key .strategy .Strategy ;
9+ import org .key_project .logic .Name ;
10+ import org .key_project .prover .rules .RuleApp ;
11+ import org .key_project .prover .rules .RuleSet ;
12+ import org .key_project .prover .sequent .PosInOccurrence ;
13+ import org .key_project .prover .strategy .costbased .NumberRuleAppCost ;
14+ import org .key_project .prover .strategy .costbased .RuleAppCost ;
15+ import org .key_project .util .collection .Pair ;
16+
17+ import java .util .ArrayList ;
18+ import java .util .List ;
19+ import java .util .Map ;
20+ import java .util .Optional ;
21+
22+ class AdditionalRulesStrategy extends FilterStrategy {
23+ /** Name of that strategy */
24+ private static final Name NAME = new Name (
25+ AdditionalRulesStrategy .class .getSimpleName ());
26+
27+ private static final Map <String , String > TRANSLATIONS =
28+ Map .of ("high" , "-50" , "medium" , "1000" , "low" , "10000" );
29+ private static final int DEFAULT_PRIORITY = 1000 ;
30+
31+ private final List <Pair <String , Integer >> additionalRules ;
32+
33+ public AdditionalRulesStrategy (Strategy delegate , String additionalRules ) {
34+ super (delegate );
35+ this .additionalRules = parseAddRules (additionalRules );
36+ }
37+
38+ private List <Pair <String , Integer >> parseAddRules (String additionalRules ) {
39+ List <Pair <String , Integer >> result = new ArrayList <>();
40+ for (String entry : additionalRules .trim ().split (" *, *" )) {
41+ String [] parts = entry .split (" *= *" , 2 );
42+ int prio ;
43+ if (parts .length == 2 ) {
44+ String prioStr = parts [1 ];
45+ prioStr = TRANSLATIONS .getOrDefault (prioStr , prioStr );
46+ try {
47+ prio = Integer .parseInt (prioStr );
48+ } catch (NumberFormatException e ) {
49+ throw new IllegalArgumentException ("Invalid value for additional rule: " + parts [1 ]);
50+ }
51+ } else {
52+ prio = DEFAULT_PRIORITY ;
53+ }
54+
55+ result .add (new Pair <>(parts [0 ], prio ));
56+ }
57+ return result ;
58+ }
59+
60+ @ Override
61+ public Name name () {
62+ return NAME ;
63+ }
64+
65+ @ Override
66+ public RuleAppCost computeCost (RuleApp app , PosInOccurrence pio , Goal goal ) {
67+ RuleAppCost localCost = computeLocalCost (app .rule ());
68+ if (localCost != null ) {
69+ return localCost ;
70+ }
71+ return super .computeCost (app , pio , goal );
72+ }
73+
74+ @ Override
75+ public boolean isApprovedApp (RuleApp app , PosInOccurrence pio , Goal goal ) {
76+ RuleAppCost localCost = computeLocalCost (app .rule ());
77+ if (localCost != null ) {
78+ return true ;
79+ }
80+ return super .isApprovedApp (app , pio , goal );
81+ }
82+
83+ private @ Nullable RuleAppCost computeLocalCost (Rule rule ) {
84+ String name = rule .name ().toString ();
85+ Optional <Integer > cost = lookup (name );
86+ if (cost .isPresent ()) {
87+ return NumberRuleAppCost .create (cost .get ());
88+ }
89+
90+ if (rule instanceof Taclet taclet ) {
91+ for (RuleSet rs : taclet .getRuleSets ()) {
92+ String rname = rs .name ().toString ();
93+ cost = lookup (rname );
94+ if (cost .isPresent ()) {
95+ return NumberRuleAppCost .create (cost .get ());
96+ }
97+ }
98+ }
99+
100+ return null ;
101+ }
102+
103+ private Optional <Integer > lookup (String name ) {
104+ return additionalRules .stream ()
105+ .filter (nameAndPrio -> name .matches (nameAndPrio .first ))
106+ .findFirst ()
107+ .map (p -> p .second );
108+ }
109+
110+ @ Override
111+ public boolean isStopAtFirstNonCloseableGoal () {
112+ return false ;
113+ }
114+
115+
116+ }
0 commit comments