Commit e141acf7 authored by LULUDBR\Lulu's avatar LULUDBR\Lulu
Browse files

Merge remote-tracking branch 'origin/master'

parents 7c42f49c 298ba538
package edu.kit.iti.formal.psdbg.interpreter.matcher;
import com.google.common.collect.Sets;
import de.uka.ilkd.key.logic.*;
import de.uka.ilkd.key.logic.op.*;
import lombok.Getter;
import lombok.Setter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class KeyTermMatcher extends KeyTermBaseVisitor<Matchings, MatchPath> {
Random random = new Random(42L);
// MatchPath peek;
private List<Integer> currentposition = new ArrayList<>();
@Setter @Getter private boolean catchAll = false;
@Setter
java.util.function.BiFunction<QuantifiableVariable, Term, Term> parseQuantVar;
public Matchings matchesToplevel(Sequent sequent, List<Term> patternTerms) {
MatchPath.MPSequent seq = MatchPathFacade.create(sequent);
Matchings ret = new MutableMatchings();
Matchings antecMatches = matchesSemisequent(MatchPathFacade.createAntecedent(seq), patternTerms);
Matchings succMatches = matchesSemisequent(MatchPathFacade.createSuccedent(seq), patternTerms);
//if(!antecMatches.equals(EmptyMatch.INSTANCE))
ret.addAll(antecMatches);
//if(!succMatches.equals(EmptyMatch.INSTANCE))
ret.addAll(succMatches);
return ret;
}
public Matchings matchesSequent(Sequent sequent, Sequent pattern) {
MatchPath.MPSequent mps = MatchPathFacade.create(sequent);
MatchPath.MPSemiSequent succPath = MatchPathFacade.createSuccedent(mps);
Matchings ms = matchesSemisequent(succPath, pattern.succedent());
Matchings ma = matchesSemisequent(MatchPathFacade.createAntecedent(mps), pattern.antecedent());
return ms.reduceConform(ma);
}
private Matchings matchesSemisequent(MatchPath.MPSemiSequent peek, Semisequent pattern) {
List<Term> patterns = pattern.asList().stream().map(SequentFormula::formula).collect(Collectors.toList());
return matchesSemisequent(peek, patterns);
}
private Matchings matchesSemisequent(MatchPath.MPSemiSequent peek, List<Term> patterns) {
Semisequent semiSeq = peek.getUnit();
if (semiSeq.isEmpty()) {
if(patterns.isEmpty()){
return MutableMatchings.emptySingleton();
} else {
return NoMatch.INSTANCE;
//return new MutableMatchings();
}
}
if(!semiSeq.isEmpty() && patterns.isEmpty()){
return MutableMatchings.emptySingleton();
}
HashMap<Term, Map<SequentFormula, Matchings>> map = new HashMap<>();
List<MatchPath.MPSequentFormula> sequentFormulas =
IntStream.range(0, semiSeq.size())
.mapToObj(pos -> MatchPathFacade.create(peek, pos))
.collect(Collectors.toList());
//cartesic product of pattern and top-level terms
for (Term subPatternTerm : patterns) {
map.put(subPatternTerm, new HashMap<>());
for (MatchPath.MPSequentFormula sf : sequentFormulas) {
Matchings temp = visit(subPatternTerm, MatchPathFacade.create(sf));
if (!temp.isNoMatch())
map.get(subPatternTerm).put(sf.getUnit(), temp);
}
}
List<Matchings> matchings = new ArrayList<>();
reduceDisjoint(map, patterns, matchings);
if (map.values().stream().allMatch(Map::isEmpty))
return NoMatch.INSTANCE;
Matchings ret = new MutableMatchings();
//.filter(x -> !x.equals(EmptyMatch.INSTANCE))
matchings.forEach(ret::addAll);
return ret;
}
/**
* Visit a '...'MatchPath'...' structure
* @param pattern
* @param subject
* @return
*/
@DispatchOn(EllipsisOp.class)
public Matchings visitEllipsisOp(Term pattern, MatchPath subject) {
Matchings matchings = new MutableMatchings();
subTerms((MatchPath.MPTerm) subject).forEach(sub -> {
Matchings s = visit(pattern.sub(0), sub);
matchings.addAll(s);
});
return matchings;
}
/**
* Visit a MatchIdentifierOP e.g., ?X or ?
* @param pattern
* @param subject
* @return
*/
@DispatchOn(MatchIdentifierOp.class)
public Matchings visitMatchIdentifierOp(Term pattern, MatchPath subject) {
if(subject != null) {
String name = pattern.op().name().toString();
if (name.equalsIgnoreCase("?")) {
name = getRandomName();
}
Matchings mSingleton = MutableMatchings.singleton(name, subject);
return mSingleton;
} else {
return NoMatch.INSTANCE;
}
}
@DispatchOn(Quantifier.class)
public Matchings visitQuantifier(Term pattern, MatchPath subject) {
Term toMatch = (Term) subject.getUnit();
if (!toMatch.op().equals(pattern.op())) {
return NoMatch.INSTANCE;
}
// Decision: Order of bounded vars
if (toMatch.boundVars().size() != pattern.boundVars().size()) {
return NoMatch.INSTANCE;
}
Matchings mm = new MutableMatchings();
Match mPaths = new Match();
mm.add(mPaths);
for (int i = 0; i < toMatch.boundVars().size(); i++) {
QuantifiableVariable bv = toMatch.boundVars().get(i);
QuantifiableVariable pv = pattern.boundVars().get(i);
if (pv instanceof MatchIdentifierOp) {
//Namensbehandlung
String name;
if (pv.name().toString().equalsIgnoreCase("?")) {
name = getRandomName();
} else {
name = pv.name().toString();
}
MatchPath mp = new MatchPath.MPQuantifiableVariable(subject, bv, -i);
mPaths.put(name, mp);
// mPaths.put(name, subject);
} else if (!pv.name().equals(bv.name())) {
return NoMatch.INSTANCE;
}
}
Term scope = toMatch.sub(0);
Matchings m = visit(pattern.sub(0), MatchPathFacade.create(subject, 0));
mm = m.reduceConform(mm);
return mm;
// return null;
}
@DispatchOn(MatchBinderOp.class)
public Matchings visitMatchBinderOp(Term pattern, MatchPath subject) {
Matchings matchings = visit(pattern.sub(1), subject);
if (matchings != NoMatch.INSTANCE) {
String name = pattern.sub(0).op().name().toString();
for (Match a : matchings.getMatchings()) {
a.put(name, subject);
}
}
return matchings;
}
@Override
protected Matchings defaultVisit(Term pattern, MatchPath subject1) {
Matchings m = MutableMatchings.emptySingleton();
//Matchings m = new MutableMatchings();
MatchPath<Term, Object> subject = (MatchPath<Term, Object>) subject1;
if (subject.getUnit().subs().size() != pattern.subs().size()) {
return NoMatch.INSTANCE;
}
// if(pattern.equals(subject1.getUnit()))
// return EmptyMatch.INSTANCE;
// return Matchings.singleton(pattern.toString(), subject1);
if(pattern.op().equals(((Term) subject1.getUnit()).op())) {
for (int i = 0; i < subject.getUnit().subs().size(); i++) {
Term tt = subject.getUnit().sub(i);
Term pt = pattern.sub(i);
Matchings msub = visit(pt, MatchPathFacade.create(subject, i));
if (msub.equals(NoMatch.INSTANCE)) {
return NoMatch.INSTANCE;
}
m = m.reduceConform(msub);
}
} else {
return NoMatch.INSTANCE;
}
return m;
}
//region helper
public String getRandomName() {
return "??_" + getRandomNumber();
}
private int getRandomNumber() {
return Math.abs(random.nextInt());
}
private Stream<MatchPath.MPTerm> subTerms(MatchPath.MPTerm peek) {
ArrayList<MatchPath.MPTerm> list = new ArrayList<>();
subTerms(list, peek);
return list.stream();
}
private void subTerms(ArrayList<MatchPath.MPTerm> list, MatchPath.MPTerm peek) {
list.add(peek);
for (int i = 0; i < peek.getUnit().arity(); i++) {
subTerms(list, MatchPathFacade.create(peek, i));
}
}
//endregion
//region Reductions
/* @param map
* @param patterns
* @param matchings
*/
private void reduceDisjoint(HashMap<Term, Map<SequentFormula, Matchings>> map,
List<Term> patterns,
List<Matchings> matchings) {
reduceDisjoint(map, patterns, matchings, 0, MutableMatchings.emptySingleton(), new HashSet<>());
}
/**
* @param map
* @param patterns
* @param matchings
* @param currentPatternPos
* @param ret
* @param chosenSequentFormulas
*/
private void reduceDisjoint(HashMap<Term, Map<SequentFormula, Matchings>> map,
List<Term> patterns,
List<Matchings> matchings,
int currentPatternPos,
Matchings ret,
Set<SequentFormula> chosenSequentFormulas) {
if (currentPatternPos >= patterns.size()) { // end of selection process is reached
matchings.add(ret);
return;
}
Term currentPattern = patterns.get(currentPatternPos);
Sets.SetView<SequentFormula> topLevelFormulas =
Sets.difference(map.get(currentPattern).keySet(), chosenSequentFormulas);
if (topLevelFormulas.size() == 0) {
return; // all top level formulas has been chosen, we have no matches left
}
for (SequentFormula formula : topLevelFormulas) { // chose a toplevel formula
// the matchings for current pattern against the toplevel
Matchings m = map.get(currentPattern).get(formula);
//join them with the current Matchings
Matchings mm = m.reduceConform(ret);
chosenSequentFormulas.add(formula); // adding the formula, so other matchings can not choose it
// recursion: choose the next matchings for the next pattern
reduceDisjoint(map, patterns, matchings,
currentPatternPos + 1, mm, chosenSequentFormulas);
chosenSequentFormulas.remove(formula); // delete the formula, so it is free to choose, again
}
}
//endregion
}
package edu.kit.iti.formal.psdbg.interpreter.matcher;
import java.util.TreeMap;
public class Match extends TreeMap<String, MatchPath> {
public Match() {
}
public Match(Match h1) {
super(h1);
}
public static Match singleton(String binder, MatchPath path) {
Match m = new Match();
m.put(binder, path);
return m;
}
public static Match empty() {
Match m = new Match();
return m;
}
}
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