diff --git a/.github/dlsmt.sh b/.github/dlsmt.sh
index 049cb4a5261..3a3a7c1e7f4 100755
--- a/.github/dlsmt.sh
+++ b/.github/dlsmt.sh
@@ -1,6 +1,6 @@
# No shebang!
-## Weigl's little helper to download SMT-solvers.
+## Weigl's little helper to download SMT-solvers.
# SPDX-License-Identifier: GPL-2.0-or-later
# This script is meant to be executed inside an Github Action to download the SMT-solver.
@@ -27,6 +27,7 @@
mkdir smt-solvers
cd smt-solvers
+set -x # exit on error
#################################################
echo "::group::{install z3}"
@@ -36,7 +37,10 @@ if readlink -f */bin/z3; then
echo "::notice::{Z3 found. Caching works! Skip installation}"
else
echo "Download Z3"
- gh release download --skip-existing -p 'z3-*-x64-glibc-*.zip' -R Z3Prover/z3
+ rm z3-*.zip
+ # gh release download --skip-existing -p 'z3-*-x64-glibc-2.35.zip' -R Z3Prover/z3
+ ## pin to a release
+ wget -q https://github.com/Z3Prover/z3/releases/download/z3-4.13.0/z3-4.13.0-x64-glibc-2.35.zip
unzip -n z3*.zip
rm z3-*-x64-glibc-*.zip
fi
@@ -51,14 +55,19 @@ echo "::endgroup::"
#################################################
echo "::group::{install cvc5}"
-if -f cvc5-Linux; then
- echo "::notice::{Z3 found. Caching works! Skip installation}"
+if -f cvc5-Linux-static/bin/cvc5; then
+ echo "::notice::{CVC5 found. Caching works! Skip installation}"
else
echo "Install CVC5"
- gh release download --skip-existing -p 'cvc5-Linux' -R cvc5/cvc5
+ # does not work anymore
+ # gh release download --skip-existing -p 'cvc5-Linux' -R cvc5/cvc5
+
+ wget -q https://github.com/cvc5/cvc5/releases/download/cvc5-1.1.2/cvc5-Linux-static.zip
+ unzip cvc5-Linux-static.zip
+ rm cvc5-Linux-static.zip
fi
-CVC5=$(readlink -f cvc5-Linux)
+CVC5=$(readlink -f cvc5-Linux-static/bin/cvc5)
echo "CVC5 installed and added to path: CVC5"
chmod u+x $CVC5
echo $(dirname $CVC5) >> $GITHUB_PATH
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index c376da14301..9125d0b7a5c 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -2,8 +2,8 @@
Thanks for submitting this pull request for KeY.
Since the project has a strict review policy, please make the
reviewer's job easier by providing the necessary information
-in the text below. The comments may remain since they will be
-invisible when showing the PR.
+in the text below. The comments can be deleted, but may also
+remain since they will be invisible when showing the PR.
-->
## Related Issue
@@ -17,26 +17,48 @@ This pull request addresses #.
+## Plan
+
+
+* [ ] Implement feature 1
+* [ ] Implement feature 2
+* [ ] Code cleanup
+* [ ] Document the changes
+
## Type of pull request
-
+
-- [ ] Bug fix (non-breaking change which fixes an issue)
-- [ ] Refactoring (behaviour should not change or only minimally change)
-- [ ] New feature (non-breaking change which adds functionality)
-- [ ] Breaking change (fix or feature that would cause existing functionality to change)
-- [ ] There are changes to the (Java) code
-- [ ] There are changes to the taclet rule base
-- [ ] There are changes to the deployment/CI infrastructure (gradle, github, ...)
-- [ ] Other:
+- Bug fix (non-breaking change which fixes an issue)
+- Refactoring (behaviour should not change or only minimally change)
+- New feature (non-breaking change which adds functionality)
+- Breaking change (fix or feature that would cause existing functionality to change)
+- There are changes to the (Java) code
+- There are changes to the taclet rule base
+- There are changes to the deployment/CI infrastructure (gradle, github, ...)
+- Other:
## Ensuring quality
+
+
-- [ ] I made sure that introduced/changed code is well documented (javadoc and inline comments).
-- [ ] I made sure that new/changed end-user features are well documented (https://github.com/KeYProject/key-docs).
-- [ ] I added new test case(s) for new functionality.
-- [ ] I have tested the feature as follows: ...
-- [ ] I have checked that runtime performance has not deteriorated.
+- I made sure that introduced/changed code is well documented (javadoc and inline comments).
+- I made sure that new/changed end-user features are well documented (https://github.com/KeYProject/key-docs).
+- I added new test case(s) for new functionality.
+- I have tested the feature as follows: ...
+- I have checked that runtime performance has not deteriorated.
## Additional information and contact(s)
diff --git a/README.md b/README.md
index 0d170796ae0..e9d834c472a 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@ The current version of KeY is 2.12.2, licensed under GPL v2.
Feel free to use the project templates to get started using KeY:
* [For Verification Projects](https://github.com/KeYProject/verification-project-template)
* [Using as a Library](https://github.com/KeYProject/key-java-example)
-* [Using as a Symbolic Execution Backend](https://github.com/KeYProject/key-symbex-example)
+* [Using as a Symbolic Execution Backend](https://github.com/KeYProject/symbex-java-example)
## Requirements
diff --git a/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/rule/QuerySideProofRule.java b/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/rule/QuerySideProofRule.java
index dc27a404782..727b69d9f19 100644
--- a/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/rule/QuerySideProofRule.java
+++ b/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/rule/QuerySideProofRule.java
@@ -31,6 +31,8 @@
import org.key_project.logic.sort.Sort;
import org.key_project.util.collection.ImmutableList;
+import org.jspecify.annotations.NonNull;
+
/**
*
* A {@link BuiltInRule} which evaluates a query in a side proof.
@@ -187,6 +189,7 @@ public IBuiltInRuleApp createApp(PosInOccurrence pos, TermServices services) {
/**
* {@inheritDoc}
*/
+ @NonNull
@Override
public ImmutableList apply(Goal goal, Services services, RuleApp ruleApp)
throws RuleAbortException {
diff --git a/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/strategy/breakpoint/AbstractConditionalBreakpoint.java b/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/strategy/breakpoint/AbstractConditionalBreakpoint.java
index 7e9bdc67670..1de93a21d02 100644
--- a/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/strategy/breakpoint/AbstractConditionalBreakpoint.java
+++ b/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/strategy/breakpoint/AbstractConditionalBreakpoint.java
@@ -335,7 +335,7 @@ private Term computeTermForCondition(String condition) {
PositionedString ps = new PositionedString(condition);
var context = Context.inMethodWithSelfVar(pm, selfVar);
- JmlIO io = new JmlIO().services(getProof().getServices()).context(context)
+ JmlIO io = new JmlIO(getProof().getServices()).context(context)
.parameters(varsForCondition);
return io.parseExpression(ps);
diff --git a/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/util/SymbolicExecutionUtil.java b/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/util/SymbolicExecutionUtil.java
index 064a2e289d1..1b9921943c1 100644
--- a/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/util/SymbolicExecutionUtil.java
+++ b/key.core.symbolic_execution/src/main/java/de/uka/ilkd/key/symbolic_execution/util/SymbolicExecutionUtil.java
@@ -77,6 +77,9 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static de.uka.ilkd.key.logic.equality.IrrelevantTermLabelsProperty.IRRELEVANT_TERM_LABELS_PROPERTY;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
/**
* Provides utility methods for symbolic execution with KeY.
*
@@ -393,7 +396,7 @@ else if (term.op() == Junctor.NOT) {
* @return true if the term represents the one
*/
private static boolean isOne(Term subOne, IntegerLDT integerLDT) {
- return subOne.equalsModIrrelevantTermLabels(integerLDT.one());
+ return subOne.equalsModProperty(integerLDT.one(), IRRELEVANT_TERM_LABELS_PROPERTY);
}
/**
@@ -1984,13 +1987,16 @@ private static void collectSpecifcationCasesPreconditions(Term normalExcDefiniti
List exceptinalConditions) throws ProofInputException {
if (term.op() == Junctor.AND) {
Term lastChild = term.sub(term.arity() - 1);
- if (lastChild.equalsModIrrelevantTermLabels(normalExcDefinition)
- || lastChild.equalsModIrrelevantTermLabels(exceptionalExcDefinition)) {
+ if (lastChild.equalsModProperty(normalExcDefinition, IRRELEVANT_TERM_LABELS_PROPERTY)
+ || lastChild.equalsModProperty(exceptionalExcDefinition,
+ IRRELEVANT_TERM_LABELS_PROPERTY)) {
// Nothing to do, condition is just true
} else {
Term firstChild = term.sub(0);
- if (firstChild.equalsModIrrelevantTermLabels(normalExcDefinition)
- || firstChild.equalsModIrrelevantTermLabels(exceptionalExcDefinition)) {
+ if (firstChild
+ .equalsModProperty(normalExcDefinition, IRRELEVANT_TERM_LABELS_PROPERTY)
+ || firstChild.equalsModProperty(exceptionalExcDefinition,
+ IRRELEVANT_TERM_LABELS_PROPERTY)) {
// Nothing to do, condition is just true
} else {
for (int i = 0; i < term.arity(); i++) {
@@ -2002,27 +2008,32 @@ private static void collectSpecifcationCasesPreconditions(Term normalExcDefiniti
}
} else if (term.op() == Junctor.IMP) {
Term leftTerm = term.sub(0);
- if (leftTerm.equalsModIrrelevantTermLabels(normalExcDefinition)
- || leftTerm.equalsModIrrelevantTermLabels(exceptionalExcDefinition)) {
+ if (leftTerm.equalsModProperty(normalExcDefinition, IRRELEVANT_TERM_LABELS_PROPERTY)
+ || leftTerm.equalsModProperty(exceptionalExcDefinition,
+ IRRELEVANT_TERM_LABELS_PROPERTY)) {
// Nothing to do, condition is just true
} else {
Term rightTerm = term.sub(1);
// Deal with heavy weight specification cases
if (rightTerm.op() == Junctor.AND && rightTerm.sub(0).op() == Junctor.IMP
&& rightTerm.sub(0).sub(0)
- .equalsModIrrelevantTermLabels(normalExcDefinition)) {
+ .equalsModProperty(normalExcDefinition,
+ IRRELEVANT_TERM_LABELS_PROPERTY)) {
normalConditions.add(leftTerm);
} else if (rightTerm.op() == Junctor.AND && rightTerm.sub(1).op() == Junctor.IMP
&& rightTerm.sub(1).sub(0)
- .equalsModIrrelevantTermLabels(exceptionalExcDefinition)) {
+ .equalsModProperty(exceptionalExcDefinition,
+ IRRELEVANT_TERM_LABELS_PROPERTY)) {
exceptinalConditions.add(leftTerm);
}
// Deal with light weight specification cases
else if (rightTerm.op() == Junctor.IMP
- && rightTerm.sub(0).equalsModIrrelevantTermLabels(normalExcDefinition)) {
+ && rightTerm.sub(0).equalsModProperty(normalExcDefinition,
+ IRRELEVANT_TERM_LABELS_PROPERTY)) {
normalConditions.add(leftTerm);
} else if (rightTerm.op() == Junctor.IMP && rightTerm.sub(0)
- .equalsModIrrelevantTermLabels(exceptionalExcDefinition)) {
+ .equalsModProperty(exceptionalExcDefinition,
+ IRRELEVANT_TERM_LABELS_PROPERTY)) {
exceptinalConditions.add(leftTerm);
} else {
Term excCondition = rightTerm;
@@ -2030,19 +2041,23 @@ else if (rightTerm.op() == Junctor.IMP
if (excCondition.op() == Junctor.AND) {
excCondition = excCondition.sub(excCondition.arity() - 1);
}
- if (excCondition.equalsModIrrelevantTermLabels(normalExcDefinition)) {
+ if (excCondition.equalsModProperty(normalExcDefinition,
+ IRRELEVANT_TERM_LABELS_PROPERTY)) {
normalConditions.add(leftTerm);
} else if (excCondition
- .equalsModIrrelevantTermLabels(exceptionalExcDefinition)) {
+ .equalsModProperty(exceptionalExcDefinition,
+ IRRELEVANT_TERM_LABELS_PROPERTY)) {
exceptinalConditions.add(leftTerm);
} else {
// Check if left child is exception definition
if (rightTerm.op() == Junctor.AND) {
excCondition = rightTerm.sub(0);
- if (excCondition.equalsModIrrelevantTermLabels(normalExcDefinition)) {
+ if (excCondition.equalsModProperty(normalExcDefinition,
+ IRRELEVANT_TERM_LABELS_PROPERTY)) {
normalConditions.add(leftTerm);
} else if (excCondition
- .equalsModIrrelevantTermLabels(exceptionalExcDefinition)) {
+ .equalsModProperty(exceptionalExcDefinition,
+ IRRELEVANT_TERM_LABELS_PROPERTY)) {
exceptinalConditions.add(leftTerm);
} else {
throw new ProofInputException("Exeptional condition expected, "
@@ -2673,7 +2688,7 @@ private static boolean checkReplaceTerm(Term toCheck, PosInOccurrence posInOccur
Term replaceTerm) {
Term termAtPio = followPosInOccurrence(posInOccurrence, toCheck);
if (termAtPio != null) {
- return termAtPio.equalsModRenaming(replaceTerm);
+ return termAtPio.equalsModProperty(replaceTerm, RENAMING_PROPERTY);
} else {
return false;
}
@@ -3419,11 +3434,13 @@ private static List findSkolemReplacements(Sequent sequent, Term skolemCon
if (term != skolemEquality) {
int skolemCheck = checkSkolemEquality(term);
if (skolemCheck == -1) {
- if (term.sub(0).equalsModIrrelevantTermLabels(skolemConstant)) {
+ if (term.sub(0).equalsModProperty(skolemConstant,
+ IRRELEVANT_TERM_LABELS_PROPERTY)) {
result.add(term.sub(1));
}
} else if (skolemCheck == 1) {
- if (term.sub(1).equalsModIrrelevantTermLabels(skolemConstant)) {
+ if (term.sub(1).equalsModProperty(skolemConstant,
+ IRRELEVANT_TERM_LABELS_PROPERTY)) {
result.add(term.sub(0));
}
}
@@ -3513,7 +3530,8 @@ public static Term computePathCondition(Node parentNode, Node childNode, boolean
}
childNode = parent;
}
- if (services.getTermBuilder().ff().equalsModIrrelevantTermLabels(pathCondition)) {
+ if (services.getTermBuilder().ff().equalsModProperty(pathCondition,
+ IRRELEVANT_TERM_LABELS_PROPERTY)) {
throw new ProofInputException(
"Path condition computation failed because the result is false.");
}
diff --git a/key.core.symbolic_execution/src/test/resources/testcase/set/useOperationContractStatementsInImpliciteConstructor/oracle/UseOperationContractStatementsInImpliciteConstructor.xml b/key.core.symbolic_execution/src/test/resources/testcase/set/useOperationContractStatementsInImpliciteConstructor/oracle/UseOperationContractStatementsInImpliciteConstructor.xml
index 5c9678ed01b..458af701a2f 100644
--- a/key.core.symbolic_execution/src/test/resources/testcase/set/useOperationContractStatementsInImpliciteConstructor/oracle/UseOperationContractStatementsInImpliciteConstructor.xml
+++ b/key.core.symbolic_execution/src/test/resources/testcase/set/useOperationContractStatementsInImpliciteConstructor/oracle/UseOperationContractStatementsInImpliciteConstructor.xml
@@ -360,62 +360,13 @@ new IllegalArgumentException("Array can't be null.");" pathCondit
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/key.core/src/main/antlr4/JmlLexer.g4 b/key.core/src/main/antlr4/JmlLexer.g4
index f1a67a2afd5..03b7d3ce068 100644
--- a/key.core/src/main/antlr4/JmlLexer.g4
+++ b/key.core/src/main/antlr4/JmlLexer.g4
@@ -280,7 +280,7 @@ SEQCONCAT: '\\seq_concat'; //KeY extension, not official JML
SEQDEF: '\\seq_def'; //KeY extension, not official JML
SEQEMPTY: '\\seq_empty'; //KeY extension, not official JML
SEQGET: '\\seq_get'; //KeY extension, not official JML
-SEQREPLACE: '\\seq_put'; //KeY extension, not official JML
+SEQREPLACE: '\\seq_upd'; //KeY extension, not official JML
SEQREVERSE: '\\seq_reverse'; //KeY extension, not official JML
SEQSINGLETON: '\\seq_singleton'; //KeY extension, not official JML
SEQSUB: '\\seq_sub'; //KeY extension, not official JML
diff --git a/key.core/src/main/antlr4/JmlParser.g4 b/key.core/src/main/antlr4/JmlParser.g4
index a66965df0fd..788187f9849 100644
--- a/key.core/src/main/antlr4/JmlParser.g4
+++ b/key.core/src/main/antlr4/JmlParser.g4
@@ -161,7 +161,7 @@ in_group_clause: IN expression;
maps_into_clause: MAPS expression;
nowarn_pragma: NOWARN expression;
debug_statement: DEBUG expression;
-set_statement: SET expression EQUAL_SINGLE expression SEMI_TOPLEVEL;
+set_statement: SET (assignee=expression) EQUAL_SINGLE (value=expression) SEMI_TOPLEVEL;
merge_point_statement:
MERGE_POINT
(MERGE_PROC (proc=STRING_LITERAL))?
diff --git a/key.core/src/main/java/de/uka/ilkd/key/informationflow/macros/StartAuxiliaryBlockComputationMacro.java b/key.core/src/main/java/de/uka/ilkd/key/informationflow/macros/StartAuxiliaryBlockComputationMacro.java
index 5438464d94c..a7b80f23363 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/informationflow/macros/StartAuxiliaryBlockComputationMacro.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/informationflow/macros/StartAuxiliaryBlockComputationMacro.java
@@ -24,6 +24,8 @@
import org.key_project.util.collection.ImmutableList;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
/**
*
@@ -78,7 +80,7 @@ public boolean canApplyTo(Proof proof, ImmutableList goals, PosInOccurrenc
final Term selfComposedExec =
f.create(InfFlowPOSnippetFactory.Snippet.SELFCOMPOSED_BLOCK_WITH_PRE_RELATION);
- return posInOcc.subTerm().equalsModRenaming(selfComposedExec);
+ return posInOcc.subTerm().equalsModProperty(selfComposedExec, RENAMING_PROPERTY);
}
@Override
diff --git a/key.core/src/main/java/de/uka/ilkd/key/informationflow/macros/StartAuxiliaryLoopComputationMacro.java b/key.core/src/main/java/de/uka/ilkd/key/informationflow/macros/StartAuxiliaryLoopComputationMacro.java
index cb65f95c391..b1eb88c652a 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/informationflow/macros/StartAuxiliaryLoopComputationMacro.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/informationflow/macros/StartAuxiliaryLoopComputationMacro.java
@@ -25,6 +25,8 @@
import org.key_project.util.collection.ImmutableList;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
public class StartAuxiliaryLoopComputationMacro extends AbstractProofMacro
implements StartSideProofMacro {
@@ -75,7 +77,7 @@ public boolean canApplyTo(Proof proof, ImmutableList goals, PosInOccurrenc
final Term selfComposedExec =
f.create(InfFlowPOSnippetFactory.Snippet.SELFCOMPOSED_LOOP_WITH_INV_RELATION);
- return posInOcc.subTerm().equalsModRenaming(selfComposedExec);
+ return posInOcc.subTerm().equalsModProperty(selfComposedExec, RENAMING_PROPERTY);
}
@Override
diff --git a/key.core/src/main/java/de/uka/ilkd/key/informationflow/macros/StartAuxiliaryMethodComputationMacro.java b/key.core/src/main/java/de/uka/ilkd/key/informationflow/macros/StartAuxiliaryMethodComputationMacro.java
index bac101e8534..33dc44f19d0 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/informationflow/macros/StartAuxiliaryMethodComputationMacro.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/informationflow/macros/StartAuxiliaryMethodComputationMacro.java
@@ -22,6 +22,8 @@
import org.key_project.util.collection.ImmutableList;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
/**
*
* @author christoph
@@ -67,7 +69,7 @@ public boolean canApplyTo(Proof proof, ImmutableList goals, PosInOccurrenc
final Term selfComposedExec =
f.create(InfFlowPOSnippetFactory.Snippet.SELFCOMPOSED_EXECUTION_WITH_PRE_RELATION);
- return posInOcc.subTerm().equalsModRenaming(selfComposedExec);
+ return posInOcc.subTerm().equalsModProperty(selfComposedExec, RENAMING_PROPERTY);
}
@Override
diff --git a/key.core/src/main/java/de/uka/ilkd/key/informationflow/proof/init/StateVars.java b/key.core/src/main/java/de/uka/ilkd/key/informationflow/proof/init/StateVars.java
index f16ebf8820f..cf131508cba 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/informationflow/proof/init/StateVars.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/informationflow/proof/init/StateVars.java
@@ -176,8 +176,7 @@ private static Term newVariable(Term t, String name, Services services) {
String newName = tb.newName(name);
ProgramElementName pen = new ProgramElementName(newName);
ProgramVariable progVar = (ProgramVariable) t.op();
- LocationVariable newVar = new LocationVariable(pen, progVar.getKeYJavaType(),
- progVar.getContainerType(), progVar.isStatic(), progVar.isModel());
+ LocationVariable newVar = LocationVariable.fromProgramVariable(progVar, pen);
register(newVar, services);
return tb.var(newVar);
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/java/JavaTools.java b/key.core/src/main/java/de/uka/ilkd/key/java/JavaTools.java
index 3d53c282b34..3898226d48d 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/java/JavaTools.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/java/JavaTools.java
@@ -3,6 +3,7 @@
* SPDX-License-Identifier: GPL-2.0-only */
package de.uka.ilkd.key.java;
+
import de.uka.ilkd.key.java.ast.ProgramElement;
import de.uka.ilkd.key.java.ast.SourceElement;
import de.uka.ilkd.key.java.ast.Statement;
@@ -18,12 +19,13 @@
import org.key_project.util.ExtList;
+import org.jspecify.annotations.Nullable;
+
/**
* Miscellaneous static methods related to Java blocks or statements in KeY. Mostly moved from
* key.util.MiscTools here.
*
* @author bruns
- *
*/
public final class JavaTools {
@@ -53,6 +55,20 @@ public static SourceElement getActiveStatement(JavaBlock jb) {
public static JavaBlock removeActiveStatement(JavaBlock jb, Services services) {
assert jb.program() != null;
final SourceElement activeStatement = JavaTools.getActiveStatement(jb);
+ return replaceStatement(jb, services, activeStatement, null);
+ }
+
+ /**
+ * Returns the passed java block with `statement` replaced with `with`.
+ *
+ * @param jb the block
+ * @param statement the statement to replace
+ * @param with what to replace with. If this is null, the statement will be removed
+ * @return the modified block
+ */
+ public static JavaBlock replaceStatement(JavaBlock jb, Services services,
+ SourceElement statement, @Nullable SourceElement with) {
+ assert jb.program() != null;
Statement newProg = (Statement) (new CreatingASTVisitor(jb.program(), false, services) {
private boolean done = false;
@@ -65,9 +81,12 @@ public ProgramElement go() {
@Override
public void doAction(ProgramElement node) {
- if (!done && node == activeStatement) {
+ if (!done && node == statement) {
done = true;
stack.pop();
+ if (with != null) {
+ addToTopOfStack(with);
+ }
changed();
} else {
super.doAction(node);
diff --git a/key.core/src/main/java/de/uka/ilkd/key/java/ast/statement/JmlAssert.java b/key.core/src/main/java/de/uka/ilkd/key/java/ast/statement/JmlAssert.java
index 527680c0f98..14c8a6c1946 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/java/ast/statement/JmlAssert.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/java/ast/statement/JmlAssert.java
@@ -3,23 +3,14 @@
* SPDX-License-Identifier: GPL-2.0-only */
package de.uka.ilkd.key.java.ast.statement;
-import java.util.Map;
import java.util.Objects;
import de.uka.ilkd.key.java.Services;
import de.uka.ilkd.key.java.ast.PositionInfo;
import de.uka.ilkd.key.java.ast.ProgramElement;
import de.uka.ilkd.key.java.visitor.Visitor;
-import de.uka.ilkd.key.logic.Term;
-import de.uka.ilkd.key.logic.TermFactory;
-import de.uka.ilkd.key.logic.op.LocationVariable;
-import de.uka.ilkd.key.pp.LogicPrinter;
-import de.uka.ilkd.key.proof.OpReplacer;
-import de.uka.ilkd.key.speclang.TermReplacementMap;
+import de.uka.ilkd.key.nparser.KeyAst;
import de.uka.ilkd.key.speclang.jml.pretranslation.TextualJMLAssertStatement;
-import de.uka.ilkd.key.speclang.jml.translation.ProgramVariableCollection;
-import de.uka.ilkd.key.speclang.njml.JmlIO;
-import de.uka.ilkd.key.speclang.njml.LabeledParserRuleContext;
import org.key_project.util.ExtList;
@@ -29,130 +20,114 @@
* @author Benjamin Takacs
*/
public class JmlAssert extends JavaStatement {
-
+ /**
+ * Index in the list of terms of
+ * {@link de.uka.ilkd.key.proof.mgt.SpecificationRepository.JmlStatementSpec}
+ */
+ public static final int INDEX_CONDITION = 0;
/**
* the kind of the statement, assert or assume
*/
private final TextualJMLAssertStatement.Kind kind;
+
/**
* the condition in parse tree form
*/
- private LabeledParserRuleContext condition;
- /**
- * the condition in Term form
- */
- private Term cond;
- /**
- * the program variables used to create the Term form of the condition
- */
- private ProgramVariableCollection vars;
- /**
- * services (needed for pretty printing)
- */
- private final Services services;
+ private KeyAst.Expression condition;
/**
- *
* @param kind assert or assume
* @param condition the condition of this statement
* @param positionInfo the position information for this statement
- * @param services needed for pretty printing (not pretty when null)
*/
- public JmlAssert(TextualJMLAssertStatement.Kind kind, LabeledParserRuleContext condition,
- PositionInfo positionInfo, Services services) {
+ public JmlAssert(TextualJMLAssertStatement.Kind kind, KeyAst.Expression condition,
+ PositionInfo positionInfo) {
super(positionInfo);
this.kind = kind;
this.condition = condition;
- this.services = services;
}
/**
- *
* @param children the children of this element
- * @param services needed for pretty printing (not pretty when null)
*/
- public JmlAssert(ExtList children, Services services) {
+ public JmlAssert(ExtList children) {
super(children);
- this.kind = children.get(TextualJMLAssertStatement.Kind.class);
- this.condition = children.get(LabeledParserRuleContext.class);
- this.cond = children.get(Term.class);
- this.vars = children.get(ProgramVariableCollection.class);
- this.services = services;
- if ((cond == null) == (condition == null)) {
- throw new IllegalArgumentException("exactly one of cond and condition has to be null");
- }
+ this.kind = Objects.requireNonNull(children.get(TextualJMLAssertStatement.Kind.class));
+ this.condition = Objects.requireNonNull(children.get(KeyAst.Expression.class));
+ }
+
+ public JmlAssert(JmlAssert other) {
+ this(other.kind, other.condition, other.getPositionInfo());
}
public TextualJMLAssertStatement.Kind getKind() {
return kind;
}
- /**
+ /*
* @return the condition in String form
+ * public String getConditionText() {
+ * if (cond != null) {
+ * return LogicPrinter.quickPrintTerm(cond, services);
+ * }
+ * // this will lose whitespace, so e.g. \forall will not be printed correctly
+ * // but normally the term form should get printed.
+ * return condition.first.getText().substring(kind.name().length());
+ * }
*/
- public String getConditionText() {
- if (cond != null) {
- return LogicPrinter.quickPrintTerm(cond, services);
- }
- // this will lose whitespace, so e.g. \forall will not be printed correctly
- // but normally the term form should get printed.
- return condition.first.getText().substring(kind.name().length());
- }
- /**
- * Returns the condition in Term form.
- *
- * You have to call translateCondition(JmlIO) before getting useful values.
- *
- * @return the condition in Term form if it was already translated else null
- */
- public Term getCond() {
- return cond;
+ /** Returns the condition as an encapsulated {@link org.antlr.v4.runtime.ParserRuleContext} */
+ public KeyAst.Expression getCondition() {
+ return condition;
}
- /**
+ /*
* Returns the condition in Term form.
*
* You have to call translateCondition(JmlIO) before getting useful values.
*
* @return the condition in Term form if it was already translated else null
+ *
* @param self the Term for {@code this} in the current context
+ *
* @param services services
+ * public Term getCond(final Term self, final Services services) {
+ * final TermFactory termFactory = services.getTermFactory();
+ * final TermReplacementMap replacementMap = new TermReplacementMap(termFactory);
+ * if (self != null) {
+ * replacementMap.replaceSelf(vars.selfVar, self, services);
+ * }
+ * replacementMap.replaceRemembranceLocalVariables(vars.atPreVars, vars.atPres, services);
+ * replacementMap.replaceRemembranceLocalVariables(vars.atBeforeVars, vars.atBefores,
+ * services);
+ * final OpReplacer replacer =
+ * new OpReplacer(replacementMap, termFactory, services.getProof());
+ * return replacer.replace(cond);
+ * }
*/
- public Term getCond(final Term self, final Services services) {
- final TermFactory termFactory = services.getTermFactory();
- final TermReplacementMap replacementMap = new TermReplacementMap(termFactory);
- if (self != null) {
- replacementMap.replaceSelf(vars.selfVar, self, services);
- }
- replacementMap.replaceRemembranceLocalVariables(vars.atPreVars, vars.atPres, services);
- replacementMap.replaceRemembranceLocalVariables(vars.atBeforeVars, vars.atBefores,
- services);
- final OpReplacer replacer =
- new OpReplacer(replacementMap, termFactory, services.getProof());
- return replacer.replace(cond);
- }
- /**
+ /*
* Translates the condition of this JML assert statement to a Term.
*
* Use as soon as possible, but can only be called once.
*
* @param jmlIo the JmlIO to use to translate the condition
+ *
* @param pv the program variables to use for the translation
+ *
* @throws IllegalStateException if this JmlAssert already has a condition in Term form
+ * public void translateCondition(final JmlIO jmlIo, final ProgramVariableCollection pv) {
+ * if (cond != null) {
+ * throw new IllegalStateException("condition can only be set once");
+ * }
+ * this.vars = pv;
+ * jmlIo.selfVar(pv.selfVar).parameters(pv.paramVars).resultVariable(pv.resultVar)
+ * .exceptionVariable(pv.excVar).atPres(pv.atPres).atBefore(pv.atBefores);
+ * this.cond = jmlIo.translateTermAsFormula(condition);
+ * condition = null;
+ * }
*/
- public void translateCondition(final JmlIO jmlIo, final ProgramVariableCollection pv) {
- if (cond != null) {
- throw new IllegalStateException("condition can only be set once");
- }
- this.vars = pv;
- jmlIo.selfVar(pv.selfVar).parameters(pv.paramVars).resultVariable(pv.resultVar)
- .exceptionVariable(pv.excVar).atPres(pv.atPres).atBefore(pv.atBefores);
- this.cond = jmlIo.translateTermAsFormula(condition);
- condition = null;
- }
@Override
public boolean equals(final Object o) {
@@ -164,15 +139,14 @@ public boolean equals(final Object o) {
}
// super.equals() check classes
final JmlAssert jmlAssert = (JmlAssert) o;
- return kind == jmlAssert.kind && Objects.equals(condition, jmlAssert.condition)
- && Objects.equals(cond, jmlAssert.cond);
+ return kind == jmlAssert.kind && Objects.equals(condition, jmlAssert.condition);
}
// hashCode() caches the result of computeHashCode()
// so override that instead of hashCode which is final
@Override
protected int computeHashCode() {
- return Objects.hash(super.computeHashCode(), kind, condition, cond);
+ return System.identityHashCode(this);
}
@Override
@@ -189,25 +163,4 @@ public ProgramElement getChildAt(int index) {
public void visit(Visitor v) {
v.performActionOnJmlAssert(this);
}
-
- public ProgramVariableCollection getVars() {
- return vars;
- }
-
- /**
- * updates this statement with prestate renaming
- *
- * @param atPres prestate renaming
- * @param services services
- */
- public void updateVars(final Map atPres, final Services services) {
- final TermFactory termFactory = services.getTermFactory();
- final TermReplacementMap replacementMap = new TermReplacementMap(termFactory);
- replacementMap.replaceRemembranceLocalVariables(vars.atPreVars, atPres, services);
- final OpReplacer replacer =
- new OpReplacer(replacementMap, termFactory, services.getProof());
- cond = replacer.replace(cond);
- vars.atPres = atPres;
-
- }
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/java/recoderext/SetStatement.java b/key.core/src/main/java/de/uka/ilkd/key/java/recoderext/SetStatement.java
new file mode 100644
index 00000000000..2f509951666
--- /dev/null
+++ b/key.core/src/main/java/de/uka/ilkd/key/java/recoderext/SetStatement.java
@@ -0,0 +1,93 @@
+/* This file is part of KeY - https://key-project.org
+ * KeY is licensed under the GNU General Public License Version 2
+ * SPDX-License-Identifier: GPL-2.0-only */
+package de.uka.ilkd.key.java.recoderext;
+
+import de.uka.ilkd.key.nparser.KeyAst.SetStatementContext;
+
+import recoder.java.ProgramElement;
+import recoder.java.SourceVisitor;
+import recoder.java.statement.JavaStatement;
+
+/**
+ * Wrapper for JML set statements which lifts the contained parse tree to the Translator.
+ *
+ * @author Julian Wiesler
+ */
+public class SetStatement extends JavaStatement {
+ /**
+ * Parser context of the assignment
+ */
+ private final SetStatementContext context;
+
+ /**
+ * Primary constructor
+ *
+ * @param context the context of the assignment
+ */
+ public SetStatement(SetStatementContext context) {
+ this.context = context;
+ }
+
+ /**
+ * copy constructor
+ *
+ * @param proto the orginal JML set statement to copy
+ */
+ public SetStatement(SetStatement proto) {
+ super(proto);
+ this.context = proto.context;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SetStatement deepClone() {
+ return new SetStatement(this);
+ }
+
+ /**
+ * Gets the contained parser context
+ *
+ * @return the parser context
+ */
+ public SetStatementContext getParserContext() {
+ return context;
+ }
+
+ /**
+ * A set statement has no recorder AST children
+ */
+ @Override
+ public int getChildCount() {
+ return 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * There are no recorder AST children.
+ *
+ * @throws IndexOutOfBoundsException always
+ */
+ @Override
+ public ProgramElement getChildAt(int index) {
+ throw new IndexOutOfBoundsException("JmlAssert has no program children");
+ }
+
+ @Override
+ public int getChildPositionCode(ProgramElement child) {
+ return -1;
+ }
+
+ @Override
+ public boolean replaceChild(ProgramElement p, ProgramElement q) {
+ return false;
+ }
+
+ @Override
+ public void accept(SourceVisitor v) {
+ // should be fine to leave blank
+ }
+}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/java/recoderext/adt/SeqPut.java b/key.core/src/main/java/de/uka/ilkd/key/java/recoderext/adt/SeqPut.java
new file mode 100644
index 00000000000..579f1355bdb
--- /dev/null
+++ b/key.core/src/main/java/de/uka/ilkd/key/java/recoderext/adt/SeqPut.java
@@ -0,0 +1,49 @@
+/* This file is part of KeY - https://key-project.org
+ * KeY is licensed under the GNU General Public License Version 2
+ * SPDX-License-Identifier: GPL-2.0-only */
+package de.uka.ilkd.key.java.recoderext.adt;
+
+import recoder.java.Expression;
+import recoder.list.generic.ASTArrayList;
+
+
+public class SeqPut extends ADTPrefixConstruct {
+
+ private static final long serialVersionUID = -4836079248155746383L;
+
+ public SeqPut(Expression seq, Expression idx, Expression val) {
+ children = new ASTArrayList<>(getArity());
+ children.add(seq);
+ children.add(idx);
+ children.add(val);
+ makeParentRoleValid();
+ }
+
+ protected SeqPut(SeqPut proto) {
+ super(proto);
+ makeParentRoleValid();
+ }
+
+ @Override
+ public SeqPut deepClone() {
+ return new SeqPut(this);
+ }
+
+
+ @Override
+ public int getArity() {
+ return 3;
+ }
+
+
+ @Override
+ public int getNotation() {
+ return PREFIX;
+ }
+
+ @Override
+ public String toSource() {
+ return "\\seq_upd(" + children.get(0).toSource() + ", " + children.get(1).toSource() + ", "
+ + children.get(2).toSource() + ")";
+ }
+}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/java/visitor/CreatingASTVisitor.java b/key.core/src/main/java/de/uka/ilkd/key/java/visitor/CreatingASTVisitor.java
index d469d3ee970..c0c6ab351a2 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/java/visitor/CreatingASTVisitor.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/java/visitor/CreatingASTVisitor.java
@@ -20,7 +20,6 @@
import de.uka.ilkd.key.java.ast.expression.operator.adt.*;
import de.uka.ilkd.key.java.ast.reference.*;
import de.uka.ilkd.key.java.ast.statement.*;
-import de.uka.ilkd.key.logic.Term;
import de.uka.ilkd.key.logic.op.IProgramVariable;
import de.uka.ilkd.key.logic.op.ProgramVariable;
@@ -606,6 +605,19 @@ ProgramElement createNewElement(ExtList changeList) {
def.doAction(x);
}
+ @Override
+ public void performActionOnSetStatement(SetStatement x) {
+ DefaultAction def = new DefaultAction(x) {
+ @Override
+ ProgramElement createNewElement(ExtList changeList) {
+ // there are no AST elements below the set statement, so we can use the copy
+ // constructor.
+ return new SetStatement(x);
+ }
+ };
+ def.doAction(x);
+ }
+
@Override
public void performActionOnPreIncrement(PreIncrement x) {
DefaultAction def = new DefaultAction(x) {
@@ -1452,6 +1464,17 @@ ProgramElement createNewElement(ExtList changeList) {
def.doAction(x);
}
+ @Override
+ public void performActionOnSeqPut(SeqPut x) {
+ DefaultAction def = new DefaultAction(x) {
+ @Override
+ ProgramElement createNewElement(ExtList changeList) {
+ return new SeqPut(changeList);
+ }
+ };
+ def.doAction(x);
+ }
+
@Override
public void performActionOnDLEmbeddedExpression(final DLEmbeddedExpression x) {
DefaultAction def = new DefaultAction(x) {
@@ -1491,20 +1514,13 @@ public void performActionOnJmlAssert(JmlAssert x) {
@Override
ProgramElement createNewElement(ExtList changeList) {
changeList.add(x.getKind());
- changeList.add(x.getVars());
- return new JmlAssert(changeList, services);
+ changeList.add(x.getCondition());
+ return new JmlAssert(changeList);
}
};
def.doAction(x);
}
- @Override
- public void performActionOnJmlAssertCondition(final Term cond) {
- // should only be called by walk(), which puts an ExtList on the stack
- assert stack.peek() != null;
- stack.peek().add(cond);
- }
-
/**
* returns the position of pe2 in the virtual child array of pe1
*
diff --git a/key.core/src/main/java/de/uka/ilkd/key/java/visitor/JavaASTVisitor.java b/key.core/src/main/java/de/uka/ilkd/key/java/visitor/JavaASTVisitor.java
index 56ae00f5b3a..3a2e18990ea 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/java/visitor/JavaASTVisitor.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/java/visitor/JavaASTVisitor.java
@@ -16,7 +16,6 @@
import de.uka.ilkd.key.java.ast.reference.*;
import de.uka.ilkd.key.java.ast.statement.*;
import de.uka.ilkd.key.logic.ProgramElementName;
-import de.uka.ilkd.key.logic.Term;
import de.uka.ilkd.key.logic.op.IProgramMethod;
import de.uka.ilkd.key.logic.op.IProgramVariable;
import de.uka.ilkd.key.logic.op.LocationVariable;
@@ -57,9 +56,6 @@ public JavaASTVisitor(ProgramElement root, Services services) {
@Override
protected void walk(ProgramElement node) {
- if (node instanceof JmlAssert) {
- performActionOnJmlAssertCondition(((JmlAssert) node).getCond());
- }
super.walk(node);
if (node instanceof LoopStatement && services != null) {
LoopSpecification li =
@@ -232,6 +228,11 @@ public void performActionOnSeqReverse(SeqReverse x) {
doDefaultAction(x);
}
+ @Override
+ public void performActionOnSeqPut(SeqPut x) {
+ doDefaultAction(x);
+ }
+
@Override
public void performActionOnDLEmbeddedExpression(DLEmbeddedExpression x) {
doDefaultAction(x);
@@ -323,6 +324,11 @@ public void performActionOnCopyAssignment(CopyAssignment x) {
doDefaultAction(x);
}
+ @Override
+ public void performActionOnSetStatement(SetStatement x) {
+ doDefaultAction(x);
+ }
+
@Override
public void performActionOnDefault(Default x) {
doDefaultAction(x);
@@ -958,9 +964,4 @@ public void performActionOnCcatchContinueWildcardParameterDeclaration(
public void performActionOnJmlAssert(JmlAssert x) {
doDefaultAction(x);
}
-
- @Override
- public void performActionOnJmlAssertCondition(final Term cond) {
- // empty
- }
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/java/visitor/ProgVarReplaceVisitor.java b/key.core/src/main/java/de/uka/ilkd/key/java/visitor/ProgVarReplaceVisitor.java
index dec62b45a04..0ff581dca25 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/java/visitor/ProgVarReplaceVisitor.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/java/visitor/ProgVarReplaceVisitor.java
@@ -3,11 +3,9 @@
* SPDX-License-Identifier: GPL-2.0-only */
package de.uka.ilkd.key.java.visitor;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Map;
+import java.util.*;
import java.util.Map.Entry;
+import java.util.function.Function;
import java.util.stream.Collectors;
import de.uka.ilkd.key.axiom_abstraction.predicateabstraction.AbstractionPredicate;
@@ -27,13 +25,8 @@
import de.uka.ilkd.key.logic.VariableNamer;
import de.uka.ilkd.key.logic.op.*;
import de.uka.ilkd.key.proof.OpReplacer;
-import de.uka.ilkd.key.speclang.AuxiliaryContract;
-import de.uka.ilkd.key.speclang.BlockContract;
-import de.uka.ilkd.key.speclang.LoopContract;
-import de.uka.ilkd.key.speclang.LoopSpecification;
-import de.uka.ilkd.key.speclang.MergeContract;
-import de.uka.ilkd.key.speclang.PredicateAbstractionMergeContract;
-import de.uka.ilkd.key.speclang.UnparameterizedMergeContract;
+import de.uka.ilkd.key.proof.mgt.SpecificationRepository;
+import de.uka.ilkd.key.speclang.*;
import de.uka.ilkd.key.speclang.jml.translation.ProgramVariableCollection;
import de.uka.ilkd.key.util.InfFlowSpec;
import de.uka.ilkd.key.util.MiscTools;
@@ -108,9 +101,8 @@ public static LocationVariable copy(ProgramVariable pv, String postFix) {
/*
* if(pv.isFinal()){ return pv; }
*/
- return new LocationVariable(
- VariableNamer.parseName(name.toString() + postFix, name.getCreationInfo()),
- pv.getKeYJavaType(), pv.isFinal());
+ return LocationVariable.fromProgramVariable(pv,
+ VariableNamer.parseName(name.toString() + postFix, name.getCreationInfo()));
}
@Override
@@ -610,30 +602,70 @@ public void performActionOnLoopInvariant(LoopStatement oldLoop, LoopStatement ne
}
@Override
- public void performActionOnJmlAssertCondition(final Term x) {
- if (x == null) {
- throw new IllegalStateException("JML assert is incomplete");
- }
- Term newCond = replaceVariablesInTerm(x);
- stack.peek().add(newCond);
- if (!x.equals(newCond)) {
- changed();
- }
+ public void performActionOnJmlAssert(final JmlAssert x) {
+ handleJmlStatements(x, JmlAssert::new);
}
@Override
- public void performActionOnJmlAssert(final JmlAssert x) {
- final ProgramVariableCollection vars = x.getVars();
- final Map atPres = vars.atPres;
- final Map newAtPres = new LinkedHashMap<>(atPres);
- final Map atPreVars = vars.atPreVars;
- final Map newAtPreVars = new LinkedHashMap<>(atPreVars);
+ public void performActionOnSetStatement(final SetStatement x) {
+ /*
+ * var spec =
+ * Objects.requireNonNull(services.getSpecificationRepository().getStatementSpec(x));
+ * ProgramVariableCollection vars = spec.vars();
+ * Map atPres = vars.atPres;
+ * Map newAtPres = new LinkedHashMap<>(atPres);
+ * Map atPreVars = vars.atPreVars;
+ * Map newAtPreVars = new LinkedHashMap<>(atPreVars);
+ *
+ * for (Entry e : atPres.entrySet()) {
+ * LocationVariable pv = e.getKey();
+ * final Term t = e.getValue();
+ * if (t == null) {
+ * continue;
+ * }
+ * if (replaceMap.containsKey(pv)) {
+ * newAtPres.remove(pv);
+ * pv = (LocationVariable) replaceMap.get(pv);
+ * newAtPreVars.put(pv, atPreVars.get(e.getKey()));
+ * }
+ * newAtPres.put(pv, replaceVariablesInTerm(t));
+ * }
+ * final ProgramVariableCollection newVars =
+ * new ProgramVariableCollection(vars.selfVar, vars.paramVars, vars.resultVar, vars.excVar,
+ * newAtPreVars, newAtPres, vars.atBeforeVars, vars.atBefores);
+ *
+ *
+ * var newTerms = spec.terms().map(this::replaceVariablesInTerm);
+ * var newSpec = new SpecificationRepository.JmlStatementSpec(newVars, newTerms);
+ *
+ * services.getSpecificationRepository().addStatementSpec(x, newSpec);
+ *
+ * /*
+ * if (!newAtPres.equals(vars.atPres)) {
+ * changed();
+ * }
+ * doDefaultAction(x);
+ */
+ handleJmlStatements(x, SetStatement::new);
+ }
+
+ public void handleJmlStatements(T x, Function cloner) {
+ var spec = Objects.requireNonNull(
+ services.getSpecificationRepository().getStatementSpec(x));
+
+ ProgramVariableCollection vars = spec.vars();
+ Map atPres = vars.atPres;
+ Map newAtPres = new LinkedHashMap<>(atPres);
+ Map atPreVars = vars.atPreVars;
+ Map newAtPreVars = new LinkedHashMap<>(atPreVars);
+
for (Entry e : atPres.entrySet()) {
LocationVariable pv = e.getKey();
final Term t = e.getValue();
if (t == null) {
continue;
}
+
if (replaceMap.containsKey(pv)) {
newAtPres.remove(pv);
pv = (LocationVariable) replaceMap.get(pv);
@@ -644,10 +676,21 @@ public void performActionOnJmlAssert(final JmlAssert x) {
final ProgramVariableCollection newVars =
new ProgramVariableCollection(vars.selfVar, vars.paramVars, vars.resultVar, vars.excVar,
newAtPreVars, newAtPres, vars.atBeforeVars, vars.atBefores);
- stack.peek().add(newVars);
- if (!newAtPres.equals(vars.atPres)) {
- changed();
- }
- super.performActionOnJmlAssert(x);
+
+
+ var newTerms = spec.terms().map(this::replaceVariablesInTerm);
+ var newSpec = new SpecificationRepository.JmlStatementSpec(newVars, newTerms);
+
+ var c = cloner.apply(x);
+ services.getSpecificationRepository().addStatementSpec(c, newSpec);
+
+ /*
+ * if (!newAtPres.equals(vars.atPres)) {
+ * changed();
+ * }
+ */
+ doDefaultAction(c);
+ changed();
}
+
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/java/visitor/ProgramVariableCollector.java b/key.core/src/main/java/de/uka/ilkd/key/java/visitor/ProgramVariableCollector.java
index 8899b4bfa02..f6ebe80e615 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/java/visitor/ProgramVariableCollector.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/java/visitor/ProgramVariableCollector.java
@@ -6,6 +6,7 @@
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.Map;
+import java.util.Objects;
import de.uka.ilkd.key.axiom_abstraction.predicateabstraction.AbstractionPredicate;
import de.uka.ilkd.key.java.Services;
@@ -260,26 +261,33 @@ public void performActionOnLoopContract(LoopContract x) {
result.addAll(collector.result());
}
+
@Override
- public void performActionOnJmlAssertCondition(final Term x) {
- if (x == null) {
- throw new IllegalStateException("JML assert is incomplete");
- }
- TermProgramVariableCollector tpvc = services.getFactory().create(services);
- x.execPostOrder(tpvc);
- result.addAll(tpvc.result());
+ public void performActionOnJmlAssert(final JmlAssert x) {
+ handleJmlStatement(x);
}
@Override
- public void performActionOnJmlAssert(final JmlAssert x) {
+ public void performActionOnSetStatement(SetStatement x) {
+ handleJmlStatement(x);
+ }
+
+ private void handleJmlStatement(Statement x) {
TermProgramVariableCollector tpvc = services.getFactory().create(services);
- for (Term v : x.getVars().atPres.values()) {
+ var spec =
+ Objects.requireNonNull(services.getSpecificationRepository().getStatementSpec(x));
+ for (Term v : spec.vars().atPres.values()) {
v.execPostOrder(tpvc);
}
- for (Term v : x.getVars().atBefores.values()) {
+ for (Term v : spec.vars().atBefores.values()) {
v.execPostOrder(tpvc);
}
- result.addAll(tpvc.result());
+ for (Term term : spec.terms()) {
+ term.execPostOrder(tpvc);
+ }
+ result.addAll(tpvc.result());
}
+
+
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/java/visitor/Visitor.java b/key.core/src/main/java/de/uka/ilkd/key/java/visitor/Visitor.java
index 820238550a6..e0036ecb368 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/java/visitor/Visitor.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/java/visitor/Visitor.java
@@ -14,8 +14,8 @@
import de.uka.ilkd.key.java.ast.expression.operator.adt.*;
import de.uka.ilkd.key.java.ast.reference.*;
import de.uka.ilkd.key.java.ast.statement.*;
+import de.uka.ilkd.key.java.statement.SetStatement;
import de.uka.ilkd.key.logic.ProgramElementName;
-import de.uka.ilkd.key.logic.Term;
import de.uka.ilkd.key.logic.op.IProgramMethod;
import de.uka.ilkd.key.logic.op.IProgramVariable;
import de.uka.ilkd.key.logic.op.LocationVariable;
@@ -81,6 +81,8 @@ public interface Visitor {
void performActionOnSeqReverse(SeqReverse x);
+ //void performActionOnSeqPut(SeqPut seqPut);
+
void performActionOnDLEmbeddedExpression(DLEmbeddedExpression x);
void performActionOnStringLiteral(StringLiteral x);
@@ -183,6 +185,8 @@ public interface Visitor {
void performActionOnCopyAssignment(CopyAssignment x);
+ //void performActionOnSetStatement(SetStatement x);
+
void performActionOnDivideAssignment(DivideAssignment x);
void performActionOnMinusAssignment(MinusAssignment x);
@@ -401,15 +405,4 @@ void performActionOnCcatchBreakWildcardParameterDeclaration(
* @param jmlAssert the statement to perform the action on.
*/
void performActionOnJmlAssert(JmlAssert jmlAssert);
-
- /**
- * Performs action on the condition of a JML assert statement.
- *
- * Note: if you don't extend JavaASTVisitor or something else that calls this methode for you,
- * you have to call it yourself, e.g. in {@link #performActionOnJmlAssert} if needed.
- *
- * @param cond the condition to perform an action on (may be {@code null} if the JML assert
- * wasn't finished)
- */
- void performActionOnJmlAssertCondition(final Term cond);
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/ldt/HeapLDT.java b/key.core/src/main/java/de/uka/ilkd/key/ldt/HeapLDT.java
index 78bde95eedc..2cebba1bcb4 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/ldt/HeapLDT.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/ldt/HeapLDT.java
@@ -24,6 +24,8 @@
import org.key_project.util.collection.ImmutableList;
import org.key_project.util.collection.ImmutableSLList;
+import org.jspecify.annotations.Nullable;
+
/**
* LDT responsible for the "Heap" sort, and the associated "Field" sort. Besides offering the usual
@@ -142,6 +144,43 @@ private String getFieldSymbolName(LocationVariable fieldPV) {
// public interface
// -------------------------------------------------------------------------
+ /**
+ * Wrapper class
+ *
+ * @param className the class name
+ * @param attributeName the attribute name
+ */
+ public record SplitFieldName(String className, String attributeName) {}
+
+ /**
+ * Splits a field name.
+ *
+ * @param symbol the field name to split.
+ * @return the split field name
+ */
+ public static @Nullable SplitFieldName trySplitFieldName(Named symbol) {
+ var name = symbol.name().toString();
+ // check for normal attribute
+ int endOfClassName = name.indexOf("::$");
+
+ int startAttributeName = endOfClassName + 3;
+
+
+ if (endOfClassName < 0) {
+ // not a normal attribute, maybe an implicit attribute like ?
+ endOfClassName = name.indexOf("::<");
+ startAttributeName = endOfClassName + 2;
+ }
+
+ if (endOfClassName < 0) {
+ return null;
+ }
+
+ String className = name.substring(0, endOfClassName);
+ String attributeName = name.substring(startAttributeName);
+ return new SplitFieldName(className, attributeName);
+ }
+
/**
* Given a constant symbol representing a field, this method returns a simplified name of the
* constant symbol to be used for pretty printing.
diff --git a/key.core/src/main/java/de/uka/ilkd/key/ldt/SeqLDT.java b/key.core/src/main/java/de/uka/ilkd/key/ldt/SeqLDT.java
index a78e3d29c96..bfdbf3cbe0f 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/ldt/SeqLDT.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/ldt/SeqLDT.java
@@ -3,6 +3,7 @@
* SPDX-License-Identifier: GPL-2.0-only */
package de.uka.ilkd.key.ldt;
+import de.uka.ilkd.key.java.Expression;
import de.uka.ilkd.key.java.Services;
import de.uka.ilkd.key.java.ast.abstraction.Type;
import de.uka.ilkd.key.java.ast.expression.Expression;
@@ -10,6 +11,7 @@
import de.uka.ilkd.key.java.ast.expression.literal.EmptySeqLiteral;
import de.uka.ilkd.key.java.ast.expression.literal.Literal;
import de.uka.ilkd.key.java.ast.expression.operator.adt.*;
+import de.uka.ilkd.key.java.expression.operator.adt.SeqPut;
import de.uka.ilkd.key.java.ast.reference.ExecutionContext;
import de.uka.ilkd.key.logic.Term;
import de.uka.ilkd.key.logic.TermServices;
@@ -39,6 +41,7 @@ public final class SeqLDT extends LDT {
private final JFunction seqConcat;
private final JFunction seqSub;
private final JFunction seqReverse;
+ private final JFunction seqUpd;
private final JFunction seqDef;
private final JFunction values;
@@ -51,6 +54,7 @@ public SeqLDT(TermServices services) {
seqConcat = addFunction(services, "seqConcat");
seqSub = addFunction(services, "seqSub");
seqReverse = addFunction(services, "seqReverse");
+ seqUpd = addFunction(services, "seqUpd");
seqIndexOf = addFunction(services, "seqIndexOf");
seqDef = addFunction(services, "seqDef");
values = addFunction(services, "values");
@@ -86,6 +90,9 @@ public JFunction getSeqSub() {
return seqSub;
}
+ public JFunction getSeqUpd() {
+ return seqUpd;
+ }
public JFunction getSeqReverse() {
return seqReverse;
@@ -127,7 +134,7 @@ public boolean isResponsible(
TermServices services, ExecutionContext ec) {
return op instanceof SeqSingleton || op instanceof SeqConcat || op instanceof SeqSub
|| op instanceof SeqReverse || op instanceof SeqIndexOf || op instanceof SeqGet
- || op instanceof SeqLength;
+ || op instanceof SeqLength || op instanceof SeqPut;
}
@@ -150,6 +157,8 @@ public JFunction getFunctionFor(
return seqSub;
} else if (op instanceof SeqReverse) {
return seqReverse;
+ } else if (op instanceof SeqPut) {
+ return seqUpd;
} else if (op instanceof SeqIndexOf) {
return seqIndexOf;
} else if (op instanceof SeqGet) {
diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/BoundVariableTools.java b/key.core/src/main/java/de/uka/ilkd/key/logic/BoundVariableTools.java
index b985dcdf7a7..d1e930e93a0 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/logic/BoundVariableTools.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/logic/BoundVariableTools.java
@@ -13,6 +13,8 @@
import org.key_project.util.collection.ImmutableArray;
import org.key_project.util.collection.ImmutableSet;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
/**
* Some generally useful tools for dealing with arrays of bound variables
@@ -206,7 +208,7 @@ public boolean equalsModRenaming(ImmutableArray vars0, Ter
return false;
}
if (vars0.size() == 0) {
- return term0.equalsModRenaming(term1);
+ return term0.equalsModProperty(term1, RENAMING_PROPERTY);
}
final ImmutableArray unifiedVars = unifyVariableArrays(vars0, vars1,
@@ -215,7 +217,7 @@ public boolean equalsModRenaming(ImmutableArray vars0, Ter
final Term renamedTerm0 = renameVariables(term0, vars0, unifiedVars, services);
final Term renamedTerm1 = renameVariables(term1, vars1, unifiedVars, services);
- return renamedTerm0.equalsModRenaming(renamedTerm1);
+ return renamedTerm0.equalsModProperty(renamedTerm1, RENAMING_PROPERTY);
}
/**
diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/JavaBlock.java b/key.core/src/main/java/de/uka/ilkd/key/logic/JavaBlock.java
index 7d16676ea81..7759cb56f5c 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/logic/JavaBlock.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/logic/JavaBlock.java
@@ -91,31 +91,6 @@ public boolean equals(Object o) {
}
}
- /**
- * returns true if the given ProgramElement is equal to the one of the JavaBlock modulo renaming
- * (see comment in SourceElement)
- */
- public boolean equalsModRenaming(Object o, NameAbstractionTable nat) {
- if (!(o instanceof JavaBlock)) {
- return false;
- }
- return equalsModRenaming(((JavaBlock) o).program(), nat);
- }
-
-
- /**
- * returns true if the given ProgramElement is equal to the one of the JavaBlock modulo renaming
- * (see comment in SourceElement)
- */
- private boolean equalsModRenaming(JavaProgramElement pe, NameAbstractionTable nat) {
- if (pe == null && program() == null) {
- return true;
- } else if (pe != null && program() != null) {
- return program().equalsModRenaming(pe, nat);
- }
- return false;
- }
-
/**
* returns the java program
*
diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/LabeledTermImpl.java b/key.core/src/main/java/de/uka/ilkd/key/logic/LabeledTermImpl.java
index f55f8e221eb..b17717cb9dd 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/logic/LabeledTermImpl.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/logic/LabeledTermImpl.java
@@ -6,6 +6,10 @@
import java.util.Objects;
import java.util.stream.Collectors;
+import de.uka.ilkd.key.logic.equality.ProofIrrelevancyProperty;
+import de.uka.ilkd.key.logic.equality.RenamingProperty;
+import de.uka.ilkd.key.logic.equality.TermEqualsModProperty;
+import de.uka.ilkd.key.logic.equality.TermProperty;
import de.uka.ilkd.key.logic.label.TermLabel;
import de.uka.ilkd.key.logic.op.Operator;
import de.uka.ilkd.key.logic.op.QuantifiableVariable;
@@ -16,16 +20,25 @@
import org.key_project.util.java.CollectionUtil;
/**
+ *
* The labeled term class is used for terms that have a label attached.
+ *
+ *
+ * Two labeled terms are equal if they have equal term structure and equal annotations. In contrast,
+ * the method {@link TermEqualsModProperty#equalsModProperty(Object, TermProperty)} can be used to
+ * compare terms while ignoring certain given properties. E.g. by using
+ * {@link RenamingProperty#RENAMING_PROPERTY}, just the term structures modulo renaming are compared
+ * whilst ignoring annotations.
+ *
+ * Prior implementations of {@link EqualsModProofIrrelevancy} are now in
+ * {@link ProofIrrelevancyProperty}.
+ *
*
- * Two labeled terms are equal if they have equal term structure and equal annotations. In contrast
- * the method {@link Term#equalsModRenaming(Term)} does not care about annotations and will just
- * compare the term structure alone modula renaming.
*
* @see Term
* @see TermImpl
*/
-class LabeledTermImpl extends TermImpl implements EqualsModProofIrrelevancy {
+class LabeledTermImpl extends TermImpl {
/**
* @see #getLabels()
@@ -38,7 +51,7 @@ class LabeledTermImpl extends TermImpl implements EqualsModProofIrrelevancy {
* @param op the top level operator
* @param subs the Term that are the subterms of this term
* @param boundVars logic variables bound by the operator
- * @param labels the terms labels (must not be null or empty)
+ * @param labels the term's labels (must not be null or empty)
* @param origin a String with origin information
*/
public LabeledTermImpl(Operator op, ImmutableArray subs,
@@ -143,43 +156,6 @@ public int computeHashCode() {
return hash;
}
- @Override
- public boolean equalsModProofIrrelevancy(Object o) {
- if (!super.equalsModProofIrrelevancy(o)) {
- return false;
- }
-
- if (o instanceof LabeledTermImpl cmp) {
- if (labels.size() == cmp.labels.size()) {
- for (int i = 0, sz = labels.size(); i < sz; i++) {
- // skip irrelevant (origin) labels that differ for no real reason
- if (!labels.get(i).isProofRelevant()) {
- continue;
- }
- // this is not optimal, but as long as number of labels limited ok
- if (!cmp.labels.contains(labels.get(i))) {
- return false;
- }
- }
- return true;
- }
- return false;
- } else {
- return o.getClass() == TermImpl.class;
- }
- }
-
- @Override
- public int hashCodeModProofIrrelevancy() {
- int hash = super.hashCodeModProofIrrelevancy();
- for (int i = 0, sz = labels.size(); i < sz; i++) {
- if (labels.get(i).isProofRelevant()) {
- hash += 7 * labels.get(i).hashCode();
- }
- }
- return hash;
- }
-
@Override
public String toString() {
StringBuilder result = new StringBuilder(super.toString());
diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/Semisequent.java b/key.core/src/main/java/de/uka/ilkd/key/logic/Semisequent.java
index d813f591bec..a8ce511c4fb 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/logic/Semisequent.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/logic/Semisequent.java
@@ -9,6 +9,8 @@
import org.key_project.util.collection.ImmutableList;
import org.key_project.util.collection.ImmutableSLList;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
/**
* This class represents the succedent or antecendent part of a sequent. It is more or less a list
@@ -184,7 +186,8 @@ private SemisequentChangeInfo insertAndRemoveRedundancyHelper(int idx,
searchList = searchList.tail();
if (sequentFormula != null
- && cf.formula().equalsModRenaming(sequentFormula.formula())) {
+ && cf.formula().equalsModProperty(sequentFormula.formula(),
+ RENAMING_PROPERTY)) {
semiCI.rejectedFormula(sequentFormula);
return semiCI; // semisequent already contains formula
diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/SequentFormula.java b/key.core/src/main/java/de/uka/ilkd/key/logic/SequentFormula.java
index cbaf19aa5f8..38325df369f 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/logic/SequentFormula.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/logic/SequentFormula.java
@@ -8,6 +8,8 @@
import org.key_project.util.EqualsModProofIrrelevancy;
+import static de.uka.ilkd.key.logic.equality.ProofIrrelevancyProperty.PROOF_IRRELEVANCY_PROPERTY;
+
/**
* A sequent formula is a wrapper around a formula that occurs as top level formula in a sequent.
@@ -42,7 +44,7 @@ public SequentFormula(Term term) {
}
this.term = term;
this.hashCode = term.hashCode() * 13;
- this.hashCode2 = term.hashCodeModProofIrrelevancy();
+ this.hashCode2 = term.hashCodeModProperty(PROOF_IRRELEVANCY_PROPERTY);
}
/** @return the stored Term */
@@ -76,7 +78,7 @@ public boolean equalsModProofIrrelevancy(Object obj) {
return true;
}
if (obj instanceof SequentFormula cmp) {
- return term.equalsModProofIrrelevancy(cmp.formula());
+ return term.equalsModProperty(cmp.formula(), PROOF_IRRELEVANCY_PROPERTY);
}
return false;
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/Term.java b/key.core/src/main/java/de/uka/ilkd/key/logic/Term.java
index 7407730b734..60c03e6fdae 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/logic/Term.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/logic/Term.java
@@ -4,6 +4,7 @@
package de.uka.ilkd.key.logic;
import de.uka.ilkd.key.ldt.JavaDLTheory;
+import de.uka.ilkd.key.logic.equality.TermEqualsModProperty;
import de.uka.ilkd.key.logic.label.TermLabel;
import de.uka.ilkd.key.logic.op.Operator;
import de.uka.ilkd.key.logic.op.QuantifiableVariable;
@@ -11,7 +12,6 @@
import org.key_project.logic.Name;
import org.key_project.logic.Visitor;
-import org.key_project.util.EqualsModProofIrrelevancy;
import org.key_project.util.collection.ImmutableArray;
import org.key_project.util.collection.ImmutableSet;
@@ -43,7 +43,7 @@
* supported: {@link Term#execPostOrder(Visitor)} and {@link Term#execPreOrder(Visitor)}.
*/
public interface Term
- extends SVSubstitute, Sorted, EqualsModProofIrrelevancy, org.key_project.logic.Term {
+ extends SVSubstitute, Sorted, TermEqualsModProperty, org.key_project.logic.Term {
@Override
Operator op();
@@ -83,15 +83,6 @@ public interface Term
@NonNull
JavaBlock javaBlock();
- /**
- * Compares if two terms are equal modulo bound renaming
- *
- * @param o another term,
- * @return true iff the given term has the same values in operator, sort, arity, varsBoundHere
- * and javaBlock as this object modulo bound renaming
- */
- boolean equalsModRenaming(Term o);
-
/**
* returns true if the term is labeled
*/
@@ -128,26 +119,6 @@ public interface Term
*/
boolean containsJavaBlockRecursive();
- /**
- * Checks if {@code o} is a term syntactically equal to this one, except for some irrelevant
- * labels.
- *
- * @param o an object
- * @return {@code true} iff {@code o} is a term syntactically equal to this one, except for
- * their labels.
- * @see TermLabel#isProofRelevant() isStrategyRelevant
- */
- boolean equalsModIrrelevantTermLabels(Object o);
-
- /**
- * Checks if {@code o} is a term syntactically equal to this one, ignoring all term
- * labels.
- *
- * @param o an object
- * @return {@code true} iff {@code o} is a term syntactically equal to this ignoring term labels
- */
- boolean equalsModTermLabels(Object o);
-
/**
* Returns a human-readable source of this term. For example the filename with line and offset.
*/
diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/TermBuilder.java b/key.core/src/main/java/de/uka/ilkd/key/logic/TermBuilder.java
index 2dd7a7a6c88..ad921064be6 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/logic/TermBuilder.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/logic/TermBuilder.java
@@ -2053,6 +2053,11 @@ public Term seqSub(Term s, Term from, Term to) {
return func(services.getTypeConverter().getSeqLDT().getSeqSub(), s, from, to);
}
+ public Term seqUpd(Term seq, Term idx, Term value) {
+ return func(services.getTypeConverter().getSeqLDT().getSeqUpd(), seq, idx, value);
+ }
+
+
public Term seqReverse(Term s) {
return func(services.getTypeConverter().getSeqLDT().getSeqReverse(), s);
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/TermImpl.java b/key.core/src/main/java/de/uka/ilkd/key/logic/TermImpl.java
index 5aecbab321a..3a49c3002b9 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/logic/TermImpl.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/logic/TermImpl.java
@@ -3,24 +3,19 @@
* SPDX-License-Identifier: GPL-2.0-only */
package de.uka.ilkd.key.logic;
-import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
-import de.uka.ilkd.key.java.NameAbstractionTable;
-import de.uka.ilkd.key.java.ast.PositionInfo;
+import de.uka.ilkd.key.java.PositionInfo;
+import de.uka.ilkd.key.logic.equality.TermProperty;
import de.uka.ilkd.key.logic.label.TermLabel;
import de.uka.ilkd.key.logic.op.*;
import org.key_project.logic.Name;
import org.key_project.logic.Visitor;
import org.key_project.logic.sort.Sort;
-import org.key_project.util.EqualsModProofIrrelevancy;
-import org.key_project.util.EqualsModProofIrrelevancyUtil;
import org.key_project.util.Strings;
import org.key_project.util.collection.DefaultImmutableSet;
import org.key_project.util.collection.ImmutableArray;
-import org.key_project.util.collection.ImmutableList;
-import org.key_project.util.collection.ImmutableSLList;
import org.key_project.util.collection.ImmutableSet;
import org.jspecify.annotations.NonNull;
@@ -31,7 +26,7 @@
* The currently only class implementing the Term interface. TermFactory should be the only class
* dealing directly with the TermImpl class.
*/
-class TermImpl implements Term, EqualsModProofIrrelevancy {
+class TermImpl implements Term {
/**
* A static empty list of terms used for memory reasons.
@@ -73,10 +68,6 @@ private enum ThreeValuedTruth {
* Cached {@link #hashCode()} value.
*/
private int hashcode = -1;
- /**
- * Cached {@link #hashCodeModProofIrrelevancy()} value.
- */
- private int hashcode2 = -1;
private Sort sort;
@@ -308,184 +299,6 @@ public void execPreOrder(Visitor visitor) {
visitor.subtreeLeft(this);
}
-
- @Override
- public final boolean equalsModRenaming(Term o) {
- if (o == this) {
- return true;
- }
- return unifyHelp(this, o, ImmutableSLList.nil(),
- ImmutableSLList.nil(), null);
- }
-
- //
- // equals modulo renaming logic
-
-
- /**
- * compare two quantifiable variables if they are equal modulo renaming
- *
- * @param ownVar first QuantifiableVariable to be compared
- * @param cmpVar second QuantifiableVariable to be compared
- * @param ownBoundVars variables bound above the current position
- * @param cmpBoundVars variables bound above the current position
- */
- private static boolean compareBoundVariables(QuantifiableVariable ownVar,
- QuantifiableVariable cmpVar, ImmutableList ownBoundVars,
- ImmutableList cmpBoundVars) {
-
- final int ownNum = indexOf(ownVar, ownBoundVars);
- final int cmpNum = indexOf(cmpVar, cmpBoundVars);
-
- if (ownNum == -1 && cmpNum == -1) {
- // if both variables are not bound the variables have to be the
- // same object
- return ownVar == cmpVar;
- }
-
- // otherwise the variables have to be bound at the same point (and both
- // be bound)
- return ownNum == cmpNum;
- }
-
- /**
- * @return the index of the first occurrence of var
in list
, or
- * -1
if the variable is not an element of the list
- */
- private static int indexOf(QuantifiableVariable var, ImmutableList list) {
- int res = 0;
- while (!list.isEmpty()) {
- if (list.head() == var) {
- return res;
- }
- ++res;
- list = list.tail();
- }
- return -1;
- }
-
- /**
- * Compares two terms modulo bound renaming
- *
- * @param t0 the first term
- * @param t1 the second term
- * @param ownBoundVars variables bound above the current position
- * @param cmpBoundVars variables bound above the current position
- * @return true
is returned iff the terms are equal modulo bound renaming
- */
- private boolean unifyHelp(Term t0, Term t1, ImmutableList ownBoundVars,
- ImmutableList cmpBoundVars, NameAbstractionTable nat) {
-
- if (t0 == t1 && ownBoundVars.equals(cmpBoundVars)) {
- return true;
- }
-
- if (t0.sort() != t1.sort() || t0.arity() != t1.arity()) {
- return false;
- }
-
- final Operator op0 = t0.op();
-
- if (op0 instanceof QuantifiableVariable) {
- return handleQuantifiableVariable(t0, t1, ownBoundVars, cmpBoundVars);
- }
-
- final Operator op1 = t1.op();
-
- if (op0 instanceof Modality mod0 && op1 instanceof Modality mod1) {
- if (mod0.kind() != mod1.kind()) {
- return false;
- }
- nat = handleJava(mod0.program(), mod1.program(), nat);
- if (nat == FAILED) {
- return false;
- }
- } else if (!(op0 instanceof ProgramVariable) && op0 != op1) {
- return false;
- }
-
- if (!(op0 instanceof SchemaVariable) && op0 instanceof ProgramVariable pv0) {
- if (op1 instanceof ProgramVariable pv1) {
- nat = checkNat(nat);
- if (!pv0.equalsModRenaming(pv1, nat)) {
- return false;
- }
- } else {
- return false;
- }
- }
-
- return descendRecursively(t0, t1, ownBoundVars, cmpBoundVars, nat);
- }
-
- private boolean handleQuantifiableVariable(Term t0, Term t1,
- ImmutableList ownBoundVars,
- ImmutableList cmpBoundVars) {
- return (t1.op() instanceof QuantifiableVariable)
- && compareBoundVariables((QuantifiableVariable) t0.op(),
- (QuantifiableVariable) t1.op(), ownBoundVars, cmpBoundVars);
- }
-
- /**
- * used to encode that handleJava results in an unsatisfiable constraint (faster than
- * using exceptions)
- */
- private static final NameAbstractionTable FAILED = new NameAbstractionTable();
-
- private static NameAbstractionTable handleJava(JavaBlock jb0, JavaBlock jb1,
- NameAbstractionTable nat) {
- if (!jb0.isEmpty() || !jb1.isEmpty()) {
- nat = checkNat(nat);
- if (!jb0.equalsModRenaming(jb1, nat)) {
- return FAILED;
- }
- }
- return nat;
- }
-
- private boolean descendRecursively(Term t0, Term t1,
- ImmutableList ownBoundVars,
- ImmutableList cmpBoundVars, NameAbstractionTable nat) {
-
- for (int i = 0; i < t0.arity(); i++) {
- ImmutableList subOwnBoundVars = ownBoundVars;
- ImmutableList subCmpBoundVars = cmpBoundVars;
-
- if (t0.varsBoundHere(i).size() != t1.varsBoundHere(i).size()) {
- return false;
- }
- for (int j = 0; j < t0.varsBoundHere(i).size(); j++) {
- final QuantifiableVariable ownVar = t0.varsBoundHere(i).get(j);
- final QuantifiableVariable cmpVar = t1.varsBoundHere(i).get(j);
- if (ownVar.sort() != cmpVar.sort()) {
- return false;
- }
-
- subOwnBoundVars = subOwnBoundVars.prepend(ownVar);
- subCmpBoundVars = subCmpBoundVars.prepend(cmpVar);
- }
-
- boolean newConstraint =
- unifyHelp(t0.sub(i), t1.sub(i), subOwnBoundVars, subCmpBoundVars, nat);
-
- if (!newConstraint) {
- return false;
- }
- }
-
- return true;
- }
-
- private static NameAbstractionTable checkNat(NameAbstractionTable nat) {
- if (nat == null) {
- return new NameAbstractionTable();
- }
- return nat;
- }
-
- // end of equals modulo renaming logic
-
-
/**
* true iff o
is syntactically equal to this term
*/
@@ -507,122 +320,6 @@ public boolean equals(Object o) {
&& javaBlock().equals(t.javaBlock());
}
- @Override
- public boolean equalsModIrrelevantTermLabels(Object o) {
- if (o == this) {
- return true;
- }
-
- if (!(o instanceof TermImpl t)) {
- return false;
- }
-
- if (!(op.equals(t.op) && boundVars.equals(t.boundVars)
- && javaBlock().equals(t.javaBlock()))) {
- return false;
- }
-
- Term other = (Term) o;
-
- for (TermLabel label : getLabels()) {
- if (label.isProofRelevant() && !other.getLabels().contains(label)) {
- return false;
- }
- }
-
- for (TermLabel label : other.getLabels()) {
- if (label.isProofRelevant() && !getLabels().contains(label)) {
- return false;
- }
- }
-
- for (int i = 0; i < subs.size(); ++i) {
- if (!subs.get(i).equalsModIrrelevantTermLabels(t.subs.get(i))) {
- return false;
- }
- }
-
- return true;
- }
-
- @Override
- public boolean equalsModTermLabels(Object o) {
- if (o == this) {
- return true;
- }
-
- if (!(o instanceof TermImpl t)) {
- return false;
- }
-
- if (!(op.equals(t.op) && boundVars.equals(t.boundVars)
- && javaBlock().equals(t.javaBlock()))) {
- return false;
- }
-
- for (int i = 0; i < subs.size(); ++i) {
- if (!subs.get(i).equalsModTermLabels(t.subs.get(i))) {
- return false;
- }
- }
- return true;
- }
-
- @Override
- public boolean equalsModProofIrrelevancy(Object o) {
- if (o == this) {
- return true;
- }
-
- if (!(o instanceof TermImpl t)) {
- return false;
- }
-
- boolean opResult = op.equalsModProofIrrelevancy(t.op);
- if (!(opResult
- && EqualsModProofIrrelevancyUtil.compareImmutableArrays(boundVars, t.boundVars)
- && javaBlock().equalsModProofIrrelevancy(t.javaBlock()))) {
- return false;
- }
-
- Term other = (Term) o;
-
- for (TermLabel label : getLabels()) {
- if (label.isProofRelevant() && !other.getLabels().contains(label)) {
- return false;
- }
- }
-
- for (TermLabel label : other.getLabels()) {
- if (label.isProofRelevant() && !getLabels().contains(label)) {
- return false;
- }
- }
-
- for (int i = 0; i < subs.size(); ++i) {
- if (!subs.get(i).equalsModProofIrrelevancy(t.subs.get(i))) {
- return false;
- }
- }
-
- return true;
- }
-
- @Override
- public int hashCodeModProofIrrelevancy() {
- if (hashcode2 == -1) {
- // compute into local variable first to be thread-safe.
- this.hashcode2 = Objects.hash(op(),
- EqualsModProofIrrelevancyUtil
- .hashCodeIterable(subs()),
- EqualsModProofIrrelevancyUtil.hashCodeIterable(boundVars()), javaBlock());
- if (hashcode2 == -1) {
- hashcode2 = 0;
- }
- }
- return hashcode2;
- }
-
@Override
public final int hashCode() {
if (hashcode == -1) {
@@ -632,7 +329,6 @@ public final int hashCode() {
return hashcode;
}
-
/**
* Performs the actual computation of the hashcode and can be overwritten by subclasses if
* necessary
@@ -650,6 +346,19 @@ protected int computeHashCode() {
return hashcode;
}
+ @Override
+ public boolean equalsModProperty(Object o, TermProperty property) {
+ if (!(o instanceof Term other)) {
+ return false;
+ }
+ return property.equalsModThisProperty(this, other);
+ }
+
+ @Override
+ public int hashCodeModProperty(TermProperty property) {
+ return property.hashCodeModThisProperty(this);
+ }
+
/**
* returns a linearized textual representation of this term
diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/equality/IrrelevantTermLabelsProperty.java b/key.core/src/main/java/de/uka/ilkd/key/logic/equality/IrrelevantTermLabelsProperty.java
new file mode 100644
index 00000000000..0909c508423
--- /dev/null
+++ b/key.core/src/main/java/de/uka/ilkd/key/logic/equality/IrrelevantTermLabelsProperty.java
@@ -0,0 +1,86 @@
+/* This file is part of KeY - https://key-project.org
+ * KeY is licensed under the GNU General Public License Version 2
+ * SPDX-License-Identifier: GPL-2.0-only */
+package de.uka.ilkd.key.logic.equality;
+
+import de.uka.ilkd.key.logic.Term;
+import de.uka.ilkd.key.logic.label.TermLabel;
+
+import org.key_project.util.collection.ImmutableArray;
+
+/**
+ * A property that can be used in
+ * {@link TermEqualsModProperty#equalsModProperty(Object, TermProperty)}.
+ * All irrelevant term labels are ignored in this equality check.
+ */
+public class IrrelevantTermLabelsProperty implements TermProperty {
+ /**
+ * The single instance of this property.
+ */
+ public static final IrrelevantTermLabelsProperty IRRELEVANT_TERM_LABELS_PROPERTY =
+ new IrrelevantTermLabelsProperty();
+
+ /**
+ * This constructor is private as a single instance of this class should be shared. The instance
+ * can be accessed
+ * through {@link IrrelevantTermLabelsProperty#IRRELEVANT_TERM_LABELS_PROPERTY} and is used as a
+ * parameter for
+ * {@link TermProperty#equalsModThisProperty(Term, Term)}.
+ */
+ private IrrelevantTermLabelsProperty() {}
+
+ /**
+ * Checks if {@code term2} is a term syntactically equal to {@code term1}, except for some
+ * irrelevant
+ * labels.
+ *
+ * @param term1 a term
+ * @param term2 the term compared to {@code term1}
+ * @return {@code true} iff {@code term2} is a term syntactically equal to {@code term1}, except
+ * for
+ * their irrelevant labels.
+ * @see TermLabel#isProofRelevant() isStrategyRelevant
+ */
+ @Override
+ public Boolean equalsModThisProperty(Term term1, Term term2) {
+ if (term2 == term1) {
+ return true;
+ }
+
+ if (!(term1.op().equals(term2.op()) && term1.boundVars().equals(term2.boundVars())
+ && term1.javaBlock().equals(term2.javaBlock()))) {
+ return false;
+ }
+
+ final ImmutableArray term1Labels = term1.getLabels();
+ final ImmutableArray term2Labels = term2.getLabels();
+ for (TermLabel label : term1Labels) {
+ if (label.isProofRelevant() && !term2Labels.contains(label)) {
+ return false;
+ }
+ }
+ for (TermLabel label : term2Labels) {
+ if (label.isProofRelevant() && !term1Labels.contains(label)) {
+ return false;
+ }
+ }
+
+ final ImmutableArray termSubs = term1.subs();
+ final ImmutableArray term2Subs = term2.subs();
+ final int numOfSubs = termSubs.size();
+ for (int i = 0; i < numOfSubs; ++i) {
+ if (!termSubs.get(i).equalsModProperty(term2Subs.get(i),
+ IRRELEVANT_TERM_LABELS_PROPERTY)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCodeModThisProperty(Term term) {
+ throw new UnsupportedOperationException(
+ "Hashing of terms modulo irrelevant term labels not yet implemented!");
+ }
+}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/equality/ProofIrrelevancyProperty.java b/key.core/src/main/java/de/uka/ilkd/key/logic/equality/ProofIrrelevancyProperty.java
new file mode 100644
index 00000000000..72aa7b28310
--- /dev/null
+++ b/key.core/src/main/java/de/uka/ilkd/key/logic/equality/ProofIrrelevancyProperty.java
@@ -0,0 +1,140 @@
+/* This file is part of KeY - https://key-project.org
+ * KeY is licensed under the GNU General Public License Version 2
+ * SPDX-License-Identifier: GPL-2.0-only */
+package de.uka.ilkd.key.logic.equality;
+
+
+import java.util.Objects;
+
+import de.uka.ilkd.key.logic.Term;
+import de.uka.ilkd.key.logic.label.TermLabel;
+
+import org.key_project.util.EqualsModProofIrrelevancy;
+import org.key_project.util.EqualsModProofIrrelevancyUtil;
+import org.key_project.util.collection.ImmutableArray;
+
+/**
+ * A property that can be used in
+ * {@link TermEqualsModProperty#equalsModProperty(Object, TermProperty)}.
+ * All proof irrelevant attributes are ignored in this equality check.
+ */
+public class ProofIrrelevancyProperty implements TermProperty {
+ /**
+ * The single instance of this property.
+ */
+ public static final ProofIrrelevancyProperty PROOF_IRRELEVANCY_PROPERTY =
+ new ProofIrrelevancyProperty();
+
+ /**
+ * This constructor is private as a single instance of this class should be shared. The instance
+ * can be accessed
+ * through {@link ProofIrrelevancyProperty#PROOF_IRRELEVANCY_PROPERTY} and is used as a
+ * parameter for
+ * {@link TermProperty#equalsModThisProperty(Term, Term)}.
+ */
+ private ProofIrrelevancyProperty() {}
+
+ /**
+ * Checks if {@code term2} is a term syntactically equal to {@code term1}, except for attributes
+ * that
+ * are not relevant for the purpose of these terms in the proof.
+ *
+ * Combines the prior implementations of {@link EqualsModProofIrrelevancy} in TermImpl and
+ * LabeledTermImpl.
+ *
+ *
+ * @param term1 a term
+ * @param term2 the term compared to {@code term1}
+ * @return true iff {@code term2} is a term syntactically equal to {@code term1}, except for
+ * proof-irrelevant attributes.
+ */
+ @Override
+ public Boolean equalsModThisProperty(Term term1, Term term2) {
+ if (term2 == term1) {
+ return true;
+ }
+
+ final boolean opResult = term1.op().equalsModProofIrrelevancy(term2.op());
+ if (!(opResult
+ && EqualsModProofIrrelevancyUtil.compareImmutableArrays(term1.boundVars(),
+ term2.boundVars())
+ && term1.javaBlock().equalsModProofIrrelevancy(term2.javaBlock()))) {
+ return false;
+ }
+
+ final ImmutableArray termLabels = term1.getLabels();
+ final ImmutableArray term2Labels = term2.getLabels();
+ for (TermLabel label : termLabels) {
+ if (label.isProofRelevant() && !term2Labels.contains(label)) {
+ return false;
+ }
+ }
+ for (TermLabel label : term2Labels) {
+ if (label.isProofRelevant() && !termLabels.contains(label)) {
+ return false;
+ }
+ }
+
+ final ImmutableArray term1Subs = term1.subs();
+ final ImmutableArray term2Subs = term2.subs();
+ final int numOfSubs = term1Subs.size();
+ for (int i = 0; i < numOfSubs; ++i) {
+ if (!term1Subs.get(i).equalsModProperty(term2Subs.get(i), PROOF_IRRELEVANCY_PROPERTY)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ *
+ * Computes a hashcode that represents the proof-relevant fields of {@code term}.
+ *
+ * Combines the prior implementations of {@link EqualsModProofIrrelevancy} in TermImpl and
+ * LabeledTermImpl.
+ *
+ * @param term the term to compute the hashcode for
+ * @return the hashcode
+ */
+ @Override
+ public int hashCodeModThisProperty(Term term) {
+ int hashcode = Objects.hash(term.op(), hashCodeIterable(term.subs()),
+ EqualsModProofIrrelevancyUtil.hashCodeIterable(term.boundVars()), term.javaBlock());
+
+ // part from LabeledTermImpl
+ final ImmutableArray labels = term.getLabels();
+ for (int i = 0, sz = labels.size(); i < sz; i++) {
+ final TermLabel currentLabel = labels.get(i);
+ if (currentLabel.isProofRelevant()) {
+ hashcode += 7 * currentLabel.hashCode();
+ }
+ }
+ return hashcode;
+ }
+
+ // -------------------------- Utility methods --------------------------------- //
+
+ /**
+ * Compute the hashcode mod proof irrelevancy of an iterable of terms using the elements'
+ * {@link TermEqualsModProperty} implementation.
+ *
+ * @param iter iterable of terms
+ * @return combined hashcode
+ */
+ public static int hashCodeIterable(Iterable extends Term> iter) {
+ // adapted from Arrays.hashCode
+ if (iter == null) {
+ return 0;
+ }
+
+ int result = 1;
+
+ for (Term element : iter) {
+ result = 31 * result + (element == null ? 0
+ : element.hashCodeModProperty(PROOF_IRRELEVANCY_PROPERTY));
+ }
+
+ return result;
+ }
+}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/equality/RenamingProperty.java b/key.core/src/main/java/de/uka/ilkd/key/logic/equality/RenamingProperty.java
new file mode 100644
index 00000000000..4e2c9488dc4
--- /dev/null
+++ b/key.core/src/main/java/de/uka/ilkd/key/logic/equality/RenamingProperty.java
@@ -0,0 +1,247 @@
+/* This file is part of KeY - https://key-project.org
+ * KeY is licensed under the GNU General Public License Version 2
+ * SPDX-License-Identifier: GPL-2.0-only */
+package de.uka.ilkd.key.logic.equality;
+
+import de.uka.ilkd.key.java.JavaProgramElement;
+import de.uka.ilkd.key.java.NameAbstractionTable;
+import de.uka.ilkd.key.logic.JavaBlock;
+import de.uka.ilkd.key.logic.Term;
+import de.uka.ilkd.key.logic.op.*;
+
+import org.key_project.util.collection.ImmutableList;
+import org.key_project.util.collection.ImmutableSLList;
+
+/**
+ * A property that can be used in
+ * {@link TermEqualsModProperty#equalsModProperty(Object, TermProperty)}.
+ * Renaming of variables is ignored in this equality check.
+ */
+public class RenamingProperty implements TermProperty {
+ /**
+ * The single instance of this property.
+ */
+ public static final RenamingProperty RENAMING_PROPERTY = new RenamingProperty();
+
+ /**
+ * This constructor is private as a single instance of this class should be shared. The instance
+ * can be accessed
+ * through {@link RenamingProperty#RENAMING_PROPERTY} and is used as a parameter for
+ * {@link TermProperty#equalsModThisProperty(Term, Term)}.
+ */
+ private RenamingProperty() {}
+
+ /**
+ * Checks if {@code term2} is a term syntactically equal to {@code term1} modulo bound renaming.
+ *
+ * @param term1 a term
+ * @param term2 the term compared to {@code term1}
+ * @return true iff {@code term2} has the same values in operator, sort, arity, varsBoundHere
+ * and javaBlock as {@code term1} modulo bound renaming
+ */
+ @Override
+ public Boolean equalsModThisProperty(Term term1, Term term2) {
+ if (term2 == term1) {
+ return true;
+ }
+ return unifyHelp(term1, term2, ImmutableSLList.nil(),
+ ImmutableSLList.nil(), null);
+ }
+
+ @Override
+ public int hashCodeModThisProperty(Term term) {
+ throw new UnsupportedOperationException(
+ "Hashing of terms modulo renaming not yet implemented!");
+ }
+
+ // equals modulo renaming logic
+
+ /**
+ * Compare two quantifiable variables if they are equal modulo renaming.
+ *
+ * @param ownVar first QuantifiableVariable to be compared
+ * @param cmpVar second QuantifiableVariable to be compared
+ * @param ownBoundVars variables bound above the current position
+ * @param cmpBoundVars variables bound above the current position
+ */
+ private static boolean compareBoundVariables(QuantifiableVariable ownVar,
+ QuantifiableVariable cmpVar, ImmutableList ownBoundVars,
+ ImmutableList cmpBoundVars) {
+
+ final int ownNum = indexOf(ownVar, ownBoundVars);
+ final int cmpNum = indexOf(cmpVar, cmpBoundVars);
+
+ if (ownNum == -1 && cmpNum == -1) {
+ // if both variables are not bound the variables have to be the
+ // same object
+ return ownVar == cmpVar;
+ }
+
+ // otherwise the variables have to be bound at the same point (and both
+ // be bound)
+ return ownNum == cmpNum;
+ }
+
+ /**
+ * @return the index of the first occurrence of var
in list
, or
+ * -1
if the variable is not an element of the list
+ */
+ private static int indexOf(QuantifiableVariable var, ImmutableList list) {
+ int res = 0;
+ while (!list.isEmpty()) {
+ if (list.head() == var) {
+ return res;
+ }
+ ++res;
+ list = list.tail();
+ }
+ return -1;
+ }
+
+ /**
+ * Compares two terms modulo bound renaming.
+ *
+ * @param t0 the first term
+ * @param t1 the second term
+ * @param ownBoundVars variables bound above the current position
+ * @param cmpBoundVars variables bound above the current position
+ * @return true
is returned iff the terms are equal modulo bound renaming
+ */
+ private boolean unifyHelp(Term t0, Term t1, ImmutableList ownBoundVars,
+ ImmutableList cmpBoundVars, NameAbstractionTable nat) {
+
+ if (t0 == t1 && ownBoundVars.equals(cmpBoundVars)) {
+ return true;
+ }
+
+ if (t0.sort() != t1.sort() || t0.arity() != t1.arity()) {
+ return false;
+ }
+
+ final Operator op0 = t0.op();
+
+ if (op0 instanceof QuantifiableVariable) {
+ return handleQuantifiableVariable(t0, t1, ownBoundVars, cmpBoundVars);
+ }
+
+ final Operator op1 = t1.op();
+
+ if (op0 instanceof Modality mod0 && op1 instanceof Modality mod1) {
+ if (mod0.kind() != mod1.kind()) {
+ return false;
+ }
+ nat = handleJava(mod0.program(), mod1.program(), nat);
+ if (nat == FAILED) {
+ return false;
+ }
+ } else if (!(op0 instanceof ProgramVariable) && op0 != op1) {
+ return false;
+ }
+
+ if (!(op0 instanceof SchemaVariable) && op0 instanceof ProgramVariable pv0) {
+ if (op1 instanceof ProgramVariable pv1) {
+ nat = checkNat(nat);
+ if (!pv0.equalsModRenaming(pv1, nat)) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ return descendRecursively(t0, t1, ownBoundVars, cmpBoundVars, nat);
+ }
+
+ private boolean handleQuantifiableVariable(Term t0, Term t1,
+ ImmutableList ownBoundVars,
+ ImmutableList cmpBoundVars) {
+ return (t1.op() instanceof QuantifiableVariable)
+ && compareBoundVariables((QuantifiableVariable) t0.op(),
+ (QuantifiableVariable) t1.op(), ownBoundVars, cmpBoundVars);
+ }
+
+ /**
+ * used to encode that handleJava results in an unsatisfiable constraint (faster than
+ * using exceptions)
+ */
+ private static final NameAbstractionTable FAILED = new NameAbstractionTable();
+
+ private static NameAbstractionTable handleJava(JavaBlock jb0, JavaBlock jb1,
+ NameAbstractionTable nat) {
+ if (!jb0.isEmpty() || !jb1.isEmpty()) {
+ nat = checkNat(nat);
+ if (javaBlocksNotEqualModRenaming(jb0, jb1, nat)) {
+ return FAILED;
+ }
+ }
+ return nat;
+ }
+
+ /**
+ * Returns true if the given {@link JavaBlock}s are not equal modulo renaming.
+ *
+ * Moved here from {@link JavaBlock} while refactoring equalsModRenaming in {@link Term}.
+ * As the implementation of equalsModRenaming in {@link JavaBlock} was only used in
+ * {@link RenamingProperty#handleJava(JavaBlock, JavaBlock, NameAbstractionTable)}
+ * and the deprecated class de.uka.ilkd.key.strategy.quantifierHeuristics.EqualityConstraint,
+ * it is now only a helper method in {@link RenamingProperty}.
+ *
+ * @param jb1 the first {@link JavaBlock}
+ * @param jb2 the second {@link JavaBlock}
+ * @param nat the {@link NameAbstractionTable} used for the comparison
+ * @return true if the given {@link JavaBlock}s are NOT equal modulo renaming
+ */
+ public static boolean javaBlocksNotEqualModRenaming(JavaBlock jb1, JavaBlock jb2,
+ NameAbstractionTable nat) {
+ JavaProgramElement pe1 = jb1.program();
+ JavaProgramElement pe2 = jb2.program();
+ if (pe1 == null && pe2 == null) {
+ return false;
+ } else if (pe1 != null && pe2 != null) {
+ return !pe1.equalsModRenaming(pe2, nat);
+ }
+ return true;
+ }
+
+ private boolean descendRecursively(Term t0, Term t1,
+ ImmutableList ownBoundVars,
+ ImmutableList cmpBoundVars, NameAbstractionTable nat) {
+
+ for (int i = 0; i < t0.arity(); i++) {
+ ImmutableList subOwnBoundVars = ownBoundVars;
+ ImmutableList subCmpBoundVars = cmpBoundVars;
+
+ if (t0.varsBoundHere(i).size() != t1.varsBoundHere(i).size()) {
+ return false;
+ }
+ for (int j = 0; j < t0.varsBoundHere(i).size(); j++) {
+ final QuantifiableVariable ownVar = t0.varsBoundHere(i).get(j);
+ final QuantifiableVariable cmpVar = t1.varsBoundHere(i).get(j);
+ if (ownVar.sort() != cmpVar.sort()) {
+ return false;
+ }
+
+ subOwnBoundVars = subOwnBoundVars.prepend(ownVar);
+ subCmpBoundVars = subCmpBoundVars.prepend(cmpVar);
+ }
+
+ boolean newConstraint =
+ unifyHelp(t0.sub(i), t1.sub(i), subOwnBoundVars, subCmpBoundVars, nat);
+
+ if (!newConstraint) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static NameAbstractionTable checkNat(NameAbstractionTable nat) {
+ if (nat == null) {
+ return new NameAbstractionTable();
+ }
+ return nat;
+ }
+ // end of equals modulo renaming logic
+
+}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/equality/TermEqualsModProperty.java b/key.core/src/main/java/de/uka/ilkd/key/logic/equality/TermEqualsModProperty.java
new file mode 100644
index 00000000000..6d541d2e72b
--- /dev/null
+++ b/key.core/src/main/java/de/uka/ilkd/key/logic/equality/TermEqualsModProperty.java
@@ -0,0 +1,31 @@
+/* This file is part of KeY - https://key-project.org
+ * KeY is licensed under the GNU General Public License Version 2
+ * SPDX-License-Identifier: GPL-2.0-only */
+package de.uka.ilkd.key.logic.equality;
+
+/**
+ * Interface to check for equality ignoring given properties and to compute according hash codes on
+ * terms.
+ *
+ * @author Tobias Reinhold
+ */
+public interface TermEqualsModProperty {
+
+ /**
+ * Checks whether this object is equal to {@code o} modulo the property described by
+ * {@code property}.
+ *
+ * @param o the object that is checked for equality
+ * @param property the property to be ignored in the equality check
+ * @return whether this object is equal to o
+ */
+ boolean equalsModProperty(Object o, TermProperty property);
+
+ /**
+ * Computes the hash code according to the given ignored {@code property}.
+ *
+ * @param property the ignored property according to which the hash code is computed
+ * @return the hash code of this object
+ */
+ int hashCodeModProperty(TermProperty property);
+}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/equality/TermLabelsProperty.java b/key.core/src/main/java/de/uka/ilkd/key/logic/equality/TermLabelsProperty.java
new file mode 100644
index 00000000000..16e14dfc0f0
--- /dev/null
+++ b/key.core/src/main/java/de/uka/ilkd/key/logic/equality/TermLabelsProperty.java
@@ -0,0 +1,67 @@
+/* This file is part of KeY - https://key-project.org
+ * KeY is licensed under the GNU General Public License Version 2
+ * SPDX-License-Identifier: GPL-2.0-only */
+package de.uka.ilkd.key.logic.equality;
+
+import de.uka.ilkd.key.logic.Term;
+
+import org.key_project.util.collection.ImmutableArray;
+
+/**
+ * A property that can be used in
+ * {@link TermEqualsModProperty#equalsModProperty(Object, TermProperty)}.
+ * All term labels are ignored in this equality check.
+ */
+public class TermLabelsProperty implements TermProperty {
+ /**
+ * The single instance of this property.
+ */
+ public static final TermLabelsProperty TERM_LABELS_PROPERTY = new TermLabelsProperty();
+
+ /**
+ * This constructor is private as a single instance of this class should be shared. The instance
+ * can be accessed
+ * through {@link TermLabelsProperty#TERM_LABELS_PROPERTY} and is used as a parameter for
+ * {@link TermProperty#equalsModThisProperty(Term, Term)}.
+ */
+ private TermLabelsProperty() {}
+
+ /**
+ * Checks if {@code term2} is a term syntactically equal to {@code term1}, ignoring all
+ * term
+ * labels.
+ *
+ * @param term1 a term
+ * @param term2 the term compared to {@code term1}
+ * @return {@code true} iff {@code term2} is a term syntactically equal to {@code term1}
+ * ignoring all
+ * term labels
+ */
+ @Override
+ public Boolean equalsModThisProperty(Term term1, Term term2) {
+ if (term2 == term1) {
+ return true;
+ }
+
+ if (!(term1.op().equals(term2.op()) && term1.boundVars().equals(term2.boundVars())
+ && term1.javaBlock().equals(term2.javaBlock()))) {
+ return false;
+ }
+
+ final ImmutableArray term1Subs = term1.subs();
+ final ImmutableArray term2Subs = term2.subs();
+ final int numOfSubs = term1Subs.size();
+ for (int i = 0; i < numOfSubs; ++i) {
+ if (!term1Subs.get(i).equalsModProperty(term2Subs.get(i), TERM_LABELS_PROPERTY)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCodeModThisProperty(Term term) {
+ throw new UnsupportedOperationException(
+ "Hashing of terms modulo term labels not yet implemented!");
+ }
+}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/equality/TermProperty.java b/key.core/src/main/java/de/uka/ilkd/key/logic/equality/TermProperty.java
new file mode 100644
index 00000000000..2f6e41b3b6a
--- /dev/null
+++ b/key.core/src/main/java/de/uka/ilkd/key/logic/equality/TermProperty.java
@@ -0,0 +1,37 @@
+/* This file is part of KeY - https://key-project.org
+ * KeY is licensed under the GNU General Public License Version 2
+ * SPDX-License-Identifier: GPL-2.0-only */
+package de.uka.ilkd.key.logic.equality;
+
+import de.uka.ilkd.key.logic.Term;
+
+/**
+ *
+ * This interface is used for equality checks and hashing modulo a certain property on terms.
+ *
+ * Objects of classes implementing this interface are given to the methods in
+ * {@link TermEqualsModProperty} as parameters to unify equality checks and hashing modulo different
+ * properties.
+ *
+ * @author Tobias Reinhold
+ */
+public interface TermProperty {
+ /**
+ * Checks {@code term1} and {@code term2} for equality ignoring a certain property.
+ *
+ * @param term1 the first term to check for equality with {@code term2}
+ * @param term2 the second term to check for equality with {@code term1}
+ * @return whether {@code term1} and {@code term2} are equal ignoring a certain property
+ */
+ Boolean equalsModThisProperty(Term term1, Term term2);
+
+ /**
+ * Computes the hash code of the {@code term} in a context where
+ * {@link this#equalsModThisProperty(Term, Term)} is used as an equality check, so that it can
+ * be used in, e.g., a HashMap.
+ *
+ * @param term the term to compute the hash code for
+ * @return the hash code of {@code term} ignoring a certain property
+ */
+ int hashCodeModThisProperty(Term term);
+}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/label/TermLabelManager.java b/key.core/src/main/java/de/uka/ilkd/key/logic/label/TermLabelManager.java
index 61c82475e69..6ac56f95a64 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/logic/label/TermLabelManager.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/logic/label/TermLabelManager.java
@@ -30,6 +30,8 @@
import org.key_project.util.collection.Pair;
import org.key_project.util.java.CollectionUtil;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
/**
*
* This class provides access to the functionality of term labels.
@@ -2011,7 +2013,8 @@ protected void mergeLabels(SequentChangeInfo currentSequent, Services services,
// Search existing SequentFormula
Semisequent s = currentSequent.getSemisequentChangeInfo(inAntecedent).semisequent();
SequentFormula existingSF = CollectionUtil.search(s,
- element -> element.formula().equalsModRenaming(rejectedTerm));
+ element -> element.formula().equalsModProperty(rejectedTerm,
+ RENAMING_PROPERTY));
if (existingSF != null) {
// Create list of new labels
Term existingTerm = existingSF.formula();
diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/op/LocationVariable.java b/key.core/src/main/java/de/uka/ilkd/key/logic/op/LocationVariable.java
index 4ffcda7f8f3..53ab0f8896a 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/logic/op/LocationVariable.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/logic/op/LocationVariable.java
@@ -76,4 +76,18 @@ public int hashCodeModProofIrrelevancy() {
argSorts(), name().toString(), arity(),
whereToBind(), isRigid());
}
+
+ /**
+ * Constructs a location variable from a program variable.
+ * This should not be done manually since it is important to keep *all* modifiers.
+ *
+ * @param variable the variable
+ * @param name the name of the variable
+ * @return a new location variable
+ */
+ public static LocationVariable fromProgramVariable(ProgramVariable variable,
+ ProgramElementName name) {
+ return new LocationVariable(name, variable.getKeYJavaType(), variable.getContainerType(),
+ variable.isStatic(), variable.isModel(), variable.isGhost(), variable.isFinal());
+ }
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ProgramSVSort.java b/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ProgramSVSort.java
index bc43b473299..1a6f692f022 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ProgramSVSort.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ProgramSVSort.java
@@ -483,7 +483,7 @@ protected boolean canStandFor(ProgramElement pe, Services services) {
|| pe instanceof SetMinus || pe instanceof AllFields || pe instanceof AllObjects
|| pe instanceof SeqSingleton || pe instanceof SeqConcat
|| pe instanceof SeqLength || pe instanceof SeqGet || pe instanceof SeqIndexOf
- || pe instanceof SeqSub || pe instanceof SeqReverse) {
+ || pe instanceof SeqSub || pe instanceof SeqReverse || pe instanceof SeqPut) {
if (pe instanceof NonTerminalProgramElement npe) {
for (int i = 0, childCount = npe.getChildCount(); i < childCount; i++) {
if (!canStandFor(npe.getChildAt(i), services)) {
diff --git a/key.core/src/main/java/de/uka/ilkd/key/macros/scripts/FocusCommand.java b/key.core/src/main/java/de/uka/ilkd/key/macros/scripts/FocusCommand.java
index 14d5fd39f6b..a27f4613191 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/macros/scripts/FocusCommand.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/macros/scripts/FocusCommand.java
@@ -19,6 +19,8 @@
import org.key_project.logic.Name;
import org.key_project.util.collection.ImmutableList;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
/**
* The command "focus" allows you to select formulas from the current sequent
* to focus verification on. This means that all other formulas are discarded
@@ -76,7 +78,8 @@ private void hideAll(Sequent toKeep) throws ScriptException {
for (SequentFormula seqFormula : ante) {
// This means "!keepAnte.contains(seqFormula.formula)" but with equality mod renaming!
- if (!keepAnte.exists(it -> it.equalsModRenaming(seqFormula.formula()))) {
+ if (!keepAnte.exists(
+ it -> it.equalsModProperty(seqFormula.formula(), RENAMING_PROPERTY))) {
Taclet tac = getHideTaclet("left");
makeTacletApp(goal, seqFormula, tac, true);
}
@@ -85,7 +88,8 @@ private void hideAll(Sequent toKeep) throws ScriptException {
ImmutableList keepSucc = toKeep.succedent().asList().map(SequentFormula::formula);
ImmutableList succ = goal.sequent().succedent().asList();
for (SequentFormula seqFormula : succ) {
- if (!keepSucc.exists(it -> it.equalsModRenaming(seqFormula.formula()))) {
+ if (!keepSucc.exists(
+ it -> it.equalsModProperty(seqFormula.formula(), RENAMING_PROPERTY))) {
Taclet tac = getHideTaclet("right");
makeTacletApp(goal, seqFormula, tac, false);
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/macros/scripts/HideCommand.java b/key.core/src/main/java/de/uka/ilkd/key/macros/scripts/HideCommand.java
index acd9c61592c..85edd078c0b 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/macros/scripts/HideCommand.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/macros/scripts/HideCommand.java
@@ -19,6 +19,8 @@
import org.key_project.logic.Name;
+import static de.uka.ilkd.key.logic.equality.TermLabelsProperty.TERM_LABELS_PROPERTY;
+
/**
* Proof script command to hide a formula from the sequent.
*
@@ -79,7 +81,7 @@ public void execute(Parameters args) throws ScriptException, InterruptedExceptio
private SequentFormula find(SequentFormula sf, Semisequent semiseq) throws ScriptException {
for (SequentFormula s : semiseq) {
- if (s.formula().equalsModTermLabels(sf.formula())) {
+ if (s.formula().equalsModProperty(sf.formula(), TERM_LABELS_PROPERTY)) {
return s;
}
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/macros/scripts/InstantiateCommand.java b/key.core/src/main/java/de/uka/ilkd/key/macros/scripts/InstantiateCommand.java
index c3d3ec0c762..41ee9436a12 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/macros/scripts/InstantiateCommand.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/macros/scripts/InstantiateCommand.java
@@ -25,6 +25,8 @@
import org.key_project.util.collection.ImmutableList;
import org.key_project.util.collection.ImmutableSLList;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
/**
* instantiate var=a occ=2 with="a_8" hide
*
@@ -108,7 +110,8 @@ private ImmutableList findAllTacletApps(Parameters p, EngineState sta
ImmutableList allApps = ImmutableSLList.nil();
for (SequentFormula sf : g.node().sequent().antecedent()) {
- if (p.formula != null && !sf.formula().equalsModRenaming(p.formula)) {
+ if (p.formula != null
+ && !sf.formula().equalsModProperty(p.formula, RENAMING_PROPERTY)) {
continue;
}
allApps = allApps.append(index.getTacletAppAtAndBelow(filter,
@@ -116,7 +119,8 @@ private ImmutableList findAllTacletApps(Parameters p, EngineState sta
}
for (SequentFormula sf : g.node().sequent().succedent()) {
- if (p.formula != null && !sf.formula().equalsModRenaming(p.formula)) {
+ if (p.formula != null
+ && !sf.formula().equalsModProperty(p.formula, RENAMING_PROPERTY)) {
continue;
}
allApps = allApps.append(index.getTacletAppAtAndBelow(filter,
@@ -132,7 +136,8 @@ private ImmutableList findAllTacletApps(Parameters p, EngineState sta
private TacletApp filterList(Parameters p, ImmutableList list) {
for (TacletApp tacletApp : list) {
if (tacletApp instanceof PosTacletApp pta) {
- if (pta.posInOccurrence().subTerm().equalsModRenaming(p.formula)) {
+ if (pta.posInOccurrence().subTerm().equalsModProperty(p.formula,
+ RENAMING_PROPERTY)) {
return pta;
}
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/macros/scripts/RewriteCommand.java b/key.core/src/main/java/de/uka/ilkd/key/macros/scripts/RewriteCommand.java
index 24a820da811..4c15504162b 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/macros/scripts/RewriteCommand.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/macros/scripts/RewriteCommand.java
@@ -22,6 +22,8 @@
import org.key_project.util.collection.ImmutableList;
import org.key_project.util.collection.ImmutableSLList;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
/**
* This class provides the command rewrite
.
*
@@ -111,7 +113,8 @@ private ImmutableList findAllTacletApps(Parameters p, EngineState sta
// filter taclets that are applicable on the given formula in the antecedent
for (SequentFormula sf : g.node().sequent().antecedent()) {
- if (p.formula != null && !sf.formula().equalsModRenaming(p.formula)) {
+ if (p.formula != null
+ && !sf.formula().equalsModProperty(p.formula, RENAMING_PROPERTY)) {
continue;
}
allApps = allApps.append(index.getTacletAppAtAndBelow(filter,
@@ -120,7 +123,8 @@ private ImmutableList findAllTacletApps(Parameters p, EngineState sta
// filter taclets that are applicable on the given formula in the succedent
for (SequentFormula sf : g.node().sequent().succedent()) {
- if (p.formula != null && !sf.formula().equalsModRenaming(p.formula)) {
+ if (p.formula != null
+ && !sf.formula().equalsModProperty(p.formula, RENAMING_PROPERTY)) {
continue;
}
allApps = allApps.append(index.getTacletAppAtAndBelow(filter,
diff --git a/key.core/src/main/java/de/uka/ilkd/key/macros/scripts/RuleCommand.java b/key.core/src/main/java/de/uka/ilkd/key/macros/scripts/RuleCommand.java
index afdf580128d..a107e4c8c96 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/macros/scripts/RuleCommand.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/macros/scripts/RuleCommand.java
@@ -23,6 +23,9 @@
import org.key_project.util.collection.ImmutableList;
import org.key_project.util.collection.ImmutableSLList;
+import static de.uka.ilkd.key.logic.equality.IrrelevantTermLabelsProperty.IRRELEVANT_TERM_LABELS_PROPERTY;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
/**
* Command that applies a calculus rule All parameters are passed as strings and converted by the
* command. The parameters are:
@@ -315,7 +318,7 @@ private ImmutableList findAllTacletApps(Parameters p, EngineState sta
private boolean isFormulaSearchedFor(Parameters p, SequentFormula sf, Services services)
throws ScriptException {
final boolean satisfiesFormulaParameter =
- p.formula != null && sf.formula().equalsModRenaming(p.formula);
+ p.formula != null && sf.formula().equalsModProperty(p.formula, RENAMING_PROPERTY);
final boolean satisfiesMatchesParameter = p.matches != null
&& formatTermString(LogicPrinter.quickPrintTerm(sf.formula(), services))
@@ -345,7 +348,8 @@ private List filterList(Parameters p, ImmutableList list)
for (TacletApp tacletApp : list) {
if (tacletApp instanceof PosTacletApp pta) {
boolean add =
- p.on == null || pta.posInOccurrence().subTerm().equalsModRenaming(p.on);
+ p.on == null || pta.posInOccurrence().subTerm()
+ .equalsModProperty(p.on, RENAMING_PROPERTY);
Iterator it = pta.instantiations().svIterator();
while (it.hasNext()) {
@@ -354,7 +358,8 @@ private List filterList(Parameters p, ImmutableList list)
Object ptaInst =
pta.instantiations().getInstantiationEntry(sv).getInstantiation();
- add &= userInst == null || userInst.equalsModIrrelevantTermLabels(ptaInst);
+ add &= userInst == null
+ || userInst.equalsModProperty(ptaInst, IRRELEVANT_TERM_LABELS_PROPERTY);
}
if (add) {
diff --git a/key.core/src/main/java/de/uka/ilkd/key/macros/scripts/SelectCommand.java b/key.core/src/main/java/de/uka/ilkd/key/macros/scripts/SelectCommand.java
index 0fb1b181bad..f43592bde92 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/macros/scripts/SelectCommand.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/macros/scripts/SelectCommand.java
@@ -20,6 +20,8 @@
import org.key_project.util.collection.ImmutableList;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
public class SelectCommand extends AbstractCommand {
public SelectCommand() {
super(Parameters.class);
@@ -133,7 +135,7 @@ private boolean contains(Sequent seq, Term formula) {
private boolean contains(Semisequent semiseq, Term formula) {
for (SequentFormula sf : semiseq.asList()) {
- if (sf.formula().equalsModRenaming(formula)) {
+ if (sf.formula().equalsModProperty(formula, RENAMING_PROPERTY)) {
return true;
}
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/nparser/KeyAst.java b/key.core/src/main/java/de/uka/ilkd/key/nparser/KeyAst.java
index c5dc159aa8e..6dde2f9ba5e 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/nparser/KeyAst.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/nparser/KeyAst.java
@@ -10,9 +10,11 @@
import de.uka.ilkd.key.nparser.builder.ChoiceFinder;
import de.uka.ilkd.key.nparser.builder.FindProblemInformation;
import de.uka.ilkd.key.nparser.builder.IncludeFinder;
+import de.uka.ilkd.key.parser.Location;
import de.uka.ilkd.key.proof.init.Includes;
import de.uka.ilkd.key.settings.Configuration;
import de.uka.ilkd.key.settings.ProofSettings;
+import de.uka.ilkd.key.speclang.njml.JmlParser;
import de.uka.ilkd.key.util.Triple;
import org.key_project.util.java.StringUtil;
@@ -53,6 +55,15 @@ public String toString() {
return getClass().getName() + ": " + BuilderHelpers.getPosition(ctx);
}
+ public Location getStartLocation() {
+ return Location.fromToken(ctx.start);
+ }
+
+ public String getText() {
+ var interval = new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex() + 1);
+ return ctx.start.getInputStream().getText(interval);
+ }
+
public static class File extends KeyAst {
File(KeYParser.FileContext ctx) {
super(ctx);
@@ -149,6 +160,26 @@ public Configuration asConfiguration() {
}
}
+ public static class SetStatementContext extends KeyAst {
+ public SetStatementContext(JmlParser.@NonNull Set_statementContext ctx) {
+ super(ctx);
+ }
+
+ public Expression getAssignee() {
+ return new Expression(ctx.assignee);
+ }
+
+ public Expression getValue() {
+ return new Expression(ctx.value);
+ }
+ }
+
+ public static class Expression extends KeyAst {
+ public Expression(JmlParser.@NonNull ExpressionContext ctx) {
+ super(ctx);
+ }
+ }
+
public static class Term extends KeyAst {
Term(KeYParser.TermContext ctx) {
diff --git a/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java b/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java
index 05ef1a2a841..ad971267ead 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java
@@ -148,7 +148,8 @@ public Object visitOne_sort_decl(KeYParser.One_sort_declContext ctx) {
: DefaultImmutableSet.fromCollection(sortOneOf);
// attention: no expand to java.lang here!
- if (sorts().lookup(sortName) == null) {
+ Sort existingSort = sorts().lookup(sortName);
+ if (existingSort == null) {
Sort s = null;
if (isGenericSort) {
try {
@@ -176,11 +177,11 @@ public Object visitOne_sort_decl(KeYParser.One_sort_declContext ctx) {
createdSorts.add(s);
} else {
// weigl: agreement on KaKeY meeting: this should be ignored until we finally have
- // local namespaces
- // for generic sorts
+ // local namespaces for generic sorts
// addWarning(ctx, "Sort declaration is ignored, due to collision.");
- LOGGER.info("Sort declaration is ignored, due to collision in {}",
- BuilderHelpers.getPosition(ctx));
+ LOGGER.info("Sort declaration of {} in {} is ignored due to collision (already "
+ + "present in {}).", sortName, BuilderHelpers.getPosition(ctx),
+ existingSort.getOrigin());
}
}
return createdSorts;
diff --git a/key.core/src/main/java/de/uka/ilkd/key/pp/LogicPrinter.java b/key.core/src/main/java/de/uka/ilkd/key/pp/LogicPrinter.java
index 0bbf69b4f75..779f02958f7 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/pp/LogicPrinter.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/pp/LogicPrinter.java
@@ -119,7 +119,7 @@ public PosTableLayouter layouter() {
return layouter;
}
- private static SequentViewLogicPrinter quickPrinter(Services services,
+ public static SequentViewLogicPrinter quickPrinter(Services services,
boolean usePrettyPrinting, boolean useUnicodeSymbols) {
final NotationInfo ni = new NotationInfo();
if (services != null) {
@@ -596,7 +596,9 @@ protected void printSchemaVariable(SchemaVariable sv) {
}
private void printSourceElement(SourceElement element) {
- new PrettyPrinter(layouter, instantiations).print(element);
+ new PrettyPrinter(layouter, instantiations, services,
+ notationInfo.isPrettySyntax(),
+ notationInfo.isUnicodeEnabled()).print(element);
}
/**
diff --git a/key.core/src/main/java/de/uka/ilkd/key/pp/PrettyPrinter.java b/key.core/src/main/java/de/uka/ilkd/key/pp/PrettyPrinter.java
index a0c82647637..b2cf4836d58 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/pp/PrettyPrinter.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/pp/PrettyPrinter.java
@@ -3,12 +3,16 @@
* SPDX-License-Identifier: GPL-2.0-only */
package de.uka.ilkd.key.pp;
+import java.util.Objects;
+
import de.uka.ilkd.key.java.ast.*;
import de.uka.ilkd.key.java.ast.abstraction.KeYJavaType;
import de.uka.ilkd.key.java.ast.abstraction.Type;
import de.uka.ilkd.key.java.ast.ccatch.*;
-import de.uka.ilkd.key.java.ast.declaration.*;
+import de.uka.ilkd.key.java.ast.declaration.ArrayInitializer;
import de.uka.ilkd.key.java.ast.expression.*;
+import de.uka.ilkd.key.java.expression.ParenthesizedExpression;
+import de.uka.ilkd.key.java.expression.PassiveExpression;
import de.uka.ilkd.key.java.ast.expression.Operator;
import de.uka.ilkd.key.java.ast.expression.literal.*;
import de.uka.ilkd.key.java.ast.expression.operator.*;
@@ -30,9 +34,12 @@
import org.key_project.util.collection.ImmutableArray;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+
/**
* A configurable pretty printer for Java source elements originally from COMPOST.
*
@@ -40,25 +47,35 @@
*
* CHANGED FOR KeY. Comments are not printed!
*/
+@NullMarked
public class PrettyPrinter implements Visitor {
private static final Logger LOGGER = LoggerFactory.getLogger(PrettyPrinter.class);
- protected final PosTableLayouter l;
+ private final PosTableLayouter layouter;
- protected boolean startAlreadyMarked = false;
- protected Object firstStatement = null;
- protected boolean endAlreadyMarked = false;
+ private boolean startAlreadyMarked;
+ @Nullable
+ private Object firstStatement;
+ private boolean endAlreadyMarked;
- protected SVInstantiations instantiations = SVInstantiations.EMPTY_SVINSTANTIATIONS;
+ private final SVInstantiations instantiations;
+ @Nullable
+ private final Services services;
+ private boolean usePrettyPrinting;
+ private boolean useUnicodeSymbols;
/** creates a new PrettyPrinter */
public PrettyPrinter(PosTableLayouter out) {
- l = out;
+ this(out, SVInstantiations.EMPTY_SVINSTANTIATIONS, null, true, true);
}
- public PrettyPrinter(PosTableLayouter o, SVInstantiations svi) {
- this(o);
+ public PrettyPrinter(PosTableLayouter o, SVInstantiations svi, @Nullable Services services,
+ boolean usePrettyPrinting, boolean useUnicodeSymbols) {
+ this.layouter = o;
this.instantiations = svi;
+ this.services = services;
+ this.usePrettyPrinting = usePrettyPrinting;
+ this.useUnicodeSymbols = useUnicodeSymbols;
}
/**
@@ -77,7 +94,7 @@ public static String getTypeNameForAccessMethods(String typeName) {
* @return the result
*/
public String result() {
- return l.result();
+ return layouter.result();
}
/**
@@ -87,9 +104,9 @@ public String result() {
* @param e what to print
*/
public void print(SourceElement e) {
- l.beginRelativeC(0);
+ layouter.beginRelativeC(0);
performActionOnStatement(e);
- l.end();
+ layouter.end();
}
/**
@@ -98,11 +115,11 @@ public void print(SourceElement e) {
* @param s source element to print
*/
public void printFragment(SourceElement s) {
- l.beginRelativeC(0);
+ layouter.beginRelativeC(0);
markStart(s);
s.visit(this);
markEnd(s);
- l.end();
+ layouter.end();
}
/**
@@ -112,7 +129,7 @@ public void printFragment(SourceElement s) {
*/
protected void markStart(Object stmt) {
if (!startAlreadyMarked) {
- l.markStartFirstStatement();
+ layouter.markStartFirstStatement();
firstStatement = stmt;
startAlreadyMarked = true;
}
@@ -123,7 +140,7 @@ protected void markStart(Object stmt) {
*/
protected void markEnd(Object stmt) {
if (!endAlreadyMarked && (firstStatement == stmt)) {
- l.markEndFirstStatement();
+ layouter.markEndFirstStatement();
endAlreadyMarked = true;
}
}
@@ -160,7 +177,7 @@ protected static String encodeUnicodeChars(String str) {
protected void writeKeywordList(ImmutableArray list) {
for (int i = 0; i < list.size(); i++) {
if (i != 0) {
- l.brk();
+ layouter.brk();
}
performActionOnModifier(list.get(i));
}
@@ -174,7 +191,7 @@ protected void writeKeywordList(ImmutableArray list) {
protected void writeCommaList(ImmutableArray extends ProgramElement> list) {
for (int i = 0; i < list.size(); i++) {
if (i != 0) {
- l.print(",").brk();
+ layouter.print(",").brk();
}
list.get(i).visit(this);
}
@@ -183,47 +200,47 @@ protected void writeCommaList(ImmutableArray extends ProgramElement> list) {
protected void printOperator(Operator x, String symbol) {
ImmutableArray children = x.getArguments();
if (children != null) {
- l.beginC();
+ layouter.beginC();
switch (x.getArity()) {
case 2 -> {
children.get(0).visit(this);
- l.print(" ");
- l.print(symbol);
- l.brk();
+ layouter.print(" ");
+ layouter.print(symbol);
+ layouter.brk();
children.get(1).visit(this);
}
case 1 -> {
switch (x.getNotation()) {
case Operator.PREFIX -> {
- l.print(symbol);
+ layouter.print(symbol);
children.get(0).visit(this);
}
case Operator.POSTFIX -> {
children.get(0).visit(this);
- l.print(symbol);
+ layouter.print(symbol);
}
default -> {
}
}
}
}
- l.end();
+ layouter.end();
}
}
private void beginMultilineBracket() {
- l.print("(").beginRelativeC(0).beginRelativeC().brk(0);
+ layouter.print("(").beginRelativeC(0).beginRelativeC().brk(0);
}
private void endMultilineBracket() {
- l.end().brk(0).end();
- l.print(")");
+ layouter.end().brk(0).end();
+ layouter.print(")");
}
private void printReferencePrefix(ReferencePrefix p) {
if (p != null) {
p.visit(this);
- l.print(".");
+ layouter.print(".");
}
}
@@ -241,65 +258,65 @@ public void performActionOnProgramElementName(ProgramElementName x) {
boolean isKey = (name.equals("int") || name.equals("float") || name.equals("char")
|| name.equals("short") || name.equals("long") || name.equals("boolean"));
if (isKey) {
- l.keyWord(name);
+ layouter.keyWord(name);
} else {
- l.print(name);
+ layouter.print(name);
}
}
@Override
public void performActionOnProgramVariable(ProgramVariable x) {
- l.print(x.name().toString());
+ layouter.print(x.name().toString());
}
@Override
public void performActionOnProgramMethod(IProgramMethod x) {
- l.print(x.getMethodDeclaration().getProgramElementName().toString());
+ layouter.print(x.getMethodDeclaration().getProgramElementName().toString());
}
@Override
public void performActionOnProgramMetaConstruct(ProgramTransformer x) {
- l.print(x.name().toString());
- l.print("(");
+ layouter.print(x.name().toString());
+ layouter.print("(");
if (x.getChildAt(0) != null) {
x.getChildAt(0).visit(this);
}
- l.print(")");
+ layouter.print(")");
}
@Override
public void performActionOnContextStatementBlock(ContextStatementBlock x) {
if (x.getStatementCount() > 0) {
- l.beginRelativeC();
- l.print("{ ..");
+ layouter.beginRelativeC();
+ layouter.print("{ ..");
for (Statement statement : x.getBody()) {
- l.nl();
+ layouter.nl();
performActionOnStatement(statement);
}
- l.end().nl();
- l.print("... }");
+ layouter.end().nl();
+ layouter.print("... }");
} else {
- l.print("{ .. ... }");
+ layouter.print("{ .. ... }");
}
}
@Override
public void performActionOnIntLiteral(IntLiteral x) {
- l.print(x.getValueString());
+ layouter.print(x.getValueString());
}
@Override
public void performActionOnBooleanLiteral(BooleanLiteral x) {
- l.keyWord(x.getValue() ? "true" : "false");
+ layouter.keyWord(x.getValue() ? "true" : "false");
}
@Override
public void performActionOnEmptySetLiteral(EmptySetLiteral x) {
- l.keyWord("\\empty");
+ layouter.keyWord("\\empty");
}
private void printDLFunctionOperator(String name, Operator operator) {
- l.keyWord(name);
+ layouter.keyWord(name);
if (operator.getArity() > 0) {
printArguments(operator.getArguments());
}
@@ -339,21 +356,21 @@ public void performActionOnAllObjects(
@Override
public void performActionOnEmptySeqLiteral(EmptySeqLiteral x) {
- l.print("\\seq_empty");
+ layouter.print("\\seq_empty");
}
@Override
public void performActionOnSeqLength(SeqLength x) {
x.getChildAt(0).visit(this);
- l.print(".length");
+ layouter.print(".length");
}
@Override
public void performActionOnSeqGet(SeqGet x) {
x.getChildAt(0).visit(this);
- l.print("[");
+ layouter.print("[");
x.getChildAt(1).visit(this);
- l.print("]");
+ layouter.print("]");
}
@Override
@@ -384,75 +401,82 @@ public void performActionOnSeqReverse(
printDLFunctionOperator("\\seq_reverse", x);
}
+ @Override
+ public void performActionOnSeqPut(
+ de.uka.ilkd.key.java.expression.operator.adt.SeqPut x) {
+ printDLFunctionOperator("\\seq_upd", x);
+ }
+
@Override
public void performActionOnDLEmbeddedExpression(DLEmbeddedExpression x) {
- l.print("\\dl_" + x.getFunctionSymbol().name());
- l.print("(");
+ layouter.print("\\dl_" + x.getFunctionSymbol().name());
+ layouter.print("(");
for (int i = 0; i < x.getChildCount(); i++) {
if (i != 0) {
- l.print(",").brk();
+ layouter.print(",").brk();
}
x.getChildAt(i).visit(this);
}
- l.print(")");
+ layouter.print(")");
}
@Override
public void performActionOnStringLiteral(StringLiteral x) {
- l.print(encodeUnicodeChars(x.getValue()));
+ layouter.print(encodeUnicodeChars(x.getValue()));
}
@Override
public void performActionOnNullLiteral(NullLiteral x) {
- l.keyWord("null");
+ layouter.keyWord("null");
}
@Override
public void performActionOnCharLiteral(CharLiteral x) {
- l.print(encodeUnicodeChars(x.toString()));
+ layouter.print(encodeUnicodeChars(x.toString()));
}
@Override
public void performActionOnDoubleLiteral(DoubleLiteral x) {
- l.print(x.getValue());
+ layouter.print(x.getValue());
}
@Override
public void performActionOnMergePointStatement(MergePointStatement x) {
- l.beginC().print("//@ merge_point (").brk(0);
+ layouter.beginC().print("//@ merge_point (").brk(0);
x.getExpression().visit(this);
- l.brk(0).print(");");
+ layouter.brk(0).print(");");
}
@Override
public void performActionOnLongLiteral(LongLiteral x) {
- l.print(x.getValueString());
+ layouter.print(x.getValueString());
}
@Override
public void performActionOnFloatLiteral(FloatLiteral x) {
- l.print(x.getValue());
+ layouter.print(x.getValue());
}
@Override
public void performActionOnPackageSpecification(PackageSpecification x) {
- l.keyWord("package");
- l.print(" ");
+ layouter.nl();
+ layouter.keyWord("package");
+ layouter.print(" ");
performActionOnPackageReference(x.getPackageReference());
- l.print(";");
+ layouter.print(";");
}
@Override
public void performActionOnAssert(Assert x) {
- l.keyWord("assert");
- l.print(" ");
+ layouter.keyWord("assert");
+ layouter.print(" ");
x.getCondition().visit(this);
if (x.getMessage() != null) {
- l.print(" :");
- l.brk();
+ layouter.print(" :");
+ layouter.brk();
x.getMessage().visit(this);
}
}
@@ -530,17 +554,17 @@ public void performActionOnLocationVariable(LocationVariable variable) {
@Override
public void performActionOnLoopInvariant(LoopSpecification x) {
- l.print("//@ loop-invariant");
+ layouter.print("//@ loop-invariant");
}
@Override
public void performActionOnBlockContract(BlockContract x) {
- l.print("//@ block-contract");
+ layouter.print("//@ block-contract");
}
@Override
public void performActionOnLoopContract(LoopContract x) {
- l.print("//@ loop-contract");
+ layouter.print("//@ loop-contract");
}
@Override
@@ -560,13 +584,7 @@ public void performActionOnLoopContract(LoopStatement oldLoop, LoopStatement new
@Override
public void performActionOnMergeContract(MergeContract x) {
- l.print("//@ merge-contract");
- }
-
- @Override
- public void performActionOnJmlAssertCondition(Term cond) {
- // Should not be reached
- throw new UnsupportedOperationException();
+ layouter.print("//@ merge-contract");
}
private void performActionOnType(Type type) {
@@ -605,7 +623,7 @@ private void printTypeReference(ReferencePrefix prefix, KeYJavaType type,
ProgramElementName name, boolean fullTypeNames) {
printReferencePrefix(prefix);
if (fullTypeNames) {
- l.print(type.getFullName());
+ layouter.print(type.getFullName());
} else {
performActionOnProgramElementName(name);
}
@@ -619,7 +637,7 @@ public void performActionOnSchemaTypeReference(SchemaTypeReference x) {
public void performActionOnFieldReference(FieldReference x) {
if (x.getName() != null
&& "javax.realtime.MemoryArea::currentMemoryArea".equals(x.getName())) {
- l.print("");
+ layouter.print("");
} else {
printTypeReference(x.getReferencePrefix(), x.getKeYJavaType(),
x.getProgramElementName(), false);
@@ -634,18 +652,18 @@ public void performActionOnPackageReference(PackageReference x) {
@Override
public void performActionOnThrows(Throws x) {
if (x.getExceptions() != null) {
- l.keyWord("throws").print(" ");
+ layouter.keyWord("throws").print(" ");
writeCommaList(x.getExceptions());
}
}
@Override
public void performActionOnArrayInitializer(ArrayInitializer x) {
- l.print("{");
+ layouter.print("{");
if (x.getArguments() != null) {
writeCommaList(x.getArguments());
}
- l.print("}");
+ layouter.print("}");
}
@Override
@@ -657,16 +675,16 @@ public void performActionOnCompilationUnit(CompilationUnit x) {
boolean hasImports = (x.getImports() != null) && (!x.getImports().isEmpty());
if (hasImports) {
if (hasPackageSpec) {
- l.nl();
+ layouter.nl();
}
for (Import i : x.getImports()) {
- l.nl();
+ layouter.nl();
performActionOnImport(i);
}
}
if (x.getDeclarations() != null) {
if (hasImports || hasPackageSpec) {
- l.nl();
+ layouter.nl();
}
for (int i = 0; i < x.getDeclarations().size(); i++) {
if (i != 0) {
@@ -689,9 +707,9 @@ public void performActionOnClassDeclaration(ClassDeclaration x) {
}
if (x.getProgramElementName() != null) {
if (hasMods) {
- l.print(" ");
+ layouter.print(" ");
}
- l.keyWord("class").print(" ");
+ layouter.keyWord("class").print(" ");
performActionOnProgramElementName(x.getProgramElementName());
}
l.end();
@@ -706,7 +724,7 @@ public void performActionOnClassDeclaration(ClassDeclaration x) {
}
// not an anonymous class
if (x.getProgramElementName() != null) {
- l.print(" ");
+ layouter.print(" ");
}
l.end();
@@ -725,13 +743,13 @@ private void performActionOnMemberDeclarations(ImmutableArray
}
endBlock();
} else {
- l.print("{}");
+ layouter.print("{}");
}
}
@Override
public void performActionOnInterfaceDeclaration(InterfaceDeclaration x) {
- l.beginC();
+ layouter.beginC();
ImmutableArray mods = x.getModifiers();
boolean hasMods = mods != null && !mods.isEmpty();
if (hasMods) {
@@ -739,9 +757,9 @@ public void performActionOnInterfaceDeclaration(InterfaceDeclaration x) {
}
if (x.getProgramElementName() != null) {
if (hasMods) {
- l.print(" ");
+ layouter.print(" ");
}
- l.keyWord("interface").print(" ");
+ layouter.keyWord("interface").print(" ");
performActionOnProgramElementName(x.getProgramElementName());
}
if (x.getExtendedTypes() != null && x.getExtendedTypes().getChildCount() != 0) {
@@ -766,19 +784,19 @@ public void performActionOnLocalVariableDeclaration(LocalVariableDeclaration x)
@Override
public void performActionOnVariableDeclaration(VariableDeclaration x) {
- l.beginI();
+ layouter.beginI();
ImmutableArray modifiers = x.getModifiers();
if (modifiers != null && !modifiers.isEmpty()) {
writeKeywordList(modifiers);
- l.print(" ");
+ layouter.print(" ");
}
x.getTypeReference().visit(this);
- l.print(" ");
+ layouter.print(" ");
ImmutableArray extends VariableSpecification> varSpecs = x.getVariables();
if (varSpecs != null) {
writeCommaList(varSpecs);
}
- l.end();
+ layouter.end();
}
@Override
@@ -788,16 +806,17 @@ public void performActionOnMethodDeclaration(MethodDeclaration x) {
boolean hasMods = mods != null && !mods.isEmpty();
if (hasMods) {
writeKeywordList(mods);
- l.print(" ");
+ layouter.print(" ");
}
if (x.getTypeReference() != null) {
x.getTypeReference().visit(this);
- l.print(" ");
+ layouter.print(" ");
} else if (x.getTypeReference() == null && !(x instanceof ConstructorDeclaration)) {
- l.keyWord("void");
- l.print(" ");
+ layouter.keyWord("void");
+ layouter.print(" ");
}
performActionOnProgramElementName(x.getProgramElementName());
+ layouter.print(" ");
beginMultilineBracket();
if (x.getParameters() != null) {
@@ -817,12 +836,12 @@ public void performActionOnMethodDeclaration(MethodDeclaration x) {
@Override
public void performActionOnClassInitializer(ClassInitializer x) {
- l.beginC();
+ layouter.beginC();
if (x.getModifiers() != null) {
writeKeywordList(x.getModifiers());
- l.print(" ");
+ layouter.print(" ");
}
- l.end();
+ layouter.end();
if (x.getBody() != null) {
printStatementBlock(x.getBody());
}
@@ -843,7 +862,7 @@ protected void performActionOnStatement(SourceElement s) {
&& !(s instanceof TypeDeclarationContainer)) {
l.print(";");
}
- l.end();
+ layouter.end();
}
@Override
@@ -852,12 +871,12 @@ public void performActionOnStatementBlock(StatementBlock x) {
}
private void beginBlock() {
- l.print("{");
- l.beginRelativeC();
+ layouter.print("{");
+ layouter.beginRelativeC();
}
private void endBlock() {
- l.end().nl().print("}");
+ layouter.end().nl().print("}");
}
public boolean printStatementBlock(StatementBlock x) {
@@ -865,13 +884,13 @@ public boolean printStatementBlock(StatementBlock x) {
if (emptyBlock) {
// We have an empty statement block ...
markStart(x);
- l.print("{}");
+ layouter.print("{}");
markEnd(x);
return false;
} else {
beginBlock();
for (Statement statement : x.getBody()) {
- l.nl();
+ layouter.nl();
performActionOnStatement(statement);
}
endBlock();
@@ -890,27 +909,27 @@ public void performActionOnBreak(Break x) {
@Override
public void performActionOnContinue(Continue x) {
- l.keyWord("continue");
+ layouter.keyWord("continue");
if (x.getLabel() != null) {
- l.brk();
+ layouter.brk();
x.getLabel().visit(this);
}
}
@Override
public void performActionOnReturn(Return x) {
- l.keyWord("return");
+ layouter.keyWord("return");
if (x.getExpression() != null) {
- l.brk();
+ layouter.brk();
x.getExpression().visit(this);
}
}
@Override
public void performActionOnThrow(Throw x) {
- l.keyWord("throw");
+ layouter.keyWord("throw");
if (x.getExpression() != null) {
- l.brk();
+ layouter.brk();
x.getExpression().visit(this);
}
}
@@ -922,16 +941,16 @@ public void performActionOnDo(Do x) {
private boolean handleBlockOrSingleStatement(Statement body) {
if (body instanceof StatementBlock) {
- l.print(" ");
+ layouter.print(" ");
return printStatementBlock((StatementBlock) body);
} else {
- l.beginRelativeC();
- l.brk();
+ layouter.beginRelativeC();
+ layouter.brk();
body.visit(this);
if (!(body instanceof BranchStatement) && !(body instanceof StatementContainer)) {
- l.print(";");
+ layouter.print(";");
}
- l.end();
+ layouter.end();
return false;
}
}
@@ -939,31 +958,31 @@ private boolean handleBlockOrSingleStatement(Statement body) {
private boolean handleBlockStatementOrEmpty(Statement body, boolean includeBody) {
if (includeBody) {
if (body == null || body instanceof EmptyStatement) {
- l.print(";");
+ layouter.print(";");
return false;
} else {
return handleBlockOrSingleStatement(body);
}
} else {
- l.print(" ... ");
+ layouter.print(" ... ");
return false;
}
}
public void performActionOnDo(Do x, boolean includeBody) {
- l.keyWord("do");
+ layouter.keyWord("do");
boolean newBlock = handleBlockStatementOrEmpty(x.getBody(), includeBody);
handleContinuationAfterNewBlock(newBlock);
- l.keyWord("while");
- l.print(" ");
+ layouter.keyWord("while");
+ layouter.print(" ");
beginMultilineBracket();
if (x.getGuard() != null) {
x.getGuard().visit(this);
}
endMultilineBracket();
- l.print(";");
+ layouter.print(";");
}
@Override
@@ -972,8 +991,8 @@ public void performActionOnEnhancedFor(EnhancedFor x) {
}
public void performActionOnEnhancedFor(EnhancedFor x, boolean includeBody) {
- l.keyWord("for");
- l.print(" ");
+ layouter.keyWord("for");
+ layouter.print(" ");
beginMultilineBracket();
ImmutableArray initializers = x.getInitializers();
@@ -981,8 +1000,8 @@ public void performActionOnEnhancedFor(EnhancedFor x, boolean includeBody) {
initializers.get(0).visit(this);
}
- l.print(" :");
- l.brk();
+ layouter.print(" :");
+ layouter.brk();
if (x.getGuard() != null) {
x.getGuardExpression().visit(this);
@@ -999,8 +1018,8 @@ public void performActionOnFor(For x) {
}
public void performActionOnFor(For x, boolean includeBody) {
- l.keyWord("for");
- l.print(" ");
+ layouter.keyWord("for");
+ layouter.print(" ");
beginMultilineBracket();
// there is no "getLoopInit" method
@@ -1010,11 +1029,11 @@ public void performActionOnFor(For x, boolean includeBody) {
if (init != null) {
init.visit(this);
}
- l.print(";").brk();
+ layouter.print(";").brk();
if (x.getGuardExpression() != null) {
x.getGuardExpression().visit(this);
}
- l.print(";").brk();
+ layouter.print(";").brk();
IForUpdates upd = x.getIForUpdates();
if (upd != null) {
@@ -1031,8 +1050,8 @@ public void performActionOnWhile(While x) {
}
public void performActionOnWhile(While x, boolean includeBody) {
- l.keyWord("while");
- l.print(" ");
+ layouter.keyWord("while");
+ layouter.print(" ");
beginMultilineBracket();
if (x.getGuardExpression() != null) {
x.getGuardExpression().visit(this);
@@ -1049,15 +1068,15 @@ public void performActionOnIf(If x) {
private void handleContinuationAfterNewBlock(boolean newBlock) {
if (newBlock) {
- l.print(" ");
+ layouter.print(" ");
} else {
- l.nl();
+ layouter.nl();
}
}
public void performActionOnIf(If x, boolean includeBranches) {
- l.keyWord("if");
- l.print(" ");
+ layouter.keyWord("if");
+ layouter.print(" ");
beginMultilineBracket();
if (x.getExpression() != null) {
x.getExpression().visit(this);
@@ -1082,8 +1101,8 @@ public void performActionOnSwitch(Switch x) {
}
public void performActionOnSwitch(Switch x, boolean includeBranches) {
- l.keyWord("switch");
- l.print(" ");
+ layouter.keyWord("switch");
+ layouter.print(" ");
beginMultilineBracket();
if (x.getExpression() != null) {
x.getExpression().visit(this);
@@ -1091,10 +1110,10 @@ public void performActionOnSwitch(Switch x, boolean includeBranches) {
endMultilineBracket();
if (includeBranches) {
- l.print(" ");
+ layouter.print(" ");
beginBlock();
for (Branch branch : x.getBranchList()) {
- l.nl();
+ layouter.nl();
branch.visit(this);
}
endBlock();
@@ -1102,8 +1121,8 @@ public void performActionOnSwitch(Switch x, boolean includeBranches) {
}
private void printTryLike(String name, StatementBlock body, ImmutableArray branches) {
- l.keyWord(name);
- l.print(" ");
+ layouter.keyWord(name);
+ layouter.print(" ");
if (body != null) {
printStatementBlock(body);
}
@@ -1123,32 +1142,32 @@ public void performActionOnTry(Try x) {
public void performActionOnLabeledStatement(LabeledStatement x) {
if (x.getLabel() != null) {
x.getLabel().visit(this);
- l.print(":");
+ layouter.print(":");
}
if (x.getBody() != null) {
- l.nl();
+ layouter.nl();
performActionOnStatement(x.getBody());
}
}
@Override
public void performActionOnMethodFrame(MethodFrame x) {
- l.keyWord("method-frame");
- l.print(" ");
+ layouter.keyWord("method-frame");
+ layouter.print(" ");
beginMultilineBracket();
IProgramVariable var = x.getProgramVariable();
var exec = x.getExecutionContext();
if (var != null) {
- l.beginRelativeC().print("result->");
+ layouter.beginRelativeC().print("result->");
var.visit(this);
if (exec != null) {
- l.print(",");
+ layouter.print(",");
}
- l.end();
+ layouter.end();
if (exec != null) {
- l.brk();
+ layouter.brk();
}
}
@@ -1159,7 +1178,7 @@ public void performActionOnMethodFrame(MethodFrame x) {
}
endMultilineBracket();
- l.print(" ");
+ layouter.print(" ");
if (x.getBody() != null) {
printStatementBlock(x.getBody());
@@ -1168,7 +1187,7 @@ public void performActionOnMethodFrame(MethodFrame x) {
@Override
public void performActionOnCatchAllStatement(CatchAllStatement x) {
- l.keyWord("#catchAll").print(" ");
+ layouter.keyWord("#catchAll").print(" ");
beginMultilineBracket();
performActionOnLocationVariable(x.getParam());
endMultilineBracket();
@@ -1180,14 +1199,14 @@ public void performActionOnMethodBodyStatement(MethodBodyStatement x) {
IProgramVariable pvar = x.getResultVariable();
if (pvar != null) {
pvar.visit(this);
- l.brk(1, 0);
- l.print("=");
- l.brk(1, 0);
+ layouter.brk(1, 0);
+ layouter.print("=");
+ layouter.brk(1, 0);
}
printMethodReference(x.getMethodReference());
// CHG:
- l.print("@");
+ layouter.print("@");
final TypeReference tr = x.getBodySourceAsTypeReference();
if (tr instanceof SchemaTypeReference) {
performActionOnSchemaTypeReference((SchemaTypeReference) tr);
@@ -1200,39 +1219,39 @@ public void performActionOnMethodBodyStatement(MethodBodyStatement x) {
@Override
public void performActionOnSynchronizedBlock(SynchronizedBlock x) {
- l.print("synchronized");
+ layouter.print("synchronized");
if (x.getExpression() != null) {
beginMultilineBracket();
x.getExpression().visit(this);
endMultilineBracket();
}
if (x.getBody() != null) {
- l.print(" ");
+ layouter.print(" ");
printStatementBlock(x.getBody());
}
}
@Override
public void performActionOnLoopScopeBlock(LoopScopeBlock x) {
- l.keyWord("loop-scope");
- l.print(" ");
+ layouter.keyWord("loop-scope");
+ layouter.print(" ");
beginMultilineBracket();
if (x.getIndexPV() != null) {
x.getIndexPV().visit(this);
}
endMultilineBracket();
- l.print(" ");
+ layouter.print(" ");
printStatementBlock(x.getBody());
}
@Override
public void performActionOnImport(Import x) {
- l.print("import ");
+ layouter.print("import ");
x.getReference().visit(this);
if (x.isMultiImport()) {
- l.print(".*;");
+ layouter.print(".*;");
} else {
- l.print(";");
+ layouter.print(";");
}
}
@@ -1260,10 +1279,10 @@ public void performActionOnImplements(Implements x) {
public void performActionOnVariableSpecification(VariableSpecification x) {
x.getProgramVariable().visit(this);
for (int i = 0; i < x.getDimensions(); i += 1) {
- l.print("[]");
+ layouter.print("[]");
}
if (x.getInitializer() != null) {
- l.print(" = ");
+ layouter.print(" = ");
x.getInitializer().visit(this);
}
}
@@ -1291,7 +1310,7 @@ public void performActionOnBinaryXOrAssignment(BinaryXOrAssignment x) {
@Override
public void performActionOnCopyAssignment(CopyAssignment x) {
x.getArguments().get(0).visit(this);
- l.print(" = ");
+ layouter.print(" = ");
x.getArguments().get(1).visit(this);
}
@@ -1374,19 +1393,19 @@ public void performActionOnBinaryXOr(BinaryXOr x) {
public void performActionOnConditional(Conditional x) {
boolean addParentheses = x.isToBeParenthesized();
if (x.getArguments() != null) {
- l.beginC();
+ layouter.beginC();
if (addParentheses) {
- l.print("(");
+ layouter.print("(");
}
x.getArguments().get(0).visit(this);
- l.print(" ?").brk();
+ layouter.print(" ?").brk();
x.getArguments().get(1).visit(this);
- l.print(" :").brk();
+ layouter.print(" :").brk();
x.getArguments().get(2).visit(this);
if (addParentheses) {
- l.print(")");
+ layouter.print(")");
}
- l.end();
+ layouter.end();
}
}
@@ -1429,46 +1448,46 @@ public void performActionOnNotEquals(NotEquals x) {
public void performActionOnNewArray(NewArray x) {
boolean addParentheses = x.isToBeParenthesized();
if (addParentheses) {
- l.print("(");
+ layouter.print("(");
}
- l.print("new ");
+ layouter.print("new ");
x.getTypeReference().visit(this);
int i = 0;
if (x.getArguments() != null) {
for (; i < x.getArguments().size(); i += 1) {
- l.print("[");
+ layouter.print("[");
x.getArguments().get(i).visit(this);
- l.print("]");
+ layouter.print("]");
}
}
for (; i < x.getDimensions(); i += 1) {
- l.print("[]");
+ layouter.print("[]");
}
if (x.getArrayInitializer() != null) {
performActionOnArrayInitializer(x.getArrayInitializer());
}
if (addParentheses) {
- l.print(")");
+ layouter.print(")");
}
}
private void printInstanceOfLike(TypeOperator op, String kw) {
boolean addParentheses = op.isToBeParenthesized();
if (addParentheses) {
- l.print("(");
+ layouter.print("(");
}
if (op.getArguments() != null) {
op.getExpressionAt(0).visit(this);
}
- l.print(" ");
- l.keyWord(kw);
- l.brk();
+ layouter.print(" ");
+ layouter.keyWord(kw);
+ layouter.brk();
if (op.getTypeReference() != null) {
op.getTypeReference().visit(this);
}
if (addParentheses) {
- l.print(")");
+ layouter.print(")");
}
}
@@ -1487,10 +1506,10 @@ public void performActionOnExactInstanceof(ExactInstanceof x) {
public void performActionOnNew(New x) {
boolean addParentheses = x.isToBeParenthesized();
if (addParentheses) {
- l.print("(");
+ layouter.print("(");
}
printReferencePrefix(x.getReferencePrefix());
- l.keyWord("new").print(" ");
+ layouter.keyWord("new").print(" ");
x.getTypeReference().visit(this);
printArguments(x.getArguments());
@@ -1498,7 +1517,7 @@ public void performActionOnNew(New x) {
performActionOnClassDeclaration(x.getClassDeclaration());
}
if (addParentheses) {
- l.print(")");
+ layouter.print(")");
}
}
@@ -1506,18 +1525,18 @@ public void performActionOnNew(New x) {
public void performActionOnTypeCast(TypeCast x) {
boolean addParentheses = x.isToBeParenthesized();
if (addParentheses) {
- l.print("(");
+ layouter.print("(");
}
- l.print("(");
+ layouter.print("(");
if (x.getTypeReference() != null) {
x.getTypeReference().visit(this);
}
- l.print(") ");
+ layouter.print(") ");
if (x.getArguments() != null) {
x.getArguments().get(0).visit(this);
}
if (addParentheses) {
- l.print(")");
+ layouter.print(")");
}
}
@@ -1586,9 +1605,9 @@ public void performActionOnArrayReference(ArrayReference x) {
x.getReferencePrefix().visit(this);
int s = x.getDimensionExpressions().size();
for (int i = 0; i < s; i += 1) {
- l.print("[");
+ layouter.print("[");
x.getDimensionExpressions().get(i).visit(this);
- l.print("]");
+ layouter.print("]");
}
}
@@ -1596,9 +1615,9 @@ public void performActionOnArrayReference(ArrayReference x) {
public void performActionOnMetaClassReference(MetaClassReference x) {
if (x.getTypeReference() != null) {
x.getTypeReference().visit(this);
- l.print(".");
+ layouter.print(".");
}
- l.print("class");
+ layouter.print("class");
}
@Override
@@ -1617,28 +1636,28 @@ protected void printMethodReference(MethodReference x) {
@Override
public void performActionOnMethod(IProgramMethod x) {
- l.print(x.name().toString());
+ layouter.print(x.name().toString());
}
public void writeFullMethodSignature(IProgramMethod x) {
- l.print(x.getName());
- l.print("(");
+ layouter.print(x.getName());
+ layouter.print("(");
boolean afterFirst = false;
for (ParameterDeclaration pd : x.getParameters()) {
if (afterFirst) {
- l.print(", ");
+ layouter.print(", ");
} else {
afterFirst = true;
}
performActionOnTypeReference(pd.getTypeReference(), true);
}
- l.print(")");
+ layouter.print(")");
}
@Override
public void performActionOnExecutionContext(ExecutionContext x) {
- l.beginRelativeC();
- l.print("source=");
+ layouter.beginRelativeC();
+ layouter.print("source=");
if (x.getMethodContext() == null) {
l.print("null");
} else {
@@ -1647,43 +1666,43 @@ public void performActionOnExecutionContext(ExecutionContext x) {
l.print("@");
x.getTypeReference().visit(this);
if (x.getRuntimeInstance() != null) {
- l.print(",").end().brk().beginRelativeC().print("this=");
+ layouter.print(",").end().brk().beginRelativeC().print("this=");
x.getRuntimeInstance().visit(this);
- l.end();
+ layouter.end();
} else {
- l.end();
+ layouter.end();
}
}
@Override
public void performActionOnSuperConstructorReference(SuperConstructorReference x) {
printReferencePrefix(x.getReferencePrefix());
- l.keyWord("super");
+ layouter.keyWord("super");
printArguments(x.getArguments());
}
@Override
public void performActionOnThisConstructorReference(ThisConstructorReference x) {
- l.keyWord("this");
+ layouter.keyWord("this");
printArguments(x.getArguments());
}
@Override
public void performActionOnSuperReference(SuperReference x) {
printReferencePrefix(x.getReferencePrefix());
- l.keyWord("super");
+ layouter.keyWord("super");
}
@Override
public void performActionOnThisReference(ThisReference x) {
printReferencePrefix(x.getReferencePrefix());
- l.keyWord("this");
+ layouter.keyWord("this");
}
@Override
public void performActionOnArrayLengthReference(ArrayLengthReference x) {
printReferencePrefix(x.getReferencePrefix());
- l.print("length");
+ layouter.print("length");
}
@Override
@@ -1693,10 +1712,10 @@ public void performActionOnThen(Then x) {
@Override
public void performActionOnElse(Else x) {
- l.keyWord("else");
+ layouter.keyWord("else");
Statement body = x.getBody();
if (body instanceof If) {
- l.print(" ");
+ layouter.print(" ");
performActionOnIf((If) body);
} else {
handleBlockOrSingleStatement(body);
@@ -1709,16 +1728,16 @@ private void printCaseBody(ImmutableArray body) {
Statement statement = body.get(i);
if (statement instanceof StatementBlock) {
if (i != 0) {
- l.nl();
+ layouter.nl();
} else {
- l.print(" ");
+ layouter.print(" ");
}
printStatementBlock((StatementBlock) statement);
} else {
- l.nl();
- l.beginRelativeC();
+ layouter.nl();
+ layouter.beginRelativeC();
performActionOnStatement(statement);
- l.end();
+ layouter.end();
}
}
}
@@ -1726,26 +1745,26 @@ private void printCaseBody(ImmutableArray body) {
@Override
public void performActionOnCase(Case x) {
- l.beginRelativeC();
- l.keyWord("case").brk();
+ layouter.beginRelativeC();
+ layouter.keyWord("case").brk();
if (x.getExpression() != null) {
x.getExpression().visit(this);
}
- l.print(":").end();
+ layouter.print(":").end();
printCaseBody(x.getBody());
}
@Override
public void performActionOnCatch(Catch x) {
- l.print(" ");
- l.keyWord("catch");
- l.print(" ");
+ layouter.print(" ");
+ layouter.keyWord("catch");
+ layouter.print(" ");
beginMultilineBracket();
if (x.getParameterDeclaration() != null) {
performActionOnParameterDeclaration(x.getParameterDeclaration());
}
endMultilineBracket();
- l.print(" ");
+ layouter.print(" ");
if (x.getBody() != null) {
printStatementBlock(x.getBody());
}
@@ -1753,15 +1772,15 @@ public void performActionOnCatch(Catch x) {
@Override
public void performActionOnDefault(Default x) {
- l.keyWord("default").print(":");
+ layouter.keyWord("default").print(":");
printCaseBody(x.getBody());
}
@Override
public void performActionOnFinally(Finally x) {
- l.print(" ");
- l.keyWord("finally");
- l.print(" ");
+ layouter.print(" ");
+ layouter.keyWord("finally");
+ layouter.print(" ");
if (x.getBody() != null) {
printStatementBlock(x.getBody());
}
@@ -1769,7 +1788,7 @@ public void performActionOnFinally(Finally x) {
@Override
public void performActionOnModifier(Modifier x) {
- l.keyWord(x.getText());
+ layouter.keyWord(x.getText());
}
@SuppressWarnings("unchecked")
@@ -1782,7 +1801,7 @@ public void performActionOnSchemaVariable(SchemaVariable x) {
Object o = instantiations.getInstantiation(x);
if (o == null) {
- l.print(x.name().toString());
+ layouter.print(x.name().toString());
} else {
if (o instanceof ProgramElement) {
((ProgramElement) o).visit(this);
@@ -1806,30 +1825,30 @@ public void performActionOnComment(Comment x) {
@Override
public void performActionOnParenthesizedExpression(ParenthesizedExpression x) {
- l.print("(");
+ layouter.print("(");
if (x.getArguments() != null) {
x.getArguments().get(0).visit(this);
}
- l.print(")");
+ layouter.print(")");
}
@Override
public void performActionOnPassiveExpression(PassiveExpression x) {
- l.print("@(");
+ layouter.print("@(");
if (x.getArguments() != null) {
x.getArguments().get(0).visit(this);
}
- l.print(")");
+ layouter.print(")");
}
@Override
public void performActionOnTransactionStatement(TransactionStatement x) {
- l.print(x.toString());
+ layouter.print(x.toString());
}
@Override
public void performActionOnEmptyMapLiteral(EmptyMapLiteral x) {
- l.print("\\map_empty");
+ layouter.print("\\map_empty");
}
@Override
@@ -1839,9 +1858,9 @@ public void performActionOnExec(Exec x) {
@Override
public void performActionOnCcatch(Ccatch x) {
- l.print(" ");
- l.keyWord("ccatch");
- l.print(" ");
+ layouter.print(" ");
+ layouter.keyWord("ccatch");
+ layouter.print(" ");
beginMultilineBracket();
if (x.hasParameterDeclaration()) {
performActionOnParameterDeclaration(x.getParameterDeclaration());
@@ -1849,7 +1868,7 @@ public void performActionOnCcatch(Ccatch x) {
x.getNonStdParameterDeclaration().visit(this);
}
endMultilineBracket();
- l.print(" ");
+ layouter.print(" ");
if (x.getBody() != null) {
printStatementBlock(x.getBody());
}
@@ -1858,33 +1877,33 @@ public void performActionOnCcatch(Ccatch x) {
@Override
public void performActionOnCcatchReturnParameterDeclaration(
CcatchReturnParameterDeclaration x) {
- l.keyWord("\\Return");
+ layouter.keyWord("\\Return");
}
@Override
public void performActionOnCcatchReturnValParameterDeclaration(
CcatchReturnValParameterDeclaration x) {
- l.keyWord("\\Return");
- l.print(" ");
+ layouter.keyWord("\\Return");
+ layouter.print(" ");
x.getDelegate().visit(this);
}
@Override
public void performActionOnCcatchContinueParameterDeclaration(
CcatchContinueParameterDeclaration x) {
- l.keyWord("\\Continue");
+ layouter.keyWord("\\Continue");
}
@Override
public void performActionOnCcatchBreakParameterDeclaration(CcatchBreakParameterDeclaration x) {
- l.keyWord("\\Break");
+ layouter.keyWord("\\Break");
}
@Override
public void performActionOnCcatchBreakLabelParameterDeclaration(
CcatchBreakLabelParameterDeclaration x) {
- l.keyWord("\\Break");
- l.print(" ");
+ layouter.keyWord("\\Break");
+ layouter.print(" ");
if (x.getLabel() != null) {
x.getLabel().visit(this);
}
@@ -1893,8 +1912,8 @@ public void performActionOnCcatchBreakLabelParameterDeclaration(
@Override
public void performActionOnCCcatchContinueLabelParameterDeclaration(
CcatchContinueLabelParameterDeclaration x) {
- l.keyWord("\\Continue");
- l.print(" ");
+ layouter.keyWord("\\Continue");
+ layouter.print(" ");
if (x.getLabel() != null) {
x.getLabel().visit(this);
}
@@ -1903,8 +1922,8 @@ public void performActionOnCCcatchContinueLabelParameterDeclaration(
@Override
public void performActionOnCcatchBreakWildcardParameterDeclaration(
CcatchBreakWildcardParameterDeclaration x) {
- l.keyWord("\\Break");
- l.print(" *");
+ layouter.keyWord("\\Break");
+ layouter.print(" *");
}
@Override
@@ -1920,13 +1939,64 @@ public void performActionOnCcatchContinueWildcardParameterDeclaration(
*/
@Override
public void performActionOnJmlAssert(JmlAssert jmlAssert) {
- l.print("//@ ");
+ layouter.print("//@ ");
final String kind = jmlAssert.getKind().name().toLowerCase();
- l.keyWord(kind);
+ layouter.keyWord(kind);
- l.beginRelativeC();
- l.brk();
- l.print(jmlAssert.getConditionText().trim());
- l.end();
+ layouter.beginRelativeC();
+ layouter.brk();
+
+ if (services == null) {
+ layouter.print(jmlAssert.getCondition().getText().trim());
+ } else {
+ var spec = services.getSpecificationRepository().getStatementSpec(jmlAssert);
+ if (spec == null) {
+ layouter.print(jmlAssert.getCondition().getText().trim());
+ } else {
+ Term t = spec.term(JmlAssert.INDEX_CONDITION);
+ String text = printInLogicPrinter(t);
+ layouter.print(text);
+ }
+ }
+ layouter.end();
+ }
+
+ /**
+ * Prints a JML set statement
+ *
+ * @param x the set statement
+ */
+ public void performActionOnSetStatement(SetStatement x) {
+ layouter.print("//@ ");
+ layouter.keyWord("set");
+
+ layouter.beginRelativeC();
+ layouter.brk();
+
+ if (services != null) {
+ var spec =
+ Objects.requireNonNull(services.getSpecificationRepository().getStatementSpec(x));
+ Term target = spec.term(SetStatement.INDEX_TARGET);
+ Term value = spec.term(SetStatement.INDEX_VALUE);
+ layouter.print(printInLogicPrinter(target));
+ layouter.print(" = ");
+ layouter.print(printInLogicPrinter(value));
+ } else {
+ var context = x.getParserContext();
+ if (context != null) {
+ // remove all whitespaces (\n\f\t...) with an empty space
+ var text = context.getText();
+ text = text.substring(4, text.length() - 1);
+ layouter.print(text);
+ }
+ }
+ layouter.end();
}
+
+ public String printInLogicPrinter(Term t) {
+ var lp = LogicPrinter.quickPrinter(services, usePrettyPrinting, useUnicodeSymbols);
+ lp.printTerm(t);
+ return lp.result();
+ }
+
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/pp/SequentViewLogicPrinter.java b/key.core/src/main/java/de/uka/ilkd/key/pp/SequentViewLogicPrinter.java
index 09bbb7746a0..e426e15d987 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/pp/SequentViewLogicPrinter.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/pp/SequentViewLogicPrinter.java
@@ -13,6 +13,7 @@
import org.key_project.util.collection.ImmutableArray;
+
/**
* Subclass of {@link LogicPrinter} used in GUI. Any GUI-specific code for pretty-printing should be
* put in here, so that code of {@link LogicPrinter} stays independent of GUI as much as possible.
diff --git a/key.core/src/main/java/de/uka/ilkd/key/proof/OpReplacer.java b/key.core/src/main/java/de/uka/ilkd/key/proof/OpReplacer.java
index 2463b3a6653..55a54a489f3 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/proof/OpReplacer.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/proof/OpReplacer.java
@@ -19,6 +19,8 @@
import org.key_project.util.collection.ImmutableSLList;
import org.key_project.util.collection.ImmutableSet;
+import static de.uka.ilkd.key.logic.equality.TermLabelsProperty.TERM_LABELS_PROPERTY;
+
/**
* Replaces operators in a term by other operators with the same signature, or subterms of the term
@@ -233,7 +235,7 @@ public Term replace(Term term) {
}
for (SVSubstitute svs : map.keySet()) {
- if (term.equalsModTermLabels(svs)) {
+ if (term.equalsModProperty(svs, TERM_LABELS_PROPERTY)) {
return (Term) map.get(svs);
}
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/proof/SemisequentTacletAppIndex.java b/key.core/src/main/java/de/uka/ilkd/key/proof/SemisequentTacletAppIndex.java
index 4a1032d9175..f70243418f7 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/proof/SemisequentTacletAppIndex.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/proof/SemisequentTacletAppIndex.java
@@ -191,7 +191,8 @@ private TermTacletAppIndex getTermIndex(PosInOccurrence pos) {
* @return all taclet apps for the given position
*/
public ImmutableList getTacletAppAt(PosInOccurrence pos, RuleFilter filter) {
- return getTermIndex(pos).getTacletAppAt(pos, filter);
+ TermTacletAppIndex termIndex = getTermIndex(pos);
+ return termIndex.getTacletAppAt(pos, filter);
}
/**
diff --git a/key.core/src/main/java/de/uka/ilkd/key/proof/init/JavaProfile.java b/key.core/src/main/java/de/uka/ilkd/key/proof/init/JavaProfile.java
index fa134a73016..36d560f9b91 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/proof/init/JavaProfile.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/proof/init/JavaProfile.java
@@ -12,12 +12,12 @@
import de.uka.ilkd.key.proof.mgt.ComplexRuleJustificationBySpec;
import de.uka.ilkd.key.proof.mgt.RuleJustification;
import de.uka.ilkd.key.prover.impl.DepthFirstGoalChooserBuilder;
+import de.uka.ilkd.key.rule.*;
import de.uka.ilkd.key.rule.AbstractAuxiliaryContractBuiltInRuleApp;
import de.uka.ilkd.key.rule.AbstractContractRuleApp;
import de.uka.ilkd.key.rule.BlockContractExternalRule;
import de.uka.ilkd.key.rule.BlockContractInternalRule;
import de.uka.ilkd.key.rule.BuiltInRule;
-import de.uka.ilkd.key.rule.JmlAssertRule;
import de.uka.ilkd.key.rule.LoopApplyHeadRule;
import de.uka.ilkd.key.rule.LoopContractExternalRule;
import de.uka.ilkd.key.rule.LoopContractInternalRule;
@@ -157,6 +157,7 @@ protected ImmutableList initBuiltInRules() {
.prepend(QueryExpand.INSTANCE).prepend(MergeRule.INSTANCE)
.prepend(LoopApplyHeadRule.INSTANCE).prepend(JmlAssertRule.ASSERT_INSTANCE)
.prepend(JmlAssertRule.ASSUME_INSTANCE)
+ .prepend(SetStatementRule.INSTANCE)
.prepend(ObserverToUpdateRule.INSTANCE);
// contract insertion rule, ATTENTION: ProofMgt relies on the fact
diff --git a/key.core/src/main/java/de/uka/ilkd/key/proof/join/JoinIsApplicable.java b/key.core/src/main/java/de/uka/ilkd/key/proof/join/JoinIsApplicable.java
index 8cf5534c20c..2568f3fe8cd 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/proof/join/JoinIsApplicable.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/proof/join/JoinIsApplicable.java
@@ -13,6 +13,8 @@
import de.uka.ilkd.key.logic.op.UpdateApplication;
import de.uka.ilkd.key.proof.Goal;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
/**
* Methods for checking the applicability of a join for a given selection and thereby computing the
* prospective join partners.
@@ -89,13 +91,13 @@ private ProspectivePartner areProspectivePartners(Goal g1, PosInOccurrence pio,
Term formula = sf.formula();
Term update2 = tb.skip();
if (formula.op() instanceof UpdateApplication
- && !formula.equalsModRenaming(referenceFormula)) {
+ && !formula.equalsModProperty(referenceFormula, RENAMING_PROPERTY)) {
update2 = formula.sub(0);// don't change the order of this and
// the following line.
formula = formula.sub(1);
}
- if (formula.equalsModRenaming(referenceFormula)) {
+ if (formula.equalsModProperty(referenceFormula, RENAMING_PROPERTY)) {
return new ProspectivePartner(referenceFormula, g1.node(), pio.sequentFormula(),
update1, g2.node(), sf, update2);
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/proof/mgt/SpecificationRepository.java b/key.core/src/main/java/de/uka/ilkd/key/proof/mgt/SpecificationRepository.java
index cf50a50222c..b4105efdb91 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/proof/mgt/SpecificationRepository.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/proof/mgt/SpecificationRepository.java
@@ -10,6 +10,7 @@
import de.uka.ilkd.key.java.JavaInfo;
import de.uka.ilkd.key.java.Services;
+import de.uka.ilkd.key.java.Statement;
import de.uka.ilkd.key.java.ast.StatementBlock;
import de.uka.ilkd.key.java.ast.abstraction.KeYJavaType;
import de.uka.ilkd.key.java.ast.declaration.ClassDeclaration;
@@ -19,6 +20,7 @@
import de.uka.ilkd.key.java.ast.statement.MergePointStatement;
import de.uka.ilkd.key.logic.*;
import de.uka.ilkd.key.logic.op.*;
+import de.uka.ilkd.key.proof.OpReplacer;
import de.uka.ilkd.key.proof.Proof;
import de.uka.ilkd.key.proof.init.ContractPO;
import de.uka.ilkd.key.proof.init.ProofOblInput;
@@ -29,6 +31,7 @@
import de.uka.ilkd.key.rule.tacletbuilder.RewriteTacletGoalTemplate;
import de.uka.ilkd.key.speclang.*;
import de.uka.ilkd.key.speclang.jml.JMLInfoExtractor;
+import de.uka.ilkd.key.speclang.jml.translation.ProgramVariableCollection;
import de.uka.ilkd.key.speclang.translation.SLTranslationException;
import de.uka.ilkd.key.util.MiscTools;
import de.uka.ilkd.key.util.Triple;
@@ -41,6 +44,7 @@
import org.key_project.util.collection.ImmutableSet;
import org.key_project.util.collection.Pair;
+import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -785,7 +789,7 @@ public ImmutableSet getOperationContracts(KeYJavaTy
* null.
*/
public Contract getContractByName(String name) {
- if (name == null || name.length() == 0) {
+ if (name == null || name.isEmpty()) {
return null;
}
String[] baseNames = name.split(CONTRACT_COMBINATION_MARKER);
@@ -884,7 +888,7 @@ public void addContracts(ImmutableSet toAdd) {
*/
public FunctionalOperationContract combineOperationContracts(
ImmutableSet toCombine) {
- assert toCombine != null && toCombine.size() > 0;
+ assert toCombine != null && !toCombine.isEmpty();
for (Contract contract : toCombine) {
assert !contract.getName().contains(CONTRACT_COMBINATION_MARKER)
: "Please combine only atomic contracts!";
@@ -1428,7 +1432,7 @@ public void removeProof(Proof proof) {
ImmutableSet sop = entry.getValue();
if (sop.contains(proof)) {
sop = sop.remove(proof);
- if (sop.size() == 0) {
+ if (sop.isEmpty()) {
proofs.remove(entry.getKey());
} else {
proofs.put(entry.getKey(), sop);
@@ -1547,7 +1551,6 @@ public ImmutableSet getMergeContracts(MergePointStatement mps) {
*
* @param block the given block.
* @param modalityKind the given modality.
- * @return
*/
public ImmutableSet getBlockContracts(final StatementBlock block,
final Modality.JavaModalityKind modalityKind) {
@@ -1853,4 +1856,94 @@ public ImmutableSet getAllWdChecks() {
}
return result;
}
+
+
+ // region Support SetStatement and JmlAssert
+ private final Map statementMap = new IdentityHashMap<>();
+
+ @Nullable
+ public JmlStatementSpec getStatementSpec(Statement statement) {
+ return statementMap.get(statement);
+ }
+
+ public JmlStatementSpec addStatementSpec(Statement statement, JmlStatementSpec spec) {
+ return statementMap.put(statement, spec);
+ }
+
+ /**
+ * This record represents information which are necessary to evaluate JML statements.
+ * JML statements need to maintain the current variable set as well as the updated information for the KeY terms
+ * they describe. This record represents this information, i.e., the scope of variables, and a list of terms, in
+ * an immutable fasion. Updates require to create instances.
+ *
+ * Note: There is a immutability hole in {@link ProgramVariableCollection} due to mutable {@link Map}
+ *
+ * For {@link de.uka.ilkd.key.java.statement.JmlAssert} this is the formula behind the assert.
+ * For {@link de.uka.ilkd.key.java.statement.SetStatement} this is the target and the value terms.
+ * You may want to use the index constant for accessing them:
+ * {@link de.uka.ilkd.key.java.statement.SetStatement#INDEX_TARGET},
+ * {@link de.uka.ilkd.key.java.statement.SetStatement#INDEX_VALUE},
+ * {@link de.uka.ilkd.key.java.statement.JmlAssert#INDEX_CONDITION}
+ *
+ * @param vars
+ * @param terms
+ */
+ public record JmlStatementSpec(
+ ProgramVariableCollection vars,
+ ImmutableList terms
+ ){
+ /**
+ * Retrieve a term
+ * @param index a index to the list of {@code terms}.
+ * @return the term at {@code index} in the {@code terms} list
+ * @throws IndexOutOfBoundsException if the given {@code index} is negative or {@code >= terms().size()}
+ */
+ public Term term(int index) {
+ return terms.get(index);
+ }
+
+ /**
+ * Retrieve a term with a update to the given {@code self} term.
+ * @param services the corresponding services instance
+ * @param self a term which describes the {@code self} object aka. this on the current sequence
+ * @param index the index of the term in {@code terms()}
+ * @return a term updated with {@code self} and the {@code vars()}.
+ */
+ public Term getTerm(Services services, Term self, int index) {
+ var term = term(index);
+
+ final TermFactory termFactory = services.getTermFactory();
+ final TermReplacementMap replacementMap = new TermReplacementMap(termFactory);
+ if (self != null) {
+ replacementMap.replaceSelf(vars().selfVar, self, services);
+ }
+ replacementMap.replaceRemembranceLocalVariables(vars().atPreVars, vars().atPres, services);
+ replacementMap.replaceRemembranceLocalVariables(vars().atBeforeVars, vars().atBefores, services);
+ final OpReplacer replacer = new OpReplacer(replacementMap, termFactory, services.getProof());
+ return replacer.replace(term);
+ }
+
+ /**
+ * Updates the variables given the new {@code atPres} (variable in pre state) map and the services.
+ * The update is applied directly and an updated specification is returned. You need to add
+ * the updated spec to the statement in the {@link SpecificationRepository} by yourself.
+ *
+ * @param atPres a non-null map of a map of program variable to a term which describes
+ * the value of this variable in the pre-state.
+ * @param services the corresponding services object
+ * @return a fresh {@link JmlStatementSpec} instance, non-registered.
+ */
+ public JmlStatementSpec updateVariables(Map atPres, Services services) {
+ var termFactory = services.getTermFactory();
+ var replacementMap = new TermReplacementMap(termFactory);
+ replacementMap.replaceRemembranceLocalVariables(vars.atPreVars, atPres, services);
+ var replacer = new OpReplacer(replacementMap, termFactory, services.getProof());
+ var newTerms = terms().map(replacer::replace);
+ return new JmlStatementSpec(
+ new ProgramVariableCollection(vars.selfVar, vars.paramVars, vars.resultVar, vars.excVar,
+ vars.atPreVars, atPres, vars.atBeforeVars, vars.atBefores),
+ newTerms);
+ }
+ }
+ // endregion
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/AbstractLoopInvariantRule.java b/key.core/src/main/java/de/uka/ilkd/key/rule/AbstractLoopInvariantRule.java
index e714cb5ce68..5bce55e5ccc 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/rule/AbstractLoopInvariantRule.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/rule/AbstractLoopInvariantRule.java
@@ -29,6 +29,8 @@
import org.key_project.util.collection.ImmutableSet;
import org.key_project.util.collection.Pair;
+import static de.uka.ilkd.key.logic.equality.IrrelevantTermLabelsProperty.IRRELEVANT_TERM_LABELS_PROPERTY;
+
/**
* An abstract super class for loop invariant rules. Extending rules should usually call
* {@link #doPreparations(Goal, Services, RuleApp)} directly at the beginning of the
@@ -441,7 +443,7 @@ protected static AnonUpdateData createAnonUpdate(LocationVariable heap, Term mod
// check for strictly pure loops
final Term anonUpdate;
- if (tb.strictlyNothing().equalsModIrrelevantTermLabels(mod)) {
+ if (tb.strictlyNothing().equalsModProperty(mod, IRRELEVANT_TERM_LABELS_PROPERTY)) {
anonUpdate = tb.skip();
} else {
anonUpdate = tb.anonUpd(heap, mod, anonHeapTerm);
@@ -505,14 +507,14 @@ protected static AdditionalHeapTerms createAdditionalHeapTerms(Services services
final Term freeMod = freeMods.get(heap);
final Term strictlyNothing = tb.strictlyNothing();
final Term currentFrame;
- if (strictlyNothing.equalsModIrrelevantTermLabels(mod)) {
- if (strictlyNothing.equalsModIrrelevantTermLabels(freeMod)) {
+ if (strictlyNothing.equalsModProperty(mod, IRRELEVANT_TERM_LABELS_PROPERTY)) {
+ if (strictlyNothing.equalsModProperty(freeMod, IRRELEVANT_TERM_LABELS_PROPERTY)) {
currentFrame = tb.frameStrictlyEmpty(tb.var(heap), heapToBeforeLoop.get(heap));
} else {
currentFrame = tb.frame(tb.var(heap), heapToBeforeLoop.get(heap), freeMod);
}
} else {
- if (strictlyNothing.equalsModIrrelevantTermLabels(freeMod)) {
+ if (strictlyNothing.equalsModProperty(freeMod, IRRELEVANT_TERM_LABELS_PROPERTY)) {
currentFrame = tb.frame(tb.var(heap), heapToBeforeLoop.get(heap), mod);
} else {
currentFrame = tb.frame(
@@ -546,7 +548,7 @@ protected record AdditionalHeapTerms(Term anonUpdate, Term wellFormedAnon, Term
/**
* A container for an instantiation of this {@link LoopScopeInvariantRule} application; contains
* the update, the program with post condition, the {@link While} loop the
- * {@link LoopScopeInvariantRule} should be applied to, the {@link LoopSpecification}, the the
+ * {@link LoopScopeInvariantRule} should be applied to, the {@link LoopSpecification}, the
* self {@link Term}.
*
* @param innermostExecutionContext TODO Removed this field; was however used in old invariant rule. Could be needed for the information flow validity goal.
diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/AuxiliaryContractBuilders.java b/key.core/src/main/java/de/uka/ilkd/key/rule/AuxiliaryContractBuilders.java
index 01e9813a1bc..78bbc669019 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/rule/AuxiliaryContractBuilders.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/rule/AuxiliaryContractBuilders.java
@@ -51,6 +51,8 @@
import com.github.javaparser.ast.key.KeyTransactionStatement;
+import static de.uka.ilkd.key.logic.equality.IrrelevantTermLabelsProperty.IRRELEVANT_TERM_LABELS_PROPERTY;
+
/**
* This contains various builders used in building formulae and terms for block and loop contracts.
*
@@ -655,7 +657,8 @@ public Term buildAnonOutUpdate(final Set vars,
.entrySet()) {
Term anonymisationUpdate = skip();
final Term modifiesClause = modifiesClauses.get(anonymisationHeap.getKey());
- if (!modifiesClause.equalsModIrrelevantTermLabels(strictlyNothing())) {
+ if (!modifiesClause.equalsModProperty(strictlyNothing(),
+ IRRELEVANT_TERM_LABELS_PROPERTY)) {
anonymisationUpdate = anonUpd(anonymisationHeap.getKey(), modifiesClause,
services.getTermBuilder().label(
services.getTermBuilder().func(anonymisationHeap.getValue()),
diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/JmlAssertRule.java b/key.core/src/main/java/de/uka/ilkd/key/rule/JmlAssertRule.java
index c52e59b0786..4426c99582d 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/rule/JmlAssertRule.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/rule/JmlAssertRule.java
@@ -10,12 +10,8 @@
import de.uka.ilkd.key.java.ast.SourceElement;
import de.uka.ilkd.key.java.ast.statement.JmlAssert;
import de.uka.ilkd.key.java.ast.statement.MethodFrame;
-import de.uka.ilkd.key.logic.JavaBlock;
-import de.uka.ilkd.key.logic.PosInOccurrence;
-import de.uka.ilkd.key.logic.SequentFormula;
-import de.uka.ilkd.key.logic.Term;
-import de.uka.ilkd.key.logic.TermBuilder;
-import de.uka.ilkd.key.logic.TermServices;
+import de.uka.ilkd.key.logic.*;
+import de.uka.ilkd.key.logic.label.OriginTermLabel;
import de.uka.ilkd.key.logic.op.Modality;
import de.uka.ilkd.key.logic.op.Transformer;
import de.uka.ilkd.key.logic.op.UpdateApplication;
@@ -30,7 +26,6 @@
/**
* A rule for JML assert/assume statements.
- *
* This implements the rules as:
*
*
@@ -132,7 +127,19 @@ public ImmutableList apply(Goal goal, Services services, RuleApp ruleApp)
final MethodFrame frame = JavaTools.getInnermostMethodFrame(target.javaBlock(), services);
final Term self = MiscTools.getSelfTerm(frame, services);
- final Term condition = jmlAssert.getCond(self, services);
+ final var spec = services.getSpecificationRepository().getStatementSpec(jmlAssert);
+
+ if (spec == null) {
+ throw new RuleAbortException(
+ "No specification found for JmlAssert. Internal Error. Not your fault");
+ }
+
+ Term condition =
+ tb.convertToFormula(spec.getTerm(services, self, JmlAssert.INDEX_CONDITION));
+
+ condition = tb.addLabel(condition, new OriginTermLabel.Origin(
+ kind == Kind.ASSERT ? OriginTermLabel.SpecType.ASSERT
+ : OriginTermLabel.SpecType.ASSUME));
final ImmutableList result;
if (kind == Kind.ASSERT) {
diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/OneStepSimplifier.java b/key.core/src/main/java/de/uka/ilkd/key/rule/OneStepSimplifier.java
index 75628fb43cc..d774250f344 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/rule/OneStepSimplifier.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/rule/OneStepSimplifier.java
@@ -46,6 +46,8 @@
import org.jspecify.annotations.NonNull;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
public final class OneStepSimplifier implements BuiltInRule {
@@ -747,8 +749,9 @@ public boolean equals(Object obj) {
obj = ((TermReplacementKey) obj).term;
}
if (obj instanceof Term t) {
- return term.equalsModRenaming(t); // Ignore naming and term labels in the way a
- // taclet rule does.
+ return term.equalsModProperty(t, RENAMING_PROPERTY); // Ignore naming and term
+ // labels in the way a
+ // taclet rule does.
} else {
return false;
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/SetStatementBuiltInRuleApp.java b/key.core/src/main/java/de/uka/ilkd/key/rule/SetStatementBuiltInRuleApp.java
new file mode 100644
index 00000000000..a836484f684
--- /dev/null
+++ b/key.core/src/main/java/de/uka/ilkd/key/rule/SetStatementBuiltInRuleApp.java
@@ -0,0 +1,49 @@
+/* This file is part of KeY - https://key-project.org
+ * KeY is licensed under the GNU General Public License Version 2
+ * SPDX-License-Identifier: GPL-2.0-only */
+package de.uka.ilkd.key.rule;
+
+import java.util.Objects;
+
+import de.uka.ilkd.key.logic.PosInOccurrence;
+import de.uka.ilkd.key.proof.Goal;
+
+import org.key_project.util.collection.ImmutableList;
+
+/**
+ * The rule application for {@link de.uka.ilkd.key.java.statement.SetStatement}
+ *
+ * @author Julian Wiesler
+ */
+public class SetStatementBuiltInRuleApp extends AbstractBuiltInRuleApp {
+ /**
+ * @param rule the rule being applied
+ * @param occurrence the position at which the rule is applied
+ */
+ public SetStatementBuiltInRuleApp(BuiltInRule rule, PosInOccurrence occurrence) {
+ super(rule, Objects.requireNonNull(occurrence, "rule application needs a position"), null);
+ if (!(rule instanceof SetStatementRule)) {
+ throw new IllegalArgumentException(String.format(
+ "can only create an application for SetStatementRule, not for %s", rule));
+ }
+ }
+
+ @Override
+ public SetStatementBuiltInRuleApp replacePos(PosInOccurrence newPos) {
+ return new SetStatementBuiltInRuleApp(rule(), newPos);
+ }
+
+ @Override
+ public IBuiltInRuleApp setIfInsts(ImmutableList ifInsts) {
+ // XXX: This is overridden in all subclasses to allow making ifInsts final
+ // when all usages of setIfInsts are corrected to use the result.
+ // Then a new instance has to be returned here.
+ setMutable(ifInsts);
+ return this;
+ }
+
+ @Override
+ public AbstractBuiltInRuleApp tryToInstantiate(Goal goal) {
+ return this;
+ }
+}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/SetStatementRule.java b/key.core/src/main/java/de/uka/ilkd/key/rule/SetStatementRule.java
new file mode 100644
index 00000000000..4cbf982d056
--- /dev/null
+++ b/key.core/src/main/java/de/uka/ilkd/key/rule/SetStatementRule.java
@@ -0,0 +1,135 @@
+/* This file is part of KeY - https://key-project.org
+ * KeY is licensed under the GNU General Public License Version 2
+ * SPDX-License-Identifier: GPL-2.0-only */
+package de.uka.ilkd.key.rule;
+
+import java.util.Optional;
+
+import de.uka.ilkd.key.java.JavaTools;
+import de.uka.ilkd.key.java.Services;
+import de.uka.ilkd.key.java.SourceElement;
+import de.uka.ilkd.key.java.statement.MethodFrame;
+import de.uka.ilkd.key.java.statement.SetStatement;
+import de.uka.ilkd.key.logic.*;
+import de.uka.ilkd.key.logic.op.Modality;
+import de.uka.ilkd.key.logic.op.Transformer;
+import de.uka.ilkd.key.logic.op.UpdateApplication;
+import de.uka.ilkd.key.proof.Goal;
+import de.uka.ilkd.key.util.MiscTools;
+
+import org.key_project.logic.Name;
+import org.key_project.util.collection.ImmutableList;
+
+import org.jspecify.annotations.NonNull;
+
+/**
+ * A rule for set statements. This unwraps the contained CopyAssignment
+ *
+ * @author Julian Wiesler
+ */
+public final class SetStatementRule implements BuiltInRule {
+
+ /**
+ * The instance
+ */
+ public static final SetStatementRule INSTANCE = new SetStatementRule();
+ /**
+ * The name of this rule
+ */
+ private static final Name name = new Name("Set Statement");
+
+ private SetStatementRule() {
+ // no statements
+ }
+
+ @Override
+ public boolean isApplicable(Goal goal, PosInOccurrence occurrence) {
+ if (AbstractAuxiliaryContractRule.occursNotAtTopLevelInSuccedent(occurrence)) {
+ return false;
+ }
+ // abort if inside of transformer
+ if (Transformer.inTransformer(occurrence)) {
+ return false;
+ }
+
+ Term target = occurrence.subTerm();
+ if (target.op() instanceof UpdateApplication) {
+ target = UpdateApplication.getTarget(target);
+ }
+ final SourceElement activeStatement = JavaTools.getActiveStatement(target.javaBlock());
+ return activeStatement instanceof SetStatement;
+ }
+
+ @Override
+ public boolean isApplicableOnSubTerms() {
+ return false;
+ }
+
+ @Override
+ public IBuiltInRuleApp createApp(PosInOccurrence occurrence, TermServices services) {
+ return new SetStatementBuiltInRuleApp(this, occurrence);
+ }
+
+ @NonNull
+ @Override
+ public ImmutableList apply(Goal goal, Services services, RuleApp ruleApp)
+ throws RuleAbortException {
+ if (!(ruleApp instanceof SetStatementBuiltInRuleApp)) {
+ throw new IllegalArgumentException("can only apply SetStatementBuiltInRuleApp");
+ }
+
+ final TermBuilder tb = services.getTermBuilder();
+ final PosInOccurrence occurrence = ruleApp.posInOccurrence();
+ final Term formula = occurrence.subTerm();
+ assert formula.op() instanceof UpdateApplication
+ : "Currently, this can only be applied if there is an update application in front of the modality";
+
+ Term update = UpdateApplication.getUpdate(formula);
+ Term target = UpdateApplication.getTarget(formula);
+
+ SetStatement setStatement =
+ Optional.ofNullable(JavaTools.getActiveStatement(target.javaBlock()))
+ .filter(SetStatement.class::isInstance).map(SetStatement.class::cast)
+ .orElseThrow(() -> new RuleAbortException("not a JML set statement."));
+
+ final MethodFrame frame = JavaTools.getInnermostMethodFrame(target.javaBlock(), services);
+ final Term self = MiscTools.getSelfTerm(frame, services);
+
+ var spec = services.getSpecificationRepository().getStatementSpec(setStatement);
+
+ if (spec == null) {
+ throw new RuleAbortException(
+ "No specification for the set statement found in the specification repository.");
+ }
+
+ var targetTerm = spec.getTerm(services, self, SetStatement.INDEX_TARGET);
+ var valueTerm = spec.getTerm(services, self, SetStatement.INDEX_VALUE);
+
+ Term newUpdate = tb.elementary(targetTerm, valueTerm);
+
+ JavaBlock javaBlock = JavaTools.removeActiveStatement(target.javaBlock(), services);
+
+ Term term =
+ tb.prog(((Modality) target.op()).kind(), javaBlock, target.sub(0), target.getLabels());
+ Term newTerm = tb.apply(update, tb.apply(newUpdate, term));
+
+ ImmutableList result = goal.split(1);
+ result.head().changeFormula(new SequentFormula(newTerm), occurrence);
+ return result;
+ }
+
+ @Override
+ public Name name() {
+ return name;
+ }
+
+ @Override
+ public String displayName() {
+ return name.toString();
+ }
+
+ @Override
+ public String toString() {
+ return name.toString();
+ }
+}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/UseDependencyContractRule.java b/key.core/src/main/java/de/uka/ilkd/key/rule/UseDependencyContractRule.java
index ff3fb1ad967..479f3fe80f9 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/rule/UseDependencyContractRule.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/rule/UseDependencyContractRule.java
@@ -32,6 +32,8 @@
import org.jspecify.annotations.NonNull;
+import static de.uka.ilkd.key.logic.equality.IrrelevantTermLabelsProperty.IRRELEVANT_TERM_LABELS_PROPERTY;
+
public final class UseDependencyContractRule implements BuiltInRule {
@@ -208,7 +210,7 @@ public static boolean isBaseOcc(Term focus, Term candidate) {
return false;
}
for (int i = 1, n = candidate.arity(); i < n; i++) {
- if (!(candidate.sub(i).equalsModIrrelevantTermLabels(focus.sub(i))
+ if (!(candidate.sub(i).equalsModProperty(focus.sub(i), IRRELEVANT_TERM_LABELS_PROPERTY)
|| candidate.sub(i).op() instanceof LogicVariable)) {
return false;
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/WhileInvariantRule.java b/key.core/src/main/java/de/uka/ilkd/key/rule/WhileInvariantRule.java
index 45b387adab5..6c58c286f17 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/rule/WhileInvariantRule.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/rule/WhileInvariantRule.java
@@ -63,6 +63,8 @@
import org.jspecify.annotations.NonNull;
+import static de.uka.ilkd.key.logic.equality.IrrelevantTermLabelsProperty.IRRELEVANT_TERM_LABELS_PROPERTY;
+
public final class WhileInvariantRule implements BuiltInRule {
/**
* The hint used to refactor the initial invariant.
@@ -263,7 +265,7 @@ private static AnonUpdateData createAnonUpdate(LocationVariable heap, Term mod,
// check for strictly pure loops
final Term anonUpdate;
- if (tb.strictlyNothing().equalsModIrrelevantTermLabels(mod)) {
+ if (tb.strictlyNothing().equalsModProperty(mod, IRRELEVANT_TERM_LABELS_PROPERTY)) {
anonUpdate = tb.skip();
} else {
anonUpdate = tb.anonUpd(heap, mod, anonHeapTerm);
@@ -826,14 +828,17 @@ public ImmutableList apply(Goal goal, Services services, final RuleApp rul
final Term freeMod = freeMods.get(heap);
final Term strictlyNothing = tb.strictlyNothing();
final Term currentFrame;
- if (strictlyNothing.equalsModIrrelevantTermLabels(mod)) {
- if (strictlyNothing.equalsModIrrelevantTermLabels(freeMod)) {
+ if (strictlyNothing.equalsModProperty(
+ mod, IRRELEVANT_TERM_LABELS_PROPERTY)) {
+ if (strictlyNothing.equalsModProperty(
+ freeMod, IRRELEVANT_TERM_LABELS_PROPERTY)) {
currentFrame = tb.frameStrictlyEmpty(tb.var(heap), heapToBeforeLoop.get(heap));
} else {
currentFrame = tb.frame(tb.var(heap), heapToBeforeLoop.get(heap), freeMod);
}
} else {
- if (strictlyNothing.equalsModIrrelevantTermLabels(freeMod)) {
+ if (strictlyNothing.equalsModProperty(
+ freeMod, IRRELEVANT_TERM_LABELS_PROPERTY)) {
currentFrame = tb.frame(tb.var(heap), heapToBeforeLoop.get(heap), mod);
} else {
currentFrame = tb.frame(
diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/conditions/ApplyUpdateOnRigidCondition.java b/key.core/src/main/java/de/uka/ilkd/key/rule/conditions/ApplyUpdateOnRigidCondition.java
index 4a71c44170b..78f40a82ba6 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/rule/conditions/ApplyUpdateOnRigidCondition.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/rule/conditions/ApplyUpdateOnRigidCondition.java
@@ -16,6 +16,8 @@
import org.key_project.util.collection.ImmutableArray;
import org.key_project.util.collection.ImmutableSet;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
/**
* This variable condition can be used to check whether an update can be performed on a formula or
@@ -213,7 +215,7 @@ public MatchConditions check(SchemaVariable var, SVSubstitute instCandidate, Mat
if (resultInst == null) {
svInst = svInst.add(result, properResultInst, services);
return mc.setInstantiations(svInst);
- } else if (resultInst.equalsModRenaming(properResultInst)) {
+ } else if (resultInst.equalsModProperty(properResultInst, RENAMING_PROPERTY)) {
return mc;
} else {
return null;
diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/conditions/FieldTypeToSortCondition.java b/key.core/src/main/java/de/uka/ilkd/key/rule/conditions/FieldTypeToSortCondition.java
index edd5f445959..a3cd6a9b0d0 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/rule/conditions/FieldTypeToSortCondition.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/rule/conditions/FieldTypeToSortCondition.java
@@ -4,6 +4,7 @@
package de.uka.ilkd.key.rule.conditions;
import de.uka.ilkd.key.java.Services;
+import de.uka.ilkd.key.ldt.HeapLDT;
import de.uka.ilkd.key.logic.Term;
import de.uka.ilkd.key.logic.op.*;
import de.uka.ilkd.key.logic.sort.GenericSort;
@@ -53,33 +54,13 @@ public MatchConditions check(SchemaVariable var, SVSubstitute svSubst,
if (svSubst instanceof Term) {
Operator op = ((Term) svSubst).op();
if (op instanceof JFunction) {
- String name = op.name().toString();
-
- String className;
- String attributeName;
-
- // check for normal attribute
- int endOfClassName = name.indexOf("::$");
-
- int startAttributeName = endOfClassName + 3;
-
-
- if (endOfClassName < 0) {
- // not a normal attribute, maybe an implicit attribute like $created?
- endOfClassName = name.indexOf("::<");
- startAttributeName = endOfClassName + 2;
- }
-
- if (endOfClassName < 0) {
+ HeapLDT.SplitFieldName split = HeapLDT.trySplitFieldName(op);
+ if (split == null) {
return null;
}
-
- className = name.substring(0, endOfClassName);
- attributeName = name.substring(startAttributeName);
-
ProgramVariable attribute =
- services.getJavaInfo().getAttribute(attributeName, className);
+ services.getJavaInfo().getAttribute(split.attributeName(), split.className());
if (attribute == null) {
return null;
diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/conditions/StaticFieldCondition.java b/key.core/src/main/java/de/uka/ilkd/key/rule/conditions/StaticFieldCondition.java
index dcd8259fca2..2d942802bf8 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/rule/conditions/StaticFieldCondition.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/rule/conditions/StaticFieldCondition.java
@@ -4,6 +4,7 @@
package de.uka.ilkd.key.rule.conditions;
import de.uka.ilkd.key.java.Services;
+import de.uka.ilkd.key.ldt.HeapLDT;
import de.uka.ilkd.key.logic.Term;
import de.uka.ilkd.key.logic.op.*;
import de.uka.ilkd.key.rule.VariableConditionAdapter;
@@ -38,29 +39,13 @@ public boolean check(SchemaVariable var, SVSubstitute instCandidate, SVInstantia
}
final Operator op = f.op();
if (op instanceof JFunction) {
- final String name = op.name().toString();
-
- // check for normal attribute
- int endOfClassName = name.indexOf("::$");
-
- int startAttributeName = endOfClassName + 3;
-
-
- if (endOfClassName < 0) {
- // not a normal attribute, maybe an implicit attribute like $created?
- endOfClassName = name.indexOf("::<");
- startAttributeName = endOfClassName + 2;
- }
-
- if (endOfClassName < 0) {
+ HeapLDT.SplitFieldName split = HeapLDT.trySplitFieldName(op);
+ if (split == null) {
return false;
}
- final String className = name.substring(0, endOfClassName);
- final String attributeName = name.substring(startAttributeName);
-
final ProgramVariable attribute =
- services.getJavaInfo().getAttribute(attributeName, className);
+ services.getJavaInfo().getAttribute(split.attributeName(), split.className());
if (attribute == null) {
return false;
diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/inst/SVInstantiations.java b/key.core/src/main/java/de/uka/ilkd/key/rule/inst/SVInstantiations.java
index 455e2e1438f..5f58388147e 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/rule/inst/SVInstantiations.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/rule/inst/SVInstantiations.java
@@ -26,6 +26,9 @@
import org.key_project.util.collection.ImmutableMapEntry;
import org.key_project.util.collection.ImmutableSLList;
+import static de.uka.ilkd.key.logic.equality.IrrelevantTermLabelsProperty.IRRELEVANT_TERM_LABELS_PROPERTY;
+import static de.uka.ilkd.key.logic.equality.ProofIrrelevancyProperty.PROOF_IRRELEVANCY_PROPERTY;
+
/**
* This class wraps an {@link ImmutableMap} from {@link SchemaVariable} to
* {@link InstantiationEntry}
@@ -549,7 +552,8 @@ public boolean equals(Object obj) {
final Object inst = e.value().getInstantiation();
assert inst != null : "Illegal null instantiation.";
if (inst instanceof Term instAsTerm) {
- if (!instAsTerm.equalsModIrrelevantTermLabels(cmp.getInstantiation(e.key()))) {
+ if (!instAsTerm.equalsModProperty(cmp.getInstantiation(e.key()),
+ IRRELEVANT_TERM_LABELS_PROPERTY)) {
return false;
}
} else if (!inst.equals(cmp.getInstantiation(e.key()))) {
@@ -579,7 +583,8 @@ public boolean equalsModProofIrrelevancy(Object obj) {
final Object inst = e.value().getInstantiation();
assert inst != null : "Illegal null instantiation.";
if (inst instanceof Term instAsTerm) {
- if (!instAsTerm.equalsModProofIrrelevancy(cmp.getInstantiation(e.key()))) {
+ if (!instAsTerm.equalsModProperty(
+ cmp.getInstantiation(e.key()), PROOF_IRRELEVANCY_PROPERTY)) {
return false;
}
} else if (!inst.equals(cmp.getInstantiation(e.key()))) {
diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/match/legacy/ElementMatcher.java b/key.core/src/main/java/de/uka/ilkd/key/rule/match/legacy/ElementMatcher.java
index 8c51e5de94a..ffe7b63a0c1 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/rule/match/legacy/ElementMatcher.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/rule/match/legacy/ElementMatcher.java
@@ -19,6 +19,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
public abstract class ElementMatcher {
public static final Logger LOGGER = LoggerFactory.getLogger(ElementMatcher.class);
@@ -127,7 +129,7 @@ protected final MatchConditions addInstantiation(AbstractSV op, Term term,
final Term t = inst.getTermInstantiation(op, inst.getExecutionContext(), services);
if (t != null) {
- if (!t.equalsModRenaming(term)) {
+ if (!t.equalsModProperty(term, RENAMING_PROPERTY)) {
LOGGER.debug(
"FAILED. Adding instantiations leads to unsatisfiable constraint. {} {}",
op, term);
diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/match/vm/VMTacletMatcher.java b/key.core/src/main/java/de/uka/ilkd/key/rule/match/vm/VMTacletMatcher.java
index e627787a65f..710b6533be3 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/rule/match/vm/VMTacletMatcher.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/rule/match/vm/VMTacletMatcher.java
@@ -35,6 +35,8 @@
import org.key_project.util.collection.ImmutableSet;
import org.key_project.util.collection.Pair;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
/**
*
* Matching algorithm using a virtual machine based approach inspired by Voronkonv et al. It matches
@@ -165,7 +167,7 @@ private Term matchUpdateContext(ImmutableList context, Term for
if (formula.op() instanceof UpdateApplication) {
final Term update = UpdateApplication.getUpdate(formula);
final UpdateLabelPair ulp = curContext.head();
- if (ulp.update().equalsModRenaming(update)
+ if (ulp.update().equalsModProperty(update, RENAMING_PROPERTY)
&& ulp.updateApplicationlabels().equals(update.getLabels())) {
curContext = curContext.tail();
formula = UpdateApplication.getTarget(formula);
diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/match/vm/instructions/MatchSchemaVariableInstruction.java b/key.core/src/main/java/de/uka/ilkd/key/rule/match/vm/instructions/MatchSchemaVariableInstruction.java
index 51b8faeffb5..c7af399ce20 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/rule/match/vm/instructions/MatchSchemaVariableInstruction.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/rule/match/vm/instructions/MatchSchemaVariableInstruction.java
@@ -14,6 +14,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
public abstract class MatchSchemaVariableInstruction
extends Instruction {
private static final Logger LOGGER =
@@ -40,7 +42,7 @@ protected final MatchConditions addInstantiation(Term term, MatchConditions matc
final Term t = inst.getTermInstantiation(op, inst.getExecutionContext(), services);
if (t != null) {
- if (!t.equalsModRenaming(term)) {
+ if (!t.equalsModProperty(term, RENAMING_PROPERTY)) {
return null;
} else {
return matchCond;
diff --git a/key.core/src/main/java/de/uka/ilkd/key/rule/merge/MergeRule.java b/key.core/src/main/java/de/uka/ilkd/key/rule/merge/MergeRule.java
index 6b3b5196bef..8b3ad769444 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/rule/merge/MergeRule.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/rule/merge/MergeRule.java
@@ -48,6 +48,7 @@
import org.jspecify.annotations.NonNull;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
import static de.uka.ilkd.key.util.mergerule.MergeRuleUtils.clearSemisequent;
import static de.uka.ilkd.key.util.mergerule.MergeRuleUtils.closeMergePartnerGoal;
import static de.uka.ilkd.key.util.mergerule.MergeRuleUtils.getConjunctiveElementsFor;
@@ -355,7 +356,7 @@ protected Triple, LinkedHashSet infFlowSpecs =
spec.getInfFlowSpecs(heap, self, atPres, services);
@@ -235,7 +239,8 @@ public void performActionOnLoopInvariant(final LoopSpecification spec) {
newInfFlowSpecs.put(heap, infFlowSpecs);
}
if (heap != services.getTypeConverter().getHeapLDT().getSavedHeap()
- || !tb.strictlyNothing().equalsModIrrelevantTermLabels(freeTerm)) {
+ || !tb.strictlyNothing().equalsModProperty(
+ freeTerm, IRRELEVANT_TERM_LABELS_PROPERTY)) {
final Term m = spec.getFreeModifies(heap, selfTerm, atPres, services);
final ImmutableList infFlowSpecs =
spec.getInfFlowSpecs(heap, selfTerm, atPres, services);
diff --git a/key.core/src/main/java/de/uka/ilkd/key/smt/AbstractSMTTranslator.java b/key.core/src/main/java/de/uka/ilkd/key/smt/AbstractSMTTranslator.java
index d1a38ae7f56..ab4ef549899 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/smt/AbstractSMTTranslator.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/smt/AbstractSMTTranslator.java
@@ -28,6 +28,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
import static de.uka.ilkd.key.smt.SMTProblem.sequentToTerm;
/**
@@ -1820,12 +1821,13 @@ private StringBuilder translateAsBindingUninterpretedPredicate(Term term, Functi
for (int i = 0; i < t.arity(); i++) {
// the terms only have to match on those positions where functions are defined
if (fun.bindVarsAt(i)) {
- termsMatch = termsMatch && t.sub(i).equalsModRenaming(term.sub(i));
+ termsMatch = termsMatch
+ && t.sub(i).equalsModProperty(term.sub(i), RENAMING_PROPERTY);
}
}
// the terms also match, if the entire sequence matches
- termsMatch = (termsMatch || t.equalsModRenaming(term));
+ termsMatch = (termsMatch || t.equalsModProperty(term, RENAMING_PROPERTY));
if (termsMatch) {
used = t;
@@ -1929,12 +1931,13 @@ private StringBuilder translateAsBindingUninterpretedFunction(Term term, Functio
for (int i = 0; i < t.arity(); i++) {
// the terms only have to match on those positions where functions are defined
if (fun.bindVarsAt(i)) {
- termsMatch = termsMatch && t.sub(i).equalsModRenaming(term.sub(i));
+ termsMatch = termsMatch
+ && t.sub(i).equalsModProperty(term.sub(i), RENAMING_PROPERTY);
}
}
// the terms also match, if the entire terms match
- termsMatch = (termsMatch || t.equalsModRenaming(term));
+ termsMatch = (termsMatch || t.equalsModProperty(term, RENAMING_PROPERTY));
if (termsMatch) {
used = t;
@@ -2103,7 +2106,7 @@ private StringBuilder getModalityPredicate(Term t, List qu
Services services) throws IllegalFormulaException {
// check, if the modality was already translated.
for (Term toMatch : modalityPredicates.keySet()) {
- if (toMatch.equalsModRenaming(t)) {
+ if (toMatch.equalsModProperty(t, RENAMING_PROPERTY)) {
return modalityPredicates.get(toMatch);
}
}
@@ -2253,7 +2256,7 @@ protected final StringBuilder translateBsumFunction(Term bsumterm,
ArrayList sub) {
StringBuilder name = null;
for (Term t : usedBsumTerms.keySet()) {
- if (t.equalsModRenaming(bsumterm)) {
+ if (t.equalsModProperty(bsumterm, RENAMING_PROPERTY)) {
name = usedBsumTerms.get(t);
}
}
@@ -2291,7 +2294,7 @@ protected final StringBuilder translateBprodFunction(Term bprodterm,
ArrayList sub) {
StringBuilder name = null;
for (Term t : usedBprodTerms.keySet()) {
- if (t.equalsModRenaming(bprodterm)) {
+ if (t.equalsModProperty(bprodterm, RENAMING_PROPERTY)) {
name = usedBprodTerms.get(t);
}
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/smt/newsmt2/SeqDefHandler.java b/key.core/src/main/java/de/uka/ilkd/key/smt/newsmt2/SeqDefHandler.java
index aef41ad8be5..94955fcca09 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/smt/newsmt2/SeqDefHandler.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/smt/newsmt2/SeqDefHandler.java
@@ -19,6 +19,8 @@
import org.key_project.util.collection.DefaultImmutableSet;
import org.key_project.util.collection.ImmutableSet;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
/**
* This handler handles the seqDef binder function specially.
*
@@ -68,7 +70,7 @@ public SExpr handle(MasterHandler trans, Term term) throws SMTTranslationExcepti
(Map) state.computeIfAbsent("SEQDEF_MAP", x -> new LinkedHashMap<>());
for (Entry entry : seqDefMap.entrySet()) {
- if (entry.getKey().equalsModRenaming(term)) {
+ if (entry.getKey().equalsModProperty(term, RENAMING_PROPERTY)) {
return entry.getValue();
}
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/smt/newsmt2/SumProdHandler.java b/key.core/src/main/java/de/uka/ilkd/key/smt/newsmt2/SumProdHandler.java
index 5825107e560..953b63ab71f 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/smt/newsmt2/SumProdHandler.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/smt/newsmt2/SumProdHandler.java
@@ -12,6 +12,8 @@
import org.key_project.logic.op.Function;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
// W I P
public class SumProdHandler implements SMTHandler {
@@ -42,7 +44,7 @@ public SExpr handle(MasterHandler trans, Term term) throws SMTTranslationExcepti
Operator op = term.op();
if (op == bsumOp) {
for (Term t : usedBsumTerms.keySet()) {
- if (t.equalsModRenaming(term)) {
+ if (t.equalsModProperty(term, RENAMING_PROPERTY)) {
return usedBsumTerms.get(t);
}
}
@@ -56,7 +58,7 @@ public SExpr handle(MasterHandler trans, Term term) throws SMTTranslationExcepti
return ret;
} else if (op == bprodOp) {
for (Term t : usedBprodTerms.keySet()) {
- if (t.equalsModRenaming(term)) {
+ if (t.equalsModProperty(term, RENAMING_PROPERTY)) {
return usedBprodTerms.get(t);
}
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/speclang/ContractFactory.java b/key.core/src/main/java/de/uka/ilkd/key/speclang/ContractFactory.java
index 036b6f71a39..76b0354a362 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/speclang/ContractFactory.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/speclang/ContractFactory.java
@@ -27,6 +27,7 @@
import org.key_project.util.collection.ImmutableArray;
import org.key_project.util.collection.ImmutableList;
+import static de.uka.ilkd.key.logic.equality.TermLabelsProperty.TERM_LABELS_PROPERTY;
import static de.uka.ilkd.key.logic.label.OriginTermLabel.*;
/**
@@ -461,7 +462,7 @@ private static void combineModifies(FunctionalOperationContractImpl t,
// check if the other mod is the same as the one in the uniform store.
// To obtain meaningful results, check for equality ignoring all term labels!
if (uniformMod.containsKey(h)) {
- if (!uniformMod.get(h).equalsModTermLabels(m2)) {
+ if (!uniformMod.get(h).equalsModProperty(m2, TERM_LABELS_PROPERTY)) {
uniformMod.remove(h);
} else {
// merge term labels (in particular origin labels) of both modifies
diff --git a/key.core/src/main/java/de/uka/ilkd/key/speclang/FunctionalOperationContractImpl.java b/key.core/src/main/java/de/uka/ilkd/key/speclang/FunctionalOperationContractImpl.java
index 327b66800cc..d586923e746 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/speclang/FunctionalOperationContractImpl.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/speclang/FunctionalOperationContractImpl.java
@@ -34,6 +34,7 @@
import org.key_project.util.collection.ImmutableSLList;
import org.key_project.util.java.MapUtil;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
import static de.uka.ilkd.key.util.Assert.assertEqualSort;
import static de.uka.ilkd.key.util.Assert.assertSubSort;
@@ -1367,14 +1368,16 @@ public String toString() {
((Services) services).getTypeConverter().getHeapLDT().getHeap();
return (globalDefs == null ? "" : "defs: " + globalDefs + "; ") + "pre: " + originalPres
+ (originalFreePres.get(heap) != null
- && !originalFreePres.get(heap).equalsModRenaming(tb.tt())
- ? "free pre: " + originalFreePres
- : "")
+ && !originalFreePres.get(heap).equalsModProperty(tb.tt(),
+ RENAMING_PROPERTY)
+ ? "free pre: " + originalFreePres
+ : "")
+ "; mby: " + originalMby + "; post: " + originalPosts
+ (originalFreePosts.get(heap) != null
- && !originalFreePosts.get(heap).equalsModRenaming(tb.tt())
- ? "free post: " + originalFreePosts
- : "")
+ && !originalFreePosts.get(heap).equalsModProperty(tb.tt(),
+ RENAMING_PROPERTY)
+ ? "free post: " + originalFreePosts
+ : "")
+ "; mods: " + originalMods + "; hasMod: " + hasRealModifiesClause
+ (originalAxioms != null && originalAxioms.size() > 0 ? ("; axioms: " + originalAxioms)
: "")
diff --git a/key.core/src/main/java/de/uka/ilkd/key/speclang/SLEnvInput.java b/key.core/src/main/java/de/uka/ilkd/key/speclang/SLEnvInput.java
index 52b5c84e6e3..c2b596da09d 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/speclang/SLEnvInput.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/speclang/SLEnvInput.java
@@ -20,6 +20,7 @@
import de.uka.ilkd.key.java.ast.statement.LabeledStatement;
import de.uka.ilkd.key.java.ast.statement.LoopStatement;
import de.uka.ilkd.key.java.ast.statement.MergePointStatement;
+import de.uka.ilkd.key.java.statement.SetStatement;
import de.uka.ilkd.key.java.visitor.JavaASTCollector;
import de.uka.ilkd.key.java.visitor.JavaASTWalker;
import de.uka.ilkd.key.logic.op.IProgramMethod;
@@ -234,18 +235,32 @@ private void addLabeledLoopContracts(SpecExtractor specExtractor,
}
}
- private void transformJmlAsserts(final IProgramMethod pm) {
+ private void transformProgramElements(final IProgramMethod pm) throws ProofInputException {
Services services = initConfig.getServices();
JMLSpecFactory jsf = new JMLSpecFactory(services);
- JavaASTWalker walker = new JavaASTWalker(pm.getBody()) {
+ var walker = new JavaASTWalker(pm.getBody()) {
+ public ProofInputException exception = null;
+
@Override
protected void doAction(final ProgramElement node) {
- if (node instanceof JmlAssert) {
- jsf.translateJmlAssertCondition((JmlAssert) node, pm);
+ try {
+ if (node instanceof JmlAssert) {
+ jsf.translateJmlAssertCondition((JmlAssert) node, pm);
+ } else if (node instanceof SetStatement) {
+ jsf.translateSetStatement((SetStatement) node, pm);
+ }
+ } catch (ProofInputException e) {
+ // Store the first exception that occurred
+ if (this.exception == null) {
+ this.exception = e;
+ }
}
}
};
walker.start();
+ if (walker.exception != null) {
+ throw walker.exception;
+ }
}
private ImmutableSet createSpecs(SpecExtractor specExtractor)
@@ -300,7 +315,7 @@ private ImmutableSet createSpecs(SpecExtractor specExtractor)
addMergePointStatements(specExtractor, specRepos, pm, params);
addLabeledBlockContracts(specExtractor, specRepos, pm);
addLabeledLoopContracts(specExtractor, specRepos, pm);
- transformJmlAsserts(pm);
+ transformProgramElements(pm);
}
// constructor contracts
diff --git a/key.core/src/main/java/de/uka/ilkd/key/speclang/WellDefinednessCheck.java b/key.core/src/main/java/de/uka/ilkd/key/speclang/WellDefinednessCheck.java
index 106872006df..a1dafc3a0a8 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/speclang/WellDefinednessCheck.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/speclang/WellDefinednessCheck.java
@@ -35,6 +35,8 @@
import org.key_project.util.collection.ImmutableSLList;
import org.key_project.util.collection.Pair;
+import static de.uka.ilkd.key.logic.equality.IrrelevantTermLabelsProperty.IRRELEVANT_TERM_LABELS_PROPERTY;
+
/**
* A contract for checking the well-definedness of a jml specification element (i.e. a class
* invariant, a method contract, a model field or any jml statement), consisting of precondition,
@@ -390,8 +392,9 @@ private String getText(boolean includeHtmlMarkup, Services services) {
final boolean showSig = !isInv && !modelField();
if (getAssignable() != null && showSig) {
String printMods = LogicPrinter.quickPrintTerm(
- getAssignable(null).equalsModIrrelevantTermLabels(TB.strictlyNothing()) ? TB.empty()
- : this.getAssignable(null),
+ getAssignable(null).equalsModProperty(TB.strictlyNothing(),
+ IRRELEVANT_TERM_LABELS_PROPERTY) ? TB.empty()
+ : this.getAssignable(null),
services);
mods = mods + (includeHtmlMarkup ? "
" : "\n") + "mod"
+ (includeHtmlMarkup ? " " : ": ")
@@ -722,19 +725,26 @@ final void setRequires(Term req) {
final void setAssignable(Term ass, TermServices services) {
this.assignable = ass;
- if (ass == null || TB.strictlyNothing().equalsModIrrelevantTermLabels(ass)
- || TB.FALSE().equalsModIrrelevantTermLabels(ass)) {
+ if (ass == null
+ || TB.strictlyNothing().equalsModProperty(
+ ass, IRRELEVANT_TERM_LABELS_PROPERTY)
+ || TB.FALSE().equalsModProperty(
+ ass, IRRELEVANT_TERM_LABELS_PROPERTY)) {
this.assignable = TB.strictlyNothing();
- } else if (TB.tt().equalsModIrrelevantTermLabels(ass)
- || TB.TRUE().equalsModIrrelevantTermLabels(ass)) {
+ } else if (TB.tt().equalsModProperty(
+ ass, IRRELEVANT_TERM_LABELS_PROPERTY)
+ || TB.TRUE().equalsModProperty(
+ ass, IRRELEVANT_TERM_LABELS_PROPERTY)) {
this.assignable = TB.allLocs();
}
}
final void combineAssignable(Term ass1, Term ass2, TermServices services) {
- if (ass1 == null || TB.strictlyNothing().equalsModIrrelevantTermLabels(ass1)) {
+ if (ass1 == null || TB.strictlyNothing().equalsModProperty(
+ ass1, IRRELEVANT_TERM_LABELS_PROPERTY)) {
setAssignable(ass2, services);
- } else if (ass2 == null || TB.strictlyNothing().equalsModIrrelevantTermLabels(ass2)) {
+ } else if (ass2 == null || TB.strictlyNothing().equalsModProperty(
+ ass2, IRRELEVANT_TERM_LABELS_PROPERTY)) {
setAssignable(ass1, services);
} else {
setAssignable(TB.union(ass1, ass2), services);
@@ -995,9 +1005,11 @@ public final Term getPost(final Condition post, ParsableVariable result,
public final Term getUpdates(Term mod, LocationVariable heap, ProgramVariable heapAtPre,
Term anonHeap, TermServices services) {
assert mod != null;
- assert anonHeap != null || TB.strictlyNothing().equalsModIrrelevantTermLabels(mod);
- final Term havocUpd = TB.strictlyNothing().equalsModIrrelevantTermLabels(mod) ? TB.skip()
- : TB.elementary(heap, TB.anon(TB.var(heap), mod, anonHeap));
+ assert anonHeap != null
+ || TB.strictlyNothing().equalsModProperty(mod, IRRELEVANT_TERM_LABELS_PROPERTY);
+ final Term havocUpd =
+ TB.strictlyNothing().equalsModProperty(mod, IRRELEVANT_TERM_LABELS_PROPERTY) ? TB.skip()
+ : TB.elementary(heap, TB.anon(TB.var(heap), mod, anonHeap));
final Term oldUpd =
heapAtPre != heap ? TB.elementary(TB.var(heapAtPre), TB.var(heap)) : TB.skip();
return TB.parallel(oldUpd, havocUpd);
diff --git a/key.core/src/main/java/de/uka/ilkd/key/speclang/jml/pretranslation/TextualJMLAssertStatement.java b/key.core/src/main/java/de/uka/ilkd/key/speclang/jml/pretranslation/TextualJMLAssertStatement.java
index 08e635fa08d..849b3f45190 100755
--- a/key.core/src/main/java/de/uka/ilkd/key/speclang/jml/pretranslation/TextualJMLAssertStatement.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/speclang/jml/pretranslation/TextualJMLAssertStatement.java
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: GPL-2.0-only */
package de.uka.ilkd.key.speclang.jml.pretranslation;
-import de.uka.ilkd.key.speclang.njml.LabeledParserRuleContext;
+import de.uka.ilkd.key.nparser.KeyAst;
import org.key_project.util.collection.ImmutableSLList;
@@ -13,17 +13,16 @@
* A JML assert/assume statement.
*/
public class TextualJMLAssertStatement extends TextualJMLConstruct {
-
- private final LabeledParserRuleContext context;
+ private final KeyAst.Expression context;
private final Kind kind;
- public TextualJMLAssertStatement(Kind kind, LabeledParserRuleContext clause) {
+ public TextualJMLAssertStatement(Kind kind, KeyAst.Expression clause) {
super(ImmutableSLList.nil(), kind.toString() + " " + clause);
this.kind = kind;
this.context = clause;
}
- public LabeledParserRuleContext getContext() {
+ public KeyAst.Expression getContext() {
return context;
}
@@ -52,9 +51,12 @@ public static void ruleContextToText(StringBuilder builder, RuleContext context)
}
public String getClauseText() {
- var builder = new StringBuilder();
- ruleContextToText(builder, context.first);
- return builder.substring(kind.toString().length());
+ return context.getText();
+ /*
+ * var builder = new StringBuilder();
+ * ruleContextToText(builder, context);
+ * return builder.substring(kind.toString().length());
+ */
}
public Kind getKind() {
diff --git a/key.core/src/main/java/de/uka/ilkd/key/speclang/jml/translation/JMLSpecFactory.java b/key.core/src/main/java/de/uka/ilkd/key/speclang/jml/translation/JMLSpecFactory.java
index e52c56b48e0..0e2969608b0 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/speclang/jml/translation/JMLSpecFactory.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/speclang/jml/translation/JMLSpecFactory.java
@@ -19,6 +19,10 @@
import de.uka.ilkd.key.java.ast.declaration.modifier.Public;
import de.uka.ilkd.key.java.ast.declaration.modifier.VisibilityModifier;
import de.uka.ilkd.key.java.ast.statement.*;
+import de.uka.ilkd.key.java.statement.SetStatement;
+import de.uka.ilkd.key.ldt.HeapLDT;
+import de.uka.ilkd.key.ldt.HeapLDT.SplitFieldName;
+import de.uka.ilkd.key.ldt.JavaDLTheory;
import de.uka.ilkd.key.logic.ProgramElementName;
import de.uka.ilkd.key.logic.Term;
import de.uka.ilkd.key.logic.TermBuilder;
@@ -26,7 +30,9 @@
import de.uka.ilkd.key.logic.label.OriginTermLabel.SpecType;
import de.uka.ilkd.key.logic.label.ParameterlessTermLabel;
import de.uka.ilkd.key.logic.op.*;
+import de.uka.ilkd.key.nparser.KeyAst;
import de.uka.ilkd.key.parser.Location;
+import de.uka.ilkd.key.proof.mgt.SpecificationRepository;
import de.uka.ilkd.key.rule.merge.MergeProcedure;
import de.uka.ilkd.key.rule.merge.procedures.MergeByIfThenElse;
import de.uka.ilkd.key.rule.merge.procedures.MergeWithPredicateAbstraction;
@@ -52,6 +58,8 @@
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
+import static de.uka.ilkd.key.logic.equality.IrrelevantTermLabelsProperty.IRRELEVANT_TERM_LABELS_PROPERTY;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
import static de.uka.ilkd.key.speclang.jml.pretranslation.TextualJMLSpecCase.Clause.DIVERGES;
import static de.uka.ilkd.key.speclang.jml.pretranslation.TextualJMLSpecCase.Clause.SIGNALS;
import static de.uka.ilkd.key.speclang.jml.pretranslation.TextualJMLSpecCase.ClauseHd.ENSURES;
@@ -148,7 +156,7 @@ private static Map translateToTermFreeInvariants(Context
} else {
freeInvariant = tb.tt();
for (LabeledParserRuleContext expr : originalFreeInvariant) {
- Term translated = new JmlIO().services(services).context(context)
+ Term translated = new JmlIO(services).context(context)
.parameters(allVars).atPres(atPres).atBefore(atPres)
.translateTerm(expr, SpecType.LOOP_INVARIANT_FREE);
freeInvariant = tb.andSC(freeInvariant, tb.convertToFormula(translated));
@@ -421,7 +429,7 @@ private void translateAccessible(Context context, ProgramVariableCollection prog
private void translateAxioms(Context context, ProgramVariableCollection progVars,
LocationVariable heap, ImmutableList axioms,
- ContractClauses clauses, Behavior originalBehavior) throws SLTranslationException {
+ ContractClauses clauses, Behavior originalBehavior) {
boolean empty = axioms.isEmpty() // either the list is empty
|| (axioms.size() == 1 // or the first element is an empty method_decl
&& axioms.head().first instanceof JmlParser.Method_declarationContext
@@ -440,7 +448,7 @@ private void translateEnsures(Context context, ProgramVariableCollection progVar
LocationVariable heap, final LocationVariable savedHeap,
ImmutableList ensures,
ImmutableList ensuresFree, ContractClauses clauses,
- Behavior originalBehavior) throws SLTranslationException {
+ Behavior originalBehavior) {
if (heap == savedHeap && ensures.isEmpty()) {
clauses.ensures.put(heap, null);
} else {
@@ -626,7 +634,8 @@ private Term translateUnionClauses(Context context, ImmutableList 1) {
throw new SLTranslationException(
"\"assignable \\less_than_nothing\" does not go with other "
@@ -705,8 +714,7 @@ private Term translateSignals(Context context, ImmutableList pa
}
private Term translateSignalsOnly(Context context, ProgramVariable excVar,
- Behavior originalBehavior, ImmutableList originalClauses)
- throws SLTranslationException {
+ Behavior originalBehavior, ImmutableList originalClauses) {
return translateSignals(context, null, null, excVar, null, null, originalBehavior,
originalClauses);
}
@@ -769,7 +777,8 @@ private boolean translateStrictlyPure(Context context, ImmutableList createDependencyOperationContract(IProgramMethod
boolean createContract = true;
for (LocationVariable heap : HeapContext.getModHeaps(services, false)) {
- if (clauses.accessibles.get(heap).equalsModRenaming(tb.allLocs())) {
+ if (clauses.accessibles.get(heap).equalsModProperty(tb.allLocs(),
+ RENAMING_PROPERTY)) {
createContract = false;
break;
}
if (pm.isModel() && pm.getStateCount() > 1) {
if (clauses.accessibles.get(progVars.atPreVars.get(heap))
- .equalsModRenaming(tb.allLocs())) {
+ .equalsModProperty(tb.allLocs(), RENAMING_PROPERTY)) {
createContract = false;
break;
}
@@ -1383,13 +1393,8 @@ public ImmutableSet createJMLLoopContracts(IProgramMethod method,
.create();
}
- /**
- * Translates the condition Term of a JmlAssert statement.
- *
- * @param jmlAssert the statement to create the condition for
- * @param pm the enclosing method
- */
- public void translateJmlAssertCondition(final JmlAssert jmlAssert, final IProgramMethod pm) {
+ private ProgramVariableCollection createProgramVariablesForStatement(Statement statement,
+ IProgramMethod pm) {
final Map atPreVars = new LinkedHashMap<>();
for (LocationVariable heap : services.getTypeConverter().getHeapLDT().getAllHeaps()) {
atPreVars.put(heap, tb.atPreVar(heap.toString(), heap.sort(), true));
@@ -1400,19 +1405,94 @@ public void translateJmlAssertCondition(final JmlAssert jmlAssert, final IProgra
tb.atPreVar(parameter.toString(), parameter.getKeYJavaType(), true));
}
final ImmutableList paramVars =
- append(collectLocalVariablesVisibleTo(jmlAssert, pm), parameters);
- final ProgramVariableCollection pv = new ProgramVariableCollection(
- tb.selfVar(pm, pm.getContainerType(), false), paramVars, tb.resultVar(pm, false),
- tb.excVar(pm, false), atPreVars, termify(atPreVars), Collections.emptyMap(), // should
- // be the
- // pre-state
- // of the
- // enclosing
- // contract
+ append(collectLocalVariablesVisibleTo(statement, pm), parameters);
+ return new ProgramVariableCollection(tb.selfVar(pm, pm.getContainerType(), false),
+ paramVars, tb.resultVar(pm, false), tb.excVar(pm, false), atPreVars, termify(atPreVars),
+ Collections.emptyMap(), // should be the pre-state of the enclosing contract
Collections.emptyMap() // ignore for now
);
- var io = new JmlIO(services).context(Context.inMethodWithSelfVar(pm, pv.selfVar));
- jmlAssert.translateCondition(io, pv);
+ }
+
+ /**
+ * Translates the condition Term of a JmlAssert statement.
+ *
+ * @param jmlAssert the statement to create the condition for
+ * @param pm the enclosing method
+ */
+ public void translateJmlAssertCondition(final JmlAssert jmlAssert, final IProgramMethod pm) {
+ final var pv = createProgramVariablesForStatement(jmlAssert, pm);
+ var io = new JmlIO(services).context(Context.inMethod(pm, tb))
+ .selfVar(pv.selfVar)
+ .parameters(pv.paramVars)
+ .resultVariable(pv.resultVar)
+ .exceptionVariable(pv.excVar)
+ .atPres(pv.atPres)
+ .atBefore(pv.atBefores);
+ Term expr = io.translateTerm(jmlAssert.getCondition());
+ services.getSpecificationRepository().addStatementSpec(
+ jmlAssert,
+ new SpecificationRepository.JmlStatementSpec(pv, ImmutableList.of(expr)));
+ }
+
+ public @Nullable String checkSetStatementAssignee(Term assignee) {
+ if (assignee.op() instanceof LocationVariable) {
+ var variable = (LocationVariable) assignee.op();
+ if (variable.isGhost()) {
+ return null;
+ } else {
+ return variable + " is not a ghost variable";
+ }
+ } else if (services.getTypeConverter().getHeapLDT().isSelectOp(assignee.op())) {
+ Term field = assignee.subs().last();
+ Operator op = field.op();
+ SplitFieldName split = HeapLDT.trySplitFieldName(op);
+ if (split != null) {
+ ProgramVariable attribute =
+ services.getJavaInfo().getAttribute(split.attributeName(), split.className());
+ if (attribute.isGhost()) {
+ return null;
+ } else {
+ return op + " is not a ghost field";
+ }
+ } else if (op.equals(services.getTypeConverter().getHeapLDT().getArr())) {
+ return "Arrays are not writeable using set statements";
+ } else {
+ return op + " is not a class field";
+ }
+ } else {
+ return "Neither a field access nor a local variable access";
+ }
+ }
+
+ /**
+ * Translates a set statement.
+ *
+ * @param statement the set statement
+ * @param pm the enclosing method
+ */
+ public void translateSetStatement(final SetStatement statement, final IProgramMethod pm)
+ throws SLTranslationException {
+ final var pv = createProgramVariablesForStatement(statement, pm);
+ KeyAst.SetStatementContext setStatementContext = statement.getParserContext();
+ var io = new JmlIO(services).context(Context.inMethod(pm, tb)).selfVar(pv.selfVar)
+ .parameters(pv.paramVars)
+ .resultVariable(pv.resultVar).exceptionVariable(pv.excVar).atPres(pv.atPres)
+ .atBefore(pv.atBefores);
+ Term assignee = io.translateTerm(setStatementContext.getAssignee());
+ Term value = io.translateTerm(setStatementContext.getValue());
+ if (value.sort() == JavaDLTheory.FORMULA) {
+ value = tb.convertToBoolean(value);
+ }
+ String error = checkSetStatementAssignee(assignee);
+ if (error != null) {
+ throw new SLTranslationException(
+ "Invalid assignment target for set statement: " + error,
+ setStatementContext.getStartLocation());
+ }
+
+ services.getSpecificationRepository().addStatementSpec(
+ statement,
+ new SpecificationRepository.JmlStatementSpec(pv, ImmutableList.of(assignee, value)));
}
/**
@@ -1423,7 +1503,6 @@ public void translateJmlAssertCondition(final JmlAssert jmlAssert, final IProgra
* @param method the method containing the block.
* @param block the block.
* @param variables an instance of {@link AuxiliaryContract.Variables} for the block.
- * @return
*/
private ProgramVariableCollection createProgramVariables(final IProgramMethod method,
final JavaStatement block, final AuxiliaryContract.Variables variables) {
diff --git a/key.core/src/main/java/de/uka/ilkd/key/speclang/njml/JmlIO.java b/key.core/src/main/java/de/uka/ilkd/key/speclang/njml/JmlIO.java
index e5fb0dce4a9..52a909ce046 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/speclang/njml/JmlIO.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/speclang/njml/JmlIO.java
@@ -13,6 +13,8 @@
import de.uka.ilkd.key.logic.op.IObserverFunction;
import de.uka.ilkd.key.logic.op.LocationVariable;
import de.uka.ilkd.key.logic.op.ProgramVariable;
+import de.uka.ilkd.key.nparser.KeyAst;
+import de.uka.ilkd.key.nparser.ParsingFacade;
import de.uka.ilkd.key.speclang.PositionedString;
import de.uka.ilkd.key.speclang.jml.translation.Context;
import de.uka.ilkd.key.speclang.translation.SLExpression;
@@ -26,6 +28,7 @@
import org.antlr.v4.runtime.ParserRuleContext;
import org.jspecify.annotations.NonNull;
+import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/**
@@ -43,26 +46,29 @@
* @version 1 (7/1/20)
* @see Translator
*/
+@NullMarked
public class JmlIO {
private ImmutableList warnings = ImmutableSLList.nil();
- private Services services;
+ private final Services services;
+
+ @Nullable
private KeYJavaType specInClass;
+ @Nullable
private ProgramVariable selfVar;
+ @Nullable
private SpecMathMode specMathMode;
+ @Nullable
private ImmutableList paramVars;
+ @Nullable
private ProgramVariable resultVar;
+ @Nullable
private ProgramVariable excVar;
+ @Nullable
private Map atPres;
+ @Nullable
private Map atBefores;
- /**
- * Generate an empty jml i/o instance. No very useful until a {@link #services(Services)} is
- * provided.
- */
- public JmlIO() {
- }
-
/**
* Generate an empty jml i/o instance.
*
@@ -84,7 +90,7 @@ public JmlIO(Services services) {
* @param atPres i do not know
* @param atBefores i do not know
*/
- public JmlIO(@NonNull Services services, @Nullable KeYJavaType specInClass,
+ public JmlIO(Services services, @Nullable KeYJavaType specInClass,
@Nullable ProgramVariable selfVar, @Nullable ImmutableList paramVars,
@Nullable ProgramVariable resultVar, @Nullable ProgramVariable excVar,
@Nullable Map atPres,
@@ -186,7 +192,14 @@ private Object interpret(ParserRuleContext ctx) {
/**
* Interpret the given parse tree as an JML expression in the current context.
*/
- public @NonNull Term translateTerm(@NonNull ParserRuleContext expr) {
+ public Term translateTerm(KeyAst.Expression expr) {
+ return translateTerm(ParsingFacade.getParseRuleContext(expr));
+ }
+
+ /**
+ * Interpret the given parse tree as an JML expression in the current context.
+ */
+ public Term translateTerm(ParserRuleContext expr) {
Object interpret = interpret(expr);
if (interpret instanceof SLExpression) {
return ((SLExpression) interpret).getTerm();
@@ -313,7 +326,7 @@ public Triple translateDependencyContract(
/**
* Sets the variable representing the {@code this} reference.
*/
- public JmlIO selfVar(ProgramVariable selfVar) {
+ public JmlIO selfVar(@Nullable ProgramVariable selfVar) {
this.selfVar = selfVar;
return this;
}
@@ -337,12 +350,12 @@ public JmlIO parameters(ImmutableList params) {
/**
* Sets the variable that is used to store exceptions.
*/
- public JmlIO exceptionVariable(ProgramVariable excVar) {
+ public JmlIO exceptionVariable(@Nullable ProgramVariable excVar) {
this.excVar = excVar;
return this;
}
- public JmlIO atPres(Map atPres) {
+ public JmlIO atPres(@Nullable Map atPres) {
this.atPres = atPres;
return this;
}
@@ -350,34 +363,26 @@ public JmlIO atPres(Map atPres) {
/**
* Sets the variable representing {@code \result}.
*/
- public JmlIO resultVariable(ProgramVariable resultVar) {
+ public JmlIO resultVariable(@Nullable ProgramVariable resultVar) {
this.resultVar = resultVar;
return this;
}
- /**
- * Sets the current services
- */
- public JmlIO services(Services services) {
- this.services = services;
- return this;
- }
-
/**
* Sets the sort/type of the class containing the interpreted JML.
*/
- public JmlIO classType(KeYJavaType classType) {
+ public JmlIO classType(@Nullable KeYJavaType classType) {
this.specInClass = classType;
return this;
}
- public JmlIO atBefore(Map atBefores) {
+ public JmlIO atBefore(@Nullable Map atBefores) {
this.atBefores = atBefores;
return this;
}
/**
- * Sets class type, spec math mode and self var.
+ * Sets class type, spec math mode and selfVar.
*/
public JmlIO context(Context context) {
this.classType(context.classType());
diff --git a/key.core/src/main/java/de/uka/ilkd/key/speclang/njml/PreParser.java b/key.core/src/main/java/de/uka/ilkd/key/speclang/njml/PreParser.java
index fa88eebbd8c..6b761b34a1e 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/speclang/njml/PreParser.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/speclang/njml/PreParser.java
@@ -18,6 +18,7 @@
import org.antlr.v4.runtime.ParserRuleContext;
import org.jspecify.annotations.NonNull;
+import org.jspecify.annotations.Nullable;
public class PreParser {
/** warnings */
@@ -92,7 +93,7 @@ private ImmutableList parseMethodLevel(JmlLexer lexer) {
* Parse and interpret class level comments.
*/
public ImmutableList parseClassLevel(String concatenatedComment,
- URI fileName, Position pos) {
+ @Nullable URI fileName, Position pos) {
return parseClassLevel(
new PositionedString(concatenatedComment, new Location(fileName, pos)));
}
@@ -109,7 +110,7 @@ private ImmutableList parseClassLevel(PositionedString posi
* Parse and interpret the given string as a method level construct.
*/
public ImmutableList parseMethodLevel(String concatenatedComment,
- URI fileName, Position position) {
+ @Nullable URI fileName, Position position) {
return parseMethodLevel(
new PositionedString(concatenatedComment, new Location(fileName, position)));
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/speclang/njml/TextualTranslator.java b/key.core/src/main/java/de/uka/ilkd/key/speclang/njml/TextualTranslator.java
index 386b7740614..50da06e90cf 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/speclang/njml/TextualTranslator.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/speclang/njml/TextualTranslator.java
@@ -5,6 +5,7 @@
import de.uka.ilkd.key.ldt.HeapLDT;
import de.uka.ilkd.key.logic.label.OriginTermLabel;
+import de.uka.ilkd.key.nparser.KeyAst;
import de.uka.ilkd.key.speclang.jml.pretranslation.*;
import org.key_project.logic.Name;
@@ -492,8 +493,7 @@ public Object visitLoop_invariant(JmlParser.Loop_invariantContext ctx) {
public Object visitAssume_statement(JmlParser.Assume_statementContext ctx) {
TextualJMLAssertStatement b =
new TextualJMLAssertStatement(TextualJMLAssertStatement.Kind.ASSUME,
- LabeledParserRuleContext.createLabeledParserRuleContext(ctx,
- OriginTermLabel.SpecType.ASSUME, attachOriginLabel));
+ new KeyAst.Expression(ctx.expression()));
constructs = constructs.append(b);
return null;
}
@@ -501,10 +501,8 @@ public Object visitAssume_statement(JmlParser.Assume_statementContext ctx) {
@Override
public Object visitAssert_statement(JmlParser.Assert_statementContext ctx) {
- TextualJMLAssertStatement b =
- new TextualJMLAssertStatement(TextualJMLAssertStatement.Kind.ASSERT,
- LabeledParserRuleContext.createLabeledParserRuleContext(ctx,
- OriginTermLabel.SpecType.ASSERT, attachOriginLabel));
+ TextualJMLAssertStatement b = new TextualJMLAssertStatement(
+ TextualJMLAssertStatement.Kind.ASSERT, new KeyAst.Expression(ctx.expression()));
constructs = constructs.append(b);
return null;
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/speclang/njml/Translator.java b/key.core/src/main/java/de/uka/ilkd/key/speclang/njml/Translator.java
index a3cfb32a8c2..0a798498eeb 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/speclang/njml/Translator.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/speclang/njml/Translator.java
@@ -1695,13 +1695,8 @@ public Object visitSequenceReplace(JmlParser.SequenceReplaceContext ctx) {
final Term minusOne = tb.zTerm("-1");
assert e2 != null;
assert e1 != null;
- final Term ante = tb.seqSub(e1.getTerm(), tb.zero(), tb.add(e2.getTerm(), minusOne));
- assert e3 != null;
- final Term insert = tb.seqSingleton(e3.getTerm());
- final Term post = tb.seqSub(e1.getTerm(), tb.add(e2.getTerm(), tb.one()),
- tb.add(tb.seqLen(e1.getTerm()), minusOne));
- final Term put = tb.seqConcat(ante, tb.seqConcat(insert, post));
- return new SLExpression(put);
+ Term updated = tb.seqUpd(e1.getTerm(), e2.getTerm(), e3.getTerm());
+ return new SLExpression(updated);
}
@Override
diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/FindTacletAppContainer.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/FindTacletAppContainer.java
index 30436ce2317..10313f11e9e 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/strategy/FindTacletAppContainer.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/FindTacletAppContainer.java
@@ -18,6 +18,8 @@
import org.key_project.util.collection.ImmutableList;
+import static de.uka.ilkd.key.logic.equality.IrrelevantTermLabelsProperty.IRRELEVANT_TERM_LABELS_PROPERTY;
+
/**
* Instances of this class are immutable
*/
@@ -132,7 +134,8 @@ private boolean independentSubformulas(PosInOccurrence changePos, SequentFormula
if (afterChangeTerm.op() instanceof Modality afterChangeMod) {
return beforeChangeMod.kind() == afterChangeMod.kind()
&& beforeChangeTerm.sub(0)
- .equalsModIrrelevantTermLabels(afterChangeTerm.sub(0));
+ .equalsModProperty(afterChangeTerm.sub(0),
+ IRRELEVANT_TERM_LABELS_PROPERTY);
} else {
return false;
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/ContainsTermFeature.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/ContainsTermFeature.java
index bbc99c47e8c..c614c7d47b5 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/ContainsTermFeature.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/ContainsTermFeature.java
@@ -14,6 +14,8 @@
import org.key_project.logic.Visitor;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
/**
* Feature for checking if the term of the first projection contains the term of the second
@@ -82,9 +84,7 @@ public boolean visitSubtree(Term visited) {
@Override
public void visit(Term visited) {
- // TODO: Fix with better equalsModRenaming handling
- var t = (Term) visited;
- found = found || t.equalsModRenaming(term);
+ found = found || visited.equalsModProperty(term, RENAMING_PROPERTY);
}
@Override
diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/DependencyContractFeature.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/DependencyContractFeature.java
index 6f1a1da1e56..6a84a3bd021 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/DependencyContractFeature.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/DependencyContractFeature.java
@@ -17,12 +17,15 @@
import org.key_project.util.collection.ImmutableSLList;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
public final class DependencyContractFeature extends BinaryFeature {
private void removePreviouslyUsedSteps(Term focus, Goal goal, List steps) {
for (RuleApp app : goal.appliedRuleApps()) {
if (app.rule() instanceof UseDependencyContractRule
- && app.posInOccurrence().subTerm().equalsModRenaming(focus)) {
+ && app.posInOccurrence().subTerm().equalsModProperty(focus,
+ RENAMING_PROPERTY)) {
final IBuiltInRuleApp bapp = (IBuiltInRuleApp) app;
for (PosInOccurrence ifInst : bapp.ifInsts()) {
steps.remove(ifInst);
diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/DiffFindAndReplacewithFeature.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/DiffFindAndReplacewithFeature.java
index ca6bcd57b1d..995a740e82e 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/DiffFindAndReplacewithFeature.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/DiffFindAndReplacewithFeature.java
@@ -11,6 +11,8 @@
import de.uka.ilkd.key.rule.tacletbuilder.RewriteTacletGoalTemplate;
import de.uka.ilkd.key.rule.tacletbuilder.TacletGoalTemplate;
+import static de.uka.ilkd.key.logic.equality.IrrelevantTermLabelsProperty.IRRELEVANT_TERM_LABELS_PROPERTY;
+
/**
* Binary feature that returns zero iff the replacewith- and find-parts of a Taclet are matched to
* different terms.
@@ -29,7 +31,8 @@ protected boolean filter(TacletApp app, PosInOccurrence pos, Goal goal, MutableS
for (TacletGoalTemplate temp : ((Taclet) app.rule()).goalTemplates()) {
RewriteTacletGoalTemplate rwtemp = (RewriteTacletGoalTemplate) temp;
- if (rwtemp.replaceWith().equalsModIrrelevantTermLabels(pos.subTerm())) {
+ if (rwtemp.replaceWith().equalsModProperty(pos.subTerm(),
+ IRRELEVANT_TERM_LABELS_PROPERTY)) {
return false;
}
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/FocusIsSubFormulaOfInfFlowContractAppFeature.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/FocusIsSubFormulaOfInfFlowContractAppFeature.java
index 196ffcab5ae..7f758b320d7 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/FocusIsSubFormulaOfInfFlowContractAppFeature.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/FocusIsSubFormulaOfInfFlowContractAppFeature.java
@@ -16,6 +16,8 @@
import org.key_project.util.collection.ImmutableList;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
/**
* Checks whether the focus of the ruleApp is contained in one of the formulas added by information
@@ -82,8 +84,7 @@ public SubFormulaVisitor(Term potentialSub) {
@Override
public void visit(Term visited) {
- var term = (Term) visited;
- isSubFormula |= term.equalsModRenaming(potentialSub);
+ isSubFormula |= visited.equalsModProperty(potentialSub, RENAMING_PROPERTY);
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/NonDuplicateAppModPositionFeature.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/NonDuplicateAppModPositionFeature.java
index 9c8de611c8b..7ab6c3849e4 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/NonDuplicateAppModPositionFeature.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/NonDuplicateAppModPositionFeature.java
@@ -10,6 +10,7 @@
import org.key_project.util.collection.ImmutableList;
+import static de.uka.ilkd.key.logic.equality.IrrelevantTermLabelsProperty.IRRELEVANT_TERM_LABELS_PROPERTY;
/**
* Binary feature that returns zero iff a certain Taclet app has not already been performed
@@ -23,7 +24,7 @@ protected boolean comparePio(TacletApp newApp, TacletApp oldApp, PosInOccurrence
PosInOccurrence oldPio) {
final Term newFocus = newPio.subTerm();
final Term oldFocus = oldPio.subTerm();
- if (!newFocus.equalsModIrrelevantTermLabels(oldFocus)) {
+ if (!newFocus.equalsModProperty(oldFocus, IRRELEVANT_TERM_LABELS_PROPERTY)) {
return false;
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/QueryExpandCost.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/QueryExpandCost.java
index 69da9cc525d..a7626199849 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/QueryExpandCost.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/feature/QueryExpandCost.java
@@ -24,6 +24,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static de.uka.ilkd.key.logic.equality.IrrelevantTermLabelsProperty.IRRELEVANT_TERM_LABELS_PROPERTY;
+
/**
* A Feature that computes the cost for using the query expand rule.
*
@@ -179,7 +181,8 @@ protected int queryExpandAlreadyAppliedAtPos(RuleApp app, PosInOccurrence pos, G
final Term oldterm = pio.subTerm();
final Term curterm = pos.subTerm();
if (appliedRuleApp.rule().equals(QueryExpand.INSTANCE)
- && oldterm.equalsModIrrelevantTermLabels(curterm)) {
+ && oldterm.equalsModProperty(curterm,
+ IRRELEVANT_TERM_LABELS_PROPERTY)) {
count++;
if (count > maxRepetitionsOnSameTerm) {
break;
diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/quantifierHeuristics/EqualityConstraint.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/quantifierHeuristics/EqualityConstraint.java
index cf61441a1cf..4ec10942fd7 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/strategy/quantifierHeuristics/EqualityConstraint.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/quantifierHeuristics/EqualityConstraint.java
@@ -13,6 +13,7 @@
import de.uka.ilkd.key.java.Services;
import de.uka.ilkd.key.logic.BooleanContainer;
import de.uka.ilkd.key.logic.Term;
+import de.uka.ilkd.key.logic.equality.RenamingProperty;
import de.uka.ilkd.key.logic.label.TermLabelState;
import de.uka.ilkd.key.logic.op.Operator;
import de.uka.ilkd.key.logic.op.ProgramVariable;
@@ -413,7 +414,8 @@ private static NameAbstractionTable handleJava(Term t0, Term t1, NameAbstraction
if (!t0.javaBlock().isEmpty() || !t1.javaBlock().isEmpty()) {
nat = checkNat(nat);
- if (!t0.javaBlock().equalsModRenaming(t1.javaBlock(), nat)) {
+ if (RenamingProperty.javaBlocksNotEqualModRenaming(t0.javaBlock(), t1.javaBlock(),
+ nat)) {
return FAILED;
}
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/quantifierHeuristics/HandleArith.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/quantifierHeuristics/HandleArith.java
index 187f7acf3f8..be6254ffe59 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/strategy/quantifierHeuristics/HandleArith.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/quantifierHeuristics/HandleArith.java
@@ -15,6 +15,8 @@
import org.key_project.util.LRUCache;
import org.key_project.util.collection.Pair;
+import static de.uka.ilkd.key.logic.equality.IrrelevantTermLabelsProperty.IRRELEVANT_TERM_LABELS_PROPERTY;
+
/**
* This class is used to prove some simple arithmetic problem which are {@code a==b}, {@code a>=b},
* {@code a<=b}; Besides it can be used to prove that {@code a>=b} or {@code a<=b} by
@@ -50,7 +52,7 @@ public static Term provedByArith(Term problem, Services services) {
final Term falseT = tb.ff();
final Term arithTerm = formatArithTerm(problem, tb, integerLDT, services.getCaches());
- if (arithTerm.equalsModIrrelevantTermLabels(falseT)) {
+ if (arithTerm.equalsModProperty(falseT, IRRELEVANT_TERM_LABELS_PROPERTY)) {
result = provedArithEqual(problem, tb, services);
putInTermCache(provedByArithCache, problem, result);
return result;
diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/quantifierHeuristics/PredictCostProver.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/quantifierHeuristics/PredictCostProver.java
index 1631242a033..a73630becb7 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/strategy/quantifierHeuristics/PredictCostProver.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/quantifierHeuristics/PredictCostProver.java
@@ -17,6 +17,9 @@
import org.key_project.util.collection.DefaultImmutableSet;
import org.key_project.util.collection.ImmutableSet;
+import static de.uka.ilkd.key.logic.equality.IrrelevantTermLabelsProperty.IRRELEVANT_TERM_LABELS_PROPERTY;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
/**
* TODO: rewrite, this seems pretty inefficient ...
*/
@@ -102,7 +105,7 @@ private Term provedBySelf(Term problem) {
op = pro.op();
}
if ((op == Equality.EQUALS || op == Equality.EQV)
- && pro.sub(0).equalsModRenaming(pro.sub(1))) {
+ && pro.sub(0).equalsModProperty(pro.sub(1), RENAMING_PROPERTY)) {
return negated ? falseT : trueT;
}
Term arithRes = HandleArith.provedByArith(pro, services);
@@ -130,7 +133,7 @@ private Term directConsequenceOrContradictionOfAxiom(Term problem, Term axiom) {
ax = ax.sub(0);
negated = !negated;
}
- if (pro.equalsModRenaming(ax)) {
+ if (pro.equalsModProperty(ax, RENAMING_PROPERTY)) {
return negated ? falseT : trueT;
}
return problem;
@@ -343,7 +346,8 @@ public boolean selfRefine(ImmutableSet lits) {
if (op == Junctor.TRUE) {
return true;
}
- if (op == Junctor.FALSE && terms[0].equalsModIrrelevantTermLabels(terms[j])) {
+ if (op == Junctor.FALSE
+ && terms[0].equalsModProperty(terms[j], IRRELEVANT_TERM_LABELS_PROPERTY)) {
next = next.remove(terms[j]);
literals = literals.remove(terms[j]);
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/termfeature/EqTermFeature.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/termfeature/EqTermFeature.java
index b5ea4a4938c..547fdf0f6d9 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/strategy/termfeature/EqTermFeature.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/termfeature/EqTermFeature.java
@@ -8,6 +8,8 @@
import de.uka.ilkd.key.strategy.feature.MutableState;
import de.uka.ilkd.key.strategy.termProjection.TermBuffer;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
/**
* Term feature for testing equality of two terms. The feature returns zero iff it is invoked on a
* term that is equal to the current value of pattern
.
@@ -29,6 +31,6 @@ private EqTermFeature(TermBuffer pattern) {
@Override
protected boolean filter(Term term, MutableState mState, Services services) {
- return term.equalsModRenaming(pattern.getContent(mState));
+ return term.equalsModProperty(pattern.getContent(mState), RENAMING_PROPERTY);
}
}
diff --git a/key.core/src/main/java/de/uka/ilkd/key/strategy/termgenerator/RootsGenerator.java b/key.core/src/main/java/de/uka/ilkd/key/strategy/termgenerator/RootsGenerator.java
index 09beab67408..43ea6a2a68a 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/strategy/termgenerator/RootsGenerator.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/strategy/termgenerator/RootsGenerator.java
@@ -23,6 +23,8 @@
import org.key_project.util.collection.ImmutableSLList;
+import static de.uka.ilkd.key.logic.equality.IrrelevantTermLabelsProperty.IRRELEVANT_TERM_LABELS_PROPERTY;
+
/**
* Term generator for inferring the range of values that a variable can have from a given non-linear
@@ -90,7 +92,7 @@ private Iterator emptyIterator() {
}
private Iterator toIterator(Term res) {
- if (res.equalsModIrrelevantTermLabels(tb.ff())) {
+ if (res.equalsModProperty(tb.ff(), IRRELEVANT_TERM_LABELS_PROPERTY)) {
return emptyIterator();
}
return ImmutableSLList.nil().prepend(res).iterator();
diff --git a/key.core/src/main/java/de/uka/ilkd/key/util/mergerule/MergeRuleUtils.java b/key.core/src/main/java/de/uka/ilkd/key/util/mergerule/MergeRuleUtils.java
index b376341ee00..8f36a10f0d8 100644
--- a/key.core/src/main/java/de/uka/ilkd/key/util/mergerule/MergeRuleUtils.java
+++ b/key.core/src/main/java/de/uka/ilkd/key/util/mergerule/MergeRuleUtils.java
@@ -49,6 +49,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
/**
* This class encapsulates static methods used in the MergeRule implementation. The methods are
* organized into different sections (see comments):
@@ -1723,7 +1725,7 @@ static class TermWrapperFactory {
public TermWrapper wrapTerm(Term term) {
for (Term existingTerm : wrappedTerms) {
- if (existingTerm.equalsModRenaming(term)) {
+ if (existingTerm.equalsModProperty(term, RENAMING_PROPERTY)) {
return new TermWrapper(term, existingTerm.hashCode());
}
}
@@ -1754,7 +1756,7 @@ record TermWrapper(Term term, int hashcode) {
@Override
public boolean equals(Object obj) {
return obj instanceof TermWrapper
- && term.equalsModRenaming(((TermWrapper) obj).term());
+ && term.equalsModProperty(((TermWrapper) obj).term(), RENAMING_PROPERTY);
}
@Override
diff --git a/key.core/src/main/javacc/de/uka/ilkd/key/parser/proofjava/ProofJavaParser.jj b/key.core/src/main/javacc/de/uka/ilkd/key/parser/proofjava/ProofJavaParser.jj
index 978c7733736..ccab2465d0d 100644
--- a/key.core/src/main/javacc/de/uka/ilkd/key/parser/proofjava/ProofJavaParser.jj
+++ b/key.core/src/main/javacc/de/uka/ilkd/key/parser/proofjava/ProofJavaParser.jj
@@ -3289,14 +3289,9 @@ Expression ADTConstructor() :
setPrefixInfo(result);
}
|
- "\\seq_put" "(" expr = Expression() "," expr2 = Expression() "," result = Expression() ")"
+ "\\seq_upd" "(" expr = Expression() "," expr2 = Expression() "," result = Expression() ")"
{
- // desugaring
- final Expression one = factory.createIntLiteral(1);
- final Expression first = new SeqSub(expr, factory.createIntLiteral(0), factory.createMinus(expr2, one));
- final Expression second = new SeqSingleton(result);
- final Expression third = new SeqSub(expr, factory.createPlus(expr2,one), factory.createMinus(new SeqLength(expr),one));
- result = new SeqConcat(first, new SeqConcat(second, third));
+ result = new SeqPut(expr, expr2, result);
setPrefixInfo(result);
}
)
diff --git a/key.core/src/main/javacc/de/uka/ilkd/key/parser/schemajava/SchemaJavaParser.jj b/key.core/src/main/javacc/de/uka/ilkd/key/parser/schemajava/SchemaJavaParser.jj
index ad2080d6403..15945643a31 100644
--- a/key.core/src/main/javacc/de/uka/ilkd/key/parser/schemajava/SchemaJavaParser.jj
+++ b/key.core/src/main/javacc/de/uka/ilkd/key/parser/schemajava/SchemaJavaParser.jj
@@ -5284,14 +5284,10 @@ Expression ADTConstructor() :
setPrefixInfo(result);
}
|
- "\\seq_put" "(" expr = Expression() "," expr2 = Expression() "," result = Expression() ")"
+ "\\seq_upd" "(" expr = Expression() "," expr2 = Expression() "," result = Expression() ")"
{
// desugaring
- final Expression one = factory.createIntLiteral(1);
- final Expression first = new SeqSub(expr, factory.createIntLiteral(0), factory.createMinus(expr2, one));
- final Expression second = new SeqSingleton(result);
- final Expression third = new SeqSub(expr, factory.createPlus(expr2,one), factory.createMinus(new SeqLength(expr),one));
- result = new SeqConcat(first, new SeqConcat(second, third));
+ result = new SeqPut(expr, expr2, result);
setPrefixInfo(result);
}
)
diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/adtProgramDecompositionRules.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/adtProgramDecompositionRules.key
index 5421e99e9b6..41673020323 100644
--- a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/adtProgramDecompositionRules.key
+++ b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/adtProgramDecompositionRules.key
@@ -303,4 +303,6 @@
\displayname "seqReverseUnfold"
};
-}
+ // seq_upd had some rules here too. But since set statements were refactored,
+ // they are not needed anymore anyway.
+ }
diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/javaHeader.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/javaHeader.key
new file mode 100644
index 00000000000..810c4692342
--- /dev/null
+++ b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/javaHeader.key
@@ -0,0 +1,31 @@
+/* This file is part of KeY - https://key-project.org
+ * KeY is licensed under the GNU General Public License Version 2
+ * SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * This file contains the declarations for Java. To find the rules, look at javaRules.key.
+ */
+
+\sorts {
+ any;
+ java.lang.Object;
+ \abstract java.lang.Cloneable \extends java.lang.Object;
+ \abstract java.io.Serializable \extends java.lang.Object;
+
+ \generic alpha, beta, gamma;
+ \generic deltaObject \extends java.lang.Object;
+
+ \generic G;
+ \generic H;
+ \generic J \extends G;
+ \generic GOS \extends Object;
+ \generic alphaObj \extends Object;
+ \generic betaObj \extends Object;
+}
+
+
+\functions {
+ alpha alpha::cast(any);
+ boolean alpha::exactInstance(any);
+ boolean alpha::instance(any);
+}
diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/javaRules.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/javaRules.key
index d390a6c7dfe..c399593766c 100644
--- a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/javaRules.key
+++ b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/javaRules.key
@@ -7,15 +7,6 @@
\include assertions;
-\sorts {
- \generic G;
- \generic H;
- \generic J \extends G;
- \generic GOS \extends Object;
- \generic alphaObj \extends Object;
- \generic betaObj \extends Object;
-}
-
\schemaVariables {
\modalOperator {diamond, box, diamond_transaction, box_transaction} #allmodal;
\modalOperator {diamond, diamond_transaction} #diamond;
diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/ldt.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/ldt.key
index 4d7e958a49c..e18a4e1721b 100644
--- a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/ldt.key
+++ b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/ldt.key
@@ -11,9 +11,12 @@
*
* Kai Wallisch 08/2014
*/
-\includeLDTs boolean,
+\includeLDTs
+ optionsDeclarations,
ruleSetsDeclarations,
+ boolean,
integerHeader,
+ javaHeader,
floatHeader,
heap,
locSets,
diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/optionsDeclarations.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/optionsDeclarations.key
new file mode 100644
index 00000000000..aac46391232
--- /dev/null
+++ b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/optionsDeclarations.key
@@ -0,0 +1,252 @@
+/* This file is part of KeY - https://key-project.org
+ * KeY is licensed under the GNU General Public License Version 2
+ * SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * This file contains the known taclet options (aka choices) as well as their documentation.
+ */
+
+\optionsDecl {
+
+ /*!
+ Treatment of Java assertion statements. Java assertions can be handled in three different ways in KeY.
+ */
+ assertions: {
+ /*!
+ If set to 'safe', the following proof obligations have to be shown:
+ - The program with assertions removed must fulfill the specification
+ - The asserted conditions must hold (without throwing an exception,
+ and with termination)
+ - The assertions do not have side effects influencing the post
+ conditions.
+ This is the default option. Proofs with this option are typically harder.
+
+ @choiceDefaultOption
+ */
+ safe,
+
+ /*! If switched 'on', assertions are treated like Java would treat them:
+ Asserted Statements are evaluated and an AssertionException is
+ raised if they turn out to be false.*/
+ on,
+
+ /*! If switched 'off', assert statements are skipped. */
+ off};
+
+ /*! Specifies whether static (class loading) initialization should be
+ taken in consideration.
+
+ Both specifications and proof obligations become significantly more
+ difficult since class loading may take place at many places.*/
+ initialisation: {/*! @choiceUnsound */
+ disableStaticInitialisation,
+ enableStaticInitialisation
+ };
+
+ /*! This option controls how integer numbers are modeled. */
+ intRules: {
+ /*! 'Arithmetic without overflow checking' treats integers as pure
+ mathematical objects. The proof obligations are often easier to
+ discharge. However, the model does not allow the verification of all
+ properties which hold with Java semantics. Moreover, it allows the
+ verification of properties which do not hold on Java's actual
+ semantics. This is the default option.
+
+ @choiceDefaultOption @choiceUnsound
+ */
+ arithmeticSemanticsIgnoringOF,
+
+ /*! 'Arithmetic with overflow checking' also treats integers as
+ mathematical objects, but ensures that no overflow occurs. While
+ this model also has a completeness gap, it prevents proving
+ incorrect properties.
+
+ @choiceIncomplete*/
+ arithmeticSemanticsCheckingOF,
+
+ /*! 'Java semantics' treat integers the same way Java would treat them.
+ The different integer types operate within their respective value
+ ranges. The bitvector arithmetic is modeled in KeY using modulo
+ expressions. This is sound and complete. Proof obligations tend
+ to get more complex with this setting.*/
+ javaSemantics
+ };
+
+ /*! Rules dealing Java language constructs can be turned off by setting this to 'None'. */
+ programRules: {Java, /*! @choiceIncomplete */ None};
+ /*! Treatment of implicit runtime exceptions */
+ runtimeExceptions: {
+ /*! If set to 'allow', implicit runtime exceptions are raised as specified
+ in the Java language specification.
+
+ @choiceIncomplete
+ */
+ ban,
+ /*!
+ If set to 'ban', any occurrence of an implicit runtime exception is
+ considered an unrecoverable program failure. For programs which do not
+ raise implicit runtime exceptions, this is usually easier to prove than
+ 'allow'. This is the default option.
+ */
+ allow,
+ /*! If set to 'ignore', it is assumed that no implicit runtime exception occurs.
+ Warning: Reasoning with these rules is unsound.
+
+ @choiceUnsound
+ */
+ ignore
+ };
+
+ /*! JavaCard is a dialect of Java designed for the use in SmartCards. It
+ lacks floating point operations and concurrency, but provides stronger
+ object persistence guarantees.
+
+ There are two values for this option 'on' and 'off'. Switching
+ on or off all taclets axiomatising JavaCard specific features like transaction.
+ */
+ JavaCard: {off, on};
+
+ /*! Loading rules dealing with Strings (charLists) can be disabled. */
+ Strings: {on, /*! @choiceIncomplete */ off};
+
+ /*!
+ Rules for model field representation clauses. JML model fields are given
+ a semantics by represents clauses. This switch sets how the rules handle these clauses.
+ */
+ modelFields: {
+ /*!
+ * If set to 'treatAsAxiom', the representation is seen as an axiom,
+ satisfiability will not be checked. This may introduce inconsistent
+ specifications, for example the following contradictory JML clause
+ will not be rejected:
+ //@ represents modelField == modelField + 1;
+ This is the default option since KeY 2.4.
+ */
+ treatAsAxiom,
+ /*!
+ If set to 'showSatisfiability', for every expansion of the represents
+ clause, it must be shown that the definition is _locally_
+ satisfiable. Cross-definition inconsistencies can still be
+ formulated, however:
+ ```
+ //@ represents modelField1 == modelField2;
+ //@ represents modelField2 == modelField1 + 1;
+ ```
+ This had been the default option previously, until KeY 2.2.
+ */
+ showSatisfiability
+ };
+ /*! Loading program rules dealing with JML's \bigint datatype can be disabled. */
+ bigint: {on, off};
+ /*! Loading rules dealing with sequences can be disabled. */
+ sequences: {on, off};
+ /*! This option allows more fine-grained control over rules dealing with sequences.
+ By default, it is disabled because the additional rules are known to have a negative impact on overall performance.
+ Activate this option if your problem is concerned with permutations or information flow.*/
+ moreSeqRules: {off, on};
+ /*! Loading rules dealing with reachability can be disabled. */
+ reach: {on, off};
+ /*!
+ Loading less commonly used rules for (mathematical) integers,
+ such as rules for bounded sums and products, modulo, or polynomials,
+ can be disabled. If they are loaded, their application in the strategy
+ can still be controlled as usual.
+
+ This option is experimental. Depending of your understanding of 'less common',
+ you may experience incompleteness. Doing proofs with Java int semantics will not work, definitely.
+
+ Not to be confused with intRules, which controls the semantics of the Java type int.
+ */
+ integerSimplificationRules: {full, /*! @choiceIncomplete */ minimal}; // TODO: further refine this option
+ permissions: {off, on};
+
+ /*!
+ Treatment of formulas and terms for welldefinedness checks:
+ */
+ wdOperator: {
+ /*!
+ More intuitive for software developers and along the lines of
+ runtime assertion semantics. Well-Definedness checks will be
+ stricter using this operator, since the order of terms/formulas
+ matters. It is based on McCarthy logic.
+ Cf. "Are the Logical Foundations of Verifying Compiler
+ Prototypes Matching User Expectations?" by Patrice Chalin.
+
+ @choiceDefaultOption
+ */
+ L,
+ /*!
+ Complete and along the lines of classical logic, where the
+ order of terms/formulas is irrelevant. This operator is
+ equivalent to the D-operator, but more efficient.
+ Cf. "Efficient Well-Definedness Checking" by Ádám Darvas,
+ Farhad Mehta, and Arsenii Rudich.
+ */
+ Y,
+ /*!
+ Complete and along the lines of classical logic, where the
+ order of terms/formulas is irrelevant. This operator is not as
+ strict as the L-operator, based on strong Kleene logic. To be
+ used with care, since formulas may blow up exponentially.
+ Cf. "Well Defined B" by Patrick Behm, Lilian Burdy, and
+ Jean-Marc Meynadier*/
+ D
+ };
+
+ /*!
+ Welldefinedness checks of JML specifications can be turned on/off.
+ This includes class invariants, operation contracts, model fields
+ as well as JML (annotation) statements as loop invariants and
+ block contracts. The former ones are checked "on-the-fly", i.e.,
+ directly when they are applied in the code while proving an operation
+ contract, since the context is needed.
+ */
+ wdChecks: {off, on};
+ /*!
+ Specifies whether a special goal "Joined node is weakening" should be
+ generated as a child of the partner node of a join operation.
+
+ For join procedures formally proven correct, this should not be necessary.
+ Enable this option when you are not sure whether a newly implemented join
+ procedure is sound. In this case, the generated "is weakening" goals should
+ only be closable if the concrete join instance is correct.
+ */
+ mergeGenerateIsWeakeningGoal: {off, on};
+
+ /*!
+ Method calls in KeY can be either handled by inlining the method body or
+ by applying the method's contract. Inlining a method body is only modularly
+ sound if it is guaranteed that no new method body can override the known
+ implementation.
+ */
+ methodExpansion: {
+ /*! Inlining is modularly sound: Methods can only be inlined if private,
+ static, final, or in a final method.
+ @choiceDefaultOption
+ */
+ modularOnly,
+ /*! Inlining is liberal: Methods can always be inlined, and all known
+ method implementations are taken into consideration. This setting
+ is sound under a closed program assumption.
+ */
+ noRestriction
+ };
+
+ /*!
+ Missing documentation
+ */
+ javaLoopTreatment: {efficient, teaching};
+
+ /*!
+ Floating points in Java may have a more precise semantics if the hardware
+ supports it. Only if the Java keyword strictfp is specified can we make
+ guarantees about the meaning of floating point expressions.
+ */
+ floatRules: {
+ /*! Require the strictfp keyword if floating points are to be treated.
+ Otherwise arithmetic remains as underspecified symbols*/
+ strictfpOnly,
+ /*! Treat all code as if it was specified strictfp. */
+ assumeStrictfp
+ };
+}
diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/ruleSetsDeclarations.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/ruleSetsDeclarations.key
index de2c6d034a2..6f04c8683b2 100644
--- a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/ruleSetsDeclarations.key
+++ b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/ruleSetsDeclarations.key
@@ -2,292 +2,17 @@
* KeY is licensed under the GNU General Public License Version 2
* SPDX-License-Identifier: GPL-2.0-only */
-//
-// This file contains rules for handling java programs
-
-
-\sorts {
- any;
- java.lang.Object;
- \abstract java.lang.Cloneable \extends java.lang.Object;
- \abstract java.io.Serializable \extends java.lang.Object;
-
- \generic alpha, beta, gamma;
- \generic deltaObject \extends java.lang.Object;
-}
-
-\functions {
- alpha alpha::cast(any);
- boolean alpha::exactInstance(any);
- boolean alpha::instance(any);
-}
/*
- return "runtimeExceptions:ignore".equals(choice) ||
- "initialisation:disableStaticInitialisation".equals(choice) ||
- "intRules:arithmeticSemanticsIgnoringOF".equals(choice);
-
-
-The optimized select rules can be turned off by setting this option to off.
-
-The unoptimized rules use inplace rewriting for the evaluation of select terms. This may lead to heap terms growing exponentially in the number of anons/stores to be evaluated. However, in some rare cases the usage of the unoptimized rules may lead to more human readable sequents.
-
-The optimized rules pull out select terms before they evaluate them. Because other occurences of the same select term are replaced by the Skolem constant introduced by the pullout rule (application of equalities), each select term has to be evaluated only once. Intelligent hiding of no longer needed auxiliary equations holds the sequent human readable and increases performance. The result of the evaluation of a select term is stored such that it can be reapplied immediately if the same select term occurs again.
-
-
-*/
-\optionsDecl {
-
- /*!
- Treatment of Java assertion statements. Java assertions can be handled in three different ways in KeY.
- */
- assertions: {
- /*!
- If set to 'safe', the following proof obligations have to be shown:
- - The program with assertions removed must fulfill the specification
- - The asserted conditions must hold (without throwing an exception,
- and with termination)
- - The assertions do not have side effects influencing the post
- conditions.
- This is the default option. Proofs with this option are typically harder.
-
- @choiceDefaultOption
- */
- safe,
-
- /*! If switched 'on', assertions are treated like Java would treat them:
- Asserted Statements are evaluated and an AssertionException is
- raised if they turn out to be false.*/
- on,
-
- /*! If switched 'off', assert statements are skipped. */
- off};
-
- /*! Specifies whether static (class loading) initialization should be
- taken in consideration.
-
- Both specifications and proof obligations become significantly more
- difficult since class loading may take place at many places.*/
- initialisation: {/*! @choiceUnsound */
- disableStaticInitialisation,
- enableStaticInitialisation
- };
-
- /*! This option controls how integer numbers are modeled. */
- intRules: {
- /*! 'Arithmetic without overflow checking' treats integers as pure
- mathematical objects. The proof obligations are often easier to
- discharge. However, the model does not allow the verification of all
- properties which hold with Java semantics. Moreover, it allows the
- verification of properties which do not hold on Java's actual
- semantics. This is the default option.
-
- @choiceDefaultOption @choiceUnsound
- */
- arithmeticSemanticsIgnoringOF,
-
- /*! 'Arithmetic with overflow checking' also treats integers as
- mathematical objects, but ensures that no overflow occurs. While
- this model also has a completeness gap, it prevents proving
- incorrect properties.
-
- @choiceIncomplete*/
- arithmeticSemanticsCheckingOF,
-
- /*! 'Java semantics' treat integers the same way Java would treat them.
- The different integer types operate within their respective value
- ranges. The bitvector arithmetic is modeled in KeY using modulo
- expressions. This is sound and complete. Proof obligations tend
- to get more complex with this setting.*/
- javaSemantics
- };
-
- /*! Rules dealing Java language constructs can be turned off by setting this to 'None'. */
- programRules: {Java, /*! @choiceIncomplete */ None};
- /*! Treatment of implicit runtime exceptions */
- runtimeExceptions: {
- /*! If set to 'allow', implicit runtime exceptions are raised as specified
- in the Java language specification.
-
- @choiceIncomplete
- */
- ban,
- /*!
- If set to 'ban', any occurrence of an implicit runtime exception is
- considered an unrecoverable program failure. For programs which do not
- raise implicit runtime exceptions, this is usually easier to prove than
- 'allow'. This is the default option.
- */
- allow,
- /*! If set to 'ignore', it is assumed that no implicit runtime exception occurs.
- Warning: Reasoning with these rules is unsound.
-
- @choiceUnsound
- */
- ignore
- };
-
- /*! JavaCard is a dialect of Java designed for the use in SmartCards. It
- lacks floating point operations and concurrency, but provides stronger
- object persistence guarantees.
-
- There are two values for this option 'on' and 'off'. Switching
- on or off all taclets axiomatising JavaCard specific features like transaction.
- */
- JavaCard: {off, on};
-
- /*! Loading rules dealing with Strings (charLists) can be disabled. */
- Strings: {on, /*! @choiceIncomplete */ off};
-
- /*!
- Rules for model field representation clauses. JML model fields are given
- a semantics by represents clauses. This switch sets how the rules handle these clauses.
- */
- modelFields: {
- /*!
- * If set to 'treatAsAxiom', the representation is seen as an axiom,
- satisfiability will not be checked. This may introduce inconsistent
- specifications, for example the following contradictory JML clause
- will not be rejected:
- //@ represents modelField == modelField + 1;
- This is the default option since KeY 2.4.
- */
- treatAsAxiom,
- /*!
- If set to 'showSatisfiability', for every expansion of the represents
- clause, it must be shown that the definition is _locally_
- satisfiable. Cross-definition inconsistencies can still be
- formulated, however:
- ```
- //@ represents modelField1 == modelField2;
- //@ represents modelField2 == modelField1 + 1;
- ```
- This had been the default option previously, until KeY 2.2.
- */
- showSatisfiability
- };
- /*! Loading program rules dealing with JML's \bigint datatype can be disabled. */
- bigint: {on, off};
- /*! Loading rules dealing with sequences can be disabled. */
- sequences: {on, off};
- /*! This option allows more fine-grained control over rules dealing with sequences.
- By default, it is disabled because the additional rules are known to have a negative impact on overall performance.
- Activate this option if your problem is concerned with permutations or information flow.*/
- moreSeqRules: {off, on};
- /*! Loading rules dealing with reachability can be disabled. */
- reach: {on, off};
- /*!
- Loading less commonly used rules for (mathematical) integers,
- such as rules for bounded sums and products, modulo, or polynomials,
- can be disabled. If they are loaded, their application in the strategy
- can still be controlled as usual.
-
- This option is experimental. Depending of your understanding of 'less common',
- you may experience incompleteness. Doing proofs with Java int semantics will not work, definitely.
-
- Not to be confused with intRules, which controls the semantics of the Java type int.
- */
- integerSimplificationRules: {full, /*! @choiceIncomplete */ minimal}; // TODO: further refine this option
- permissions: {off, on};
-
- /*!
- Treatment of formulas and terms for welldefinedness checks:
- */
- wdOperator: {
- /*!
- More intuitive for software developers and along the lines of
- runtime assertion semantics. Well-Definedness checks will be
- stricter using this operator, since the order of terms/formulas
- matters. It is based on McCarthy logic.
- Cf. "Are the Logical Foundations of Verifying Compiler
- Prototypes Matching User Expectations?" by Patrice Chalin.
-
- @choiceDefaultOption
- */
- L,
- /*!
- Complete and along the lines of classical logic, where the
- order of terms/formulas is irrelevant. This operator is
- equivalent to the D-operator, but more efficient.
- Cf. "Efficient Well-Definedness Checking" by Ádám Darvas,
- Farhad Mehta, and Arsenii Rudich.
- */
- Y,
- /*!
- Complete and along the lines of classical logic, where the
- order of terms/formulas is irrelevant. This operator is not as
- strict as the L-operator, based on strong Kleene logic. To be
- used with care, since formulas may blow up exponentially.
- Cf. "Well Defined B" by Patrick Behm, Lilian Burdy, and
- Jean-Marc Meynadier*/
- D
- };
-
- /*!
- Welldefinedness checks of JML specifications can be turned on/off.
- This includes class invariants, operation contracts, model fields
- as well as JML (annotation) statements as loop invariants and
- block contracts. The former ones are checked "on-the-fly", i.e.,
- directly when they are applied in the code while proving an operation
- contract, since the context is needed.
- */
- wdChecks: {off, on};
- /*!
- Specifies whether a special goal "Joined node is weakening" should be
- generated as a child of the partner node of a join operation.
-
- For join procedures formally proven correct, this should not be necessary.
- Enable this option when you are not sure whether a newly implemented join
- procedure is sound. In this case, the generated "is weakening" goals should
- only be closable if the concrete join instance is correct.
- */
- mergeGenerateIsWeakeningGoal: {off, on};
-
- /*!
- Method calls in KeY can be either handled by inlining the method body or
- by applying the method's contract. Inlining a method body is only modularly
- sound if it is guaranteed that no new method body can override the known
- implementation.
- */
- methodExpansion: {
- /*! Inlining is modularly sound: Methods can only be inlined if private,
- static, final, or in a final method.
- @choiceDefaultOption
- */
- modularOnly,
- /*! Inlining is liberal: Methods can always be inlined, and all known
- method implementations are taken into consideration. This setting
- is sound under a closed program assumption.
- */
- noRestriction
- };
-
- /*!
- Missing documentation
- */
- javaLoopTreatment: {efficient, teaching};
-
- /*!
- Floating points in Java may have a more precise semantics if the hardware
- supports it. Only if the Java keyword strictfp is specified can we make
- guarantees about the meaning of floating point expressions.
- */
- floatRules: {
- /*! Require the strictfp keyword if floating points are to be treated.
- Otherwise arithmetic remains as underspecified symbols*/
- strictfpOnly,
- /*! Treat all code as if it was specified strictfp. */
- assumeStrictfp
- };
-
-}
+ * This file contains the known heuristics (rule sets) of KeY.
+ */
// ***************************************
// Places in KeY with hard-coded rule sets
// (check there when changing rule sets):
// ***************************************
// 1) NodeInfo#symbolicExecNames
-// 2)
-
+// 2) OneStepSimplifier#ruleSets
+// 3) macro implementations (e.g. IntegerSimplificationMacro, FinishSymbolicExecutionMacro, ...)
\heuristicsDecl {
// These rules are not permitted during symbolic execution
diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/seq.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/seq.key
index e88d2e928ad..e9fa73b1381 100644
--- a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/seq.key
+++ b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/seq.key
@@ -30,6 +30,7 @@
Seq seqConcat(Seq, Seq);
Seq seqSub(Seq, int, int);
Seq seqReverse(Seq);
+ Seq seqUpd(Seq, int, any);
Seq seqDef {false, false, true}(int, int, any);
Seq seqSwap(Seq, int, int);
diff --git a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/seqRules.key b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/seqRules.key
index 25d302e550f..6feb4890641 100644
--- a/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/seqRules.key
+++ b/key.core/src/main/resources/de/uka/ilkd/key/proof/rules/seqRules.key
@@ -91,6 +91,18 @@
};
+ defOfSeqUpd {
+ \schemaVar \term Seq seq;
+ \schemaVar \term int idx;
+ \schemaVar \term any value;
+ \schemaVar \variables int uSub;
+
+ \find(seqUpd(seq, idx, value))
+
+ \varcond(\notFreeIn(uSub, idx), \notFreeIn(uSub, value), \notFreeIn(uSub, seq))
+ \replacewith(seqDef{uSub;}(0, seqLen(seq), \if(uSub=idx) \then(value) \else(any::seqGet(seq,uSub))))
+ };
+
// --------------------------------------------------------------------
// rule for seqIndexOf
// This is logically equivalent to a conditional (partial)
@@ -241,6 +253,17 @@
\heuristics(simplify_enlarging)
};
+ \lemma
+ getOfSeqUpd {
+ \schemaVar \term Seq seq;
+ \schemaVar \term int idx, jdx;
+ \schemaVar \term any value;
+
+ \find(alpha::seqGet(seqUpd(seq, idx, value), jdx))
+ \replacewith(\if(0<=jdx & jdx < seqLen(seq) & idx=jdx) \then((alpha)value) \else(alpha::seqGet(seq, jdx)))
+ \heuristics(simplify_enlarging)
+ };
+
// --------------------------------------------------------------------
// derived rule for lenOfX
// --------------------------------------------------------------------
@@ -299,6 +322,18 @@
\heuristics(simplify)
};
+ \lemma
+ lenOfSeqUpd {
+ \schemaVar \term Seq seq;
+ \schemaVar \term int idx;
+ \schemaVar \term any value;
+
+ \find(seqLen(seqUpd(seq, idx, value)))
+ \replacewith(seqLen(seq))
+ \heuristics(simplify)
+ };
+
+
// --------------------------------------------------------------------------
// derived EQ versions
// --------------------------------------------------------------------------
diff --git a/key.core/src/test/java/de/uka/ilkd/key/logic/TestTerm.java b/key.core/src/test/java/de/uka/ilkd/key/logic/TestTerm.java
index 17e61c0831e..b6d4722a86d 100644
--- a/key.core/src/test/java/de/uka/ilkd/key/logic/TestTerm.java
+++ b/key.core/src/test/java/de/uka/ilkd/key/logic/TestTerm.java
@@ -6,6 +6,7 @@
import de.uka.ilkd.key.java.ast.StatementBlock;
import de.uka.ilkd.key.java.ast.declaration.LocalVariableDeclaration;
import de.uka.ilkd.key.ldt.JavaDLTheory;
+import de.uka.ilkd.key.logic.equality.RenamingProperty;
import de.uka.ilkd.key.logic.op.*;
import de.uka.ilkd.key.logic.sort.SortImpl;
import de.uka.ilkd.key.rule.TacletForTests;
@@ -111,9 +112,11 @@ public void testFreeVars4() {
public void testProgramElementEqualsModRenaming() {
Term match1 = TacletForTests.parseTerm("\\<{ int i; }\\>true & \\<{ int i; }\\>true");
Term match2 = TacletForTests.parseTerm("\\<{ int i; }\\>true ");
- assertTrue(match1.sub(0).equalsModRenaming(match2),
+ assertTrue(
+ match1.sub(0).equalsModProperty(match2, RenamingProperty.RENAMING_PROPERTY),
"Terms should be equalModRenaming (0).");
- assertTrue(match1.sub(0).equalsModRenaming(match1.sub(1)),
+ assertTrue(
+ match1.sub(0).equalsModProperty(match1.sub(1), RenamingProperty.RENAMING_PROPERTY),
"Terms should be equalModRenaming (1).");
Term match3 = TacletForTests.parseTerm("\\<{ int j = 0; }\\>true ");
assertNotEquals(match1, match3, "Terms should not be equal.");
@@ -124,13 +127,16 @@ public void testProgramElementEqualsModRenaming() {
public void testEqualsModRenamingWithLabels() {
Term match1 = TacletForTests.parseTerm("\\<{ label0:{ label1:{ } } }\\>true");
Term match2 = TacletForTests.parseTerm("\\<{ label0:{ label1:{ } } }\\>true");
- assertTrue(match1.equalsModRenaming(match2), "Terms should be equalModRenaming.");
+ assertTrue(match1.equalsModProperty(match2, RenamingProperty.RENAMING_PROPERTY),
+ "Terms should be equalModRenaming.");
Term match3 = TacletForTests.parseTerm("\\<{ label0:{ label1:{ int i = 0; } } }\\>true");
Term match4 = TacletForTests.parseTerm("\\<{ label0:{ label1:{ int j = 0; } } }\\>true");
- assertTrue(match3.equalsModRenaming(match4), "Terms should be equalModRenaming.");
+ assertTrue(match3.equalsModProperty(match4, RenamingProperty.RENAMING_PROPERTY),
+ "Terms should be equalModRenaming.");
Term match5 = TacletForTests.parseTerm("\\<{ label0:{ label1:{ int i = 0; } } }\\>true");
Term match6 = TacletForTests.parseTerm("\\<{ label0:{ label1:{ int i = 0; } } }\\>true");
- assertTrue(match5.equalsModRenaming(match6), "Terms should be equalModRenaming.");
+ assertTrue(match5.equalsModProperty(match6, RenamingProperty.RENAMING_PROPERTY),
+ "Terms should be equalModRenaming.");
}
@Test
@@ -142,7 +148,7 @@ public void testEqualsModRenaming() {
final Term pz = tf.createTerm(p, new Term[] { tf.createTerm(z) }, null, null);
final Term quant2 = tb.all(z, tb.all(z, tb.all(z, pz)));
- assertTrue(quant1.equalsModRenaming(quant2),
+ assertTrue(quant1.equalsModProperty(quant2, RenamingProperty.RENAMING_PROPERTY),
"Terms " + quant1 + " and " + quant2 + " should be equal mod renaming");
}
diff --git a/key.core/src/test/java/de/uka/ilkd/key/logic/TestTermLabelManager.java b/key.core/src/test/java/de/uka/ilkd/key/logic/TestTermLabelManager.java
index 9b3d61245cf..72cd2e79a33 100644
--- a/key.core/src/test/java/de/uka/ilkd/key/logic/TestTermLabelManager.java
+++ b/key.core/src/test/java/de/uka/ilkd/key/logic/TestTermLabelManager.java
@@ -33,6 +33,7 @@
import org.key_project.util.collection.ImmutableList;
import org.key_project.util.collection.ImmutableSLList;
+import org.jspecify.annotations.NonNull;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -831,10 +832,11 @@ public DummyRule(String name) {
this.name = name;
}
+ @NonNull
@Override
public ImmutableList apply(Goal goal, Services services, RuleApp ruleApp)
throws RuleAbortException {
- return null;
+ throw new RuleAbortException("no implementation");
}
@Override
diff --git a/key.core/src/test/java/de/uka/ilkd/key/logic/equality/TestEqualsModProperty.java b/key.core/src/test/java/de/uka/ilkd/key/logic/equality/TestEqualsModProperty.java
new file mode 100644
index 00000000000..c50e185ed12
--- /dev/null
+++ b/key.core/src/test/java/de/uka/ilkd/key/logic/equality/TestEqualsModProperty.java
@@ -0,0 +1,287 @@
+/* This file is part of KeY - https://key-project.org
+ * KeY is licensed under the GNU General Public License Version 2
+ * SPDX-License-Identifier: GPL-2.0-only */
+package de.uka.ilkd.key.logic.equality;
+
+import java.util.Arrays;
+
+import de.uka.ilkd.key.logic.*;
+import de.uka.ilkd.key.logic.label.*;
+import de.uka.ilkd.key.logic.op.*;
+import de.uka.ilkd.key.rule.TacletForTests;
+import de.uka.ilkd.key.util.HelperClassForTests;
+
+import org.key_project.util.collection.ImmutableArray;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static de.uka.ilkd.key.logic.equality.IrrelevantTermLabelsProperty.IRRELEVANT_TERM_LABELS_PROPERTY;
+import static de.uka.ilkd.key.logic.equality.ProofIrrelevancyProperty.PROOF_IRRELEVANCY_PROPERTY;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+import static de.uka.ilkd.key.logic.equality.TermLabelsProperty.TERM_LABELS_PROPERTY;
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Tests for {@link TermEqualsModProperty}.
+ *
+ * @author Tobias Reinhold
+ */
+public class TestEqualsModProperty {
+ private TermBuilder tb;
+
+ private TermFactory tf;
+
+ final private TermLabel relevantLabel1 = ParameterlessTermLabel.UNDEFINED_VALUE_LABEL;
+ final private TermLabel relevantLabel2 = ParameterlessTermLabel.SHORTCUT_EVALUATION_LABEL;
+ private static TermLabel irrelevantLabel = null;
+ final private static OriginTermLabelFactory factory = new OriginTermLabelFactory();
+
+ @BeforeAll
+ public static void setIrrelevantLabel() {
+ try {
+ irrelevantLabel = factory.parseInstance(Arrays.stream(new String[] {
+ "User_Interaction @ node 0 (Test Test)", "[]" }).toList(),
+ HelperClassForTests.createServices());
+ } catch (TermLabelException e) {
+ fail(e);
+ }
+ }
+
+ @BeforeEach
+ public void setUp() {
+ tb = TacletForTests.services().getTermBuilder();
+ tf = TacletForTests.services().getTermFactory();
+ }
+
+ // equalsModProperty(...) with RENAMING_TERM_PROPERTY
+ @Test
+ public void renaming() {
+ // ------------ differing terms to begin with
+ Term term1 =
+ tf.createTerm(Junctor.AND, tf.createTerm(Junctor.TRUE), tf.createTerm(Junctor.FALSE));
+ Term term2 =
+ tf.createTerm(Junctor.AND, tf.createTerm(Junctor.TRUE), tf.createTerm(Junctor.TRUE));
+ assertFalse(term1.equalsModProperty(term2, RENAMING_PROPERTY),
+ "Terms are different to begin with, so they shouldn't be equal");
+ assertFalse(term2.equalsModProperty(term1, RENAMING_PROPERTY),
+ "Terms are different to begin with, so they shouldn't be equal");
+ // other tests for equality already in TestTerm.java
+
+ // ------------ comparison with something that is not a term
+ assertFalse(term1.equalsModProperty(1, RENAMING_PROPERTY),
+ "Should be false as other object is not a term");
+
+ // ------------ differing labels
+ term1 =
+ tf.createTerm(Junctor.AND, tf.createTerm(Junctor.TRUE), tf.createTerm(Junctor.FALSE));
+ term2 =
+ tf.createTerm(Junctor.AND, tf.createTerm(Junctor.TRUE), tf.createTerm(Junctor.FALSE));
+ ImmutableArray labels1 = new ImmutableArray<>(irrelevantLabel);
+ term1 = tb.label(term1, labels1);
+ assertTrue(term1.equalsModProperty(term2, RENAMING_PROPERTY),
+ "Should be true as labels do not matter");
+ assertTrue(term2.equalsModProperty(term1, RENAMING_PROPERTY),
+ "Should be true as labels do not matter");
+
+ labels1 = new ImmutableArray<>(relevantLabel1);
+ term1 = tb.label(term1, labels1);
+ assertTrue(term1.equalsModProperty(term2, RENAMING_PROPERTY),
+ "Should be true as labels do not matter");
+ assertTrue(term2.equalsModProperty(term1, RENAMING_PROPERTY),
+ "Should be true as labels do not matter");
+
+ ImmutableArray labels2 = new ImmutableArray<>(relevantLabel2);
+ term2 = tb.label(term2, labels2);
+ assertTrue(term1.equalsModProperty(term2, RENAMING_PROPERTY),
+ "Should be true as labels do not matter");
+ assertTrue(term2.equalsModProperty(term1, RENAMING_PROPERTY),
+ "Should be true as labels do not matter");
+ }
+
+ // equalsModProperty(...) with IRRELEVANT_TERM_LABELS_PROPERTY
+ @Test
+ public void irrelevantTermLabels() {
+ // ------------ different terms to begin with
+ Term term1 =
+ tf.createTerm(Junctor.AND, tf.createTerm(Junctor.TRUE), tf.createTerm(Junctor.FALSE));
+ Term term2 =
+ tf.createTerm(Junctor.AND, tf.createTerm(Junctor.TRUE), tf.createTerm(Junctor.TRUE));
+ assertFalse(term1.equalsModProperty(term2, IRRELEVANT_TERM_LABELS_PROPERTY),
+ "Terms are different to begin with, so they shouldn't be equal");
+ assertFalse(term2.equalsModProperty(term1, IRRELEVANT_TERM_LABELS_PROPERTY),
+ "Terms are different to begin with, so they shouldn't be equal");
+
+ // ------------ comparison with something that is not a term
+ assertFalse(term1.equalsModProperty(1, IRRELEVANT_TERM_LABELS_PROPERTY),
+ "Should be false as other object is not a term");
+
+ // base terms stay the same for the rest of the tests
+ term1 =
+ tf.createTerm(Junctor.AND, tf.createTerm(Junctor.TRUE), tf.createTerm(Junctor.FALSE));
+ term2 =
+ tf.createTerm(Junctor.AND, tf.createTerm(Junctor.TRUE), tf.createTerm(Junctor.FALSE));
+
+ // ------------ only one term has labels
+ ImmutableArray labels1 =
+ new ImmutableArray<>(relevantLabel1, irrelevantLabel);
+ term1 = tb.label(term1, labels1);
+ assertFalse(term1.equalsModProperty(term2, IRRELEVANT_TERM_LABELS_PROPERTY),
+ "Should be false as term1 has a proof relevant term label, but term2 does not have any labels");
+ assertFalse(term2.equalsModProperty(term1, IRRELEVANT_TERM_LABELS_PROPERTY),
+ "Should be false as term1 has a proof relevant term label, but term2 does not have any labels");
+
+ labels1 = new ImmutableArray<>(irrelevantLabel);
+ term1 = tb.label(term1, labels1);
+ assertTrue(term1.equalsModProperty(term2, IRRELEVANT_TERM_LABELS_PROPERTY),
+ "Should be true as term1 has no relevant term labels and term2 does not have any labels");
+ assertTrue(term2.equalsModProperty(term1, IRRELEVANT_TERM_LABELS_PROPERTY),
+ "Should be true as term1 has no relevant term labels and term2 does not have any labels");
+
+ // ------------ same relevant labels
+ labels1 = new ImmutableArray<>(relevantLabel1, relevantLabel2);
+ ImmutableArray labels2 =
+ new ImmutableArray<>(relevantLabel1, relevantLabel2, irrelevantLabel);
+ term1 = tb.label(term1, labels1);
+ term2 = tb.label(term2, labels2);
+ assertTrue(term1.equalsModProperty(term2, IRRELEVANT_TERM_LABELS_PROPERTY),
+ "Should be true as both terms have the same relevant term labels");
+ assertTrue(term2.equalsModProperty(term1, IRRELEVANT_TERM_LABELS_PROPERTY),
+ "Should be true as both terms have the same relevant term labels");
+
+ // ------------ not the same relevant labels
+ labels1 = new ImmutableArray<>(relevantLabel1, irrelevantLabel);
+ labels2 = new ImmutableArray<>(relevantLabel1, relevantLabel2);
+ term1 = tb.label(term1, labels1);
+ term2 = tb.label(term2, labels2);
+ assertFalse(term1.equalsModProperty(term2, IRRELEVANT_TERM_LABELS_PROPERTY),
+ "Should be false as terms do not have the same relevant term labels");
+ assertFalse(term2.equalsModProperty(term1, IRRELEVANT_TERM_LABELS_PROPERTY),
+ "Should be false as terms do not have the same relevant term labels");
+ }
+
+ // equalsModProperty(...) with TERM_LABELS_PROPERTY
+ @Test
+ public void allTermLabels() {
+ // ------------ different terms to begin with
+ Term term1 =
+ tf.createTerm(Junctor.AND, tf.createTerm(Junctor.TRUE), tf.createTerm(Junctor.FALSE));
+ Term term2 =
+ tf.createTerm(Junctor.AND, tf.createTerm(Junctor.TRUE), tf.createTerm(Junctor.TRUE));
+ assertFalse(term1.equalsModProperty(term2, TERM_LABELS_PROPERTY),
+ "Terms are different to begin with, so they shouldn't be equal");
+ assertFalse(term2.equalsModProperty(term1, TERM_LABELS_PROPERTY),
+ "Terms are different to begin with, so they shouldn't be equal");
+
+ // ------------ comparison with something that is not a term
+ assertFalse(term1.equalsModProperty(1, TERM_LABELS_PROPERTY),
+ "Should be false as other object is not a term");
+
+ // base terms stay the same for the rest of the tests
+ term1 =
+ tf.createTerm(Junctor.AND, tf.createTerm(Junctor.TRUE), tf.createTerm(Junctor.FALSE));
+ term2 =
+ tf.createTerm(Junctor.AND, tf.createTerm(Junctor.TRUE), tf.createTerm(Junctor.FALSE));
+
+ // ------------ only one term has labels
+ ImmutableArray labels1 =
+ new ImmutableArray<>(relevantLabel1, irrelevantLabel);
+ term1 = tb.label(term1, labels1);
+ assertTrue(term1.equalsModProperty(term2, TERM_LABELS_PROPERTY),
+ "Should be true as underlying terms are equal");
+ assertTrue(term2.equalsModProperty(term1, TERM_LABELS_PROPERTY),
+ "Should be true as underlying terms are equal");
+
+ // ------------ same relevant labels
+ labels1 = new ImmutableArray<>(relevantLabel1, relevantLabel2);
+ ImmutableArray labels2 =
+ new ImmutableArray<>(relevantLabel1, relevantLabel2, irrelevantLabel);
+ term1 = tb.label(term1, labels1);
+ term2 = tb.label(term2, labels2);
+ assertTrue(term1.equalsModProperty(term2, TERM_LABELS_PROPERTY),
+ "Should be true as underlying terms are equal");
+ assertTrue(term2.equalsModProperty(term1, TERM_LABELS_PROPERTY),
+ "Should be true as underlying terms are equal");
+
+ // ------------ not the same relevant labels
+ labels1 = new ImmutableArray<>(relevantLabel1, irrelevantLabel);
+ labels2 = new ImmutableArray<>(relevantLabel1, relevantLabel2);
+ term1 = tb.label(term1, labels1);
+ term2 = tb.label(term2, labels2);
+ assertTrue(term1.equalsModProperty(term2, TERM_LABELS_PROPERTY),
+ "Should be true as underlying terms are equal");
+ assertTrue(term2.equalsModProperty(term1, TERM_LABELS_PROPERTY),
+ "Should be true as underlying terms are equal");
+ }
+
+ // equalsModProperty(...) with PROOF_IRRELEVANCY_PROPERTY
+ @Test
+ public void proofIrrelevancy() {
+ // ------------ different terms to begin with
+ Term term1 =
+ tf.createTerm(Junctor.AND, tf.createTerm(Junctor.TRUE), tf.createTerm(Junctor.FALSE));
+ Term term2 =
+ tf.createTerm(Junctor.AND, tf.createTerm(Junctor.TRUE), tf.createTerm(Junctor.TRUE));
+ assertFalse(term1.equalsModProperty(term2, PROOF_IRRELEVANCY_PROPERTY),
+ "Terms are different to begin with, so they shouldn't be equal");
+ assertFalse(term2.equalsModProperty(term1, PROOF_IRRELEVANCY_PROPERTY),
+ "Terms are different to begin with, so they shouldn't be equal");
+
+ // ------------ comparison with something that is not a term
+ assertFalse(term1.equalsModProperty(1, PROOF_IRRELEVANCY_PROPERTY),
+ "Should be false as other object is not a term");
+
+ // base terms stay the same for the rest of the tests
+ term1 =
+ tf.createTerm(Junctor.AND, tf.createTerm(Junctor.TRUE), tf.createTerm(Junctor.FALSE));
+ term2 =
+ tf.createTerm(Junctor.AND, tf.createTerm(Junctor.TRUE), tf.createTerm(Junctor.FALSE));
+
+ // ------------ only one term has labels
+ ImmutableArray labels1 =
+ new ImmutableArray<>(relevantLabel1, irrelevantLabel);
+ term1 = tb.label(term1, labels1);
+ assertFalse(term1.equalsModProperty(term2, PROOF_IRRELEVANCY_PROPERTY),
+ "Should be false as term1 has a proof relevant term label, but term2 does not have any labels");
+ assertFalse(term2.equalsModProperty(term1, PROOF_IRRELEVANCY_PROPERTY),
+ "Should be false as term1 has a proof relevant term label, but term2 does not have any labels");
+
+ labels1 = new ImmutableArray<>(irrelevantLabel);
+ term1 = tb.label(term1, labels1);
+ assertTrue(term1.equalsModProperty(term2, PROOF_IRRELEVANCY_PROPERTY),
+ "Should be true as term1 has no relevant term labels and term2 does not have any labels");
+ assertTrue(term2.equalsModProperty(term1, PROOF_IRRELEVANCY_PROPERTY),
+ "Should be true as term1 has no relevant term labels and term2 does not have any labels");
+
+ // ------------ same relevant labels
+ labels1 = new ImmutableArray<>(relevantLabel1, relevantLabel2, irrelevantLabel);
+ ImmutableArray labels2 =
+ new ImmutableArray<>(relevantLabel1, relevantLabel2, irrelevantLabel);
+ term1 = tb.label(term1, labels1);
+ term2 = tb.label(term2, labels2);
+ assertTrue(term1.equalsModProperty(term2, PROOF_IRRELEVANCY_PROPERTY),
+ "Should be true as both terms have the same relevant term labels");
+ assertTrue(term2.equalsModProperty(term1, PROOF_IRRELEVANCY_PROPERTY),
+ "Should be true as both terms have the same relevant term labels");
+
+ labels1 = new ImmutableArray<>(relevantLabel1, relevantLabel2, irrelevantLabel);
+ labels2 = new ImmutableArray<>(relevantLabel1, relevantLabel2);
+ term1 = tb.label(term1, labels1);
+ term2 = tb.label(term2, labels2);
+ assertTrue(term1.equalsModProperty(term2, PROOF_IRRELEVANCY_PROPERTY),
+ "Should be true as both terms have the same relevant term labels and irrelevant labels do not matter");
+ assertTrue(term2.equalsModProperty(term1, PROOF_IRRELEVANCY_PROPERTY),
+ "Should be true as both terms have the same relevant term labels and irrelevant labels do not matter");
+
+ // ------------ not the same relevant labels
+ labels1 = new ImmutableArray<>(relevantLabel1);
+ labels2 = new ImmutableArray<>(relevantLabel2);
+ term1 = tb.label(term1, labels1);
+ term2 = tb.label(term2, labels2);
+ assertFalse(term1.equalsModProperty(term2, PROOF_IRRELEVANCY_PROPERTY),
+ "Should be false as terms do not have the same relevant term labels");
+ assertFalse(term2.equalsModProperty(term1, PROOF_IRRELEVANCY_PROPERTY),
+ "Should be false as terms do not have the same relevant term labels");
+ }
+}
diff --git a/key.core/src/test/java/de/uka/ilkd/key/parser/TestIntLiteralParsing.java b/key.core/src/test/java/de/uka/ilkd/key/parser/TestIntLiteralParsing.java
index 5e18e686b48..72b25a51d0b 100644
--- a/key.core/src/test/java/de/uka/ilkd/key/parser/TestIntLiteralParsing.java
+++ b/key.core/src/test/java/de/uka/ilkd/key/parser/TestIntLiteralParsing.java
@@ -153,7 +153,7 @@ public class TestIntLiteralParsing extends AbstractTestTermParser {
public TestIntLiteralParsing() {
containerType = services.getJavaInfo().getKeYJavaType("testTermParserHeap.A");
self = services.getJavaInfo().getCanonicalFieldProgramVariable("next", containerType);
- jio = new JmlIO().services(getServices()).classType(containerType)
+ jio = new JmlIO(getServices()).classType(containerType)
.specMathMode(SpecMathMode.BIGINT).selfVar(self);
}
diff --git a/key.core/src/test/java/de/uka/ilkd/key/parser/TestJMLParserAssociativity.java b/key.core/src/test/java/de/uka/ilkd/key/parser/TestJMLParserAssociativity.java
index 6c898c5985a..4d485b6daba 100644
--- a/key.core/src/test/java/de/uka/ilkd/key/parser/TestJMLParserAssociativity.java
+++ b/key.core/src/test/java/de/uka/ilkd/key/parser/TestJMLParserAssociativity.java
@@ -31,7 +31,7 @@ public Term parseTerm(String s) throws Exception {
KeYJavaType containerType = services.getJavaInfo().getKeYJavaType("testTermParserHeap.A");
ProgramVariable self =
services.getJavaInfo().getCanonicalFieldProgramVariable("next", containerType);
- JmlIO io = new JmlIO().services(getServices()).classType(containerType)
+ JmlIO io = new JmlIO(getServices()).classType(containerType)
.specMathMode(SpecMathMode.BIGINT).selfVar(self);
return io.parseExpression(p);
}
diff --git a/key.core/src/test/java/de/uka/ilkd/key/parser/TestTermParser.java b/key.core/src/test/java/de/uka/ilkd/key/parser/TestTermParser.java
index 6d50fa5e56f..9098756c2b1 100644
--- a/key.core/src/test/java/de/uka/ilkd/key/parser/TestTermParser.java
+++ b/key.core/src/test/java/de/uka/ilkd/key/parser/TestTermParser.java
@@ -21,6 +21,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
import static org.junit.jupiter.api.Assertions.*;
public class TestTermParser extends AbstractTestTermParser {
@@ -256,7 +257,8 @@ public void test13() throws Exception {
Term t4 =
parseTerm("\\exists int_sort ci; (\\<{ int p_y = 1;" + " {int s = 2;} }\\>" + " true ->"
+ "\\<{ int p_y = 1;boolean p_x = 2<1;" + "while(p_x){ int s=3 ;} }\\>" + " true)");
- assertTrue(t3.equalsModRenaming(t4), "Terms should be equalModRenaming");
+ assertTrue(t3.equalsModProperty(t4, RENAMING_PROPERTY),
+ "Terms should be equalModRenaming");
}
@Test
diff --git a/key.core/src/test/java/de/uka/ilkd/key/proof/runallproofs/ProofCollections.java b/key.core/src/test/java/de/uka/ilkd/key/proof/runallproofs/ProofCollections.java
index d217367f555..9fff4dd58d4 100644
--- a/key.core/src/test/java/de/uka/ilkd/key/proof/runallproofs/ProofCollections.java
+++ b/key.core/src/test/java/de/uka/ilkd/key/proof/runallproofs/ProofCollections.java
@@ -20,6 +20,9 @@
* @version 1 (08.02.23)
*/
public class ProofCollections {
+
+ public static final String ENV_KEY_RAP_FUN_KEEP = "KEY_RAP_FUN_KEEP";
+
public static ProofCollection automaticJavaDL() throws IOException {
var settings = new ProofCollectionSettings(new Date());
/*
@@ -236,11 +239,14 @@ public static ProofCollection automaticJavaDL() throws IOException {
g.provable("heap/javacard/arrayFillNonAtomic.key");
+ g = c.group("other");
// Other tests:
g.provable("heap/coincidence_count/project.key");
g.provable("heap/verifyThis11_1_Maximum/project.key");
g.provable("heap/fm12_01_LRS/lcp.key");
g.provable("heap/SemanticSlicing/project.key");
+
+ g = c.group("funOfIF");
g.provable("heap/information_flow/ArrayList_contains.key");
g.provable("heap/information_flow/ArrayList_get.key");
g.provable("heap/information_flow/ArrayList_size.key");
@@ -313,9 +319,11 @@ public static ProofCollection automaticJavaDL() throws IOException {
g.provable("heap/list_seq/ArrayList.contains.key");
g.provable("heap/list_seq/ArrayList.enlarge.key");
g.provable("heap/list_seq/ArrayList.get.key");
+ g.provable("heap/list_seq/ArrayList.set.key");
g.provable("heap/list_seq/ArrayList.newArray.key");
g.provable("heap/list_seq/ArrayList.remove.0.key");
g.provable("heap/list_seq/ArrayList.remove.1.key");
+ g.provable("heap/list_seq/LinkedList.set.key");
g = c.group("observer");
@@ -972,6 +980,12 @@ public static ProofCollection automaticJavaDL() throws IOException {
g.loadable("standard_key/adt/dt_color.proof");
g.loadable("standard_key/adt/dt_list_deconstruct.key");
+ // use for debugging purposes.
+ // c.keep("VSTTE10");
+ String s = System.getenv(ENV_KEY_RAP_FUN_KEEP);
+ if (s != null) {
+ c.keep(s.split(","));
+ }
return c;
}
diff --git a/key.core/src/test/java/de/uka/ilkd/key/proof/runallproofs/ProveTest.java b/key.core/src/test/java/de/uka/ilkd/key/proof/runallproofs/ProveTest.java
index e87ab3b9dc2..d3c59e03731 100644
--- a/key.core/src/test/java/de/uka/ilkd/key/proof/runallproofs/ProveTest.java
+++ b/key.core/src/test/java/de/uka/ilkd/key/proof/runallproofs/ProveTest.java
@@ -73,44 +73,55 @@ protected void assertUnLoadability(String file) throws Exception {
}
private void runKey(String file, TestProperty testProperty) throws Exception {
+ File keyFile = new File(file);
+
+ // a name for this run. helps to find it in the mass of logger
+ final var caseId = "%s|%d".formatted(keyFile.getName(), keyFile.hashCode());
+
+ LOGGER.info("{}: Run Test: {} with {}", caseId, file, testProperty);
+
// Initialize KeY settings.
ProofSettings.DEFAULT_SETTINGS.loadSettingsFromPropertyString(globalSettings);
- if (localSettings != null && !"".equals(localSettings)) {
+ if (localSettings != null && !localSettings.isEmpty()) {
// local settings must be complete to have desired effect
ProofSettings.DEFAULT_SETTINGS.loadSettingsFromPropertyString(localSettings);
}
- File keyFile = new File(file);
- assertTrue(keyFile.exists(), "File " + keyFile + " does not exists");
+ LOGGER.info("({}) Active Settings: {}", caseId,
+ ProofSettings.DEFAULT_SETTINGS.settingsToString());
- // Name resolution for the available KeY file.
- debugOut("Now processing file %s", keyFile);
+ assertTrue(keyFile.exists(), "File " + keyFile + " does not exists");
// File that the created proof will be saved to.
File proofFile = new File(keyFile.getAbsolutePath() + ".proof");
+ LOGGER.info("({}) Proof will be saved to: {}", caseId, proofFile);
+
KeYEnvironment env = null;
Proof loadedProof = null;
boolean success;
try {
+ LOGGER.info("({}) Start proving", caseId);
// Initialize KeY environment and load proof.
Pair, Pair> pair =
load(keyFile);
+ LOGGER.info("({}) Proving done", caseId);
+
env = pair.first;
Pair script = pair.second;
loadedProof = env.getLoadedProof();
AbstractProblemLoader.ReplayResult replayResult = env.getReplayResult();
if (replayResult.hasErrors() && verbose) {
- LOGGER.info("... error(s) while loading");
+ LOGGER.info("({}) {} Error(s) while loading", caseId, replayResult.getErrorList());
for (Throwable error : replayResult.getErrorList()) {
- LOGGER.info("Error", error);
+ LOGGER.info("({}) Error", caseId, error);
}
}
if (testProperty == TestProperty.NOTLOADABLE) {
assertTrue(replayResult.hasErrors(),
- "Loading problem file succeded but it shouldn't");
+ "Loading problem file succeeded but it shouldn't");
success = true;
} else {
assertFalse(replayResult.hasErrors(), "Loading problem file failed");
@@ -118,12 +129,13 @@ private void runKey(String file, TestProperty testProperty) throws Exception {
// For a reload test we are done at this point. Loading was successful.
if (testProperty == TestProperty.LOADABLE) {
success = true;
- debugOut("... success: loaded");
+ LOGGER.info("({}) Success: loaded", caseId);
} else {
autoMode(env, loadedProof, script);
boolean closed = loadedProof.closed();
success = (testProperty == TestProperty.PROVABLE) == closed;
- debugOut("... finished proof: " + (closed ? "closed." : "open goal(s)"));
+ LOGGER.info("({}) Finished proof: {}", caseId,
+ (closed ? "closed." : "open goal(s)"));
appendStatistics(loadedProof, keyFile);
if (success) {
reload(proofFile, loadedProof);
@@ -139,7 +151,8 @@ private void runKey(String file, TestProperty testProperty) throws Exception {
}
}
- String message = String.format("%sVerifying property \"%s\"%sfor file: %s",
+ String message = String.format("(%s) %sVerifying property \"%s\"%sfor file: %s",
+ caseId,
success ? "pass: " : "FAIL: ", testProperty.toString().toLowerCase(),
success ? " was successful " : " failed ", keyFile);
diff --git a/key.core/src/test/java/de/uka/ilkd/key/proof/runallproofs/proofcollection/ProofCollection.java b/key.core/src/test/java/de/uka/ilkd/key/proof/runallproofs/proofcollection/ProofCollection.java
index ce3dc6c1bbc..ad6e1d764b4 100644
--- a/key.core/src/test/java/de/uka/ilkd/key/proof/runallproofs/proofcollection/ProofCollection.java
+++ b/key.core/src/test/java/de/uka/ilkd/key/proof/runallproofs/proofcollection/ProofCollection.java
@@ -8,6 +8,7 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
+import java.util.function.Predicate;
import de.uka.ilkd.key.proof.runallproofs.RunAllProofsTestUnit;
@@ -86,4 +87,17 @@ public GroupedProofCollectionUnit group(String name) {
units.add(unit);
return unit;
}
+
+ /**
+ * Removes all groups from this collection except the given names
+ *
+ * @param groupNames a list of groups to be kept
+ */
+ public void keep(String... groupNames) {
+ Arrays.sort(groupNames);
+ Predicate toBeKept = (String s) -> Arrays.binarySearch(groupNames, s) >= 0;
+ Predicate super ProofCollectionUnit> pred =
+ c -> c instanceof GroupedProofCollectionUnit u && toBeKept.test(u.getName());
+ units.removeIf(pred.negate());
+ }
}
diff --git a/key.core/src/test/java/de/uka/ilkd/key/rule/TestApplyTaclet.java b/key.core/src/test/java/de/uka/ilkd/key/rule/TestApplyTaclet.java
index 8222553647e..4e5c282d8cc 100644
--- a/key.core/src/test/java/de/uka/ilkd/key/rule/TestApplyTaclet.java
+++ b/key.core/src/test/java/de/uka/ilkd/key/rule/TestApplyTaclet.java
@@ -27,6 +27,7 @@
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
import static org.junit.jupiter.api.Assertions.*;
@@ -739,7 +740,7 @@ private void doTestCatchList(int p_proof) {
Term resultFormula = goals.head().sequent().getFormulabyNr(1).formula();
Term correctFormula = correctSeq.getFormulabyNr(1).formula();
- assertTrue(resultFormula.equalsModRenaming(correctFormula),
+ assertTrue(resultFormula.equalsModProperty(correctFormula, RENAMING_PROPERTY),
"Wrong result. Expected:"
+ ProofSaver.printAnything(correctFormula, TacletForTests.services()) + " But was:"
+ ProofSaver.printAnything(resultFormula, TacletForTests.services()));
diff --git a/key.core/src/test/java/de/uka/ilkd/key/rule/conditions/TestApplyUpdateOnRigidCondition.java b/key.core/src/test/java/de/uka/ilkd/key/rule/conditions/TestApplyUpdateOnRigidCondition.java
index aa6faa6f5a2..91ff2692110 100644
--- a/key.core/src/test/java/de/uka/ilkd/key/rule/conditions/TestApplyUpdateOnRigidCondition.java
+++ b/key.core/src/test/java/de/uka/ilkd/key/rule/conditions/TestApplyUpdateOnRigidCondition.java
@@ -16,6 +16,7 @@
import org.junit.jupiter.api.Test;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
import static org.junit.jupiter.api.Assertions.*;
public class TestApplyUpdateOnRigidCondition {
@@ -24,7 +25,7 @@ void updateWithoutVariables() {
Term term = TacletForTests.parseTerm("{i:=0}\\forall int a; a = i");
Term result = applyUpdateOnFormula(term);
Term expected = TacletForTests.parseTerm("\\forall int a; {i:=0}(a = i)");
- assertTrue(expected.equalsModRenaming(result),
+ assertTrue(expected.equalsModProperty(result, RENAMING_PROPERTY),
"Update without free variables was not properly applied on formula!");
term = TacletForTests.parseTerm("{i:=0}(i = 0)");
@@ -36,7 +37,7 @@ void updateWithoutVariables() {
term = TacletForTests.parseTerm("{i:=0} f(const)");
result = applyUpdateOnTerm(term);
expected = TacletForTests.parseTerm("f({i:=0} const)");
- assertTrue(expected.equalsModRenaming(result),
+ assertTrue(expected.equalsModProperty(result, RENAMING_PROPERTY),
"Update without free variables was not properly applied on term!");
}
@@ -50,21 +51,21 @@ void updateWithVariablesNoClash() {
Term result = tb.all(b, applyUpdateOnFormula(term.sub(0)));
Term expected =
TacletForTests.parseTerm("\\forall int b; \\forall java.lang.Object a; {i:=b} (a = i)");
- assertTrue(expected.equalsModRenaming(result),
+ assertTrue(expected.equalsModProperty(result, RENAMING_PROPERTY),
"Update is not simply pulled over quantification!");
term = TacletForTests.parseTerm("\\forall int b; {i:=b} (0 = i)");
b = term.boundVars().get(0);
result = tb.all(b, applyUpdateOnFormula(term.sub(0)));
expected = TacletForTests.parseTerm("\\forall int b; {i:=b} 0 = {i:=b} i");
- assertTrue(expected.equalsModRenaming(result),
+ assertTrue(expected.equalsModProperty(result, RENAMING_PROPERTY),
"Update is not simply pulled over equality!");
term = TacletForTests.parseTerm("\\forall int b; {i:=b} f(const) = 0");
b = term.boundVars().get(0);
result = tb.all(b, tb.equals(applyUpdateOnTerm(term.sub(0).sub(0)), term.sub(0).sub(1)));
expected = TacletForTests.parseTerm("\\forall int b; f({i:=b} const) = 0");
- assertTrue(expected.equalsModRenaming(result),
+ assertTrue(expected.equalsModProperty(result, RENAMING_PROPERTY),
"Update is not simply pulled over function symbol!");
}
@@ -78,7 +79,8 @@ void updateWithVariablesAndClash() {
Term result = tb.all(a, applyUpdateOnFormula(term.sub(0)));
Term expected = TacletForTests
.parseTerm("\\forall int a; \\forall java.lang.Object a1; {i:=a} (a1 = i)");
- assertTrue(expected.equalsModRenaming(result), "Renaming or applying update afterwards !");
+ assertTrue(expected.equalsModProperty(result, RENAMING_PROPERTY),
+ "Renaming or applying update afterwards !");
term = TacletForTests.parseTerm(
"\\forall int a1; \\forall int a; {i:=a}\\forall java.lang.Object a; i = a1");
@@ -87,7 +89,7 @@ void updateWithVariablesAndClash() {
result = tb.all(a, tb.all(a1, applyUpdateOnFormula(term.sub(0).sub(0))));
expected = TacletForTests.parseTerm(
"\\forall int a1; \\forall int a; \\forall java.lang.Object a2; {i:=a} (i = a1)");
- assertTrue(expected.equalsModProofIrrelevancy(result),
+ assertTrue(expected.equalsModProperty(result, RENAMING_PROPERTY),
"Counter appended to stem was not increased high enough!");
}
diff --git a/key.core/src/test/java/de/uka/ilkd/key/smt/newsmt2/ProveSMTLemmasTest.java b/key.core/src/test/java/de/uka/ilkd/key/smt/newsmt2/ProveSMTLemmasTest.java
index c249a963a4f..9cec342e8fc 100644
--- a/key.core/src/test/java/de/uka/ilkd/key/smt/newsmt2/ProveSMTLemmasTest.java
+++ b/key.core/src/test/java/de/uka/ilkd/key/smt/newsmt2/ProveSMTLemmasTest.java
@@ -33,6 +33,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+
/**
* This test case makes sure that all KeY formulas which are translated to axioms in SMT can
* actually be proved in KeY.
@@ -90,7 +92,7 @@ public void testSMTLemmaSoundness(String name, String lemmaString) throws Except
KeyIO io = new KeyIO(loadedProof.getServices());
Term parsedLemma = io.parseExpression(lemmaString);
Term actual = loadedProof.root().sequent().succedent().get(0).formula();
- if (!actual.equalsModRenaming(parsedLemma)) {
+ if (!actual.equalsModProperty(parsedLemma, RENAMING_PROPERTY)) {
LOGGER.info("Stored : {}", parsedLemma);
LOGGER.warn("Proven : {}", actual);
Assertions.fail("The proven lemma is different from the stored one.");
diff --git a/key.core/src/test/java/de/uka/ilkd/key/speclang/SetStatementTest.java b/key.core/src/test/java/de/uka/ilkd/key/speclang/SetStatementTest.java
new file mode 100644
index 00000000000..514d89e0392
--- /dev/null
+++ b/key.core/src/test/java/de/uka/ilkd/key/speclang/SetStatementTest.java
@@ -0,0 +1,121 @@
+/* This file is part of KeY - https://key-project.org
+ * KeY is licensed under the GNU General Public License Version 2
+ * SPDX-License-Identifier: GPL-2.0-only */
+package de.uka.ilkd.key.speclang;
+
+import java.io.File;
+
+import de.uka.ilkd.key.java.JavaInfo;
+import de.uka.ilkd.key.java.Position;
+import de.uka.ilkd.key.java.Services;
+import de.uka.ilkd.key.java.abstraction.KeYJavaType;
+import de.uka.ilkd.key.java.abstraction.PrimitiveType;
+import de.uka.ilkd.key.logic.ProgramElementName;
+import de.uka.ilkd.key.logic.Term;
+import de.uka.ilkd.key.logic.op.LocationVariable;
+import de.uka.ilkd.key.logic.op.ProgramVariable;
+import de.uka.ilkd.key.speclang.jml.pretranslation.TextualJMLConstruct;
+import de.uka.ilkd.key.speclang.jml.pretranslation.TextualJMLSetStatement;
+import de.uka.ilkd.key.speclang.jml.translation.Context;
+import de.uka.ilkd.key.speclang.jml.translation.JMLSpecFactory;
+import de.uka.ilkd.key.speclang.njml.JmlIO;
+import de.uka.ilkd.key.speclang.njml.JmlParser;
+import de.uka.ilkd.key.util.HelperClassForTests;
+
+import org.key_project.util.collection.ImmutableList;
+import org.key_project.util.collection.ImmutableSLList;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * This class holds tests for the SetStatement.
+ *
+ * @author Julian Wiesler
+ */
+public class SetStatementTest {
+ /**
+ * the filename of the key file which is needed to create Services and JavaInfo
+ */
+ private static final String TEST_FILE = HelperClassForTests.TESTCASE_DIRECTORY + File.separator
+ + "setStatements" + File.separator + "testFile.key";
+
+ /**
+ * JavaInfo containing information about the available datatypes and methods
+ */
+ private JavaInfo javaInfo;
+
+ /**
+ * services needed for translation
+ */
+ private Services services;
+
+ /**
+ * service for JML translation
+ */
+ private JmlIO jmlIO;
+
+ /**
+ * context information needed for JmlIO/parser
+ */
+ private KeYJavaType testClassType;
+
+ /**
+ * Creates the JavaInfo, Services, and JmlIO.
+ */
+ @BeforeEach
+ public synchronized void setUp() {
+ if (javaInfo == null) {
+ javaInfo =
+ new HelperClassForTests().parse(new File(TEST_FILE)).getFirstProof().getJavaInfo();
+ services = javaInfo.getServices();
+ testClassType = javaInfo.getKeYJavaType("testPackage.TestClass");
+ }
+ var selfVar = new LocationVariable(new ProgramElementName("self"), testClassType);
+
+ var normalLocal = new LocationVariable(new ProgramElementName("normalLocal"),
+ javaInfo.getKeYJavaType(PrimitiveType.JAVA_INT));
+ var ghostLocal = new LocationVariable(new ProgramElementName("ghostLocal"),
+ javaInfo.getKeYJavaType(PrimitiveType.JAVA_INT), true, false);
+
+ jmlIO = new JmlIO(services)
+ .context(Context.inClass(testClassType, false, services.getTermBuilder()))
+ .selfVar(selfVar)
+ .parameters(ImmutableSLList.nil().append(ghostLocal, normalLocal));
+ }
+
+ @Test
+ public void test() {
+ testError("//@ set this.ghostArray[0] = 0;", "write to array");
+ testError("//@ set this.normalField = 0;", "write to normal field");
+ testNoError("//@ set this.ghostArray[0].ghostField = 0;", "write ghost field");
+ testNoError("//@ set this.ghostField = 0;", "write to ghost field");
+ testNoError("//@ set ghostLocal = 0;", "write to ghost local");
+ testError("//@ set normalLocal = 0;", "write to normal local");
+ }
+
+ private void testError(String statement, String reason) {
+ assertNotNull(parseAndCheck(statement),
+ "'" + statement + "' should produce an error: " + reason);
+ }
+
+ private void testNoError(String statement, String reason) {
+ assertNull(parseAndCheck(statement),
+ "'" + statement + "' should not produce an error: " + reason);
+ }
+
+ private String parseAndCheck(String statementText) {
+ JMLSpecFactory jsf = new JMLSpecFactory(services);
+ ImmutableList constructs =
+ new de.uka.ilkd.key.speclang.njml.PreParser(true).parseMethodLevel(statementText, null,
+ Position.newOneBased(1, 1));
+ assertEquals(constructs.size(), 1);
+ assertInstanceOf(TextualJMLSetStatement.class, constructs.head());
+ var statement = (TextualJMLSetStatement) constructs.head();
+ JmlParser.Set_statementContext context = statement.getAssignment();
+ Term assignee = jmlIO.translateTerm(context.assignee);
+ return jsf.checkSetStatementAssignee(assignee);
+ }
+}
diff --git a/key.core/src/test/java/de/uka/ilkd/key/speclang/jml/TestJMLTranslator.java b/key.core/src/test/java/de/uka/ilkd/key/speclang/jml/TestJMLTranslator.java
index 0687e3ad13e..d3c5697e58a 100644
--- a/key.core/src/test/java/de/uka/ilkd/key/speclang/jml/TestJMLTranslator.java
+++ b/key.core/src/test/java/de/uka/ilkd/key/speclang/jml/TestJMLTranslator.java
@@ -31,6 +31,8 @@
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
+import static de.uka.ilkd.key.logic.equality.RenamingProperty.RENAMING_PROPERTY;
+import static de.uka.ilkd.key.logic.equality.TermLabelsProperty.TERM_LABELS_PROPERTY;
import static java.lang.String.format;
import static org.junit.jupiter.api.Assertions.*;
@@ -57,7 +59,7 @@ public synchronized void setUp() {
atPres.put(services.getTypeConverter().getHeapLDT().getHeap(),
TB.var(TB.heapAtPreVar("heapAtPre", false)));
}
- jmlIO = new JmlIO().services(services).classType(testClassType)
+ jmlIO = new JmlIO(services).classType(testClassType)
.specMathMode(JMLInfoExtractor.getSpecMathModeOrDefault(testClassType))
.selfVar(buildSelfVarAsProgVar());
}
@@ -184,7 +186,7 @@ public void testForAll() {
services.getNamespaces().sorts().lookup(new Name("int")));
Term expected = TB.all(i, TB.imp(TB.inInt(TB.var(i)),
TB.and(TB.leq(TB.zTerm("0"), TB.var(i)), TB.leq(TB.var(i), TB.zTerm("2147483647")))));
- assertTrue(result.equalsModRenaming(expected),
+ assertTrue(result.equalsModProperty(expected, RENAMING_PROPERTY),
"Result was: " + result + "; \nExpected was: " + expected);
}
@@ -200,7 +202,7 @@ public void testForEx() {
services.getNamespaces().sorts().lookup(new Name("int")));
Term expected = TB.ex(i, TB.and(TB.inInt(TB.var(i)),
TB.and(TB.leq(TB.zTerm("0"), TB.var(i)), TB.leq(TB.var(i), TB.zTerm("2147483647")))));
- assertTrue(result.equalsModRenaming(expected),
+ assertTrue(result.equalsModProperty(expected, RENAMING_PROPERTY),
"Result was: " + result + "; \nExpected was: " + expected);
}
@@ -216,7 +218,7 @@ public void testBsumInt() {
TB.bsum(i, TB.zTerm("0"), TB.zTerm("2147483647"), TB.var(i)));
assertNotNull(result);
Assertions.assertSame(q, result.sub(0).op());
- assertTrue(result.equalsModRenaming(expected),
+ assertTrue(result.equalsModProperty(expected, RENAMING_PROPERTY),
"Result was: " + result + "; \nExpected was: " + expected);
}
@@ -230,7 +232,7 @@ public void testBsumBigInt() {
Term expected = TB.bsum(i, TB.zTerm("0"), TB.zTerm("2147483647"), TB.var(i));
assertNotNull(result);
Assertions.assertSame(q, result.op());
- assertTrue(result.equalsModRenaming(expected),
+ assertTrue(result.equalsModProperty(expected, RENAMING_PROPERTY),
"Result was: " + result + "; \nExpected was: " + expected);
}
@@ -247,7 +249,7 @@ public void testInfiniteUnion() {
TB.not(TB.equals(TB.var(o), TB.NULL())));
Term expected = TB.infiniteUnion(new QuantifiableVariable[] { o },
TB.ife(guard, TB.empty(), TB.empty()));
- assertTrue(result.equalsModRenaming(expected),
+ assertTrue(result.equalsModProperty(expected, RENAMING_PROPERTY),
"Result was: " + result + "; \nExpected was: " + expected);
}
@@ -265,7 +267,7 @@ public void testInfiniteUnion2() {
TB.or(TB.convertToFormula(TB.created(TB.var(o))), TB.equals(TB.var(o), TB.NULL()));
Term expected = TB.infiniteUnion(new QuantifiableVariable[] { o },
TB.ife(guard, TB.empty(), TB.empty()));
- assertTrue(result.equalsModRenaming(expected),
+ assertTrue(result.equalsModProperty(expected, RENAMING_PROPERTY),
"Result was: " + result + "; \nExpected was: " + expected);
}
@@ -446,7 +448,7 @@ public void testCorrectImplicitThisResolution() {
TB.not(TB.equals(TB.var(qv), TB.NULL()))), // implicit non null
TB.equals(TB.var(qv), TB.var(selfVar))));
- final boolean condition = result.equalsModRenaming(expected);
+ final boolean condition = result.equalsModProperty(expected, RENAMING_PROPERTY);
assertTrue(condition, format("Expected:%s\n Was:%s",
ProofSaver.printTerm(expected, services), ProofSaver.printTerm(result, services)));
}
@@ -477,7 +479,7 @@ public void testOperatorOverloading(String expression, String expected) {
fail("Cannot parse " + expected, e);
}
- if (!tTrans.equalsModTermLabels(tExp)) {
+ if (!tTrans.equalsModProperty(tExp, TERM_LABELS_PROPERTY)) {
// this gives nicer error
assertEquals(tExp, tTrans);
}
diff --git a/key.core/src/test/java/de/uka/ilkd/key/speclang/jml/pretranslation/TextualJMLAssertStatementTest.java b/key.core/src/test/java/de/uka/ilkd/key/speclang/jml/pretranslation/TextualJMLAssertStatementTest.java
index 3da50fba1ee..340032497a0 100644
--- a/key.core/src/test/java/de/uka/ilkd/key/speclang/jml/pretranslation/TextualJMLAssertStatementTest.java
+++ b/key.core/src/test/java/de/uka/ilkd/key/speclang/jml/pretranslation/TextualJMLAssertStatementTest.java
@@ -8,7 +8,8 @@
import org.key_project.util.collection.ImmutableList;
-import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
import static org.junit.jupiter.api.Assertions.*;
@@ -18,25 +19,20 @@ private static ImmutableList parseMethodLevel(String ms) {
return new PreParser(true).parseMethodLevel(ms, null, Position.newOneBased(1, 1));
}
- private static void assertTextRepr(String input, String text) {
+ @ParameterizedTest
+ @CsvSource(delimiter = '#',
+ textBlock = """
+ //@ assert true; # true;
+ //@ assert 1 + 2 == 3 && 2 != 3; # 1 + 2 == 3 && 2 != 3;
+ //@ assert (\\forall int j; 0 <= j < 10; true); # (\\forall int j; 0 <= j < 10; true);
+ //@ assert (\\forall int j; 0 <= j < 10; (\\exists int k; 0 <= k < 10; j == k)); # (\\forall int j; 0 <= j < 10; (\\exists int k; 0 <= k < 10; j == k));
+ """)
+ void assertTextRepr(String input, String text) {
var constructs = parseMethodLevel(input);
assertNotNull(constructs);
assertEquals(1, constructs.size());
- assertTrue(constructs.head() instanceof TextualJMLAssertStatement);
+ assertInstanceOf(TextualJMLAssertStatement.class, constructs.head());
var jmlAssert = (TextualJMLAssertStatement) constructs.head();
- var builder = new StringBuilder();
- TextualJMLAssertStatement.ruleContextToText(builder, jmlAssert.getContext().first);
- assertEquals(builder.toString(), text);
- }
-
- @Test
- public void testTextRepr() {
- assertTextRepr("//@ assert true;", "assert true ;");
- assertTextRepr("//@ assert 1 + 2 == 3 && 2 != 3;", "assert 1 + 2 == 3 && 2 != 3 ;");
- assertTextRepr("//@ assert (\\forall int j; 0 <= j < 10; true);",
- "assert ( \\forall int j ; 0 <= j < 10 ; true ) ;");
- assertTextRepr(
- "//@ assert (\\forall int j; 0 <= j < 10; (\\exists int k; 0 <= k < 10; j == k));",
- "assert ( \\forall int j ; 0 <= j < 10 ; ( \\exists int k ; 0 <= k < 10 ; j == k ) ) ;");
+ assertEquals(text, jmlAssert.getContext().getText());
}
}
diff --git a/key.core/src/test/resources/testcase/setStatements/testFile.key b/key.core/src/test/resources/testcase/setStatements/testFile.key
new file mode 100644
index 00000000000..ba49a870628
--- /dev/null
+++ b/key.core/src/test/resources/testcase/setStatements/testFile.key
@@ -0,0 +1,4 @@
+
+\javaSource "testPackage";
+
+\problem { true }
diff --git a/key.core/src/test/resources/testcase/setStatements/testPackage/TestClass.java b/key.core/src/test/resources/testcase/setStatements/testPackage/TestClass.java
new file mode 100644
index 00000000000..ec8c7f6b1f9
--- /dev/null
+++ b/key.core/src/test/resources/testcase/setStatements/testPackage/TestClass.java
@@ -0,0 +1,8 @@
+package testPackage;
+
+public class TestClass {
+ //@ ghost TestClass[] ghostArray;
+ //@ ghost int ghostField;
+ int normalField;
+ TestClass[] normalArray;
+}
diff --git a/key.core/tacletProofs/seqRules/Taclet_getOfSeqUpd.proof b/key.core/tacletProofs/seqRules/Taclet_getOfSeqUpd.proof
new file mode 100644
index 00000000000..7d18742aaaa
--- /dev/null
+++ b/key.core/tacletProofs/seqRules/Taclet_getOfSeqUpd.proof
@@ -0,0 +1,165 @@
+\profile "Java Profile";
+
+\settings // Proof-Settings-Config-File
+{
+ "Choice" : {
+ "JavaCard" : "JavaCard:off",
+ "Strings" : "Strings:on",
+ "assertions" : "assertions:safe",
+ "bigint" : "bigint:on",
+ "floatRules" : "floatRules:strictfpOnly",
+ "initialisation" : "initialisation:disableStaticInitialisation",
+ "intRules" : "intRules:arithmeticSemanticsIgnoringOF",
+ "integerSimplificationRules" : "integerSimplificationRules:full",
+ "javaLoopTreatment" : "javaLoopTreatment:efficient",
+ "mergeGenerateIsWeakeningGoal" : "mergeGenerateIsWeakeningGoal:off",
+ "methodExpansion" : "methodExpansion:modularOnly",
+ "modelFields" : "modelFields:treatAsAxiom",
+ "moreSeqRules" : "moreSeqRules:off",
+ "permissions" : "permissions:off",
+ "programRules" : "programRules:Java",
+ "reach" : "reach:on",
+ "runtimeExceptions" : "runtimeExceptions:ban",
+ "sequences" : "sequences:on",
+ "wdChecks" : "wdChecks:off",
+ "wdOperator" : "wdOperator:L"
+ },
+ "Labels" : {
+ "UseOriginLabels" : true
+ },
+ "NewSMT" : {
+
+ },
+ "SMTSettings" : {
+ "SelectedTaclets" : [
+
+ ],
+ "UseBuiltUniqueness" : false,
+ "explicitTypeHierarchy" : false,
+ "instantiateHierarchyAssumptions" : true,
+ "integersMaximum" : 2147483645,
+ "integersMinimum" : -2147483645,
+ "invariantForall" : false,
+ "maxGenericSorts" : 2,
+ "useConstantsForBigOrSmallIntegers" : true,
+ "useUninterpretedMultiplication" : true
+ },
+ "Strategy" : {
+ "ActiveStrategy" : "JavaCardDLStrategy",
+ "MaximumNumberOfAutomaticApplications" : 10000,
+ "Timeout" : -1,
+ "options" : {
+ "AUTO_INDUCTION_OPTIONS_KEY" : "AUTO_INDUCTION_OFF",
+ "BLOCK_OPTIONS_KEY" : "BLOCK_CONTRACT_INTERNAL",
+ "CLASS_AXIOM_OPTIONS_KEY" : "CLASS_AXIOM_FREE",
+ "DEP_OPTIONS_KEY" : "DEP_ON",
+ "INF_FLOW_CHECK_PROPERTY" : "INF_FLOW_CHECK_FALSE",
+ "LOOP_OPTIONS_KEY" : "LOOP_SCOPE_INV_TACLET",
+ "METHOD_OPTIONS_KEY" : "METHOD_CONTRACT",
+ "MPS_OPTIONS_KEY" : "MPS_MERGE",
+ "NON_LIN_ARITH_OPTIONS_KEY" : "NON_LIN_ARITH_NONE",
+ "OSS_OPTIONS_KEY" : "OSS_ON",
+ "QUANTIFIERS_OPTIONS_KEY" : "QUANTIFIERS_NON_SPLITTING_WITH_PROGS",
+ "QUERYAXIOM_OPTIONS_KEY" : "QUERYAXIOM_ON",
+ "QUERY_NEW_OPTIONS_KEY" : "QUERY_OFF",
+ "SPLITTING_OPTIONS_KEY" : "SPLITTING_DELAYED",
+ "STOPMODE_OPTIONS_KEY" : "STOPMODE_DEFAULT",
+ "SYMBOLIC_EXECUTION_ALIAS_CHECK_OPTIONS_KEY" : "SYMBOLIC_EXECUTION_ALIAS_CHECK_NEVER",
+ "SYMBOLIC_EXECUTION_NON_EXECUTION_BRANCH_HIDING_OPTIONS_KEY" : "SYMBOLIC_EXECUTION_NON_EXECUTION_BRANCH_HIDING_OFF",
+ "USER_TACLETS_OPTIONS_KEY1" : "USER_TACLETS_OFF",
+ "USER_TACLETS_OPTIONS_KEY2" : "USER_TACLETS_OFF",
+ "USER_TACLETS_OPTIONS_KEY3" : "USER_TACLETS_OFF",
+ "VBT_PHASE" : "VBT_SYM_EX"
+ }
+ }
+ }
+
+\proofObligation "#Proof Obligation Settings
+#Wed Jan 10 23:17:36 CET 2024
+name=getOfSeqUpd
+class=de.uka.ilkd.key.taclettranslation.lemma.TacletProofObligationInput
+";
+
+\proof {
+(keyLog "0" (keyUser "mattias" ) (keyVersion "4a2b5ce3719644caff60bd1214c21ec1cdc945ee"))
+
+(autoModeTime "574")
+
+(branch "dummy ID"
+(rule "ifthenelse_split" (formula "1") (term "1") (newnames "f_seq,f_idx,f_value,f_jdx") (userinteraction))
+(branch "0 <= f_jdx & f_jdx < f_seq.length & f_idx = f_jdx TRUE"
+ (rule "defOfSeqUpd" (formula "2") (term "0,0") (inst "uSub=uSub") (userinteraction))
+ (rule "andLeft" (formula "1"))
+ (rule "andLeft" (formula "1"))
+ (rule "eqSymm" (formula "3"))
+ (rule "getOfSeqDef" (formula "4") (term "0"))
+ (rule "add_zero_right" (formula "4") (term "1,2,0,1,0"))
+ (rule "add_zero_right" (formula "4") (term "0,0,0,1,0"))
+ (rule "replace_known_left" (formula "4") (term "0,0,0") (ifseqformula "1"))
+ (builtin "One Step Simplification" (formula "4") (ifInst "" (formula "3")))
+ (rule "orRight" (formula "4"))
+ (rule "polySimp_elimSub" (formula "4") (term "1"))
+ (rule "times_zero_2" (formula "4") (term "1,1"))
+ (rule "add_zero_right" (formula "4") (term "1"))
+ (rule "close" (formula "4") (ifseqformula "2"))
+)
+(branch "0 <= f_jdx & f_jdx < f_seq.length & f_idx = f_jdx FALSE"
+ (rule "andRight" (formula "1") (userinteraction))
+ (branch "Case 1"
+ (rule "seqSelfDefinition" (formula "2") (term "0,1") (inst "s=s") (inst "u=u") (userinteraction))
+ (rule "allLeftHide" (formula "1") (inst "t=f_seq") (userinteraction))
+ (rule "applyEqRigid" (formula "3") (term "0,1") (ifseqformula "1") (userinteraction))
+ (rule "defOfSeqUpd" (formula "3") (term "0,0") (inst "uSub=uSub") (userinteraction))
+ (rule "getOfSeqDef" (formula "3") (term "0") (userinteraction))
+ (rule "getOfSeqDef" (formula "3") (term "1") (userinteraction))
+ (rule "sub_zero_2" (formula "3") (term "1,1,0,1") (userinteraction))
+ (rule "sub_zero_2" (formula "3") (term "1,1,0,0") (userinteraction))
+ (rule "replace_known_right" (formula "3") (term "0,0") (ifseqformula "2") (userinteraction))
+ (rule "replace_known_right" (formula "3") (term "0,1") (ifseqformula "2") (userinteraction))
+ (builtin "One Step Simplification" (formula "3"))
+ (rule "closeTrue" (formula "3"))
+ )
+ (branch "Case 2"
+ (rule "defOfSeqUpd" (formula "2") (term "0,0") (inst "uSub=uSub") (userinteraction))
+ (rule "getOfSeqDef" (formula "2") (term "0") (userinteraction))
+ (rule "add_zero_right" (formula "2") (term "0,0,0,1,0") (userinteraction))
+ (rule "eqSymm" (formula "2") (term "0,0,1,0") (userinteraction))
+ (rule "replace_known_right" (formula "2") (term "0,0,1,0") (ifseqformula "1") (userinteraction))
+ (builtin "One Step Simplification" (formula "2") (userinteraction))
+ (rule "add_zero_right" (formula "2") (term "1,0,1,0") (userinteraction))
+ (rule "ifthenelse_split" (formula "2") (term "0") (userinteraction))
+ (branch "0 <= f_jdx & f_jdx < f_seq.length - 0 TRUE"
+ (rule "andLeft" (formula "1"))
+ (rule "eqSymm" (formula "3"))
+ (rule "polySimp_elimSub" (formula "2") (term "1"))
+ (rule "times_zero_2" (formula "2") (term "1,1"))
+ (rule "add_zero_right" (formula "2") (term "1"))
+ (rule "castedGetAny" (formula "4") (term "0"))
+ (builtin "One Step Simplification" (formula "4"))
+ (rule "closeTrue" (formula "4"))
+ )
+ (branch "0 <= f_jdx & f_jdx < f_seq.length - 0 FALSE"
+ (rule "sub_zero_2" (formula "2") (term "1,1") (userinteraction))
+ (rule "seqSelfDefinition" (formula "3") (term "0,1") (inst "s=s") (inst "u=u") (userinteraction))
+ (rule "allLeftHide" (formula "1") (inst "t=f_seq") (userinteraction))
+ (rule "applyEqRigid" (formula "4") (term "0,1") (ifseqformula "1") (userinteraction))
+ (rule "eqSymm" (formula "4"))
+ (rule "eqSymm" (formula "1"))
+ (rule "eqSymm" (formula "2"))
+ (rule "getOfSeqDef" (formula "4") (term "0"))
+ (builtin "One Step Simplification" (formula "4"))
+ (rule "add_zero_right" (formula "4") (term "1,0,0,1"))
+ (rule "orRight" (formula "4"))
+ (rule "notRight" (formula "4"))
+ (rule "andLeft" (formula "1"))
+ (rule "replace_known_left" (formula "5") (term "0") (ifseqformula "1"))
+ (builtin "One Step Simplification" (formula "5"))
+ (rule "polySimp_elimSub" (formula "2") (term "1"))
+ (rule "times_zero_2" (formula "2") (term "1,1"))
+ (rule "add_zero_right" (formula "2") (term "1"))
+ (rule "close" (formula "5") (ifseqformula "2"))
+ )
+ )
+)
+)
+}
diff --git a/key.core/tacletProofs/seqRules/Taclet_lenOfSeqUpd.proof b/key.core/tacletProofs/seqRules/Taclet_lenOfSeqUpd.proof
new file mode 100644
index 00000000000..075a04ca117
--- /dev/null
+++ b/key.core/tacletProofs/seqRules/Taclet_lenOfSeqUpd.proof
@@ -0,0 +1,119 @@
+\profile "Java Profile";
+
+\settings // Proof-Settings-Config-File
+{
+ "Choice" : {
+ "JavaCard" : "JavaCard:off",
+ "Strings" : "Strings:on",
+ "assertions" : "assertions:safe",
+ "bigint" : "bigint:on",
+ "floatRules" : "floatRules:strictfpOnly",
+ "initialisation" : "initialisation:disableStaticInitialisation",
+ "intRules" : "intRules:arithmeticSemanticsIgnoringOF",
+ "integerSimplificationRules" : "integerSimplificationRules:full",
+ "javaLoopTreatment" : "javaLoopTreatment:efficient",
+ "mergeGenerateIsWeakeningGoal" : "mergeGenerateIsWeakeningGoal:off",
+ "methodExpansion" : "methodExpansion:modularOnly",
+ "modelFields" : "modelFields:treatAsAxiom",
+ "moreSeqRules" : "moreSeqRules:off",
+ "permissions" : "permissions:off",
+ "programRules" : "programRules:Java",
+ "reach" : "reach:on",
+ "runtimeExceptions" : "runtimeExceptions:ban",
+ "sequences" : "sequences:on",
+ "wdChecks" : "wdChecks:off",
+ "wdOperator" : "wdOperator:L"
+ },
+ "Labels" : {
+ "UseOriginLabels" : true
+ },
+ "NewSMT" : {
+
+ },
+ "SMTSettings" : {
+ "SelectedTaclets" : [
+
+ ],
+ "UseBuiltUniqueness" : false,
+ "explicitTypeHierarchy" : false,
+ "instantiateHierarchyAssumptions" : true,
+ "integersMaximum" : 2147483645,
+ "integersMinimum" : -2147483645,
+ "invariantForall" : false,
+ "maxGenericSorts" : 2,
+ "useConstantsForBigOrSmallIntegers" : true,
+ "useUninterpretedMultiplication" : true
+ },
+ "Strategy" : {
+ "ActiveStrategy" : "JavaCardDLStrategy",
+ "MaximumNumberOfAutomaticApplications" : 10000,
+ "Timeout" : -1,
+ "options" : {
+ "AUTO_INDUCTION_OPTIONS_KEY" : "AUTO_INDUCTION_OFF",
+ "BLOCK_OPTIONS_KEY" : "BLOCK_CONTRACT_INTERNAL",
+ "CLASS_AXIOM_OPTIONS_KEY" : "CLASS_AXIOM_FREE",
+ "DEP_OPTIONS_KEY" : "DEP_ON",
+ "INF_FLOW_CHECK_PROPERTY" : "INF_FLOW_CHECK_FALSE",
+ "LOOP_OPTIONS_KEY" : "LOOP_SCOPE_INV_TACLET",
+ "METHOD_OPTIONS_KEY" : "METHOD_CONTRACT",
+ "MPS_OPTIONS_KEY" : "MPS_MERGE",
+ "NON_LIN_ARITH_OPTIONS_KEY" : "NON_LIN_ARITH_NONE",
+ "OSS_OPTIONS_KEY" : "OSS_ON",
+ "QUANTIFIERS_OPTIONS_KEY" : "QUANTIFIERS_NON_SPLITTING_WITH_PROGS",
+ "QUERYAXIOM_OPTIONS_KEY" : "QUERYAXIOM_ON",
+ "QUERY_NEW_OPTIONS_KEY" : "QUERY_OFF",
+ "SPLITTING_OPTIONS_KEY" : "SPLITTING_DELAYED",
+ "STOPMODE_OPTIONS_KEY" : "STOPMODE_DEFAULT",
+ "SYMBOLIC_EXECUTION_ALIAS_CHECK_OPTIONS_KEY" : "SYMBOLIC_EXECUTION_ALIAS_CHECK_NEVER",
+ "SYMBOLIC_EXECUTION_NON_EXECUTION_BRANCH_HIDING_OPTIONS_KEY" : "SYMBOLIC_EXECUTION_NON_EXECUTION_BRANCH_HIDING_OFF",
+ "USER_TACLETS_OPTIONS_KEY1" : "USER_TACLETS_OFF",
+ "USER_TACLETS_OPTIONS_KEY2" : "USER_TACLETS_OFF",
+ "USER_TACLETS_OPTIONS_KEY3" : "USER_TACLETS_OFF",
+ "VBT_PHASE" : "VBT_SYM_EX"
+ }
+ }
+ }
+
+\proofObligation "#Proof Obligation Settings
+#Wed Jan 10 23:18:07 CET 2024
+name=lenOfSeqUpd
+class=de.uka.ilkd.key.taclettranslation.lemma.TacletProofObligationInput
+";
+
+\proof {
+(keyLog "0" (keyUser "mattias" ) (keyVersion "4a2b5ce3719644caff60bd1214c21ec1cdc945ee"))
+
+(autoModeTime "58")
+
+(branch "dummy ID"
+(rule "defOfSeqUpd" (formula "1") (term "0,0") (newnames "f_seq,f_idx,f_value") (inst "uSub=uSub") (userinteraction))
+(rule "lenOfSeqDef" (formula "1") (term "0"))
+(rule "polySimp_elimSub" (formula "1") (term "1,0"))
+(rule "times_zero_2" (formula "1") (term "1,1,0"))
+(rule "add_zero_right" (formula "1") (term "1,0"))
+ (builtin "One Step Simplification" (formula "1"))
+(rule "orRight" (formula "1"))
+(rule "eqSymm" (formula "2"))
+(rule "inEqSimp_ltRight" (formula "1"))
+(rule "add_zero_right" (formula "1") (term "0"))
+(rule "polySimp_mulComm0" (formula "1") (term "0"))
+(rule "inEqSimp_invertInEq1" (formula "1"))
+(rule "times_zero_2" (formula "1") (term "1"))
+(rule "polySimp_mulLiterals" (formula "1") (term "0"))
+(rule "polySimp_elimOne" (formula "1") (term "0"))
+(rule "inEqSimp_strengthen0" (formula "1") (ifseqformula "2"))
+(rule "add_zero_right" (formula "1") (term "1"))
+(rule "inEqSimp_contradEq3" (formula "2") (ifseqformula "1"))
+(rule "times_zero_1" (formula "2") (term "1,0,0"))
+(rule "add_zero_right" (formula "2") (term "0,0"))
+(rule "qeq_literals" (formula "2") (term "0"))
+ (builtin "One Step Simplification" (formula "2"))
+(rule "false_right" (formula "2"))
+(rule "lenNonNegative" (formula "1") (term "0"))
+(rule "inEqSimp_commuteLeq" (formula "1"))
+(rule "inEqSimp_contradInEq0" (formula "1") (ifseqformula "2"))
+(rule "qeq_literals" (formula "1") (term "0"))
+ (builtin "One Step Simplification" (formula "1"))
+(rule "closeFalse" (formula "1"))
+)
+}
diff --git a/key.ui/examples/heap/list_seq/ArrayList.set.key b/key.ui/examples/heap/list_seq/ArrayList.set.key
new file mode 100644
index 00000000000..be5bba83056
--- /dev/null
+++ b/key.ui/examples/heap/list_seq/ArrayList.set.key
@@ -0,0 +1,3 @@
+\javaSource "src";
+
+\chooseContract "ArrayList[List::set(int,java.lang.Object)].JML normal_behavior operation contract.0";
diff --git a/key.ui/examples/heap/list_seq/LinkedList.set.key b/key.ui/examples/heap/list_seq/LinkedList.set.key
new file mode 100644
index 00000000000..b545b972920
--- /dev/null
+++ b/key.ui/examples/heap/list_seq/LinkedList.set.key
@@ -0,0 +1,3 @@
+\javaSource "src";
+
+\chooseContract "LinkedList[List::set(int,java.lang.Object)].JML normal_behavior operation contract.0";
diff --git a/key.ui/examples/heap/list_seq/src/ArrayList.java b/key.ui/examples/heap/list_seq/src/ArrayList.java
index 298efbaa31c..4764c90692b 100644
--- a/key.ui/examples/heap/list_seq/src/ArrayList.java
+++ b/key.ui/examples/heap/list_seq/src/ArrayList.java
@@ -20,7 +20,6 @@ public class ArrayList implements List {
this.array = newArray(10);
//@set seq = \seq_empty;
//@set footprint = \set_union(\all_fields(array), \all_fields(this));
- {}
}
/*@ private normal_behavior
@@ -62,14 +61,20 @@ public int size() {
return size;
}
-
public Object get(int index) {
if(index < 0 || size <= index) {
throw new IndexOutOfBoundsException();
}
return array[index];
}
-
+
+ public void set(int index, Object o) {
+ if(index < 0 || size <= index) {
+ throw new IndexOutOfBoundsException();
+ }
+ array[index] = o;
+ //@ set seq = \seq_upd(seq, index, o);
+ }
public boolean contains(Object o) {
/*@ loop_invariant 0 <= i && i <= size
@@ -85,14 +90,12 @@ public boolean contains(Object o) {
return false;
}
-
public void add(Object o) {
if(size == array.length) {
enlarge();
}
array[size++] = o;
//@set seq = \seq_concat(seq, \seq_singleton(o));
- {}
}
public void remove(Object o) {
@@ -114,7 +117,7 @@ public void remove(Object o) {
array[j] = array[j+1];
}
size--;
- //@ set seq = \seq_concat(\seq_sub(seq, 0, i), \seq_sub(seq,i+1, \seq_length(seq)));
+ //@ set seq = \seq_concat(\seq_sub(seq, 0, i), \seq_sub(seq,i+1, seq.length));
return;
}
}
diff --git a/key.ui/examples/heap/list_seq/src/LinkedList.java b/key.ui/examples/heap/list_seq/src/LinkedList.java
index 43244d520c6..ce87e933b40 100644
--- a/key.ui/examples/heap/list_seq/src/LinkedList.java
+++ b/key.ui/examples/heap/list_seq/src/LinkedList.java
@@ -53,7 +53,24 @@ public Object get(int index) {
return node.data;
}
+
+ public void set(int index, Object o) {
+ if(index < 0 || size <= index) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ Node node = first;
+ /*@ loop_invariant 0 <= i && i <= index && node == (Node)nodeseq[i];
+ @ assignable \strictly_nothing;
+ @ decreases index - i;
+ @*/
+ for(int i = 0; i < index; i++) {
+ node = node.next;
+ }
+ node.data = o;
+ //@ set seq = \seq_upd(seq, index, o);
+ }
public boolean contains(Object o) {
if(size == 0) {
@@ -115,8 +132,8 @@ public void remove(Object o) {
if(first == null) {
last = null;
}
- //@ set seq = \seq_sub(seq, 1, \seq_length(seq)-1);
- //@ set nodeseq = \seq_sub(nodeseq, 1, \seq_length(nodeseq)-1);
+ //@ set seq = \seq_sub(seq, 1, seq.length-1);
+ //@ set nodeseq = \seq_sub(nodeseq, 1, nodeseq.length-1);
size--;
return;
}
@@ -135,8 +152,8 @@ public void remove(Object o) {
if(n == last) {
last = m;
}
- //@ set seq = \seq_concat(\seq_sub(seq,0,i-1), \seq_sub(seq,i+1,\seq_length(seq)-1));
- //@ set nodeseq = \seq_concat(\seq_sub(nodeseq,0,i-1), \seq_sub(nodeseq,i+1,\seq_length(nodeseq)-1));
+ //@ set seq = \seq_concat(\seq_sub(seq,0,i-1), \seq_sub(seq,i+1,seq.length-1));
+ //@ set nodeseq = \seq_concat(\seq_sub(nodeseq,0,i-1), \seq_sub(nodeseq,i+1,nodeseq.length-1));
//@ set footprint = \set_minus(footprint, \all_fields(n));
size --;
return;
diff --git a/key.ui/examples/heap/list_seq/src/List.java b/key.ui/examples/heap/list_seq/src/List.java
index 7a982350190..69ff41be808 100644
--- a/key.ui/examples/heap/list_seq/src/List.java
+++ b/key.ui/examples/heap/list_seq/src/List.java
@@ -25,7 +25,17 @@ public interface List {
@ signals_only IndexOutOfBoundsException;
@*/
public /*@pure@*/ Object get(int index);
-
+
+ /*@ public normal_behaviour
+ @ requires 0 <= index && index < seq.length;
+ @ ensures seq == \seq_upd(\old(seq), index, o);
+ @ assignable footprint;
+ @
+ @ also public exceptional_behaviour
+ @ requires index < 0 || seq.length <= index;
+ @ signals_only IndexOutOfBoundsException;
+ @*/
+ public void set(int index, Object o);
/*@ public normal_behaviour
@ accessible footprint;
diff --git a/key.ui/examples/heap/list_seq/src/SimplifiedLL.java b/key.ui/examples/heap/list_seq/src/SimplifiedLL.java
index 4d7fc60973a..73a266f036a 100644
--- a/key.ui/examples/heap/list_seq/src/SimplifiedLL.java
+++ b/key.ui/examples/heap/list_seq/src/SimplifiedLL.java
@@ -43,7 +43,7 @@ public void remove(int i) {
Node node = getNext(i-1);
Node node2 = getNext(i);
node.next = node2.next;
- //@ set nodeseq = (\seq_concat(\seq_sub(nodeseq,0,i), \seq_sub(nodeseq,i+1,\seq_length(nodeseq))));
+ //@ set nodeseq = (\seq_concat(\seq_sub(nodeseq,0,i), \seq_sub(nodeseq,i+1,nodeseq.length)));
size --;
}
}
diff --git a/key.ui/examples/heap/vacid0_05_RedBlackTrees/src/vacid0/redblacktree/AbstractMap.java b/key.ui/examples/heap/vacid0_05_RedBlackTrees/src/vacid0/redblacktree/AbstractMap.java
index 2598ef3a42e..9f3f9b633ff 100644
--- a/key.ui/examples/heap/vacid0_05_RedBlackTrees/src/vacid0/redblacktree/AbstractMap.java
+++ b/key.ui/examples/heap/vacid0_05_RedBlackTrees/src/vacid0/redblacktree/AbstractMap.java
@@ -36,7 +36,7 @@ public interface AbstractMap{
/** Set the value of key; add it if it is not in the map yet */
/*@ public normal_behavior
@ requires 0 <= key && key < contents.length;
- @ ensures contents == \seq_put(\old(contents),key,value);
+ @ ensures contents == \seq_upd(\old(contents),key,value);
@ ensures \new_elems_fresh(footprint);
@ assignable footprint;
@*/
@@ -45,7 +45,7 @@ public interface AbstractMap{
/** Remove key from the map */
/*@ public normal_behavior
@ requires 0 <= key && key < contents.length;
- @ ensures contents == \seq_put(\old(contents),key,defaultValue);
+ @ ensures contents == \seq_upd(\old(contents),key,defaultValue);
@ ensures \new_elems_fresh(footprint);
@ assignable footprint;
@*/
diff --git a/key.ui/examples/heap/vacid0_05_RedBlackTrees/src/vacid0/redblacktree/RedBlackTree.java b/key.ui/examples/heap/vacid0_05_RedBlackTrees/src/vacid0/redblacktree/RedBlackTree.java
index 8a7c07fcc7d..4a04644366a 100644
--- a/key.ui/examples/heap/vacid0_05_RedBlackTrees/src/vacid0/redblacktree/RedBlackTree.java
+++ b/key.ui/examples/heap/vacid0_05_RedBlackTrees/src/vacid0/redblacktree/RedBlackTree.java
@@ -80,7 +80,7 @@ private void delete(Node z) {
//TODO set height
/*@ ghost int idx;
@ set idx = \indexOf(theNodes,z);
- @ set theNodes = \seq_concat(\seq_sub(theNodes, 0, idx-1),\seq_sub(theNodes, idx+1, \seq_length(theNodes)-1));
+ @ set theNodes = \seq_concat(\seq_sub(theNodes, 0, idx-1),\seq_sub(theNodes, idx+1, theNodes.length-1));
@*/
if (!y.isRed){
deleteFix(x);
diff --git a/key.ui/examples/heap/vstte12_03_RingBuffer/src/RingBuffer.java b/key.ui/examples/heap/vstte12_03_RingBuffer/src/RingBuffer.java
index f25f1564ab3..a98c174a75f 100644
--- a/key.ui/examples/heap/vstte12_03_RingBuffer/src/RingBuffer.java
+++ b/key.ui/examples/heap/vstte12_03_RingBuffer/src/RingBuffer.java
@@ -67,7 +67,7 @@ int pop() {
first = modulo(first + 1);
len--;
- //@ set list = \seq_sub(list,1,\seq_length(list));
+ //@ set list = \seq_sub(list,1,list.length);
return r;
}
diff --git a/key.ui/src/main/java/de/uka/ilkd/key/gui/IssueDialog.java b/key.ui/src/main/java/de/uka/ilkd/key/gui/IssueDialog.java
index 1575a424518..b8434c73daf 100644
--- a/key.ui/src/main/java/de/uka/ilkd/key/gui/IssueDialog.java
+++ b/key.ui/src/main/java/de/uka/ilkd/key/gui/IssueDialog.java
@@ -740,6 +740,11 @@ private void addHighlights(DefaultHighlighter dh, PositionedString ps) {
}
}
+ private boolean isJava(String fileName) {
+ // fileName can be null for URIs like "jar:file:/xxx/yyy.jar!aaa.java"
+ return fileName != null && fileName.endsWith(".java");
+ }
+
public static int getOffsetFromLineColumn(String source, Position pos) {
// Position has 1-based line and column, we need them 0-based
return getOffsetFromLineColumn(source, pos.line() - 1, pos.column() - 1);
diff --git a/key.ui/src/main/java/de/uka/ilkd/key/gui/nodeviews/HTMLSyntaxHighlighter.java b/key.ui/src/main/java/de/uka/ilkd/key/gui/nodeviews/HTMLSyntaxHighlighter.java
index e7531b942b3..c079c57265d 100644
--- a/key.ui/src/main/java/de/uka/ilkd/key/gui/nodeviews/HTMLSyntaxHighlighter.java
+++ b/key.ui/src/main/java/de/uka/ilkd/key/gui/nodeviews/HTMLSyntaxHighlighter.java
@@ -121,10 +121,15 @@ public class HTMLSyntaxHighlighter {
private static final String PROGVAR_REPLACEMENT =
"$1$2$3";
- private static final Pattern SINGLE_LINE_COMMENT_PATTERN = Pattern.compile("(//.*?)
");
+ private static final Pattern SINGLE_LINE_COMMENT_PATTERN = Pattern.compile("(//[^@].*?)
");
+
+ private static final Pattern SINGLE_LINE_JML_PATTERN = Pattern.compile("(//@.*?)
");
+
private static final String SINGLE_LINE_COMMENT_REPLACEMENT =
"
";
+ private static final String SINGLE_LINE_JML_REPLACEMENT =
+ "$1
";
private static final Pattern SEQUENT_ARROW_PATTERN = Pattern.compile("(==>|⟹)");
private static final String SEQUENT_ARROW_REPLACEMENT =
"$1";
@@ -136,22 +141,15 @@ public class HTMLSyntaxHighlighter {
* @param document The {@link HTMLDocument}
*/
public static void addCSSRulesTo(HTMLDocument document) {
- final String propLogicHighlightRule =
- ".prop_logic_highlight { color: #000000; font-weight: bold; }";
- final String foLogicHighlightRule =
- ".dynamic_logic_highlight { color: #0000C0; font-weight: bold; }";
- final String javaHighlightRule = ".java_highlight { color: #7F0055; font-weight: bold; }";
- final String progVarHighlightRule = ".progvar_highlight { color: #6A3E3E; }";
- final String commentHighlightRule = ".comment_highlight { color: #3F7F5F; }";
- final String sequentArrowHighlightRule =
- ".sequent_arrow_highlight { color: #000000; font-size: 1.7em }";
-
- document.getStyleSheet().addRule(propLogicHighlightRule);
- document.getStyleSheet().addRule(progVarHighlightRule);
- document.getStyleSheet().addRule(javaHighlightRule);
- document.getStyleSheet().addRule(foLogicHighlightRule);
- document.getStyleSheet().addRule(commentHighlightRule);
- document.getStyleSheet().addRule(sequentArrowHighlightRule);
+ document.getStyleSheet().addRule("""
+ .prop_logic_highlight { color: #000000; font-weight: bold; }
+ .dynamic_logic_highlight { color: #0000C0; font-weight: bold; }
+ .java_highlight { color: #7F0055; font-weight: bold; }
+ .progvar_highlight { color: #6A3E3E; }
+ .comment_highlight { color: #3F7F5F; }
+ .jml_highlight { color: #5553c2; }
+ .sequent_arrow_highlight { color: #000000; font-size: 1.7em }
+ """);
}
/**
@@ -235,6 +233,9 @@ private static String addSyntaxHighlighting(String htmlString,
modality = SINGLE_LINE_COMMENT_PATTERN.matcher(modality)
.replaceAll(SINGLE_LINE_COMMENT_REPLACEMENT);
+ modality = SINGLE_LINE_JML_PATTERN.matcher(modality)
+ .replaceAll(SINGLE_LINE_JML_REPLACEMENT);
+
htmlString = htmlString.replace(modalityMatcher.group(), modality);
}
diff --git a/key.ui/src/main/java/de/uka/ilkd/key/gui/sourceview/JavaDocument.java b/key.ui/src/main/java/de/uka/ilkd/key/gui/sourceview/JavaDocument.java
index 2eb275be4c5..9868aa84ce5 100644
--- a/key.ui/src/main/java/de/uka/ilkd/key/gui/sourceview/JavaDocument.java
+++ b/key.ui/src/main/java/de/uka/ilkd/key/gui/sourceview/JavaDocument.java
@@ -194,7 +194,8 @@ private enum CommentState {
"invariant_free", "model_behavior", "model_behaviour", "monitors_for", "normal_behavior",
"normal_behaviour", "readable", "writable",
// ADT functions:
- "\\seq_empty", "\\seq_def", "\\seq_singleton", "\\seq_get", "\\seq_put", "\\seq_reverse",
+ "\\seq_empty", "\\seq_def", "\\seq_singleton", "\\seq_get", "\\seq_upd", "\\seq_upd",
+ "\\seq_reverse", "\\seq_sub",
"\\seq_length", "\\index_of", "\\seq_concat", "\\empty", "\\singleton", "\\set_union",
"\\intersect", "\\set_minus", "\\all_fields", "\\infinite_union",
"\\strictly_than_nothing" };
diff --git a/recoder/build.gradle b/recoder/build.gradle
index 27147e285c5..598d8e64a13 100644
--- a/recoder/build.gradle
+++ b/recoder/build.gradle
@@ -5,7 +5,7 @@ repositories {
mavenCentral()
}
dependencies {
- implementation 'org.ow2.asm:asm:9.6'
+ implementation 'org.ow2.asm:asm:9.7'
implementation 'org.apache-extras.beanshell:bsh:2.0b6'
implementation 'net.sf.retrotranslator:retrotranslator-runtime:1.2.9'
implementation 'net.sf.retrotranslator:retrotranslator-transformer:1.2.9'
diff --git a/test/Test.java b/test/Test.java
new file mode 100644
index 00000000000..2fbd2fe0440
--- /dev/null
+++ b/test/Test.java
@@ -0,0 +1,40 @@
+class Test {
+ //@ ghost int x;
+
+ int a;
+
+ //@ requires true; ensures x==a;
+ void foo() {
+ //@set x = 0;
+ a = 0;
+ //@set x = x + 1;
+ a = a + 1;
+ //@set x = x + 1;
+ a = a + 1;
+ //@set x = x + 1;
+ a = a + 1;
+ //@set x = x + 1;
+ a = a + 1;
+ //@set x = x + 1;
+ a = a + 1;
+ }
+
+
+ //@ ghost int rec;
+ int cer;
+
+ //@ requires a >= 0; ensures rec == cer; measured_by a;
+ int voo(int a) {
+ if (a == 0) {
+ //@ set rec = 0;
+ cer = 0;
+ return 0;
+ } else {
+ int r = voo(a - 1) + 1;
+ //@ set rec = r;
+ cer = r;
+ return r;
+ }
+ }
+
+}