All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fujitsu.vdmj.po.definitions.POImplicitOperationDefinition Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 *
 *	Copyright (c) 2016 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 .
 *	SPDX-License-Identifier: GPL-3.0-or-later
 *
 ******************************************************************************/

package com.fujitsu.vdmj.po.definitions;

import java.util.List;
import java.util.Vector;

import com.fujitsu.vdmj.Settings;
import com.fujitsu.vdmj.lex.Dialect;
import com.fujitsu.vdmj.po.annotations.POAnnotationList;
import com.fujitsu.vdmj.po.definitions.visitors.PODefinitionVisitor;
import com.fujitsu.vdmj.po.expressions.POExpression;
import com.fujitsu.vdmj.po.patterns.POPattern;
import com.fujitsu.vdmj.po.patterns.POPatternList;
import com.fujitsu.vdmj.po.statements.POErrorCaseList;
import com.fujitsu.vdmj.po.statements.POExternalClauseList;
import com.fujitsu.vdmj.po.statements.POStatement;
import com.fujitsu.vdmj.po.types.POPatternListTypePair;
import com.fujitsu.vdmj.po.types.POPatternListTypePairList;
import com.fujitsu.vdmj.po.types.POPatternTypePair;
import com.fujitsu.vdmj.pog.OperationPostConditionObligation;
import com.fujitsu.vdmj.pog.POContextStack;
import com.fujitsu.vdmj.pog.POFunctionDefinitionContext;
import com.fujitsu.vdmj.pog.POImpliesContext;
import com.fujitsu.vdmj.pog.PONoCheckContext;
import com.fujitsu.vdmj.pog.POOperationDefinitionContext;
import com.fujitsu.vdmj.pog.ParameterPatternObligation;
import com.fujitsu.vdmj.pog.ProofObligationList;
import com.fujitsu.vdmj.pog.SatisfiabilityObligation;
import com.fujitsu.vdmj.pog.StateInvariantObligation;
import com.fujitsu.vdmj.pog.SubTypeObligation;
import com.fujitsu.vdmj.pog.TotalFunctionObligation;
import com.fujitsu.vdmj.tc.lex.TCNameList;
import com.fujitsu.vdmj.tc.lex.TCNameToken;
import com.fujitsu.vdmj.tc.types.TCOperationType;
import com.fujitsu.vdmj.tc.types.TCType;
import com.fujitsu.vdmj.typechecker.Environment;
import com.fujitsu.vdmj.typechecker.TypeComparator;
import com.fujitsu.vdmj.util.Utils;

/**
 * A class to hold an explicit operation definition.
 */
public class POImplicitOperationDefinition extends PODefinition
{
	private static final long serialVersionUID = 1L;
	public final POPatternListTypePairList parameterPatterns;
	public final POPatternTypePair result;
	public final POExternalClauseList externals;
	public final POStatement body;
	public final POExpression precondition;
	public final POExpression postcondition;
	public final POErrorCaseList errors;

	public final TCOperationType type;
	public final POExplicitFunctionDefinition predef;
	public final POExplicitFunctionDefinition postdef;
	public final TCType actualResult;
	public final PODefinition state;
	public final boolean isConstructor;

	public POImplicitOperationDefinition(POAnnotationList annotations,
		TCNameToken name,
		POPatternListTypePairList parameterPatterns,
		POPatternTypePair result, POStatement body,
		POExternalClauseList externals,
		POExpression precondition,
		POExpression postcondition,
		POErrorCaseList errors,
		TCOperationType type,
		POExplicitFunctionDefinition predef,
		POExplicitFunctionDefinition postdef,
		TCType actualResult,
		POStateDefinition stateDefinition,
		boolean isConstructor)
	{
		super(name.getLocation(), name);
		
		this.annotations = annotations;
		this.parameterPatterns = parameterPatterns;
		this.result = result;
		this.body = body;
		this.externals = externals;
		this.precondition = precondition;
		this.postcondition = postcondition;
		this.errors = errors;
		this.type = type;
		this.predef = predef;
		this.postdef = postdef;
		this.actualResult = actualResult;
		this.state = stateDefinition;
		this.isConstructor = isConstructor;
	}

	@Override
	public String toString()
	{
		return	(type.isPure() ? "pure " : "") + name +
				Utils.listToString("(", parameterPatterns, ", ", ")") +
				(result == null ? "" : " " + result) +
				(externals == null ? "" : "\n\text " + externals) +
				(precondition == null ? "" : "\n\tpre " + precondition) +
				(postcondition == null ? "" : "\n\tpost " + postcondition) +
				(errors == null ? "" : "\n\terrs " + errors);
	}

	@Override
	public TCType getType()
	{
		return type;
	}

	@Override
	public ProofObligationList getProofObligations(POContextStack ctxt, Environment env)
	{
		ProofObligationList obligations =
				(annotations != null) ? annotations.poBefore(this, ctxt) : new ProofObligationList();
		TCNameList pids = new TCNameList();
		boolean matchNeeded = false;

		for (POPatternListTypePair pltp: parameterPatterns)
		{
			for (POPattern p: pltp.patterns)
			{
				pids.addAll(p.getVariableNames());
			}
			
			if (!pltp.patterns.alwaysMatches())
			{
				matchNeeded = true;
			}
		}

		if (pids.hasDuplicates() || matchNeeded)
		{
			obligations.add(new ParameterPatternObligation(this, ctxt));
		}

		/**
		 * Pre- and postconditions for OO dialects are not clearly defined, and obligations
		 * generated from them are generally not type-checkable. So we conditionally
		 * exclude them, depending on the dialect.
		 */
		if (precondition != null && Settings.dialect == Dialect.VDM_SL)
		{
			obligations.addAll(predef.getProofObligations(ctxt, env));
		}

		if (postcondition != null && Settings.dialect == Dialect.VDM_SL)
		{
			if (precondition != null)
			{
				ctxt.push(new POFunctionDefinitionContext(postdef, true));
				ctxt.push(new POImpliesContext(this));
				obligations.add(new TotalFunctionObligation(postdef, ctxt));
				ctxt.pop();
				ctxt.pop();
			}
			else
			{
				obligations.addAll(postdef.getProofObligations(ctxt, env));
			}
			
			ctxt.push(new PONoCheckContext());
			obligations.add(new OperationPostConditionObligation(this, ctxt));
			ctxt.pop();
		}
		
		if (body != null)
		{
			ctxt.push(new PONoCheckContext());
			obligations.addAll(body.getProofObligations(ctxt, env));

			if (isConstructor &&
				classDefinition != null &&
				classDefinition.invariant != null)
			{
				obligations.add(new StateInvariantObligation(this, ctxt));
			}

			if (!isConstructor &&
				!TypeComparator.isSubType(actualResult, type.result))
			{
				obligations.add(new SubTypeObligation(this, actualResult, ctxt));
			}
			
			ctxt.pop();
		}
		else
		{
			if (postcondition != null && Settings.dialect == Dialect.VDM_SL)
			{
				ctxt.push(new POOperationDefinitionContext(this, false, state));
				obligations.add(new SatisfiabilityObligation(this, state, ctxt));
				ctxt.pop();
			}
		}

		if (annotations != null) annotations.poAfter(this, obligations, ctxt);
		return obligations;
	}

	public List getListParamPatternList()
	{
		List list = new Vector();
		
		for (POPatternListTypePair p: parameterPatterns)
		{
			list.add(p.patterns);
		}
		
		return list;
	}
	
	public POPatternList getParamPatternList()
	{
		POPatternList plist = new POPatternList();

		for (POPatternListTypePair pl: parameterPatterns)
		{
			plist.addAll(pl.patterns);
		}

		return plist;
	}


	@Override
	public  R apply(PODefinitionVisitor visitor, S arg)
	{
		return visitor.caseImplicitOperationDefinition(this, arg);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy