/*******************************************************************************
*
* 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.contexts;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;
import org.overture.ast.expressions.AElementsUnaryExp;
import org.overture.ast.expressions.AExists1Exp;
import org.overture.ast.expressions.AExistsExp;
import org.overture.ast.expressions.AForAllExp;
import org.overture.ast.expressions.AIotaExp;
import org.overture.ast.expressions.ALambdaExp;
import org.overture.ast.expressions.ALetBeStExp;
import org.overture.ast.expressions.AMapCompMapExp;
import org.overture.ast.expressions.ASeqCompSeqExp;
import org.overture.ast.expressions.ASetCompSetExp;
import org.overture.ast.expressions.PExp;
import org.overture.ast.factory.AstFactory;
import org.overture.ast.patterns.ASeqBind;
import org.overture.ast.patterns.ASetBind;
import org.overture.ast.patterns.ASetMultipleBind;
import org.overture.ast.patterns.ATypeBind;
import org.overture.ast.patterns.ATypeMultipleBind;
import org.overture.ast.patterns.PBind;
import org.overture.ast.patterns.PMultipleBind;
import org.overture.ast.patterns.PPattern;
import org.overture.ast.types.ABooleanBasicType;
import org.overture.pog.pub.IPogAssistantFactory;
import org.overture.typechecker.assistant.ITypeCheckerAssistantFactory;
public class POForAllContext extends POContext
{
public final List<PMultipleBind> bindings;
public POForAllContext(AMapCompMapExp exp)
{
this.bindings = exp.getBindings();
}
public POForAllContext(ASetCompSetExp exp)
{
this.bindings = exp.getBindings();
}
public POForAllContext(ASeqCompSeqExp exp,
IPogAssistantFactory assistantFactory)
{
if (exp.getSetBind() != null)
{
this.bindings = getMultipleBindList(exp.getSetBind());
}
else
{
this.bindings = getMultipleBindList(exp.getSeqBind());
}
}
public POForAllContext(AForAllExp exp)
{
this.bindings = exp.getBindList();
}
public POForAllContext(AExistsExp exp)
{
this.bindings = exp.getBindList();
}
public POForAllContext(ITypeCheckerAssistantFactory af, AExists1Exp exp)
{
this.bindings = af.createPBindAssistant().getMultipleBindList(exp.getBind());
}
public POForAllContext(ITypeCheckerAssistantFactory af, AIotaExp exp)
{
this.bindings = af.createPBindAssistant().getMultipleBindList(exp.getBind());
}
public POForAllContext(ALambdaExp exp)
{
this.bindings = new Vector<PMultipleBind>();
for (ATypeBind tb : exp.getBindList())
{
List<PPattern> pl = new ArrayList<PPattern>();
pl.add(tb.getPattern().clone());
ATypeMultipleBind mtb = AstFactory.newATypeMultipleBind(pl, tb.getType().clone());
bindings.add(mtb);
}
}
public POForAllContext(ALetBeStExp exp,
IPogAssistantFactory assistantFactory)
{
this.bindings = cloneBinds(assistantFactory.createPMultipleBindAssistant().getMultipleBindList(exp.getBind()));
}
public POForAllContext(PBind bind, PExp exp)
{
// Create new binding for "bind.pattern in set elems exp"
bindings = new Vector<PMultipleBind>();
List<PPattern> pl = new ArrayList<PPattern>();
pl.add(bind.getPattern().clone());
AElementsUnaryExp elems = AstFactory.newAElementsUnaryExp(exp.getLocation(), exp.clone());
ASetMultipleBind msb = AstFactory.newASetMultipleBind(pl, elems);
bindings.add(msb);
}
private List<PMultipleBind> cloneBinds(List<PMultipleBind> multipleBindList)
{
List<PMultipleBind> r = new LinkedList<PMultipleBind>();
for (PMultipleBind pmb : multipleBindList)
{
r.add(pmb.clone());
}
return r;
}
@Override
public PExp getContextNode(PExp stitch)
{
return getSuperContext(stitch);
}
protected AForAllExp getSuperContext(PExp stitch)
{
AForAllExp forAllExp = new AForAllExp();
forAllExp.setType(new ABooleanBasicType());
forAllExp.setBindList(cloneBinds(bindings));
forAllExp.setPredicate(stitch);
return forAllExp;
}
@Override
public boolean isScopeBoundary()
{
return true;
}
@Override
public String getContext()
{
StringBuilder sb = new StringBuilder();
sb.append("forall ");
String prefix = "";
for (PMultipleBind mb : bindings)
{
sb.append(prefix);
sb.append(mb);
prefix = ", ";
}
sb.append(" &");
return sb.toString();
}
public List<PMultipleBind> getMultipleBindList(PBind bind)
{
List<PPattern> plist = new ArrayList<PPattern>();
plist.add(bind.getPattern());
List<PMultipleBind> mblist = new Vector<PMultipleBind>();
if (bind instanceof ASetBind)
{
mblist.add(AstFactory.newASetMultipleBind(plist, ((ASetBind)bind).getSet()));
}
else
{
mblist.add(AstFactory.newASetMultipleBind(plist, ((ASeqBind)bind).getSeq()));
}
return mblist;
}
}