/*******************************************************************************
*
* 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.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.Vector;
import org.overture.ast.analysis.AnalysisException;
import org.overture.ast.definitions.AExplicitFunctionDefinition;
import org.overture.ast.definitions.AExplicitOperationDefinition;
import org.overture.ast.definitions.AImplicitFunctionDefinition;
import org.overture.ast.definitions.AImplicitOperationDefinition;
import org.overture.ast.definitions.PDefinition;
import org.overture.ast.expressions.AEqualsBinaryExp;
import org.overture.ast.expressions.AExistsExp;
import org.overture.ast.expressions.AForAllExp;
import org.overture.ast.expressions.AImpliesBooleanBinaryExp;
import org.overture.ast.expressions.PExp;
import org.overture.ast.factory.AstExpressionFactory;
import org.overture.ast.intf.lex.ILexNameToken;
import org.overture.ast.patterns.PMultipleBind;
import org.overture.ast.patterns.PPattern;
import org.overture.ast.typechecker.NameScope;
import org.overture.ast.types.AFunctionType;
import org.overture.ast.types.AOperationType;
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 ParameterPatternObligation extends ProofObligation
{
private static final long serialVersionUID = 6831031423902894299L;
public IPogAssistantFactory assistantFactory; // gkanos:variable added by me to pass it as param to the method
// generate.
public ParameterPatternObligation(AExplicitFunctionDefinition def,
IPOContextStack ctxt, IPogAssistantFactory af)
throws AnalysisException
{
super(def, POType.FUNC_PATTERNS, ctxt, def.getLocation(), af);
this.assistantFactory = af;
// valuetree.setContext(ctxt.getContextNodeList());
// cannot clone getPredef as it can be null. We protect the ast in
// the generate method where it's used
stitch = generate(def.getPredef(), cloneListPatternList(def.getParamPatternList()), cloneListType(((AFunctionType) def.getType()).getParameters()), ((AFunctionType) def.getType()).getResult().clone());
valuetree.setPredicate(ctxt.getPredWithContext(stitch));
}
public ParameterPatternObligation(AImplicitFunctionDefinition def,
IPOContextStack ctxt, IPogAssistantFactory af)
throws AnalysisException
{
super(def, POType.FUNC_PATTERNS, ctxt, def.getLocation(), af);
this.assistantFactory = af;
stitch = generate(def.getPredef(), cloneListPatternList(assistantFactory.createAImplicitFunctionDefinitionAssistant().getParamPatternList(def)), cloneListType(((AFunctionType) def.getType()).getParameters()), ((AFunctionType) def.getType()).getResult().clone());
valuetree.setPredicate(ctxt.getPredWithContext(stitch));
}
public ParameterPatternObligation(AExplicitOperationDefinition def,
IPOContextStack ctxt, IPogAssistantFactory af)
throws AnalysisException
{
super(def, POType.OPERATION_PATTERNS, ctxt, def.getLocation(), af);
this.assistantFactory = af;
stitch = generate(def.getPredef(), cloneListPatternList(assistantFactory.createAExplicitOperationDefinitionAssistant().getParamPatternList(def)), cloneListType(((AOperationType) def.getType()).getParameters()), ((AOperationType) def.getType()).getResult().clone());
valuetree.setPredicate(ctxt.getPredWithContext(stitch));
}
public ParameterPatternObligation(AImplicitOperationDefinition def,
IPOContextStack ctxt, IPogAssistantFactory af)
throws AnalysisException
{
super(def, POType.OPERATION_PATTERNS, ctxt, def.getLocation(), af);
this.assistantFactory = af;
stitch = generate(def.getPredef(), cloneListPatternList(assistantFactory.createAImplicitOperationDefinitionAssistant().getListParamPatternList(def)), cloneListType(((AOperationType) def.getType()).getParameters()), ((AOperationType) def.getType()).getResult().clone());
valuetree.setPredicate(ctxt.getPredWithContext(stitch));
}
private PExp generate(PDefinition predef, List<List<PPattern>> plist,
List<PType> params, PType result) throws AnalysisException
{
AForAllExp forallExp = new AForAllExp();
List<PMultipleBind> forallBindList = new Vector<PMultipleBind>();
List<PExp> arglist = new Vector<PExp>();
PExp forallPredicate = null;
for (List<PPattern> paramList : plist)
{
Iterator<PType> titer = params.iterator();
if (!paramList.isEmpty())
{
AExistsExp existsExp = new AExistsExp();
List<PMultipleBind> existsBindList = new Vector<PMultipleBind>();
PExp existsPredicate = null;
Set<ILexNameToken> previousBindings = new HashSet<ILexNameToken>();
for (PPattern param : paramList)
{
ILexNameToken aname = getUnique("arg");
ILexNameToken bname = getUnique("bind");
PType atype = titer.next();
PExp pmatch = patternToExp(param);
arglist.add(pmatch.clone());
forallBindList.add(getMultipleTypeBind(atype, aname));
existsBindList.add(getMultipleTypeBind(atype, bname));
for (PDefinition def : assistantFactory.createPPatternAssistant().getDefinitions(param, atype, NameScope.LOCAL))
{
if (def.getName() != null
&& !previousBindings.contains(def.getName()))
{
existsBindList.add(getMultipleTypeBind(def.getType(), def.getName()));
previousBindings.add(def.getName());
}
}
AEqualsBinaryExp eq1 = getEqualsExp(getVarExp(aname), getVarExp(bname));
AEqualsBinaryExp eq2 = getEqualsExp(pmatch, getVarExp(bname));
existsPredicate = makeAnd(existsPredicate, makeAnd(eq1, eq2));
}
existsExp.setBindList(existsBindList);
existsExp.setPredicate(existsPredicate);
forallPredicate = makeAnd(forallPredicate, existsExp);
}
if (result instanceof AFunctionType)
{
AFunctionType ft = (AFunctionType) result;
result = ft.getResult();
params = ft.getParameters();
} else
{
break;
}
}
forallExp.setBindList(forallBindList);
if (predef != null)
{
AImpliesBooleanBinaryExp implies = AstExpressionFactory.newAImpliesBooleanBinaryExp(getApplyExp(getVarExp(predef.getName().clone()), arglist), forallPredicate);
forallExp.setPredicate(implies);
} else
{
forallExp.setPredicate(forallPredicate);
}
return forallExp;
}
private List<List<PPattern>> cloneListPatternList(List<List<PPattern>> list)
{
List<List<PPattern>> r = new LinkedList<List<PPattern>>();
for (List<PPattern> list2 : list)
{
r.add(cloneList(list2));
}
return r;
}
private List<PPattern> cloneList(List<PPattern> list)
{
List<PPattern> r = new LinkedList<PPattern>();
for (PPattern p : list)
{
r.add(p);
}
return r;
}
}