/*******************************************************************************
*
* 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.io.Serializable;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;
import org.overture.ast.analysis.AnalysisException;
import org.overture.ast.definitions.PDefinition;
import org.overture.ast.expressions.AAndBooleanBinaryExp;
import org.overture.ast.expressions.AApplyExp;
import org.overture.ast.expressions.AEqualsBinaryExp;
import org.overture.ast.expressions.AIntLiteralExp;
import org.overture.ast.expressions.AOrBooleanBinaryExp;
import org.overture.ast.expressions.AVariableExp;
import org.overture.ast.expressions.PExp;
import org.overture.ast.factory.AstExpressionFactory;
import org.overture.ast.intf.lex.ILexIntegerToken;
import org.overture.ast.intf.lex.ILexLocation;
import org.overture.ast.intf.lex.ILexNameToken;
import org.overture.ast.lex.LexIntegerToken;
import org.overture.ast.lex.LexKeywordToken;
import org.overture.ast.lex.VDMToken;
import org.overture.ast.node.INode;
import org.overture.ast.patterns.AIdentifierPattern;
import org.overture.ast.patterns.ASetMultipleBind;
import org.overture.ast.patterns.ATypeMultipleBind;
import org.overture.ast.patterns.PMultipleBind;
import org.overture.ast.patterns.PPattern;
import org.overture.ast.types.ABooleanBasicType;
import org.overture.ast.types.PType;
import org.overture.pof.AVdmPoTree;
import org.overture.pog.pub.IPOContextStack;
import org.overture.pog.pub.IPogAssistantFactory;
import org.overture.pog.pub.IProofObligation;
import org.overture.pog.pub.POStatus;
import org.overture.pog.pub.POType;
import org.overture.pog.utility.UniqueNameGenerator;
import org.overture.pog.visitors.PatternToExpVisitor;
/**
* New class for Proof Obligations with a an AST-based representation of PO expressions
*
* @author ldc
*/
abstract public class ProofObligation implements IProofObligation, Serializable
{
private static final long serialVersionUID = 1L;
public final INode rootNode;
public final String name;
public String isaName;
public AVdmPoTree valuetree;
public PExp stitch;
public POStatus status;
public final POType kind;
public int number;
private final UniqueNameGenerator generator;
private ILexLocation location;
private String locale;
private final IPogAssistantFactory af;
public ProofObligation(INode rootnode, POType kind,
IPOContextStack context, ILexLocation location,
IPogAssistantFactory af) throws AnalysisException
{
this.locale = rootnode.apply(af.getLocaleExtractVisitor());
this.rootNode = rootnode;
this.location = location;
this.kind = kind;
this.af = af;
this.name = context.getName();
this.status = POStatus.UNPROVED;
this.valuetree = new AVdmPoTree();
this.generator = new UniqueNameGenerator(rootNode);
}
@Override
public String getLocale()
{
return locale;
}
public void setLocale(String locale)
{
this.locale = locale;
}
public UniqueNameGenerator getUniqueGenerator()
{
return generator;
}
public AVdmPoTree getValueTree()
{
return valuetree;
}
// this method should call a visitor on the potree that creates the "value"
// string as it exists in the current version
@Override
public String getFullPredString()
{
if (valuetree.getPredicate() == null)
{
return "";
}
String result = valuetree.getPredicate().toString();
return result;
}
@Override
public String getDefPredString()
{
if (stitch == null)
{
return "";
}
String result = stitch.toString();
return result;
}
@Override
public void setStatus(POStatus status)
{
this.status = status;
}
@Override
public String toString()
{
return name + ": " + kind + " obligation " + "@ " + location + "\n"
+ getFullPredString();
}
public String getIsaName()
{
if (isaName == null)
{
isaName = "PO" + name;
isaName = isaName.replaceAll(", ", "_");
isaName = isaName.replaceAll("\\(.*\\)|\\$", "");
isaName = isaName + getNumber();
}
return isaName;
}
@Override
public String getUniqueName()
{
return getName() + getNumber();
}
@Override
public INode getNode()
{
return rootNode;
}
// I'm not sure why the comparable is implemented...
public int compareTo(IProofObligation other)
{
return number - other.getNumber();
}
@Override
public POType getKind()
{
return kind;
}
@Override
public String getName()
{
return name;
}
@Override
public String getKindString()
{
return kind.toString();
}
@Override
public POStatus getStatus()
{
return status;
}
@Override
public void setNumber(int i)
{
number = i;
}
@Override
public int getNumber()
{
return number;
}
@Override
public ILexLocation getLocation()
{
return location;
}
/**
* Create a multiple type bind with a varargs list of pattern variables, like a,b,c:T. This is used by several
* obligations.
*/
protected PMultipleBind getMultipleTypeBind(PType patternType,
ILexNameToken... patternNames)
{
ATypeMultipleBind typeBind = new ATypeMultipleBind();
List<PPattern> patternList = new Vector<PPattern>();
for (ILexNameToken patternName : patternNames)
{
AIdentifierPattern pattern = new AIdentifierPattern();
pattern.setName(patternName.clone());
patternList.add(pattern);
}
typeBind.setPlist(patternList);
typeBind.setType(patternType.clone());
return typeBind;
}
/**
* Create a multiple set bind with a varargs list of pattern variables, like a,b,c in set S. This is used by several
* obligations.
*/
protected PMultipleBind getMultipleSetBind(PExp setExp,
ILexNameToken... patternNames)
{
ASetMultipleBind setBind = new ASetMultipleBind();
List<PPattern> patternList = new Vector<PPattern>();
for (ILexNameToken patternName : patternNames)
{
AIdentifierPattern pattern = new AIdentifierPattern();
pattern.setName(patternName.clone());
patternList.add(pattern);
}
setBind.setPlist(patternList);
setBind.setSet(setExp.clone());
return setBind;
}
/**
* As above, but create a List of PMultipleBind with one element, for convenience.
*/
protected List<PMultipleBind> getMultipleTypeBindList(PType patternType,
ILexNameToken... patternNames)
{
List<PMultipleBind> typeBindList = new Vector<PMultipleBind>();
typeBindList.add(getMultipleTypeBind(patternType, patternNames));
return typeBindList;
}
/**
* As above, but create a List of PMultipleBind with one element, for convenience.
*/
protected List<PMultipleBind> getMultipleSetBindList(PExp setExp,
ILexNameToken... patternNames)
{
List<PMultipleBind> setBindList = new Vector<PMultipleBind>();
setBindList.add(getMultipleSetBind(setExp, patternNames));
return setBindList;
}
/**
* Create a LexNameToken with a numbered variable name, based on the stem passed. (See getVar above).
*/
protected ILexNameToken getUnique(String name)
{
return generator.getUnique(name);
}
/**
* Generate an AEqualsBinaryExp
*/
protected AEqualsBinaryExp getEqualsExp(PExp left, PExp right)
{
return AstExpressionFactory.newAEqualsBinaryExp(left.clone(), right.clone());
}
/**
* Generate an AVariableExp
*/
protected AVariableExp getVarExp(ILexNameToken name)
{
AVariableExp var = new AVariableExp();
var.setName(name.clone());
var.setOriginal(name.getFullName());
return var;
}
/**
* Generate a Var Exp with associated type.
*/
protected AVariableExp getVarExp(ILexNameToken name, PType type)
{
AVariableExp var = getVarExp(name);
var.setType(type.clone());
return var;
}
/**
* Generate AVariableExp with corresponding definition
*/
protected AVariableExp getVarExp(ILexNameToken name, PDefinition vardef)
{
AVariableExp var = new AVariableExp();
var.setName(name.clone());
var.setOriginal(name.getFullName());
var.setVardef(vardef.clone());
return var;
}
/**
* Generate Var Exp with everything!
* @return
*/
protected AVariableExp getVarExp(ILexNameToken name, PDefinition vardef, PType type){
AVariableExp var = getVarExp(name, vardef);
var.setType(type);
return var;
}
protected AApplyExp getApplyExp(PExp root, PType type, PExp... arglist)
{
AApplyExp exp = getApplyExp(root, arglist);
exp.setType(type.clone());
return exp;
}
/**
* Generate an AApplyExp with varargs arguments
*/
protected AApplyExp getApplyExp(PExp root, PExp... arglist)
{
return getApplyExp(root, Arrays.asList(arglist));
}
/**
* Generate an AApplyExp
*/
protected AApplyExp getApplyExp(PExp root, List<PExp> arglist)
{
AApplyExp apply = new AApplyExp();
apply.setRoot(root.clone());
List<PExp> args = new Vector<PExp>();
for (PExp arg : arglist)
{
args.add(arg.clone());
}
apply.setArgs(args);
return apply;
}
/**
* Generate an AIntLiteral from a long.
*/
protected AIntLiteralExp getIntLiteral(long i)
{
AIntLiteralExp number = new AIntLiteralExp();
ILexIntegerToken literal = new LexIntegerToken(i, null);
number.setValue(literal);
return number;
}
/**
* Chain an AND expression onto a root, or just return the new expression if the root is null. Called in a loop,
* this left-associates an AND tree.
*/
protected PExp makeAnd(PExp root, PExp e)
{
if (root != null)
{
AAndBooleanBinaryExp a = new AAndBooleanBinaryExp();
a.setLeft(root.clone());
a.setOp(new LexKeywordToken(VDMToken.AND, null));
a.setType(new ABooleanBasicType());
a.setRight(e.clone());
return a;
} else
{
return e;
}
}
/**
* Chain an OR expression onto a root, or just return the new expression if the root is null. Called in a loop, this
* left-associates an OR tree.
*/
protected PExp makeOr(PExp root, PExp e)
{
if (root != null)
{
AOrBooleanBinaryExp o = new AOrBooleanBinaryExp();
o.setLeft(root.clone());
o.setOp(new LexKeywordToken(VDMToken.OR, null));
o.setType(new ABooleanBasicType());
o.setRight(e.clone());
return o;
} else
{
return e;
}
}
/**
* Create an expression equivalent to a pattern.
*/
protected PExp patternToExp(PPattern pattern) throws AnalysisException
{
PatternToExpVisitor visitor = new PatternToExpVisitor(getUniqueGenerator(), af);
return pattern.apply(visitor);
}
protected List<PMultipleBind> cloneListMultipleBind(
List<PMultipleBind> binds)
{
List<PMultipleBind> r = new LinkedList<PMultipleBind>();
for (PMultipleBind bind : binds)
{
r.add(bind.clone());
}
return r;
}
/**
* Clone a list of PTypes (and return a typed list)
*
* @param types the
* list to clone
* @return a Typed list of PTypes
*/
protected List<PType> cloneListType(List<PType> types)
{
List<PType> r = new LinkedList<PType>();
for (PType type : types)
{
r.add(type.clone());
}
return r;
}
/**
* Clone a list of PExps (and return a typed list)
*
* @param args the
* list to clone
* @return a Typed list of PExps
*/
protected List<PExp> cloneListPExp(List<PExp> args)
{
List<PExp> clones = new LinkedList<PExp>();
for (PExp pexp : args)
{
clones.add(pexp.clone());
}
return clones;
}
}