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

com.fujitsu.vdmj.tc.statements.TCObjectApplyDesignator 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.tc.statements;

import com.fujitsu.vdmj.tc.expressions.TCExpression;
import com.fujitsu.vdmj.tc.expressions.TCExpressionList;
import com.fujitsu.vdmj.tc.types.TCFunctionType;
import com.fujitsu.vdmj.tc.types.TCMapType;
import com.fujitsu.vdmj.tc.types.TCOperationType;
import com.fujitsu.vdmj.tc.types.TCSeqType;
import com.fujitsu.vdmj.tc.types.TCType;
import com.fujitsu.vdmj.tc.types.TCTypeList;
import com.fujitsu.vdmj.tc.types.TCTypeSet;
import com.fujitsu.vdmj.tc.types.TCUnknownType;
import com.fujitsu.vdmj.typechecker.Environment;
import com.fujitsu.vdmj.typechecker.NameScope;
import com.fujitsu.vdmj.typechecker.TypeComparator;
import com.fujitsu.vdmj.util.Utils;

public class TCObjectApplyDesignator extends TCObjectDesignator
{
	private static final long serialVersionUID = 1L;
	public final TCObjectDesignator object;
	public final TCExpressionList args;

	public TCObjectApplyDesignator(TCObjectDesignator object, TCExpressionList args)
	{
		super(object.location);
		this.object = object;
		this.args = args;
	}

	@Override
	public String toString()
	{
		return "(" + object + "(" + Utils.listToString(args) + "))";
	}

	@Override
	public TCType typeCheck(Environment env, TCTypeList qualifiers)
	{
		TCTypeList argtypes = new TCTypeList();

		for (TCExpression a: args)
		{
			argtypes.add(a.typeCheck(env, null, NameScope.NAMESANDSTATE, null));
		}

		TCType type = object.typeCheck(env, argtypes);
		boolean unique = !type.isUnion(location);
		TCTypeSet result = new TCTypeSet();

		if (type.isMap(location))
		{
			TCMapType map = type.getMap();
			result.add(mapApply(map, env, NameScope.NAMESANDSTATE, unique));
		}

		if (type.isSeq(location))
		{
			TCSeqType seq = type.getSeq();
			result.add(seqApply(seq, env, NameScope.NAMESANDSTATE, unique));
		}

		if (type.isFunction(location))
		{
			TCFunctionType ft = type.getFunction();
			ft.typeResolve(env);
			result.add(functionApply(ft, env, NameScope.NAMESANDSTATE, unique));
		}

		if (type.isOperation(location))
		{
			TCOperationType ot = type.getOperation();
			ot.typeResolve(env);
			result.add(operationApply(ot, env, NameScope.NAMESANDSTATE, unique));
		}

		if (result.isEmpty())
		{
			report(3249, "Object designator is not a map, sequence, function or operation");
			detail2("Designator", object, "Type", type);
			return new TCUnknownType(location);
		}

		return result.getType(location);
	}

	private TCType mapApply(
		TCMapType map, Environment env, NameScope scope, boolean unique)
	{
		if (args.size() != 1)
		{
			concern(unique, 3250, "Map application must have one argument");
			return new TCUnknownType(location);
		}

		TCType argtype = args.get(0).typeCheck(env, null, scope, null);

		if (!TypeComparator.compatible(map.from, argtype))
		{
			concern(unique, 3251, "Map application argument is incompatible type");
			detail2(unique, "Map domain", map.from, "Argument", argtype);
		}

		return map.to;
	}

	private TCType seqApply(
		TCSeqType seq, Environment env, NameScope scope, boolean unique)
	{
		if (args.size() != 1)
		{
			concern(unique, 3252, "Sequence application must have one argument");
			return new TCUnknownType(location);
		}

		TCType argtype = args.get(0).typeCheck(env, null, scope, null);

		if (!argtype.isNumeric(location))
		{
			concern(unique, 3253, "Sequence argument is not numeric");
			detail(unique, "Type", argtype);
		}

		return seq.seqof;
	}

	private TCType functionApply(
		TCFunctionType ftype, Environment env, NameScope scope, boolean unique)
	{
		TCTypeList ptypes = ftype.parameters;

		if (args.size() > ptypes.size())
		{
			concern(unique, 3254, "Too many arguments");
			detail2(unique, "Args", args, "Params", ptypes);
			return ftype.result;
		}
		else if (args.size() < ptypes.size())
		{
			concern(unique, 3255, "Too few arguments");
			detail2(unique, "Args", args, "Params", ptypes);
			return ftype.result;
		}

		int i=0;

		for (TCExpression a: args)
		{
			TCType at = a.typeCheck(env, null, scope, null);
			TCType pt = ptypes.get(i++);

			if (!TypeComparator.compatible(pt, at))
			{
				concern(unique, 3256, "Inappropriate type for argument " + i);
				detail2(unique, "Expect", pt, "Actual", at);
			}
		}

		return ftype.result;
	}

	private TCType operationApply(
		TCOperationType optype, Environment env, NameScope scope, boolean unique)
	{
		TCTypeList ptypes = optype.parameters;

		if (args.size() > ptypes.size())
		{
			concern(unique, 3257, "Too many arguments");
			detail2(unique, "Args", args, "Params", ptypes);
			return optype.result;
		}
		else if (args.size() < ptypes.size())
		{
			concern(unique, 3258, "Too few arguments");
			detail2(unique, "Args", args, "Params", ptypes);
			return optype.result;
		}

		int i=0;

		for (TCExpression a: args)
		{
			TCType at = a.typeCheck(env, null, scope, null);
			TCType pt = ptypes.get(i++);

			if (!TypeComparator.compatible(pt, at))
			{
				concern(unique, 3259, "Inappropriate type for argument " + i);
				detail2(unique, "Expect", pt, "Actual", at);
			}
		}

		return optype.result;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy