Skip to content

Commit

Permalink
Merge branch 'main' into windowsSMTPathBug
Browse files Browse the repository at this point in the history
  • Loading branch information
WolframPfeifer committed Mar 1, 2024
2 parents 5321d2c + 573c82c commit f423328
Show file tree
Hide file tree
Showing 19 changed files with 477 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public Object visitDatatype_decl(KeYParser.Datatype_declContext ctx) {
: null;
var origin = BuilderHelpers.getPosition(ctx);
var s = new SortImpl(new Name(name), ImmutableSet.empty(), false, doc, origin);
sorts().add(s);
sorts().addSafely(s);
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import de.uka.ilkd.key.java.Services;
import de.uka.ilkd.key.logic.Name;
import de.uka.ilkd.key.logic.Namespace;
import de.uka.ilkd.key.logic.NamespaceSet;
import de.uka.ilkd.key.logic.op.Function;
import de.uka.ilkd.key.logic.op.SortDependingFunction;
Expand Down Expand Up @@ -52,16 +53,30 @@ public Object visitDatatype_decl(KeYParser.Datatype_declContext ctx) {
// weigl: all datatypes are free ==> functions are unique!
// boolean freeAdt = ctx.FREE() != null;
var sort = sorts().lookup(ctx.name.getText());
var dtNamespace = new Namespace<Function>();
for (KeYParser.Datatype_constructorContext constructorContext : ctx
.datatype_constructor()) {
Name name = new Name(constructorContext.name.getText());
Sort[] args = new Sort[constructorContext.sortId().size()];
var argNames = constructorContext.argName;
for (int i = 0; i < args.length; i++) {
args[i] = accept(constructorContext.sortId(i));
Sort argSort = accept(constructorContext.sortId(i));
args[i] = argSort;
var argName = argNames.get(i).getText();
var alreadyDefinedFn = dtNamespace.lookup(argName);
if (alreadyDefinedFn != null
&& (!alreadyDefinedFn.sort().equals(argSort)
|| !alreadyDefinedFn.argSort(0).equals(sort))) {
throw new RuntimeException("Name already in namespace: " + argName);
}
Function fn = new Function(new Name(argName), argSort, new Sort[] { sort }, null,
false, false);
dtNamespace.add(fn);
}
Function function = new Function(name, sort, args, null, true, false);
namespaces().functions().add(function);
namespaces().functions().addSafely(function);
}
namespaces().functions().addSafely(dtNamespace.allElements());
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,9 +243,95 @@ public Object visitDatatype_decl(KeYParser.Datatype_declContext ctx) {
var tbSplit = createConstructorSplit(ctx);
registerTaclet(ctx, tbSplit);

Sort dtSort = namespaces().sorts().lookup(ctx.name.getText());
for (var constructor : ctx.datatype_constructor()) {
for (int i = 0; i < constructor.sortId().size(); i++) {
var argName = constructor.argName.get(i).getText();

var tbDeconstructor = createDeconstructorTaclet(constructor, argName, i);
registerTaclet(ctx, tbDeconstructor);

var tbDeconsEq = createDeconstructorEQTaclet(constructor, argName, i, dtSort);
registerTaclet(ctx, tbDeconsEq);
}
}

return null;
}

private TacletBuilder<? extends Taclet> createDeconstructorTaclet(
KeYParser.Datatype_constructorContext constructor, String argName, int argIndex) {
var tacletBuilder = new RewriteTacletBuilder<>();
tacletBuilder
.setName(new Name(String.format("%s_Dec_%s", argName, constructor.name.getText())));
tacletBuilder.setDisplayName(
String.format("%s_Deconstruct_%s", argName, constructor.name.getText()));

var schemaVariables = new SchemaVariable[constructor.argName.size()];
var args = new Term[constructor.argName.size()];
var tb = services.getTermBuilder();

// Schema vars for constructor, e.g., Cons(head_sv, tail_sv)
for (int i = 0; i < constructor.argName.size(); i++) {
var name = constructor.argName.get(i).getText() + "_sv";
Sort sort = accept(constructor.argSort.get(i));
var sv = declareSchemaVariable(constructor, name, sort, false, false, false,
new SchemaVariableModifierSet.TermSV());
schemaVariables[i] = sv;
args[i] = tb.var(sv);
}

var function = namespaces().functions().lookup(argName);
var consFn = namespaces().functions().lookup(constructor.name.getText());

// Find, e.g, tail(Cons(head_sv, tail_sv))
tacletBuilder.setFind(tb.func(function, tb.func(consFn, args)));
tacletBuilder.addTacletGoalTemplate(
new RewriteTacletGoalTemplate(tb.var(schemaVariables[argIndex])));
tacletBuilder.setApplicationRestriction(RewriteTaclet.SAME_UPDATE_LEVEL);

return tacletBuilder;
}

private TacletBuilder<? extends Taclet> createDeconstructorEQTaclet(
KeYParser.Datatype_constructorContext constructor, String argName, int argIndex,
Sort dtSort) {
var tacletBuilder = new RewriteTacletBuilder<>();
tacletBuilder.setName(
new Name(String.format("%s_DecEQ_%s", argName, constructor.name.getText())));
tacletBuilder.setDisplayName(
String.format("%s_DeconstructEQ_%s", argName, constructor.name.getText()));

var schemaVariables = new SchemaVariable[constructor.argName.size()];
var args = new Term[constructor.argName.size()];
var tb = services.getTermBuilder();

// Schema vars for constructor, e.g., Cons(head_sv, tail_sv)
for (int i = 0; i < constructor.argName.size(); i++) {
var name = constructor.argName.get(i).getText() + "_sv";
Sort sort = accept(constructor.argSort.get(i));
var sv = declareSchemaVariable(constructor, name, sort, false, false, false,
new SchemaVariableModifierSet.TermSV());
schemaVariables[i] = sv;
args[i] = tb.var(sv);
}

var function = namespaces().functions().lookup(argName);
var consFn = namespaces().functions().lookup(constructor.name.getText());

var x = declareSchemaVariable(constructor, argName + "_x", dtSort, false, false, false,
new SchemaVariableModifierSet.TermSV());
var res = schemaVariables[argIndex];

tacletBuilder.setFind(tb.func(function, tb.var(x)));
tacletBuilder.setIfSequent(Sequent.createAnteSequent(
new Semisequent(new SequentFormula(tb.equals(tb.var(x), tb.func(consFn, args))))));
tacletBuilder.addTacletGoalTemplate(new RewriteTacletGoalTemplate(tb.var(res)));
tacletBuilder.setApplicationRestriction(RewriteTaclet.SAME_UPDATE_LEVEL);

return tacletBuilder;
}


private TacletBuilder<? extends Taclet> createInductionTaclet(
KeYParser.Datatype_declContext ctx) {
Expand Down Expand Up @@ -359,12 +445,14 @@ private RewriteTacletBuilder<RewriteTaclet> createConstructorSplit(
KeYParser.Datatype_declContext ctx) {
final var tb = services.getTermBuilder();

final String prefix = ctx.name.getText() + "_";

Map<String, Term> variables = new HashMap<>();
for (KeYParser.Datatype_constructorContext context : ctx.datatype_constructor()) {
for (int i = 0; i < context.argName.size(); i++) {
var name = context.argName.get(i).getText();
var sort = sorts().lookup(context.argSort.get(i).getText());
var sv = declareSchemaVariable(ctx, name, sort,
var sv = declareSchemaVariable(ctx, prefix + name, sort,
false, true, false,
new SchemaVariableModifierSet.TermSV());
variables.put(name, tb.var(sv));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,24 @@ public class GeneralSettings extends AbstractSettings {

private static final String CATEGORY = "General";

private static final String TACLET_FILTER = "StupidMode";
private static final String DND_DIRECTION_SENSITIVE_KEY = "DnDDirectionSensitive";
private static final String USE_JML_KEY = "UseJML";
public static final String TACLET_FILTER = "StupidMode";
public static final String DND_DIRECTION_SENSITIVE_KEY = "DnDDirectionSensitive";
public static final String USE_JML_KEY = "UseJML";

private static final String KEY_JML_ENABLED_KEYS = "JML_ENABLED_KEYS";
public static final String KEY_JML_ENABLED_KEYS = "JML_ENABLED_KEYS";

private static final String RIGHT_CLICK_MACROS_KEY = "RightClickMacros";
private static final String AUTO_SAVE = "AutoSavePeriod";
public static final String RIGHT_CLICK_MACROS_KEY = "RightClickMacros";
public static final String AUTO_SAVE = "AutoSavePeriod";

/**
* The key for storing the ensureSourceConsistency flag in settings
*/
private static final String ENSURE_SOURCE_CONSISTENCY = "EnsureSourceConsistency";

private Set<String> jmlEnabledKeys = new TreeSet<>(Set.of("key"));
/** Default value for {@link #getJmlEnabledKeys()} */
public static final Set<String> JML_ENABLED_KEYS_DEFAULT = Set.of("key");

private Set<String> jmlEnabledKeys = new TreeSet<>(JML_ENABLED_KEYS_DEFAULT);

/**
* minimize interaction is on by default
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,7 @@ public SLExpression visitEqualityexpr(JmlParser.EqualityexprContext ctx) {
if (floatResult != null) {
return floatResult;
}
exc.updatePosition(ctx.getStart());
if (tok.getText().equals("==")) {
result = termFactory.eq(result, expr.get(i));
} else {
Expand Down
60 changes: 60 additions & 0 deletions key.core/src/test/java/de/uka/ilkd/key/nparser/AdtTests.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/* 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.nparser;

import java.io.File;
import java.util.Collection;

import de.uka.ilkd.key.control.KeYEnvironment;
import de.uka.ilkd.key.logic.Name;
import de.uka.ilkd.key.proof.io.ProblemLoaderException;
import de.uka.ilkd.key.rule.Taclet;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

/**
* Tests for handling of abstract datatypes in KeY files.
*/
public class AdtTests {
private static final String EXPECTED_PRED_DEC_SUCC = """
pred_Dec_succ {
\\find(pred(succ(pred_sv)))
\\sameUpdateLevel\\replacewith(pred_sv)\s
Choices: true}""";
private static final String EXPECTED_PRED_DECEQ_SUCC = """
pred_DecEQ_succ {
\\assumes ([equals(pred_x,succ(pred_sv))]==>[])\s
\\find(pred(pred_x))
\\sameUpdateLevel\\replacewith(pred_sv)\s
Choices: true}""";

@Test
public void destructorTest() throws ProblemLoaderException {
var path = new File("../key.ui/examples/standard_key/adt/dt_nat.key");
var env = KeYEnvironment.load(path);
var taclets = env.getInitConfig().activatedTaclets();

for (Taclet taclet : taclets) {
if (taclet.name().toString().contains("_Dec"))
System.out.println(taclet.name());
}

var predDecsucc = get("pred_Dec_succ", taclets);
var predDecEqSucc = get("pred_DecEQ_succ", taclets);

Assertions.assertEquals(EXPECTED_PRED_DEC_SUCC, predDecsucc.toString());
Assertions.assertEquals(EXPECTED_PRED_DECEQ_SUCC, predDecEqSucc.toString());

}

private Taclet get(String name, Collection<Taclet> taclets) {
var n = new Name(name);
var t = taclets.stream().filter(it -> n.equals(it.name())).findAny().orElse(null);
Assertions.assertNotNull(t);
return t;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -970,6 +970,7 @@ public static ProofCollection automaticJavaDL() throws IOException {
g.loadable("standard_key/adt/dt_list_revrev.proof");
g.loadable("standard_key/adt/dt_list_appnil.proof");
g.loadable("standard_key/adt/dt_color.proof");
g.loadable("standard_key/adt/dt_list_deconstruct.key");

return c;
}
Expand Down
90 changes: 90 additions & 0 deletions key.core/src/test/java/de/uka/ilkd/key/smt/newsmt2/TestSMTMod.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/* 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.smt.newsmt2;

import java.io.File;

import de.uka.ilkd.key.control.DefaultUserInterfaceControl;
import de.uka.ilkd.key.control.KeYEnvironment;
import de.uka.ilkd.key.proof.Goal;
import de.uka.ilkd.key.proof.Proof;
import de.uka.ilkd.key.proof.io.ProblemLoaderException;
import de.uka.ilkd.key.smt.SMTProblem;
import de.uka.ilkd.key.smt.SMTSolverResult;
import de.uka.ilkd.key.smt.SMTTestSettings;
import de.uka.ilkd.key.smt.SolverLauncher;
import de.uka.ilkd.key.smt.solvertypes.SolverType;
import de.uka.ilkd.key.smt.solvertypes.SolverTypeImplementation;
import de.uka.ilkd.key.smt.solvertypes.SolverTypes;

import org.key_project.util.helper.FindResources;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.junit.jupiter.api.Assertions.*;

/**
* This class is for testing the translation of modulo from KeY to SMT
*
* @author Nils Buchholz, 2024
*/
public class TestSMTMod {

private static final Logger LOGGER = LoggerFactory.getLogger(TestSMTMod.class);

private static final File testCaseDirectory = FindResources.getTestCasesDirectory();

private static final SolverType Z3_SOLVER = SolverTypes.getSolverTypes().stream()
.filter(it -> it.getClass().equals(SolverTypeImplementation.class)
&& it.getName().equals("Z3"))
.findFirst().orElse(null);

private static final SolverType CVC4_SOLVER = SolverTypes.getSolverTypes().stream()
.filter(it -> it.getClass().equals(SolverTypeImplementation.class)
&& it.getName().equals("CVC4"))
.findFirst().orElse(null);

/**
* This tests if x mod y is non-negative and x mod y < |y| for y != 0
* thus satisfying the definition of euclidean modulo
* Tests for Z3 and CVC4
*
* @throws ProblemLoaderException Occured Exception during load of problem file
*/
@Test
public void testModSpec() throws ProblemLoaderException {
KeYEnvironment<DefaultUserInterfaceControl> env =
KeYEnvironment.load(new File(testCaseDirectory, "smt/modSpec.key"));
try {
Proof proof = env.getLoadedProof();
assertNotNull(proof);
assertEquals(1, proof.openGoals().size());
Goal g = proof.openGoals().iterator().next();
SMTSolverResult result;
if (Z3_SOLVER.isInstalled(true)) {
result = checkGoal(g, Z3_SOLVER);
assertSame(SMTSolverResult.ThreeValuedTruth.VALID, result.isValid());
} else {
LOGGER.warn("Warning:Z3 solver not installed, tests skipped.");
}
if (CVC4_SOLVER.isInstalled(true)) {
result = checkGoal(g, CVC4_SOLVER);
assertSame(SMTSolverResult.ThreeValuedTruth.VALID, result.isValid());
} else {
LOGGER.warn("Warning:CVC4 solver not installed, tests skipped.");
}
} finally {
env.dispose();
}
}

private SMTSolverResult checkGoal(Goal g, SolverType solverType) {
SolverLauncher launcher = new SolverLauncher(new SMTTestSettings());
SMTProblem problem = new SMTProblem(g);
launcher.launch(problem, g.proof().getServices(), solverType);
return problem.getFinalResult();
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
// exceptionClass: RuntimeException
// msgContains: Error in equality-expression
// position: 12/17
// position: 11/19
// verbose: true
// broken: true

// It's not the best of error messages ...
// and there is no file location information
Expand Down
9 changes: 9 additions & 0 deletions key.core/src/test/resources/testcase/smt/modSpec.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
\functions {
int y;
int x;
}

\problem {
((y>0) -> x % y >= 0 & x % y < y) & ((y<0) -> x%y >= 0 & x % y < -y)
}

2 changes: 1 addition & 1 deletion key.ui/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ run {
systemProperties["key.examples.dir"] = "$projectDir/examples"
//systemProperties["slf4j.detectLoggerNameMismatch"] = true
//systemProperties["KeyDebugFlag"] = "on"
args "--experimental"
//args "--experimental"

// this can be used to solve a problem where the OS hangs during debugging of popup menus
// (see https://docs.oracle.com/javase/10/troubleshoot/awt.htm#JSTGD425)
Expand Down
Loading

0 comments on commit f423328

Please sign in to comment.