/******************************************************************************* * * 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.Collection; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Vector; import org.overture.ast.definitions.AExplicitFunctionDefinition; import org.overture.ast.definitions.AImplicitFunctionDefinition; 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.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.AFunctionType; import org.overture.ast.types.PType; import org.overture.pog.pub.IPogAssistantFactory; public class POFunctionDefinitionContext extends POContext { public final ILexNameToken name; public final AFunctionType deftype; public final List<List<PPattern>> paramPatternList; public final List<PType> argtypes; public final boolean addPrecond; public final PExp precondition; public POFunctionDefinitionContext(AExplicitFunctionDefinition definition, boolean precond) { this.name = definition.getName(); this.deftype = (AFunctionType) definition.getType(); this.paramPatternList = definition.getParamPatternList(); this.addPrecond = precond; this.precondition = definition.getPrecondition(); this.argtypes = calculateTypes(deftype,definition.getIsCurried()); } private List<PType> calculateTypes(AFunctionType ftype, boolean curried) { List<PType> r = new LinkedList<PType>(); for (PType t : ftype.getParameters()) { r.add(t.clone()); } if (curried) { r.addAll(handleCurries(ftype.getResult())); } return r; } private Collection<? extends PType> handleCurries(PType result) { List<PType> r = new LinkedList<PType>(); if (result instanceof AFunctionType) { AFunctionType ft = (AFunctionType) result; for (PType p : ft.getParameters()) { r.add(p.clone()); } r.addAll(handleCurries(ft.getResult())); } return r; } public POFunctionDefinitionContext(AImplicitFunctionDefinition definition, boolean precond, IPogAssistantFactory assistantFactory) { this.name = definition.getName(); this.deftype = (AFunctionType) definition.getType(); this.addPrecond = precond; this.paramPatternList = assistantFactory .createAImplicitFunctionDefinitionAssistant() .getParamPatternList(definition); this.precondition = definition.getPrecondition(); this.argtypes = calculateTypes(deftype, false); } @Override public PExp getContextNode(PExp stitch) { AForAllExp forAllExp = new AForAllExp(); forAllExp.setBindList(makeBinds()); forAllExp.setType(new ABooleanBasicType()); if (deftype.getParameters().isEmpty()) { return stitch; } if (addPrecond && precondition != null) { AImpliesBooleanBinaryExp implies = AstExpressionFactory .newAImpliesBooleanBinaryExp(precondition.clone(), stitch); implies.setType(new ABooleanBasicType()); forAllExp.setPredicate(implies); } else { forAllExp.setPredicate(stitch); } return forAllExp; } private List<PMultipleBind> makeBinds() { List<PMultipleBind> result = new LinkedList<PMultipleBind>(); Iterator<PType> types = argtypes.iterator(); for (List<PPattern> params : paramPatternList) { for (PPattern param : params) { ATypeMultipleBind typeBind = new ATypeMultipleBind(); List<PPattern> one = new Vector<PPattern>(); one.add(param.clone()); typeBind.setPlist(one); PType type = types.next(); typeBind.setType(type.clone()); result.add(typeBind); } } return result; } @Override public String getContext() { StringBuilder sb = new StringBuilder(); if (!deftype.getParameters().isEmpty()) { sb.append("forall "); String sep = ""; AFunctionType ftype = deftype; for (List<PPattern> pl : paramPatternList) { Iterator<PType> types = ftype.getParameters().iterator(); for (PPattern p : pl) { if (!(p instanceof AIgnorePattern)) { sb.append(sep); sb.append(p.toString()); sb.append(":"); sb.append(types.next()); sep = ", "; } } if (ftype.getResult() instanceof AFunctionType) { ftype = (AFunctionType) ftype.getResult(); } else { break; } } sb.append(" &"); if (addPrecond && precondition != null) { sb.append(" "); sb.append(precondition); sb.append(" =>"); } } return sb.toString(); } }