CommonFunctionDeclarationNode.java

package edu.udel.cis.vsl.abc.ast.node.common.declaration;

import java.io.PrintStream;

import edu.udel.cis.vsl.abc.ast.IF.ASTException;
import edu.udel.cis.vsl.abc.ast.IF.DifferenceObject;
import edu.udel.cis.vsl.abc.ast.IF.DifferenceObject.DiffKind;
import edu.udel.cis.vsl.abc.ast.entity.IF.Function;
import edu.udel.cis.vsl.abc.ast.node.IF.ASTNode;
import edu.udel.cis.vsl.abc.ast.node.IF.IdentifierNode;
import edu.udel.cis.vsl.abc.ast.node.IF.SequenceNode;
import edu.udel.cis.vsl.abc.ast.node.IF.acsl.ContractNode;
import edu.udel.cis.vsl.abc.ast.node.IF.declaration.FunctionDeclarationNode;
import edu.udel.cis.vsl.abc.ast.node.IF.type.TypeNode;
import edu.udel.cis.vsl.abc.token.IF.Source;

public class CommonFunctionDeclarationNode extends CommonOrdinaryDeclarationNode
		implements
			FunctionDeclarationNode {

	private boolean inlineFunctionSpecifier = false;

	private boolean noreturnFunctionSpecifier = false;

	private boolean globalFunctionSpecifier = false;

	private boolean atomicFunctionSpecifier = false;// $atomic_f
	private boolean stateFunctionSpecifier = false;
	private boolean pureFunctionSpecifier = false;
	private boolean systemFunctionSpecifier = false;
	private String systemLibrary = null;

	/**
	 * a flag indicating if the declared function is a logic function
	 */
	private boolean isLogic = false;

	public CommonFunctionDeclarationNode(Source source,
			IdentifierNode identifier, TypeNode type,
			SequenceNode<ContractNode> contract) {
		super(source, identifier, type);
		addChild(contract); // child 2
	}

	@Override
	public Function getEntity() {
		return (Function) super.getEntity();
	}

	@Override
	public boolean hasInlineFunctionSpecifier() {
		return inlineFunctionSpecifier;
	}

	@Override
	public void setInlineFunctionSpecifier(boolean value) {
		this.inlineFunctionSpecifier = value;
	}

	@Override
	public boolean hasNoreturnFunctionSpecifier() {
		return this.noreturnFunctionSpecifier;
	}

	@Override
	public void setNoreturnFunctionSpecifier(boolean value) {
		this.noreturnFunctionSpecifier = value;
	}

	@Override
	public boolean hasGlobalFunctionSpecifier() {
		return this.globalFunctionSpecifier;
	}

	@Override
	public void setGlobalFunctionSpecifier(boolean value) {
		this.globalFunctionSpecifier = value;
	}

	protected void printKind(PrintStream out) {
		out.print("FunctionDeclaration");
	}

	@Override
	protected void printBody(PrintStream out) {
		boolean needSeparator = false;

		printKind(out);
		if (hasExternStorage()) {
			out.print("[");
			out.print("extern");
			needSeparator = true;
		}
		if (hasStaticStorage()) {
			out.print(needSeparator ? ", " : "[");
			out.print("static");
			needSeparator = true;
		}
		if (inlineFunctionSpecifier) {
			out.print(needSeparator ? ", " : "[");
			out.print("inline");
			needSeparator = true;
		}
		if (noreturnFunctionSpecifier) {
			out.print(needSeparator ? ", " : "[");
			out.print("noreturn");
			needSeparator = true;
		}
		if (needSeparator)
			out.print("]");
	}

	@SuppressWarnings("unchecked")
	@Override
	public SequenceNode<ContractNode> getContract() {
		return (SequenceNode<ContractNode>) child(2);
	}

	@Override
	public void setContract(SequenceNode<ContractNode> contract) {
		setChild(2, contract);
	}

	@Override
	public FunctionDeclarationNode copy() {
		CommonFunctionDeclarationNode result = new CommonFunctionDeclarationNode(
				getSource(), duplicate(getIdentifier()),
				duplicate(getTypeNode()), duplicate(getContract()));

		result.setInlineFunctionSpecifier(hasInlineFunctionSpecifier());
		result.setNoreturnFunctionSpecifier(hasNoreturnFunctionSpecifier());
		result.setGlobalFunctionSpecifier(hasGlobalFunctionSpecifier());
		result.setAtomicFunctionSpecifier(this.hasAtomicFunctionSpecifier());
		result.setSystemFunctionSpecifier(this.hasSystemFunctionSpecifier());
		result.setPureFunctionSpecifier(this.hasPureFunctionSpecifier());
		result.setStatefFunctionSpecifier(this.hasStatefFunctionSpecifier());
		copyStorage(result);
		result.setSystemLibrary(this.systemLibrary);
		return result;
	}

	@Override
	public NodeKind nodeKind() {
		return NodeKind.FUNCTION_DECLARATION;
	}

	@Override
	public OrdinaryDeclarationKind ordinaryDeclarationKind() {
		return OrdinaryDeclarationKind.FUNCTION_DECLARATION;
	}

	@Override
	protected DifferenceObject diffWork(ASTNode that) {
		if (that instanceof FunctionDeclarationNode) {
			FunctionDeclarationNode thatFunction = (FunctionDeclarationNode) that;

			if (!(this.inlineFunctionSpecifier == thatFunction
					.hasInlineFunctionSpecifier()
					&& this.noreturnFunctionSpecifier == thatFunction
							.hasNoreturnFunctionSpecifier()))
				return new DifferenceObject(this, that, DiffKind.OTHER,
						"different function inline/noreturn specifier");
			else
				return null;
		}
		return new DifferenceObject(this, that);
	}

	@Override
	public void setStatefFunctionSpecifier(boolean value) {
		this.stateFunctionSpecifier = value;
	}

	@Override
	public void setAtomicFunctionSpecifier(boolean value) {
		this.atomicFunctionSpecifier = value;
	}

	@Override
	public void setSystemFunctionSpecifier(boolean value) {
		this.systemFunctionSpecifier = value;
	}

	@Override
	public boolean hasStatefFunctionSpecifier() {
		return this.stateFunctionSpecifier;
	}

	@Override
	public boolean hasAtomicFunctionSpecifier() {
		return this.atomicFunctionSpecifier;
	}

	@Override
	public boolean hasSystemFunctionSpecifier() {
		return this.systemFunctionSpecifier;
	}

	@Override
	public String getSystemLibrary() {
		return this.systemLibrary;
	}

	@Override
	public void setSystemLibrary(String library) {
		this.systemLibrary = library;
	}

	@Override
	public boolean hasPureFunctionSpecifier() {
		return this.pureFunctionSpecifier;
	}

	@Override
	public void setPureFunctionSpecifier(boolean value) {
		this.pureFunctionSpecifier = value;
	}

	@Override
	public boolean isLogicFunction() {
		return isLogic;
	}

	@Override
	public void setIsLogicFunction(boolean isLogicFunction) {
		this.isLogic = isLogicFunction;
	}

	@Override
	public ASTNode setChild(int index, ASTNode child) {
		if (index == 2 && !(child == null || child instanceof SequenceNode))
			throw new ASTException(
					"Child of CommonFunctionDeclarationNode at index " + index
							+ " must be an SequenceNode, but saw " + child
							+ " with type " + child.nodeKind());
		return super.setChild(index, child);
	}
}