/******************************************************************************* * * 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.Iterator; import java.util.LinkedList; import java.util.List; import org.overture.ast.definitions.AExplicitOperationDefinition; import org.overture.ast.definitions.AImplicitOperationDefinition; import org.overture.ast.definitions.AStateDefinition; import org.overture.ast.definitions.PDefinition; import org.overture.ast.definitions.SClassDefinition; 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.lex.LexNameToken; import org.overture.ast.patterns.AIdentifierPattern; import org.overture.ast.patterns.AIgnorePattern; 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.AOperationType; import org.overture.ast.types.PType; import org.overture.pog.pub.IPogAssistantFactory; public class POOperationDefinitionContext extends POContext { public final ILexNameToken name; public final AOperationType deftype; public final List<PPattern> paramPatternList; public final boolean addPrecond; public final PExp precondition; public final PDefinition stateDefinition; final PDefinition opDef; protected POOperationDefinitionContext(ILexNameToken name, AOperationType deftype, LinkedList<PPattern> paramPatternList, boolean addPrecond, PExp precondition, PDefinition stateDefinition, PDefinition opDef) { super(); this.name = name; this.deftype = deftype; this.paramPatternList = paramPatternList; this.addPrecond = addPrecond; this.precondition = precondition; this.stateDefinition = stateDefinition; this.opDef = opDef; } public POOperationDefinitionContext( AExplicitOperationDefinition definition, boolean precond, PDefinition stateDefinition) { this.name = definition.getName(); this.deftype = (AOperationType) definition.getType(); this.addPrecond = precond; this.paramPatternList = cloneList(definition.getParameterPatterns()); this.precondition = definition.getPrecondition(); this.stateDefinition = stateDefinition; this.opDef = definition; } private List<PPattern> cloneList(LinkedList<PPattern> parameterPatterns) { List<PPattern> r = new LinkedList<PPattern>(); for (PPattern p : parameterPatterns) { r.add(p.clone()); } return r; } public POOperationDefinitionContext( AImplicitOperationDefinition definition, boolean precond, PDefinition stateDefinition, IPogAssistantFactory assistantFactory) { this.name = definition.getName(); this.deftype = (AOperationType) definition.getType(); this.addPrecond = precond; this.paramPatternList = assistantFactory.createAImplicitOperationDefinitionAssistant().getParamPatternList(definition); this.precondition = definition.getPrecondition(); this.stateDefinition = stateDefinition; this.opDef = definition; } protected boolean anyBinds() { return !deftype.getParameters().isEmpty(); } @Override public PExp getContextNode(PExp stitch) { if (anyBinds()) { AForAllExp forAllExp = new AForAllExp(); forAllExp.setType(new ABooleanBasicType()); forAllExp.setBindList(makeBinds()); if (addPrecond && precondition != null) { AImpliesBooleanBinaryExp impliesExp = AstExpressionFactory.newAImpliesBooleanBinaryExp(precondition.clone(), stitch); forAllExp.setPredicate(impliesExp); } else { forAllExp.setPredicate(stitch); } return forAllExp; } else { if (addPrecond && precondition != null) { AImpliesBooleanBinaryExp impliesExp = AstExpressionFactory.newAImpliesBooleanBinaryExp(precondition.clone(), stitch); return impliesExp; } } return stitch; } private static final ILexNameToken OLD_STATE_ARG = new LexNameToken("", "oldstate", null); private static final ILexNameToken OLD_SELF_ARG = new LexNameToken("", "oldself", null); private void addParameterBinds(LinkedList<PMultipleBind> r) { Iterator<PType> types = deftype.getParameters().iterator(); for (PPattern p : paramPatternList) { ATypeMultipleBind tmBind = new ATypeMultipleBind(); List<PPattern> pats = new LinkedList<PPattern>(); pats.add(p.clone()); tmBind.setType(types.next().clone()); tmBind.setPlist(pats); r.add(tmBind); } } protected void addStateBinds(LinkedList<PMultipleBind> r) { if (stateDefinition != null) { ATypeMultipleBind tmBind2 = new ATypeMultipleBind(); AIdentifierPattern pattern = new AIdentifierPattern(); if (stateDefinition instanceof AStateDefinition) { AStateDefinition def = (AStateDefinition) stateDefinition; tmBind2.setType(def.getRecordType().clone()); pattern.setName(OLD_STATE_ARG.clone()); } else { SClassDefinition def = (SClassDefinition) stateDefinition; tmBind2.setType(def.getClasstype().clone()); pattern.setName(OLD_SELF_ARG.clone()); } List<PPattern> plist = new LinkedList<PPattern>(); plist.add(pattern); tmBind2.setPlist(plist); r.add(tmBind2); } } private List<? extends PMultipleBind> makeBinds() { LinkedList<PMultipleBind> r = new LinkedList<PMultipleBind>(); addParameterBinds(r); addStateBinds(r); return r; } @Override public String getContext() { StringBuilder sb = new StringBuilder(); if (!deftype.getParameters().isEmpty()) { sb.append("forall "); String sep = ""; Iterator<PType> types = deftype.getParameters().iterator(); for (PPattern p : paramPatternList) { if (!(p instanceof AIgnorePattern)) { sb.append(sep); sb.append(p.toString()); sb.append(":"); sb.append(types.next()); sep = ", "; } } if (stateDefinition != null) { appendStatePatterns(sb); } sb.append(" &"); if (addPrecond && precondition != null) { sb.append(" "); sb.append(precondition); sb.append(" =>"); } } return sb.toString(); } private void appendStatePatterns(StringBuilder sb) { if (stateDefinition == null) { return; } else if (stateDefinition instanceof AStateDefinition) { AStateDefinition def = (AStateDefinition) stateDefinition; sb.append(", oldstate:"); sb.append(def.getName().getName()); } else { SClassDefinition def = (SClassDefinition) stateDefinition; sb.append(", oldself:"); sb.append(def.getName().getName()); } } }