diff --git a/de.prob.core/src/de/prob/eventb/translator/internal/TranslationVisitor.java b/de.prob.core/src/de/prob/eventb/translator/internal/TranslationVisitor.java new file mode 100644 index 0000000000000000000000000000000000000000..24f3ab2676b564a37c77b74775797bbc948b834f --- /dev/null +++ b/de.prob.core/src/de/prob/eventb/translator/internal/TranslationVisitor.java @@ -0,0 +1,679 @@ +/** + * (c) 2009 Lehrstuhl fuer Softwaretechnik und Programmiersprachen, + * Heinrich Heine Universitaet Duesseldorf + * This software is licenced under EPL 1.0 (http://www.eclipse.org/org/documents/epl-v10.html) + * */ + +package de.prob.eventb.translator.internal; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eventb.core.ast.AssociativeExpression; +import org.eventb.core.ast.AssociativePredicate; +import org.eventb.core.ast.AtomicExpression; +import org.eventb.core.ast.BecomesEqualTo; +import org.eventb.core.ast.BecomesMemberOf; +import org.eventb.core.ast.BecomesSuchThat; +import org.eventb.core.ast.BinaryExpression; +import org.eventb.core.ast.BinaryPredicate; +import org.eventb.core.ast.BoolExpression; +import org.eventb.core.ast.BoundIdentDecl; +import org.eventb.core.ast.BoundIdentifier; +import org.eventb.core.ast.Expression; +import org.eventb.core.ast.ExtendedExpression; +import org.eventb.core.ast.ExtendedPredicate; +import org.eventb.core.ast.Formula; +import org.eventb.core.ast.FreeIdentifier; +import org.eventb.core.ast.ISimpleVisitor; +import org.eventb.core.ast.IntegerLiteral; +import org.eventb.core.ast.LiteralPredicate; +import org.eventb.core.ast.MultiplePredicate; +import org.eventb.core.ast.Predicate; +import org.eventb.core.ast.QuantifiedExpression; +import org.eventb.core.ast.QuantifiedPredicate; +import org.eventb.core.ast.RelationalPredicate; +import org.eventb.core.ast.SetExtension; +import org.eventb.core.ast.SimplePredicate; +import org.eventb.core.ast.UnaryExpression; +import org.eventb.core.ast.UnaryPredicate; + +import de.be4.classicalb.core.parser.node.*; + +public class TranslationVisitor implements ISimpleVisitor { + private static final String UNCOVERED_PREDICATE = "Uncovered Predicate"; + + private LookupStack<PPredicate> predicates = new LookupStack<PPredicate>(); + private LookupStack<PExpression> expressions = new LookupStack<PExpression>(); + private LookupStack<PSubstitution> substitutions = new LookupStack<PSubstitution>(); + private LookupStack<String> boundVariables = new LookupStack<String>(); + + public void visitAssociativeExpression( + final AssociativeExpression expression) { + // BUNION, BINTER, BCOMP, FCOMP, OVR, PLUS, MUL + List<PExpression> exprs = getSubExpressions(expression.getChildren()); + final PExpression result; + switch (expression.getTag()) { + case Formula.BUNION: + result = recurseBUNION(exprs); + break; + case Formula.BINTER: + result = recurseBINTER(exprs); + break; + case Formula.BCOMP: + result = recurseBCOMP(exprs); + break; + case Formula.FCOMP: + result = recurseFCOMP(exprs); + break; + case Formula.OVR: + result = recurseOVR(exprs); + break; + case Formula.PLUS: + result = recursePLUS(exprs); + break; + case Formula.MUL: + result = recurseMUL(exprs); + break; + default: + throw new AssertionError(UNCOVERED_PREDICATE); + } + expressions.push(result); + } + + private PExpression recurseFCOMP(final List<PExpression> list) { + final PExpression right = list.size() == 2 ? list.get(1) + : recurseFCOMP(list.subList(1, list.size())); + return new ACompositionExpression(list.get(0), right); + } + + private PExpression recurseOVR(final List<PExpression> list) { + final PExpression right = list.size() == 2 ? list.get(1) + : recurseOVR(list.subList(1, list.size())); + return new AOverwriteExpression(list.get(0), right); + } + + private PExpression recursePLUS(final List<PExpression> list) { + final PExpression right = list.size() == 2 ? list.get(1) + : recursePLUS(list.subList(1, list.size())); + return new AAddExpression(list.get(0), right); + } + + private PExpression recurseMUL(final List<PExpression> list) { + final PExpression right = list.size() == 2 ? list.get(1) + : recurseMUL(list.subList(1, list.size())); + return new AMultiplicationExpression(list.get(0), right); + } + + private PExpression recurseBUNION(final List<PExpression> list) { + final PExpression right = list.size() == 2 ? list.get(1) + : recurseBUNION(list.subList(1, list.size())); + return new AUnionExpression(list.get(0), right); + } + + private PExpression recurseBINTER(final List<PExpression> list) { + final PExpression right = list.size() == 2 ? list.get(1) + : recurseBINTER(list.subList(1, list.size())); + return new AIntersectionExpression(list.get(0), right); + } + + private PExpression recurseBCOMP(final List<PExpression> list) { + final PExpression right = list.size() == 2 ? list.get(1) + : recurseBCOMP(list.subList(1, list.size())); + return new ARingExpression(list.get(0), right); + } + + public void visitAssociativePredicate(final AssociativePredicate predicate) { + List<PPredicate> children = getSubPredicates(predicate.getChildren()); + final PPredicate result; + switch (predicate.getTag()) { + case Formula.LOR: + result = recurseOR(children); + break; + case Formula.LAND: + result = recurseAND(children); + break; + case Formula.LEQV: + result = recurseEQV(children); + break; + default: + throw new AssertionError(UNCOVERED_PREDICATE); + } + predicates.push(result); + } + + private PPredicate recurseOR(final List<PPredicate> list) { + final PPredicate right = list.size() == 2 ? list.get(1) + : recurseOR(list.subList(1, list.size())); + return new ADisjunctPredicate(list.get(0), right); + } + + private PPredicate recurseAND(final List<PPredicate> list) { + final PPredicate right = list.size() == 2 ? list.get(1) + : recurseAND(list.subList(1, list.size())); + return new AConjunctPredicate(list.get(0), right); + } + + private PPredicate recurseEQV(final List<PPredicate> list) { + final PPredicate right = list.size() == 2 ? list.get(1) + : recurseEQV(list.subList(1, list.size())); + return new AEquivalencePredicate(list.get(0), right); + } + + public void visitAtomicExpression(final AtomicExpression expression) { + final PExpression result; + switch (expression.getTag()) { + case Formula.INTEGER: + result = new AIntegerSetExpression(); + break; + case Formula.NATURAL: + result = new ANaturalSetExpression(); + break; + case Formula.NATURAL1: + result = new ANatural1SetExpression(); + break; + case Formula.BOOL: + result = new ABoolSetExpression(); + break; + case Formula.TRUE: + result = new ABooleanTrueExpression(); + break; + case Formula.FALSE: + result = new ABooleanFalseExpression(); + break; + case Formula.EMPTYSET: + result = new AEmptySetExpression(); + break; + case Formula.KPRED: + result = new APredecessorExpression(); + break; + case Formula.KSUCC: + result = new ASuccessorExpression(); + break; + case Formula.KPRJ1_GEN: // see task#215 + result = new AEventBFirstProjectionV2Expression(); + break; + case Formula.KPRJ2_GEN: + result = new AEventBSecondProjectionV2Expression(); + break; + case Formula.KID_GEN: + result = new AEventBIdentityExpression(); + break; + default: + throw new AssertionError("Uncovered Expression " + expression); + } + expressions.push(result); + } + + public void visitBecomesEqualTo(final BecomesEqualTo assignment) { + final List<PExpression> lhs = getSubExpressions(assignment + .getAssignedIdentifiers()); + final List<PExpression> rhs = getSubExpressions(assignment + .getExpressions()); + substitutions.push(new AAssignSubstitution(lhs, rhs)); + } + + public void visitBecomesMemberOf(final BecomesMemberOf assignment) { + final List<PExpression> lhs = getSubExpressions(assignment + .getAssignedIdentifiers()); + final PExpression set = getExpression(assignment.getSet()); + substitutions.push(new ABecomesElementOfSubstitution(lhs, set)); + } + + public void visitBecomesSuchThat(final BecomesSuchThat assignment) { + final List<PExpression> lhs = getSubExpressions(assignment + .getAssignedIdentifiers()); + final int originalBoundSize = boundVariables.size(); + for (final FreeIdentifier id : assignment.getFreeIdentifiers()) { + boundVariables.push(id.getName() + "'"); + } + final PPredicate predicate = getPredicate(assignment.getCondition()); + boundVariables.shrinkToSize(originalBoundSize); + substitutions.push(new ABecomesSuchSubstitution(lhs, predicate)); + } + + public void visitBinaryExpression(final BinaryExpression expression) { + final PExpression exL = getExpression(expression.getLeft()); + final PExpression exR = getExpression(expression.getRight()); + final PExpression result; + switch (expression.getTag()) { + case Formula.MAPSTO: + result = new ACoupleExpression(Arrays.asList(new PExpression[] { + exL, exR })); + break; + case Formula.REL: + result = new ARelationsExpression(exL, exR); + break; + case Formula.TREL: + result = new ATotalRelationExpression(exL, exR); + break; + case Formula.SREL: + result = new ASurjectionRelationExpression(exL, exR); + break; + case Formula.STREL: + result = new ATotalSurjectionRelationExpression(exL, exR); + break; + case Formula.PFUN: + result = new APartialFunctionExpression(exL, exR); + break; + case Formula.TFUN: + result = new ATotalFunctionExpression(exL, exR); + break; + case Formula.PINJ: + result = new APartialInjectionExpression(exL, exR); + break; + case Formula.TINJ: + result = new ATotalInjectionExpression(exL, exR); + break; + case Formula.PSUR: + result = new APartialSurjectionExpression(exL, exR); + break; + case Formula.TSUR: + result = new ATotalSurjectionExpression(exL, exR); + break; + case Formula.TBIJ: + result = new ATotalBijectionExpression(exL, exR); + break; + case Formula.SETMINUS: + result = new ASetSubtractionExpression(exL, exR); + break; + case Formula.CPROD: + result = new ACartesianProductExpression(exL, exR); + break; + case Formula.DPROD: + result = new ADirectProductExpression(exL, exR); + break; + case Formula.PPROD: + result = new AParallelProductExpression(exL, exR); + break; + case Formula.DOMRES: + result = new ADomainRestrictionExpression(exL, exR); + break; + case Formula.DOMSUB: + result = new ADomainSubtractionExpression(exL, exR); + break; + case Formula.RANRES: + result = new ARangeRestrictionExpression(exL, exR); + break; + case Formula.RANSUB: + result = new ARangeSubtractionExpression(exL, exR); + break; + case Formula.UPTO: + result = new AIntervalExpression(exL, exR); + break; + case Formula.MINUS: + result = new AMinusExpression(exL, exR); + break; + case Formula.DIV: + result = new ADivExpression(exL, exR); + break; + case Formula.MOD: + result = new AModuloExpression(exL, exR); + break; + case Formula.EXPN: + result = new APowerOfExpression(exL, exR); + break; + case Formula.FUNIMAGE: + result = new AFunctionExpression(exL, + Arrays.asList(new PExpression[] { exR })); + break; + case Formula.RELIMAGE: + result = new AImageExpression(exL, exR); + break; + default: + throw new AssertionError("Uncovered Expression"); + } + expressions.push(result); + } + + public void visitBinaryPredicate(final BinaryPredicate predicate) { + final PPredicate right = getPredicate(predicate.getLeft()); + final PPredicate left = getPredicate(predicate.getRight()); + final PPredicate result; + switch (predicate.getTag()) { + case Formula.LIMP: + result = new AImplicationPredicate(left, right); + break; + case Formula.LEQV: + result = new AEquivalencePredicate(left, right); + break; + default: + throw new AssertionError(UNCOVERED_PREDICATE); + } + predicates.push(result); + } + + public void visitBoolExpression(final BoolExpression expression) { + final PPredicate pred = getPredicate(expression.getPredicate()); + expressions.push(new AConvertBoolExpression(pred)); + } + + public void visitBoundIdentDecl(final BoundIdentDecl boundIdentDecl) { + final String name = boundIdentDecl.getName(); + boundVariables.push(name); + expressions.push(createIdentifierExpression(name)); + } + + private AIdentifierExpression createIdentifierExpression(final String name) { + return new AIdentifierExpression( + Arrays.asList(new TIdentifierLiteral[] { new TIdentifierLiteral( + name) })); + } + + public void visitBoundIdentifier(final BoundIdentifier identifierExpression) { + final String name = boundVariables.get(identifierExpression + .getBoundIndex()); + expressions.push(createIdentifierExpression(name)); + } + + public void visitFreeIdentifier(final FreeIdentifier identifierExpression) { + expressions.push(createIdentifierExpression(identifierExpression + .getName())); + } + + public void visitIntegerLiteral(final IntegerLiteral expression) { + final String value = expression.getValue().toString(); + expressions.push(new AIntegerExpression(new TIntegerLiteral(value))); + } + + public void visitLiteralPredicate(final LiteralPredicate predicate) { + final PPredicate result; + switch (predicate.getTag()) { + case Formula.BTRUE: + result = new ATruthPredicate(); + break; + case Formula.BFALSE: + result = new AFalsityPredicate(); + break; + default: + throw new AssertionError(UNCOVERED_PREDICATE); + } + predicates.push(result); + } + + public void visitQuantifiedExpression(final QuantifiedExpression expression) { + // Add quantified identifiers to bound list and recursively create + // subtrees representing the identifiers + int originalBoundSize = boundVariables.size(); + final List<PExpression> list = getSubExpressions(expression + .getBoundIdentDecls()); + final PPredicate pr = getPredicate(expression.getPredicate()); + final PExpression ex = getExpression(expression.getExpression()); + boundVariables.shrinkToSize(originalBoundSize); + + final PExpression result; + switch (expression.getTag()) { + case Formula.QUNION: + result = new AQuantifiedUnionExpression(list, pr, ex); + break; + case Formula.QINTER: + result = new AQuantifiedIntersectionExpression(list, pr, ex); + break; + case Formula.CSET: + result = new AEventBComprehensionSetExpression(list, ex, pr); + break; + default: + throw new AssertionError(UNCOVERED_PREDICATE); + } + expressions.push(result); + } + + public void visitQuantifiedPredicate(final QuantifiedPredicate predicate) { + // Add quantified identifiers to bound list and recursively create + // subtrees representing the identifiers + int originalBoundSize = boundVariables.size(); + final List<PExpression> list = getSubExpressions(predicate + .getBoundIdentDecls()); + // Recursively analyze the predicate (important, bounds are already set) + final PPredicate pred = getPredicate(predicate.getPredicate()); + boundVariables.shrinkToSize(originalBoundSize); + + final PPredicate result; + switch (predicate.getTag()) { + case Formula.EXISTS: + result = new AExistsPredicate(list, pred); + break; + case Formula.FORALL: + final PPredicate impl = pred instanceof AImplicationPredicate ? pred + : new AImplicationPredicate(new ATruthPredicate(), pred); + result = new AForallPredicate(list, impl); + break; + default: + throw new AssertionError(UNCOVERED_PREDICATE); + } + predicates.push(result); + } + + public void visitRelationalPredicate(final RelationalPredicate predicate) { + // EQUAL, NOTEQUAL, LT, LE, GT, GE, IN, NOTIN, SUBSET, + // NOTSUBSET, SUBSETEQ, NOTSUBSETEQ + predicate.getLeft().accept(this); + final PExpression left = expressions.pop(); + predicate.getRight().accept(this); + final PExpression right = expressions.pop(); + final PPredicate result; + switch (predicate.getTag()) { + case Formula.EQUAL: + result = new AEqualPredicate(left, right); + break; + case Formula.NOTEQUAL: + result = new ANotEqualPredicate(left, right); + break; + case Formula.LT: + result = new ALessPredicate(left, right); + break; + case Formula.LE: + result = new ALessEqualPredicate(left, right); + break; + case Formula.GT: + result = new AGreaterPredicate(left, right); + break; + case Formula.GE: + result = new AGreaterEqualPredicate(left, right); + break; + case Formula.IN: + result = new AMemberPredicate(left, right); + break; + case Formula.NOTIN: + result = new ANotMemberPredicate(left, right); + break; + case Formula.SUBSET: + result = new ASubsetStrictPredicate(left, right); + break; + case Formula.NOTSUBSET: + result = new ANotSubsetStrictPredicate(left, right); + break; + case Formula.SUBSETEQ: + result = new ASubsetPredicate(left, right); + break; + case Formula.NOTSUBSETEQ: + result = new ANotSubsetPredicate(left, right); + break; + default: + throw new AssertionError(UNCOVERED_PREDICATE); + } + predicates.push(result); + } + + public void visitSetExtension(final SetExtension expression) { + final Expression[] members = expression.getMembers(); + final List<PExpression> list = getSubExpressions(members); + expressions.push(new ASetExtensionExpression(list)); + } + + public void visitSimplePredicate(final SimplePredicate predicate) { + final PPredicate result; + if (predicate.getTag() == Formula.KFINITE) { + result = new AFinitePredicate( + getExpression(predicate.getExpression())); + } else { + throw new AssertionError(UNCOVERED_PREDICATE); + } + predicates.push(result); + } + + @SuppressWarnings("deprecation") + public void visitUnaryExpression(final UnaryExpression expression) { + final PExpression exp = getExpression(expression.getChild()); + final PExpression result; + switch (expression.getTag()) { + case Formula.KCARD: + result = new ACardExpression(exp); + break; + case Formula.POW: + result = new APowSubsetExpression(exp); + break; + case Formula.POW1: + result = new APow1SubsetExpression(exp); + break; + case Formula.KUNION: + result = new AGeneralUnionExpression(exp); + break; + case Formula.KINTER: + result = new AGeneralIntersectionExpression(exp); + break; + case Formula.KDOM: + result = new ADomainExpression(exp); + break; + case Formula.KRAN: + result = new ARangeExpression(exp); + break; + case Formula.KPRJ1: + result = new AEventBFirstProjectionExpression(exp); + break; + case Formula.KPRJ2: + result = new AEventBSecondProjectionExpression(exp); + break; + case Formula.KID: + result = new AIdentityExpression(exp); + break; + case Formula.KMIN: + result = new AMinExpression(exp); + break; + case Formula.KMAX: + result = new AMaxExpression(exp); + break; + case Formula.CONVERSE: + result = new AReverseExpression(exp); + break; + case Formula.UNMINUS: + result = new AUnaryMinusExpression(exp); + break; + default: + throw new AssertionError("Uncovered Expression"); + } + expressions.push(result); + } + + public void visitUnaryPredicate(final UnaryPredicate predicate) { + final PPredicate result; + if (predicate.getTag() == Formula.NOT) { + result = new ANegationPredicate(getPredicate(predicate.getChild())); + } else { + throw new AssertionError(UNCOVERED_PREDICATE); + } + predicates.push(result); + } + + public void visitMultiplePredicate(final MultiplePredicate predicate) { + final PPredicate result; + if (predicate.getTag() == Formula.KPARTITION) { + final List<PExpression> expressions = getSubExpressions(predicate + .getChildren()); + if (expressions.size() > 0) { + PExpression set = expressions.remove(0); + result = new APartitionPredicate(set, expressions); + } else { + throw new AssertionError("to few arguments for PARTITION"); + } + } else { + throw new AssertionError(UNCOVERED_PREDICATE); + } + predicates.push(result); + } + + @Override + public void visitExtendedExpression(final ExtendedExpression expression) { + final String symbol = expression.getExtension().getSyntaxSymbol(); + List<PExpression> childExprs = getSubExpressions(expression + .getChildExpressions()); + List<PPredicate> childPreds = getSubPredicates(expression + .getChildPredicates()); + expressions.push(new AExtendedExprExpression(new TIdentifierLiteral( + symbol), childExprs, childPreds)); + } + + @Override + public void visitExtendedPredicate(final ExtendedPredicate predicate) { + final String symbol = predicate.getExtension().getSyntaxSymbol(); + List<PExpression> childExprs = getSubExpressions(predicate + .getChildExpressions()); + List<PPredicate> childPreds = getSubPredicates(predicate + .getChildPredicates()); + predicates.push(new AExtendedPredPredicate(new TIdentifierLiteral( + symbol), childExprs, childPreds)); + } + + private List<PExpression> getSubExpressions(final Formula<?>[] children) { + for (final Formula<?> f : children) { + f.accept(this); + } + return expressions.removeLastElements(children.length); + } + + private List<PPredicate> getSubPredicates(final Formula<?>[] children) { + for (final Formula<?> f : children) { + f.accept(this); + } + return predicates.removeLastElements(children.length); + } + + private PPredicate getPredicate(final Predicate predicate) { + predicate.accept(this); + return predicates.pop(); + } + + private PExpression getExpression(final Expression expression) { + expression.accept(this); + return expressions.pop(); + } + + private static class LookupStack<T> { + private List<T> elements = new ArrayList<T>(); + + public void push(T elem) { + elements.add(elem); + } + + public T pop() { + return elements.remove(elements.size() - 1); + } + + public int size() { + return elements.size(); + } + + public T get(int pos) { + return elements.get(elements.size() - pos - 1); + } + + void shrinkToSize(int size) { + final int rSize = size - elements.size(); + for (int i = 0; i < rSize; i++) { + elements.remove(size - 1 - i); + } + } + + List<T> removeLastElements(int toRemove) { + final int targetSize = elements.size() - toRemove; + List<T> result = new ArrayList<T>(toRemove); + for (int i = 0; i < toRemove; i++) { + result.add(elements.get(targetSize + i)); + } + shrinkToSize(targetSize); + return result; + + } + } +}