package org.overture.pog.visitors; import org.overture.ast.analysis.AnalysisException; import org.overture.ast.analysis.QuestionAnswerAdaptor; import org.overture.ast.definitions.PDefinition; import org.overture.ast.definitions.SOperationDefinitionBase; import org.overture.ast.expressions.PExp; import org.overture.ast.node.INode; import org.overture.ast.patterns.AIgnorePattern; import org.overture.ast.patterns.ASeqBind; import org.overture.ast.patterns.ASetBind; import org.overture.ast.patterns.ATypeBind; import org.overture.ast.statements.AAlwaysStm; import org.overture.ast.statements.AAssignmentStm; import org.overture.ast.statements.AAtomicStm; import org.overture.ast.statements.ABlockSimpleBlockStm; import org.overture.ast.statements.ACallObjectStm; import org.overture.ast.statements.ACallStm; import org.overture.ast.statements.ACaseAlternativeStm; import org.overture.ast.statements.ACasesStm; import org.overture.ast.statements.AElseIfStm; import org.overture.ast.statements.AErrorCase; import org.overture.ast.statements.AExitStm; import org.overture.ast.statements.AForAllStm; import org.overture.ast.statements.AForIndexStm; import org.overture.ast.statements.AForPatternBindStm; import org.overture.ast.statements.AIfStm; import org.overture.ast.statements.ALetBeStStm; import org.overture.ast.statements.ALetStm; import org.overture.ast.statements.AReturnStm; import org.overture.ast.statements.ASpecificationStm; import org.overture.ast.statements.AStartStm; import org.overture.ast.statements.ATixeStm; import org.overture.ast.statements.ATixeStmtAlternative; import org.overture.ast.statements.ATrapStm; import org.overture.ast.statements.AWhileStm; import org.overture.ast.statements.PStm; import org.overture.ast.statements.SSimpleBlockStm; import org.overture.pog.contexts.AssignmentContext; import org.overture.pog.contexts.OpPostConditionContext; import org.overture.pog.contexts.POForAllContext; import org.overture.pog.contexts.PONameContext; import org.overture.pog.contexts.POScopeContext; import org.overture.pog.obligation.LetBeExistsObligation; import org.overture.pog.obligation.OperationCallObligation; import org.overture.pog.obligation.ProofObligationList; import org.overture.pog.obligation.SeqMembershipObligation; import org.overture.pog.obligation.SetMembershipObligation; import org.overture.pog.obligation.StateInvariantObligation; import org.overture.pog.obligation.TypeCompatibilityObligation; import org.overture.pog.obligation.WhileLoopObligation; import org.overture.pog.pub.IPOContextStack; import org.overture.pog.pub.IPogAssistantFactory; import org.overture.pog.pub.IProofObligationList; import org.overture.pog.utility.POException; import org.overture.pog.utility.PogAssistantFactory; public class PogParamStmVisitor<Q extends IPOContextStack, A extends IProofObligationList> extends QuestionAnswerAdaptor<IPOContextStack, IProofObligationList> { final private QuestionAnswerAdaptor<IPOContextStack, ? extends IProofObligationList> rootVisitor; final private QuestionAnswerAdaptor<IPOContextStack, ? extends IProofObligationList> mainVisitor; final private IPogAssistantFactory aF; public PogParamStmVisitor( QuestionAnswerAdaptor<IPOContextStack, ? extends IProofObligationList> parentVisitor, QuestionAnswerAdaptor<IPOContextStack, ? extends IProofObligationList> mainVisitor, IPogAssistantFactory assistantFactory) { this.rootVisitor = parentVisitor; this.mainVisitor = mainVisitor; this.aF = assistantFactory; } /** * <b>Warning!</b> This constructor is not for use with Overture extensions as it sets several customisable fields * to Overture defaults. Use * {@link #PogParamStmVisitor(QuestionAnswerAdaptor, QuestionAnswerAdaptor, IPogAssistantFactory)} instead * * @param parentVisitor */ public PogParamStmVisitor( QuestionAnswerAdaptor<IPOContextStack, ? extends IProofObligationList> parentVisitor) { this.rootVisitor = parentVisitor; this.mainVisitor = this; this.aF = new PogAssistantFactory(); } @Override public IProofObligationList defaultPStm(PStm node, IPOContextStack question) { return new ProofObligationList(); } @Override public IProofObligationList caseAAlwaysStm(AAlwaysStm node, IPOContextStack question) throws AnalysisException { try { IProofObligationList obligations = node.getAlways().apply(mainVisitor, question); obligations.addAll(node.getBody().apply(mainVisitor, question)); return obligations; } catch (Exception e) { throw new POException(node, e.getMessage()); } } @Override public IProofObligationList caseAAssignmentStm(AAssignmentStm node, IPOContextStack question) throws AnalysisException { try { IProofObligationList obligations = new ProofObligationList(); if (!node.getInConstructor() && node.getClassDefinition() != null && node.getClassDefinition().getInvariant() != null || node.getStateDefinition() != null && node.getStateDefinition().getInvExpression() != null) { obligations.add(new StateInvariantObligation(node, question, aF)); } obligations.addAll(node.getTarget().apply(rootVisitor, question)); obligations.addAll(node.getExp().apply(rootVisitor, question)); if (!aF.getTypeComparator().isSubType(question.checkType(node.getExp(), node.getExpType()), node.getTargetType())) { TypeCompatibilityObligation sto = TypeCompatibilityObligation.newInstance(node.getExp(), node.getTargetType(), node.getExpType(), question, aF); if (sto != null) { obligations.add(sto); } } question.push(new AssignmentContext(node, aF, question)); return obligations; } catch (Exception e) { throw new POException(node, e.getMessage()); } } @Override public IProofObligationList caseAAtomicStm(AAtomicStm node, IPOContextStack question) throws AnalysisException { try { IProofObligationList obligations = new ProofObligationList(); boolean needsInv = false; for (AAssignmentStm stmt : node.getAssignments()) { stmt.apply(mainVisitor, question); // collect the assignments if (!stmt.getInConstructor() && stmt.getClassDefinition() != null && stmt.getClassDefinition().getInvariant() != null || stmt.getStateDefinition() != null && stmt.getStateDefinition().getInvExpression() != null) { needsInv = true; } } if (needsInv) { // FIXME State Inv For Atomic assignments obligations.add(new StateInvariantObligation(node, question, aF)); } return obligations; } catch (Exception e) { throw new POException(node, e.getMessage()); } } @Override public IProofObligationList caseACallObjectStm(ACallObjectStm node, IPOContextStack question) throws AnalysisException { try { IProofObligationList obligations = new ProofObligationList(); for (PExp exp : node.getArgs()) { obligations.addAll(exp.apply(rootVisitor, question)); } return obligations; } catch (Exception e) { throw new POException(node, e.getMessage()); } } @Override public IProofObligationList caseACallStm(ACallStm node, IPOContextStack question) throws AnalysisException { try { IProofObligationList obligations = new ProofObligationList(); for (PExp exp : node.getArgs()) { obligations.addAll(exp.apply(rootVisitor, question)); } // stick possible op post_condition in the context SOperationDefinitionBase calledOp = node.apply(new GetOpCallVisitor()); if (calledOp != null) { if (calledOp.getPrecondition() != null) { obligations.add(new OperationCallObligation(node, calledOp, question, aF)); } question.push(new OpPostConditionContext(calledOp.getPostdef(), node, calledOp, aF, question)); } return obligations; } catch (Exception e) { throw new POException(node, e.getMessage()); } } @Override public IProofObligationList caseACasesStm(ACasesStm node, IPOContextStack question) throws AnalysisException { try { IProofObligationList obligations = new ProofObligationList(); boolean hasIgnore = false; for (ACaseAlternativeStm alt : node.getCases()) { if (alt.getPattern() instanceof AIgnorePattern) { hasIgnore = true; } obligations.addAll(alt.apply(mainVisitor, question)); } if (node.getOthers() != null && !hasIgnore) { obligations.addAll(node.getOthers().apply(rootVisitor, question)); } return obligations; } catch (Exception e) { throw new POException(node, e.getMessage()); } } @Override public IProofObligationList caseACaseAlternativeStm( ACaseAlternativeStm node, IPOContextStack question) throws AnalysisException { try { IProofObligationList obligations = new ProofObligationList(); obligations.addAll(node.getResult().apply(mainVisitor, question)); return obligations; } catch (Exception e) { throw new POException(node, e.getMessage()); } } @Override public IProofObligationList caseAElseIfStm(AElseIfStm node, IPOContextStack question) throws AnalysisException { try { IProofObligationList obligations = node.getElseIf().apply(rootVisitor, question); obligations.addAll(node.getThenStm().apply(mainVisitor, question)); return obligations; } catch (Exception e) { throw new POException(node, e.getMessage()); } } @Override public IProofObligationList caseAExitStm(AExitStm node, IPOContextStack question) throws AnalysisException { try { IProofObligationList obligations = new ProofObligationList(); if (node.getExpression() != null) { obligations.addAll(node.getExpression().apply(rootVisitor, question)); } return obligations; } catch (Exception e) { throw new POException(node, e.getMessage()); } } @Override public IProofObligationList caseAForAllStm(AForAllStm node, IPOContextStack question) throws AnalysisException { try { IProofObligationList obligations = node.getSet().apply(rootVisitor, question); obligations.addAll(node.getStatement().apply(mainVisitor, question)); return obligations; } catch (Exception e) { throw new POException(node, e.getMessage()); } } @Override public IProofObligationList caseAForIndexStm(AForIndexStm node, IPOContextStack question) throws AnalysisException { try { IProofObligationList obligations = node.getFrom().apply(rootVisitor, question); obligations.addAll(node.getTo().apply(rootVisitor, question)); if (node.getBy() != null) { obligations.addAll(node.getBy().apply(rootVisitor, question)); } question.push(new POScopeContext()); obligations.addAll(node.getStatement().apply(mainVisitor, question)); question.pop(); return obligations; } catch (Exception e) { throw new POException(node, e.getMessage()); } } @Override public IProofObligationList caseAForPatternBindStm(AForPatternBindStm node, IPOContextStack question) throws AnalysisException { try { IProofObligationList list = node.getExp().apply(rootVisitor, question); if (node.getPatternBind().getPattern() != null) { // Nothing to do } else if (node.getPatternBind().getBind() instanceof ATypeBind) { // Nothing to do } else if (node.getPatternBind().getBind() instanceof ASetBind) { ASetBind bind = (ASetBind) node.getPatternBind().getBind(); list.addAll(bind.getSet().apply(rootVisitor, question)); question.push(new POForAllContext(bind, node.getExp())); list.add(new SetMembershipObligation(bind.getPattern(), bind.getSet(), question, aF)); question.pop(); } else if (node.getPatternBind().getBind() instanceof ASeqBind) { ASeqBind bind = (ASeqBind) node.getPatternBind().getBind(); list.addAll(bind.getSeq().apply(rootVisitor, question)); question.push(new POForAllContext(bind, node.getExp())); list.add(new SeqMembershipObligation(bind.getPattern(), bind.getSeq(), question, aF)); question.pop(); } list.addAll(node.getStatement().apply(mainVisitor, question)); return list; } catch (Exception e) { throw new POException(node, e.getMessage()); } } @Override public IProofObligationList caseAIfStm(AIfStm node, IPOContextStack question) throws AnalysisException { try { IProofObligationList obligations = node.getIfExp().apply(rootVisitor, question); obligations.addAll(node.getThenStm().apply(mainVisitor, question)); for (AElseIfStm stmt : node.getElseIf()) { obligations.addAll(stmt.apply(mainVisitor, question)); } if (node.getElseStm() != null) { obligations.addAll(node.getElseStm().apply(mainVisitor, question)); } return obligations; } catch (Exception e) { throw new POException(node, e.getMessage()); } } @Override public IProofObligationList caseALetBeStStm(ALetBeStStm node, IPOContextStack question) throws AnalysisException { try { IProofObligationList obligations = new ProofObligationList(); obligations.add(new LetBeExistsObligation(node, question, aF)); obligations.addAll(node.getBind().apply(rootVisitor, question)); if (node.getSuchThat() != null) { obligations.addAll(node.getSuchThat().apply(rootVisitor, question)); } question.push(new POScopeContext()); obligations.addAll(node.getStatement().apply(mainVisitor, question)); question.pop(); return obligations; } catch (Exception e) { throw new POException(node, e.getMessage()); } } // @Override // public IProofObligationList caseALetStm(ALetStm node, // IPOContextStack question) throws AnalysisException // { // try // { // IProofObligationList obligations = new ProofObligationList(); // obligations.addAll(assistantFactory.createPDefinitionAssistant().getProofObligations(node.getLocalDefs(), // rootVisitor, question)); // // question.push(new POScopeContext()); // obligations.addAll(node.getStatement().apply(mainVisitor, question)); // question.pop(); // // return obligations; // } catch (Exception e) // { // throw new POException(node, e.getMessage()); // } // } @Override public IProofObligationList caseAReturnStm(AReturnStm node, IPOContextStack question) throws AnalysisException { try { IProofObligationList obligations = new ProofObligationList(); if (node.getExpression() != null) { obligations.addAll(node.getExpression().apply(rootVisitor, question)); } return obligations; } catch (Exception e) { throw new POException(node, e.getMessage()); } } // @Override // public IProofObligationList caseSSimpleBlockStm(SSimpleBlockStm node, // IPOContextStack question) { // // IProofObligationList obligations = new ProofObligationList(); // // for (PStm stmt: node.getStatements()) // { // obligations.addAll(stmt.apply(mainVisitor,question)); // } // // return obligations; // } @Override public IProofObligationList caseASpecificationStm(ASpecificationStm node, IPOContextStack question) throws AnalysisException { try { IProofObligationList obligations = new ProofObligationList(); if (node.getErrors() != null) { for (AErrorCase err : node.getErrors()) { obligations.addAll(err.getLeft().apply(rootVisitor, question)); obligations.addAll(err.getRight().apply(rootVisitor, question)); } } if (node.getPrecondition() != null) { obligations.addAll(node.getPrecondition().apply(rootVisitor, question)); } if (node.getPostcondition() != null) { obligations.addAll(node.getPostcondition().apply(rootVisitor, question)); } return obligations; } catch (Exception e) { throw new POException(node, e.getMessage()); } } @Override public IProofObligationList caseAStartStm(AStartStm node, IPOContextStack question) throws AnalysisException { try { return node.getObj().apply(rootVisitor, question); } catch (Exception e) { throw new POException(node, e.getMessage()); } } @Override public IProofObligationList caseATixeStm(ATixeStm node, IPOContextStack question) throws AnalysisException { try { IProofObligationList obligations = new ProofObligationList(); for (ATixeStmtAlternative alt : node.getTraps()) { obligations.addAll(alt.apply(rootVisitor, question)); if (alt.getPatternBind().getBind() instanceof ASetBind) { ASetBind bind = (ASetBind) alt.getPatternBind().getBind(); obligations.addAll(bind.getSet().apply(rootVisitor, question)); obligations.add(new SetMembershipObligation(bind.getPattern(), bind.getSet(), question, aF)); } else if (alt.getPatternBind().getBind() instanceof ASeqBind) { ASeqBind bind = (ASeqBind) alt.getPatternBind().getBind(); obligations.addAll(bind.getSeq().apply(rootVisitor, question)); obligations.add(new SeqMembershipObligation(bind.getPattern(), bind.getSeq(), question, aF)); } } obligations.addAll(node.getBody().apply(rootVisitor, question)); return obligations; } catch (Exception e) { throw new POException(node, e.getMessage()); } } @Override public IProofObligationList caseATrapStm(ATrapStm node, IPOContextStack question) throws AnalysisException { try { IProofObligationList list = new ProofObligationList(); if (node.getPatternBind().getPattern() != null) { // Nothing to do } else if (node.getPatternBind().getBind() instanceof ATypeBind) { // Nothing to do } else if (node.getPatternBind().getBind() instanceof ASetBind) { ASetBind bind = (ASetBind) node.getPatternBind().getBind(); list.addAll(bind.getSet().apply(rootVisitor, question)); list.add(new SetMembershipObligation(bind.getPattern(), bind.getSet(), question, aF)); } else if (node.getPatternBind().getBind() instanceof ASeqBind) { ASeqBind bind = (ASeqBind) node.getPatternBind().getBind(); list.addAll(bind.getSeq().apply(rootVisitor, question)); list.add(new SeqMembershipObligation(bind.getPattern(), bind.getSeq(), question, aF)); } list.addAll(node.getWith().apply(rootVisitor, question)); list.addAll(node.getBody().apply(rootVisitor, question)); return list; } catch (Exception e) { throw new POException(node, e.getMessage()); } } @Override public IProofObligationList caseAWhileStm(AWhileStm node, IPOContextStack question) throws AnalysisException { try { IProofObligationList obligations = new ProofObligationList(); obligations.add(new WhileLoopObligation(node, question, aF)); obligations.addAll(node.getExp().apply(rootVisitor, question)); obligations.addAll(node.getStatement().apply(mainVisitor, question)); return obligations; } catch (Exception e) { throw new POException(node, e.getMessage()); } } @Override public IProofObligationList caseALetStm(ALetStm node, IPOContextStack question) throws AnalysisException { try { IProofObligationList obligations = new ProofObligationList(); for (PDefinition localDef : node.getLocalDefs()) { // PDefinitionAssistantTC.get question.push(new PONameContext(aF.createPDefinitionAssistant().getVariableNames(localDef))); obligations.addAll(localDef.apply(rootVisitor, question)); question.pop(); } question.push(new POScopeContext()); obligations.addAll(node.getStatement().apply(mainVisitor, question)); question.pop(); return obligations; } catch (Exception e) { throw new POException(node, e.getMessage()); } } public IProofObligationList defaultSSimpleBlockStm(SSimpleBlockStm node, IPOContextStack question) throws AnalysisException { try { IProofObligationList obligations = new ProofObligationList(); for (PStm stmt : node.getStatements()) { obligations.addAll(stmt.apply(mainVisitor, question)); } return obligations; } catch (Exception e) { throw new POException(node, e.getMessage()); } } @Override public IProofObligationList caseABlockSimpleBlockStm( ABlockSimpleBlockStm node, IPOContextStack question) throws AnalysisException { try { IProofObligationList obligations = aF.createPDefinitionAssistant().getProofObligations(node.getAssignmentDefs(), rootVisitor, question); question.push(new POScopeContext()); obligations.addAll(defaultSSimpleBlockStm(node, question)); question.pop(); return obligations; } catch (Exception e) { throw new POException(node, e.getMessage()); } } @Override public IProofObligationList createNewReturnValue(INode node, IPOContextStack question) { return new ProofObligationList(); } @Override public IProofObligationList createNewReturnValue(Object node, IPOContextStack question) { return new ProofObligationList(); } }