/******************************************************************************* * * Copyright (C) 2008 Fujitsu Services Ltd. * * Author: Nick Battle * * This file is part of VDMJ. * * VDMJ is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * VDMJ is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with VDMJ. If not, see <http://www.gnu.org/licenses/>. * ******************************************************************************/ package org.overture.pog.obligation; import java.util.List; import java.util.Vector; import org.overture.ast.analysis.AnalysisException; import org.overture.ast.expressions.ACompBinaryExp; import org.overture.ast.expressions.AForAllExp; import org.overture.ast.expressions.APreExp; import org.overture.ast.expressions.PExp; import org.overture.ast.factory.AstExpressionFactory; import org.overture.ast.intf.lex.ILexNameToken; import org.overture.ast.types.PType; import org.overture.pog.pub.IPOContextStack; import org.overture.pog.pub.IPogAssistantFactory; import org.overture.pog.pub.POType; public class FuncComposeObligation extends ProofObligation { private static final long serialVersionUID = 8813166638915813635L; // add last parameter to pass assistantFactory to the method. public FuncComposeObligation(ACompBinaryExp exp, ILexNameToken pref1, ILexNameToken pref2, IPOContextStack ctxt, IPogAssistantFactory assistantFactory) throws AnalysisException { super(exp, POType.FUNC_COMPOSE, ctxt, exp.getLocation(), assistantFactory); // Function composition must be of two functions with a single parameter each. // The obligation depends on whether the left/right expressions of the "comp" // are not directly functions (pref is null) or whether they are functions // that do or do not have preconditions (pref is "" or a name like "pre_FN"). // // Given f1(a:A), f2(b:B), the obligation for "f1 comp f2" is then: // // forall arg:A & pre_f2(arg) => pre_f1(f2(arg)) // // And for exp1 comp exp2 (where the arguments evaluate to functions): // // forall arg:A & pre_(exp2, arg) => pre_(exp1, exp2(arg)) // // Similarly for mixtures of functions and expressions. If f2 is a function without // a precondition, there is not LHS to the =>, only the RHS. ILexNameToken arg = getUnique("arg"); AForAllExp forallExp = new AForAllExp(); PType leftPType = assistantFactory.createPTypeAssistant().getFunction(exp.getLeft().getType()).getParameters().get(0).clone(); forallExp.setBindList(getMultipleTypeBindList(leftPType, arg)); PExp firstPart = null; if (pref2 == null || pref2.getFullName() != "") // An expression or a function with a precondition { if (pref2 != null) { // pref2(arg) => firstPart = getApplyExp(getVarExp(pref2), getVarExp(arg)); } else { // pre_(exp.getRight(), arg) => APreExp preExp = new APreExp(); preExp.setFunction(exp.getRight().clone()); List<PExp> args = new Vector<PExp>(); args.add(getVarExp(arg)); preExp.setArgs(args); firstPart = preExp; } } PExp secondPart = null; if (pref1 != null) { // pref1(exp.getRight()(arg)) secondPart = getApplyExp(getVarExp(pref1), getApplyExp(exp.getRight(), getVarExp(arg))); } else { // pre_(exp.getLeft(), exp.getRight()(arg)) APreExp preExp = new APreExp(); preExp.setFunction(exp.getLeft().clone()); List<PExp> args = new Vector<PExp>(); args.add(getApplyExp(exp.getRight().clone(), getVarExp(arg))); preExp.setArgs(args); secondPart = preExp; } if (firstPart == null) { forallExp.setPredicate(secondPart); } else { forallExp.setPredicate(AstExpressionFactory.newAImpliesBooleanBinaryExp(firstPart, secondPart)); } stitch = forallExp.clone(); valuetree.setPredicate(ctxt.getPredWithContext(forallExp)); } }