/******************************************************************************* * * 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.LinkedList; import java.util.List; import org.overture.ast.analysis.AnalysisException; import org.overture.ast.definitions.AExplicitFunctionDefinition; import org.overture.ast.definitions.AImplicitFunctionDefinition; import org.overture.ast.definitions.AValueDefinition; import org.overture.ast.definitions.PDefinition; import org.overture.ast.expressions.AApplyExp; import org.overture.ast.expressions.AFieldNumberExp; import org.overture.ast.expressions.AFuncInstatiationExp; import org.overture.ast.expressions.AGreaterNumericBinaryExp; import org.overture.ast.expressions.AIfExp; import org.overture.ast.expressions.ALetDefExp; import org.overture.ast.expressions.ANotEqualBinaryExp; import org.overture.ast.expressions.AVariableExp; import org.overture.ast.expressions.PExp; import org.overture.ast.factory.AstExpressionFactory; import org.overture.ast.intf.lex.ILexNameToken; import org.overture.ast.lex.LexIntegerToken; import org.overture.ast.lex.LexNameToken; import org.overture.ast.patterns.AIdentifierPattern; import org.overture.ast.patterns.APatternListTypePair; import org.overture.ast.patterns.PPattern; 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 RecursiveObligation extends ProofObligation { private static final long serialVersionUID = -6975984943449362262L; private static final String LEFT_MEASURE_NAME = "LME"; private static final String RIGHT_MEASURE_NAME = "RME"; public RecursiveObligation(AExplicitFunctionDefinition def, AApplyExp apply, IPOContextStack ctxt, IPogAssistantFactory af) throws AnalysisException { super(apply, POType.RECURSIVE, ctxt, apply.getLocation(), af); PExp measureLeft_exp = buildMeasureLeft(def, apply); PExp measureRight_exp = buildMeasureRight(def, apply); PExp lt_exp = buildStructuralComparison(measureLeft_exp, measureRight_exp, def.getMeasureLexical()); stitch = lt_exp; valuetree.setPredicate(ctxt.getPredWithContext(lt_exp)); } public RecursiveObligation(AImplicitFunctionDefinition def, AApplyExp apply, IPOContextStack ctxt, IPogAssistantFactory af) throws AnalysisException { super(def, POType.RECURSIVE, ctxt, apply.getLocation(), af); PExp measureLeft_exp = buildMeasureLeft(def, apply); PExp measureRight_exp = buildMeasureRight(def, apply); PExp lt_exp = buildStructuralComparison(measureLeft_exp, measureRight_exp, def.getMeasureLexical()); stitch = lt_exp; valuetree.setPredicate(ctxt.getPredWithContext(lt_exp)); } private PExp buildMeasureLeft(AExplicitFunctionDefinition def, AApplyExp apply) throws AnalysisException { List<PPattern> paramPatterns = new LinkedList<PPattern>(); for (List<PPattern> list : def.getParamPatternList()) { paramPatterns.addAll(list); } return buildMeasureLeftParams(apply, def.getTypeParams(), def.getActualResult(), def.getMeasure(), paramPatterns); } private PExp buildMeasureLeft(AImplicitFunctionDefinition def, AApplyExp apply) throws AnalysisException { List<PPattern> paramPatterns = new LinkedList<PPattern>(); for (APatternListTypePair pair : def.getParamPatterns()) { paramPatterns.addAll(pair.getPatterns()); } return buildMeasureLeftParams(apply, def.getTypeParams(), def.getActualResult(), def.getMeasure(), paramPatterns); } private PExp buildMeasureLeftParams(AApplyExp apply, List<ILexNameToken> typeParams, PType actualResult, ILexNameToken measure, List<PPattern> paramPatterns) throws AnalysisException { AApplyExp apply_exp = new AApplyExp(); if (typeParams != null && !typeParams.isEmpty()) { if (apply.getRoot() instanceof AFuncInstatiationExp) { AFuncInstatiationExp func_exp = (AFuncInstatiationExp) apply.getRoot().clone(); func_exp.setFunction(wrapName(measure.clone())); apply_exp.setRoot(func_exp); } else { AFuncInstatiationExp func_exp = new AFuncInstatiationExp(); func_exp.setActualTypes(cloneListType(apply.getArgtypes())); // Not sure about this? func_exp.setFunction(wrapName(measure.clone())); apply_exp.setRoot(func_exp); } } else { apply_exp.setRoot(wrapName(measure.clone())); } List<PExp> args = new LinkedList<PExp>(); for (PPattern p : paramPatterns) { args.add(patternToExp(p.clone())); } apply_exp.setType(actualResult.clone()); apply_exp.setArgs(args); return apply_exp; } private PExp buildMeasureRight(AExplicitFunctionDefinition def, AApplyExp apply) { return buildMeasureRightParams(apply, def.getMeasure(), def.getActualResult()); } private PExp buildMeasureRight(AImplicitFunctionDefinition def, AApplyExp apply) { return buildMeasureRightParams(apply, def.getMeasure(), def.getActualResult()); } private PExp buildMeasureRightParams(AApplyExp apply, ILexNameToken measure, PType actualResult) { PExp start = null; PExp root = apply.getRoot().clone(); if (root instanceof AApplyExp) { AApplyExp aexp = (AApplyExp) root; start = buildMeasureRightParams(aexp, measure, actualResult); } else if (root instanceof AVariableExp) { start = wrapName(measure.clone()); } else if (root instanceof AFuncInstatiationExp) { AFuncInstatiationExp fie = (AFuncInstatiationExp) root; AFuncInstatiationExp func_exp = new AFuncInstatiationExp(); func_exp.setActualTypes(cloneListType(fie.getActualTypes())); func_exp.setFunction(wrapName(measure.clone())); start = func_exp; } else { start = root; } List<PExp> arglist = new LinkedList<PExp>(); for (PExp arg : apply.getArgs()) { arglist.add(arg.clone()); } AApplyExp apply_exp = getApplyExp(start, arglist); apply_exp.setType(actualResult.clone()); return apply_exp; } private PExp buildStructuralComparison(PExp left_exp, PExp right_exp, int measureLexical) { if (measureLexical == 0) // what about 1 measures? same as 0? { return AstExpressionFactory.newAGreaterNumericBinaryExp(left_exp, right_exp); } ALetDefExp let_exp = new ALetDefExp(); AValueDefinition left_def = buildValueDef(left_exp, LEFT_MEASURE_NAME); AValueDefinition right_def = buildValueDef(right_exp, RIGHT_MEASURE_NAME); List<PDefinition> localDefs = new LinkedList<PDefinition>(); localDefs.add(left_def); localDefs.add(right_def); let_exp.setLocalDefs(localDefs); // let left = [left expression], right=[right expression] // in ... // we don't strictly need the let in AVariableExp leftName_exp = wrapName(new LexNameToken(null, LEFT_MEASURE_NAME, null)); AVariableExp rightName_exp = wrapName(new LexNameToken(null, RIGHT_MEASURE_NAME, null)); // build the left < right structural comparison expression let_exp.setExpression(buildStructuralLessThan(leftName_exp, rightName_exp, 1, measureLexical).clone()); return let_exp; } private PExp buildStructuralLessThan(PExp left_exp, PExp right_exp, int tupleCounter, int recCounter) { // left.i AFieldNumberExp leftField_exp = new AFieldNumberExp(); leftField_exp.setTuple(left_exp.clone()); leftField_exp.setField(new LexIntegerToken(tupleCounter, null)); // right.i AFieldNumberExp rightField_exp = new AFieldNumberExp(); rightField_exp.setTuple(right_exp.clone()); rightField_exp.setField(new LexIntegerToken(tupleCounter, null)); if (recCounter == 1) { // last one. don't chain further ifs return AstExpressionFactory.newAGreaterNumericBinaryExp(leftField_exp, rightField_exp); } // left.i <> right.i ANotEqualBinaryExp notEquals_exp = AstExpressionFactory.newANotEqualBinaryExp(leftField_exp, rightField_exp); // if left.i <>right.i then left.i , right.i else [recurse] AGreaterNumericBinaryExp gt_exp = AstExpressionFactory.newAGreaterNumericBinaryExp(leftField_exp.clone(), rightField_exp.clone()); AIfExp if_exp = new AIfExp(); if_exp.setTest(notEquals_exp); if_exp.setThen(gt_exp); if_exp.setElse(buildStructuralLessThan(left_exp.clone(), right_exp.clone(), tupleCounter + 1, recCounter - 1)); return if_exp; } private AValueDefinition buildValueDef(PExp exp, String name) { AValueDefinition valDef = new AValueDefinition(); valDef.setType(exp.getType().clone()); valDef.setExpression(exp.clone()); AIdentifierPattern pattern = new AIdentifierPattern(); pattern.setName(new LexNameToken(null, name, null)); valDef.setPattern(pattern); return valDef; } private AVariableExp wrapName(ILexNameToken name) { AVariableExp r = new AVariableExp(); r.setName(name.clone()); r.setOriginal(name.getFullName()); return r; } }