Commit a7b1ed25 authored by Sarah Grebing's avatar Sarah Grebing

partly working matcher

parent c467d761
Pipeline #19950 failed with stages
in 2 minutes and 35 seconds
......@@ -4,6 +4,8 @@ import de.uka.ilkd.key.java.Services;
import de.uka.ilkd.key.logic.Semisequent;
import de.uka.ilkd.key.logic.Sequent;
import de.uka.ilkd.key.logic.Term;
import de.uka.ilkd.key.parser.DefaultTermParser;
import de.uka.ilkd.key.parser.ParserException;
import edu.kit.iti.formal.psdbg.termmatcher.MatchPatternLexer;
import edu.kit.iti.formal.psdbg.termmatcher.MatchPatternParser;
import edu.kit.iti.formal.psdbg.termmatcher.mp.MatchPathFacade;
......@@ -13,6 +15,8 @@ import org.antlr.v4.runtime.CommonTokenStream;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.StringReader;
/**
* A facade for capturing everything we want to do with matchers.
*
......@@ -25,6 +29,8 @@ public class MatcherFacade {
public static Matchings matches(String pattern, Term keyTerm, Services services) {
MatcherImpl matcher = new MatcherImpl(services);
matcher.setCatchAll(false);
MatchPatternParser mpp = getParser(pattern);
MatchPatternParser.TermPatternContext ctx = mpp.termPattern();
return matcher.accept(ctx, MatchPathFacade.createRoot(keyTerm));
......
......@@ -3,5 +3,5 @@ description = ''
dependencies {
compile project(':rt')
compile project(':keydeps')
compile project(':matcher')
// compile project(':matcher')
}
......@@ -2,7 +2,6 @@ package edu.kit.iti.formal.psdbg.interpreter;
import de.uka.ilkd.key.api.KeYApi;
import de.uka.ilkd.key.api.ProofApi;
import de.uka.ilkd.key.api.ScriptApi;
import de.uka.ilkd.key.control.KeYEnvironment;
import de.uka.ilkd.key.macros.ProofMacro;
import de.uka.ilkd.key.macros.scripts.ProofScriptCommand;
......@@ -14,6 +13,7 @@ import edu.kit.iti.formal.psdbg.interpreter.data.GoalNode;
import edu.kit.iti.formal.psdbg.interpreter.data.KeyData;
import edu.kit.iti.formal.psdbg.interpreter.data.VariableAssignment;
import edu.kit.iti.formal.psdbg.interpreter.funchdl.*;
import edu.kit.iti.formal.psdbg.interpreter.matcher.KeYMatcher;
import edu.kit.iti.formal.psdbg.parser.Facade;
import edu.kit.iti.formal.psdbg.parser.Visitor;
import edu.kit.iti.formal.psdbg.parser.ast.CallStatement;
......
package edu.kit.iti.formal.psdbg.interpreter.functions;
import edu.kit.iti.formal.psdbg.interpreter.Evaluator;
import edu.kit.iti.formal.psdbg.interpreter.KeYMatcher;
import edu.kit.iti.formal.psdbg.interpreter.matcher.KeYMatcher;
import edu.kit.iti.formal.psdbg.interpreter.data.KeyData;
import edu.kit.iti.formal.psdbg.interpreter.data.VariableAssignment;
import edu.kit.iti.formal.psdbg.parser.NotWelldefinedException;
......
package edu.kit.iti.formal.psdbg.interpreter.matcher;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface DispatchOn {
Class<?> value();
}
package edu.kit.iti.formal.psdbg.interpreter;
package edu.kit.iti.formal.psdbg.interpreter.matcher;
import de.uka.ilkd.key.java.Services;
import de.uka.ilkd.key.logic.Name;
......@@ -12,6 +12,7 @@ import de.uka.ilkd.key.proof.init.Profile;
import de.uka.ilkd.key.rule.NoPosTacletApp;
import de.uka.ilkd.key.rule.Taclet;
import de.uka.ilkd.key.rule.TacletApp;
import edu.kit.iti.formal.psdbg.interpreter.MatcherApi;
import edu.kit.iti.formal.psdbg.interpreter.data.GoalNode;
import edu.kit.iti.formal.psdbg.interpreter.data.KeyData;
import edu.kit.iti.formal.psdbg.interpreter.data.SortType;
......@@ -20,9 +21,6 @@ import edu.kit.iti.formal.psdbg.parser.ast.Signature;
import edu.kit.iti.formal.psdbg.parser.data.Value;
import edu.kit.iti.formal.psdbg.parser.types.SimpleType;
import edu.kit.iti.formal.psdbg.parser.types.TermType;
import edu.kit.iti.formal.psdbg.termmatcher.MatcherFacade;
import edu.kit.iti.formal.psdbg.termmatcher.Matchings;
import edu.kit.iti.formal.psdbg.termmatcher.mp.MatchPath;
import lombok.Getter;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
......@@ -170,14 +168,11 @@ public class KeYMatcher implements MatcherApi<KeyData> {
}
@Override
public List<VariableAssignment> matchSeq(GoalNode<KeyData> currentState,
String data,
Signature sig) {
//System.out.println("State that will be matched " + currentState.getData().getNode().sequent() + " with pattern " + data);
public List<VariableAssignment> matchSeq(GoalNode<KeyData> currentState, String pattern, Signature sig) {
KeyMatcherFacade kmf = new KeyMatcherFacade(currentState.getData().getEnv(), currentState.getData().getNode().sequent());
//System.out.println("State that will be matched " + currentState.getData().getNode().sequent() + " with pattern " + pattern);
//System.out.println("Signature " + sig.toString());
Matchings m = MatcherFacade.matches(data,
currentState.getData().getNode().sequent(), false, currentState.getData().getProof().getServices());
Matchings m = kmf.matches(pattern, sig);
if (m.isEmpty()) {
LOGGER.debug("currentState has no match= " + currentState.getData().getNode().sequent());
......
package edu.kit.iti.formal.psdbg.interpreter.matcher;
import de.uka.ilkd.key.control.KeYEnvironment;
import de.uka.ilkd.key.logic.Sequent;
import de.uka.ilkd.key.logic.Term;
import de.uka.ilkd.key.parser.DefaultTermParser;
import de.uka.ilkd.key.parser.ParserException;
import edu.kit.iti.formal.psdbg.parser.ast.Signature;
import lombok.Builder;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
@Builder
public class KeyMatcherFacade {
private static Logger logger = LogManager.getLogger(KeyMatcherFacade.class);
private final DefaultTermParser dtp = new DefaultTermParser();
private final KeYEnvironment environment;
private final Sequent sequent;
public Matchings matches(String pattern, Signature sig) {
if(pattern.contains("==>")) {
return matchesSequent(pattern, sig);
} else {
return matchesTerm(pattern, sig);
}
}
private Matchings matchesTerm(String pattern, Signature sig) {
List<Term> positions = new ArrayList<>();
for (String patternTerm : hasToplevelComma(pattern)) {
try {
Term t = dtp.parse(createReader(patternTerm), null, environment.getServices(), environment.getServices().getNamespaces(), null, true);
positions.add(t);
} catch (ParserException e) {
e.printStackTrace();
}
}
KeyTermMatcher keyTermMatcher = new KeyTermMatcher();
return keyTermMatcher.matchesToplevel(sequent, positions);
}
static List<String> hasToplevelComma(String pattern) {
ArrayList<String> rt = new ArrayList<>();
char[] c = pattern.toCharArray();
int level = 0;
int lastPosition = 0;
for (int i = 0; i < c.length; i++) {
if(c[i]==',' && level==0){
rt.add(pattern.substring(lastPosition, i));
lastPosition=i;
}
if(c[i]=='(' || c[i]=='{')
level++;
if(c[i]==')' || c[i]=='}')
level--;
}
if(rt.isEmpty())
rt.add(pattern);
return rt;
}
private Matchings matchesSequent(String pattern, Signature sig) {
Sequent seq = null;
try {
seq = dtp.parseSeq(createReader(pattern), environment.getServices(), environment.getServices().getNamespaces(), null,true);
} catch (ParserException e) {
e.printStackTrace();
}
KeyTermMatcher keyTermMatcher = new KeyTermMatcher();
return keyTermMatcher.matchesSequent(sequent, seq);
}
private Reader createReader(String pattern) {
StringReader sr = new StringReader(pattern);
return sr;
}
}
package edu.kit.iti.formal.psdbg.interpreter.matcher;
import de.uka.ilkd.key.logic.Term;
import de.uka.ilkd.key.logic.op.Operator;
import de.uka.ilkd.key.logic.op.SchemaVariable;
import javax.xml.validation.Schema;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public abstract class KeyTermBaseVisitor<T,S> {
private Map<Class<?>, TermAcceptor<T,S>> dispatchMap = new HashMap<>();
public KeyTermBaseVisitor() {
populateMap();
}
protected void populateMap() {
Class me = getClass();
for (Method m: me.getMethods()) {
DispatchOn anno = m.getAnnotation(DispatchOn.class);
if(anno!=null){
dispatchMap.put(anno.value(),
(term,arg) -> (T) m.invoke(this, term,arg));
}
}
}
public T visit(Term term, S arg) {
Class<? extends Operator> opClazz = term.op().getClass();
if(!dispatchMap.containsKey(opClazz)) {
return defaultVisit(term, arg);
}
try {
return dispatchMap.get(opClazz).visit(term, arg);
} catch (InvocationTargetException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
protected T defaultVisit(Term term, S arg) {
throw new RuntimeException("Visiting of " +term.getClass() + " not handled by visitor: "
+ getClass().getSimpleName());
}
interface TermAcceptor<T, S> {
T visit(Term term, S arg) throws InvocationTargetException, IllegalAccessException;
}
}
package edu.kit.iti.formal.psdbg.interpreter.matcher;
import de.uka.ilkd.key.logic.*;
import de.uka.ilkd.key.logic.op.QuantifiableVariable;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* @author Alexander Weigl
* @version 1 (24.08.17)
*/
@Data
@EqualsAndHashCode(of = {"unit"})
public abstract class MatchPath<T, P> {
public static final int SEQUENT_FORMULA_ROOT = -1;
public static final int POSITION_ANTECEDENT = -2;
public static final int POSITION_SUCCEDENT = -3;
private final MatchPath<? extends P, ?> parent;
private final T unit;
private final int posInParent;
private MatchPath(MatchPath<? extends P, ?> parent, T unit, int pos) {
posInParent = pos;
this.unit = unit;
this.parent = parent;
}
public abstract PosInOccurrence pio();
public Sequent getSequent() {
if (getParent() != null)
return getParent().getSequent();
return null;
}
public SequentFormula getSequentFormula() {
if (getParent() != null)
return getParent().getSequentFormula();
return null;
}
public abstract int depth();
public String toString() {
return unit.toString();
}
public static final class MPQuantifiableVariable extends MatchPath<QuantifiableVariable, Object> {
public MPQuantifiableVariable(MatchPath<? extends Object, ?> parent, QuantifiableVariable unit, int pos) {
super(parent, unit, pos);
}
@Override
public PosInOccurrence pio() {
return null;
}
@Override
public Sequent getSequent() {
return null;
}
@Override
public SequentFormula getSequentFormula() {
return null;
}
@Override
public int depth() {
return getParent().depth() + 1;
}
}
public static class MPTerm extends MatchPath<Term, Object> {
public MPTerm(MatchPath<? extends Object, ?> parent, Term unit, int pos) {
super(parent, unit, pos);
}
@Override
public PosInOccurrence pio() {
if(getParent()==null) return null;
PosInOccurrence pio = getParent().pio();
if(getPosInParent()==SEQUENT_FORMULA_ROOT)
return pio;
return pio.down(getPosInParent());
}
@Override
public int depth() {
return getUnit().depth();
}
}
public static class MPSequentFormula extends MatchPath<SequentFormula, Semisequent> {
public MPSequentFormula(MatchPath<Semisequent, Sequent> parent, SequentFormula unit, int pos) {
super(parent, unit, pos);
}
@Override
public PosInOccurrence pio() {
return new PosInOccurrence(getUnit(), PosInTerm.getTopLevel(),
getParent().getPosInParent() == POSITION_ANTECEDENT
);
}
@Override
public Sequent getSequent() {
if (getParent() != null)
return getParent().getSequent();
return null;
}
@Override
public SequentFormula getSequentFormula() {
return getUnit();
}
@Override
public int depth() {
return getUnit().formula().depth();
}
}
public static class MPSequent extends MatchPath<Sequent, Void> {
public MPSequent(Sequent unit) {
super(null, unit, SEQUENT_FORMULA_ROOT);
}
@Override
public int depth() {
return 0;
}
@Override
public PosInOccurrence pio() {
return null;
}
@Override
public Sequent getSequent() {
return getUnit();
}
@Override
public SequentFormula getSequentFormula() {
return null;
}
}
public static class MPSemiSequent extends MatchPath<Semisequent, Sequent> {
public MPSemiSequent(MPSequent parent, Semisequent unit, boolean antec) {
super(parent, unit, antec ? POSITION_ANTECEDENT : POSITION_SUCCEDENT);
}
@Override
public int depth() {
return 1;
}
@Override
public PosInOccurrence pio() {
return null;
}
@Override
public Sequent getSequent() {
if (getParent() == null) return null;
return getParent().getSequent();
}
@Override
public SequentFormula getSequentFormula() {
return null;
}
}
}
package edu.kit.iti.formal.psdbg.interpreter.matcher;
import de.uka.ilkd.key.logic.Semisequent;
import de.uka.ilkd.key.logic.Sequent;
import de.uka.ilkd.key.logic.Term;
/**
* @author Alexander Weigl
* @version 1 (27.08.17)
*/
public class MatchPathFacade {
public static MatchPath.MPTerm create(MatchPath<Term, ?> path, int subTerm) {
return new MatchPath.MPTerm(path, path.getUnit().sub(subTerm), subTerm);
}
public static MatchPath.MPSequentFormula create(MatchPath.MPSemiSequent ss, int pos) {
return new MatchPath.MPSequentFormula(ss, ss.getUnit().get(pos), pos);
}
public static MatchPath.MPSemiSequent create(MatchPath.MPSequent s, boolean antec) {
MatchPath.MPSemiSequent mp = new MatchPath.MPSemiSequent(
s, antec
? s.getUnit().antecedent()
: s.getUnit().succedent(),
antec);
return mp;
}
public static MatchPath.MPSequent create(Sequent s) {
return new MatchPath.MPSequent(s);
}
public static MatchPath.MPTerm create(MatchPath.MPSequentFormula sf) {
return new MatchPath.MPTerm(sf, sf.getUnit().formula(), MatchPath.SEQUENT_FORMULA_ROOT);
}
public static MatchPath.MPSemiSequent createSuccedent(MatchPath.MPSequent sequent) {
return create(sequent, false);
}
public static MatchPath.MPSemiSequent createAntecedent(MatchPath.MPSequent sequent) {
return create(sequent, true);
}
/**
* only for testing
*
* @param keyTerm
* @return
*/
public static MatchPath createRoot(Term keyTerm) {
return new MatchPath.MPTerm(null, keyTerm, MatchPath.SEQUENT_FORMULA_ROOT);
}
/**
* only for testing
*
* @param semiSeq
* @return
*/
public static MatchPath createRoot(Semisequent semiSeq) {
return new MatchPath.MPSemiSequent(null, semiSeq, true);
}
}
package edu.kit.iti.formal.psdbg.interpreter.matcher;
import com.google.common.collect.Sets;
import java.util.*;
public class Matchings extends TreeSet<Map<String, MatchPath>> {
public Matchings() {
super(new VariableAssignmentComparator());
}
public Matchings(TreeMap<String, MatchPath> m) {
this();
add(m);
}
public static Matchings singleton(String name, MatchPath term) {
Matchings matchings = new Matchings();
Map<String, MatchPath> va = new TreeMap<>();
va.put(name, term);
matchings.add(va);
return matchings;
}
}
class VariableAssignmentComparator implements Comparator<Map<String, MatchPath>> {
/**
* <ol>
* <li>both maps contains the same keys</li>
* <li>foreach key in lexi-order, the depth has to be greater</li>
* </ol>
*
* @return
*/
@Override
public int compare(Map<String, MatchPath> o1, Map<String, MatchPath> o2) {
if (isTrueSubset(o1.keySet(), o2.keySet())) {
return 1;
}
if (isTrueSubset(o2.keySet(), o1.keySet())) {
return -1;
}
if (!o1.keySet().equals(o2.keySet())) {
// different domains,
// there exists at least one variable that is not assign in the other
int cmp = Integer.compare(o1.size(), o2.size());
if (cmp != 0) {
return cmp;
} else {
return compareVariableName(o1, o2);
}
}
ArrayList<String> keys = new ArrayList<>(Sets.intersection(o1.keySet(), o2.keySet()));
keys.sort(String::compareTo); // order of the traversal
keys.remove("EMPTY_MATCH");
for (String k : keys) {
int depthA = o1.get(k).depth();
int depthB = o2.get(k).depth();
int cmp = Integer.compare(depthA, depthB);
if (cmp != 0)
return cmp;
}
// all terms same depth: now let the lexi-order decide
for (String k : keys) {
int cmp = o1.get(k).toString().compareTo(o2.get(k).toString());
if (cmp != 0)
return cmp;
}
return 0;
}
private int compareVariableName(Map<String, MatchPath> o1, Map<String, MatchPath> o2) {
return variableNames(o1).compareTo(variableNames(o2));
}
private String variableNames(Map<String, MatchPath> va) {
return va.keySet().stream().reduce((a, b) -> a + '#' + b).orElse("#");
}
/**
* @param a
* @param b
* @return
*/
private boolean isTrueSubset(Set<String> a, Set<String> b) {
return b.containsAll(a) && !a.containsAll(b);
}
}
\ No newline at end of file
......@@ -6,6 +6,7 @@ import de.uka.ilkd.key.proof.Goal;
import de.uka.ilkd.key.proof.Proof;
import edu.kit.iti.formal.psdbg.interpreter.data.GoalNode;
import edu.kit.iti.formal.psdbg.interpreter.data.KeyData;
import edu.kit.iti.formal.psdbg.interpreter.matcher.KeYMatcher;
import org.junit.Assert;
import org.junit.Test;
......
package edu.kit.iti.formal.psdbg.interpreter.matcher;
import de.uka.ilkd.key.control.DefaultUserInterfaceControl;
import de.uka.ilkd.key.control.KeYEnvironment;
import de.uka.ilkd.key.java.Services;
import de.uka.ilkd.key.logic.NamespaceSet;
import de.uka.ilkd.key.logic.Sequent;
import de.uka.ilkd.key.parser.DefaultTermParser;
import de.uka.ilkd.key.parser.ParserException;
import de.uka.ilkd.key.pp.AbbrevMap;
import de.uka.ilkd.key.proof.io.ProblemLoaderException;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.io.File;
import java.io.Reader;
import java.io.StringReader;
public class KeyMatcherFacadeTest {
private final static DefaultTermParser dtp = new DefaultTermParser();
private Services services;
private AbbrevMap abbrev;
private NamespaceSet namespace;
private KeYEnvironment keyenv;
@Before
public void loadKeyEnv() throws ProblemLoaderException {
String file = getClass().getResource("test.key").toExternalForm().substring(5);
KeYEnvironment<DefaultUserInterfaceControl> env =
KeYEnvironment.load(new File(file));
keyenv = env;
services = env.getServices();
namespace = env.getServices().getNamespaces();
abbrev = new AbbrevMap();
}
@Test
public void matchSeq() throws Exception {
shouldMatch("==> pred(a), q", "==> pred(?X:S), q");
shouldMatch("==> p, q", "==> ?X:Formula");
shouldMatch("==> p, q", "==> p, q");
shouldMatch("==> p, q", "==> q, p");
shouldMatch("==> pred(a), q", "==> pred(?X)");
}
@Test
public void hasToplevelComma() throws Exception {
Assert.assertTrue(!KeyMatcherFacade.hasToplevelComma("a=b,c=d").isEmpty());
Assert.assertFalse(KeyMatcherFacade.hasToplevelComma("f(a,b)").isEmpty());
}