From 0ac45da8d830f5729c952324841c49eb9e0a1302 Mon Sep 17 00:00:00 2001 From: Daejun Park Date: Mon, 27 Apr 2020 17:14:49 -0500 Subject: [PATCH] java-backend: support SMTLIB translation for KVar binders (#1237) --- .../backend/java/symbolic/KILtoSMTLib.java | 33 +++++++++++++++++++ .../regression-new/smtlib-forall/Makefile | 9 +++++ .../regression-new/smtlib-forall/a-spec.k | 13 ++++++++ .../regression-new/smtlib-forall/a-spec.k.out | 1 + .../tests/regression-new/smtlib-forall/a.k | 25 ++++++++++++++ 5 files changed, 81 insertions(+) create mode 100644 k-distribution/tests/regression-new/smtlib-forall/Makefile create mode 100644 k-distribution/tests/regression-new/smtlib-forall/a-spec.k create mode 100644 k-distribution/tests/regression-new/smtlib-forall/a-spec.k.out create mode 100644 k-distribution/tests/regression-new/smtlib-forall/a.k diff --git a/java-backend/src/main/java/org/kframework/backend/java/symbolic/KILtoSMTLib.java b/java-backend/src/main/java/org/kframework/backend/java/symbolic/KILtoSMTLib.java index 4874c99090c..9548b87c442 100644 --- a/java-backend/src/main/java/org/kframework/backend/java/symbolic/KILtoSMTLib.java +++ b/java-backend/src/main/java/org/kframework/backend/java/symbolic/KILtoSMTLib.java @@ -38,6 +38,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Set; +import java.util.Stack; public class KILtoSMTLib extends CopyOnWriteTransformer { @@ -243,6 +244,7 @@ public static CharSequence translateImplication( private final LinkedHashSet variables; private final LinkedHashMap termAbstractionMap; private final LinkedHashMap tokenEncoding; + private final Stack binders; private KILtoSMTLib(boolean allowNewVars, GlobalContext global) { this(allowNewVars, global.getDefinition(), global.krunOptions, global, new LinkedHashMap<>()); @@ -267,6 +269,7 @@ private KILtoSMTLib(boolean allowNewVars, Definition definition, KRunOptions kru this.termAbstractionMap = termAbstractionMap; variables = new LinkedHashSet<>(); tokenEncoding = new LinkedHashMap<>(); + binders = new Stack<>(); } private SMTLibTerm translate(JavaSymbolicObject object) { @@ -524,6 +527,29 @@ public SMTLibTerm transform(KItem kItem) { throw new UnsupportedOperationException(); } + if (kLabel.isBinder()) { + for (Integer keyIndex : kLabel.getBinderMap().keySet()) { + Term binderKVar = kList.get(keyIndex); + if (binderKVar instanceof UninterpretedToken && binderKVar.sort() == Sort.KVARIABLE) { + binders.push(binderKVar); + } else { + throw new UnsupportedOperationException(); + } + } + } + SMTLibTerm smtLibTerm = transformSupportedKItem(kItem); + if (kLabel.isBinder()) { + for (Integer keyIndex : kLabel.getBinderMap().keySet()) { + binders.pop(); + } + } + return smtLibTerm; + } + + private SMTLibTerm transformSupportedKItem(KItem kItem) { + KLabelConstant kLabel = (KLabelConstant) kItem.kLabel(); + KList kList = (KList) kItem.kList(); + String label = kLabel.smtlib(); if (kLabel.label().equals("Map:lookup") && krunOptions.experimental.smt.mapAsIntArray) { label = "select"; @@ -656,6 +682,13 @@ public SMTLibTerm transform(BitVector bitVector) { @Override public SMTLibTerm transform(UninterpretedToken uninterpretedToken) { + if (uninterpretedToken.sort() == Sort.KVARIABLE) { + if (binders.contains(uninterpretedToken)) { + return new SMTLibTerm(uninterpretedToken.javaBackendValue()); + } else { + throw new SMTTranslationFailure("unbounded K variable: " + uninterpretedToken); + } + } if (tokenEncoding.get(uninterpretedToken) == null) { tokenEncoding.put(uninterpretedToken, tokenEncoding.size()); } diff --git a/k-distribution/tests/regression-new/smtlib-forall/Makefile b/k-distribution/tests/regression-new/smtlib-forall/Makefile new file mode 100644 index 00000000000..436d125d262 --- /dev/null +++ b/k-distribution/tests/regression-new/smtlib-forall/Makefile @@ -0,0 +1,9 @@ +DEF=a +EXT=a +KOMPILE_FLAGS=--syntax-module A +KOMPILE_BACKEND?=java +KPROVE_FLAGS= + +TESTDIR=. + +include ../../../include/ktest.mak diff --git a/k-distribution/tests/regression-new/smtlib-forall/a-spec.k b/k-distribution/tests/regression-new/smtlib-forall/a-spec.k new file mode 100644 index 00000000000..5049668a1bc --- /dev/null +++ b/k-distribution/tests/regression-new/smtlib-forall/a-spec.k @@ -0,0 +1,13 @@ +module A-SPEC + +imports A + +rule foo(L) => 0 ... +requires forall(x, L, x >Int 10) + ensures forall(x, L, x >Int 0) + +rule bar(L1, L2) => 0 ... +requires forall(x, L1, forall(y, L2, x >Int y)) + ensures forall(x, L2, forall(y, L1, x (inI #1 #2) #3)))] +rule forall(X, V Vs, E) => E[V / X] andBool forall(X, Vs, E) +rule forall(_, .IntList, _) => true + +syntax IntList ::= List{Int,""} +syntax Bool ::= Int "inI" IntList [function, smtlib(inI)] + +syntax KItem ::= foo(IntList) +rule foo(L) => 0 + +syntax KItem ::= bar(IntList, IntList) +rule bar(L1, L2) => 0 + +syntax KVar ::= "x" [token] + | "y" [token] + +endmodule