ASTNode.java

package dev.civl.abc.ast.node.IF;

import java.io.PrintStream;
import java.util.List;
import java.util.NoSuchElementException;

import dev.civl.abc.ast.IF.AST;
import dev.civl.abc.ast.IF.ASTException;
import dev.civl.abc.ast.IF.ASTFactory;
import dev.civl.abc.ast.IF.DifferenceObject;
import dev.civl.abc.ast.entity.IF.Scope;
import dev.civl.abc.ast.node.IF.acsl.ContractNode;
import dev.civl.abc.ast.node.IF.acsl.TransformNode;
import dev.civl.abc.ast.node.IF.compound.ArrayDesignatorNode;
import dev.civl.abc.ast.node.IF.compound.DesignationNode;
import dev.civl.abc.ast.node.IF.compound.FieldDesignatorNode;
import dev.civl.abc.ast.node.IF.declaration.EnumeratorDeclarationNode;
import dev.civl.abc.ast.node.IF.declaration.FieldDeclarationNode;
import dev.civl.abc.ast.node.IF.declaration.FunctionDeclarationNode;
import dev.civl.abc.ast.node.IF.declaration.FunctionDefinitionNode;
import dev.civl.abc.ast.node.IF.declaration.TypedefDeclarationNode;
import dev.civl.abc.ast.node.IF.declaration.VariableDeclarationNode;
import dev.civl.abc.ast.node.IF.expression.ExpressionNode;
import dev.civl.abc.ast.node.IF.expression.GenericSelectionNode;
import dev.civl.abc.ast.node.IF.expression.ResultNode;
import dev.civl.abc.ast.node.IF.label.OrdinaryLabelNode;
import dev.civl.abc.ast.node.IF.label.SwitchLabelNode;
import dev.civl.abc.ast.node.IF.omp.OmpNode;
import dev.civl.abc.ast.node.IF.omp.OmpReductionNode;
import dev.civl.abc.ast.node.IF.statement.DeclarationListNode;
import dev.civl.abc.ast.node.IF.statement.StatementNode;
import dev.civl.abc.ast.node.IF.type.TypeNode;
import dev.civl.abc.token.IF.Source;

/**
 * <p>
 * Root of the AST node type hierarchy. All AST nodes implement this interface.
 * </p>
 * 
 * <p>
 * An AST node has some number <i>n</i> of <strong>children</strong>. Each child
 * is either an AST node or <code>null</code>. The children are arranged in an
 * ordered sequences and numbered from 0.
 * </p>
 * 
 * <p>
 * Every AST node has at most one parent. If a node <i>u</i> has a (non-
 * <code>null</code>) parent <i>v</i>, then it is guaranteed that <i>u</i> is a
 * child of <i>v</i>. This class is designed so that it is not possible to
 * violate these invariants.
 * </p>
 * 
 * <p>
 * Nodes are mutable objects. It is possible to modify various aspects of the
 * node, to remove a node from its parent, to add new children to a node, and so
 * on.
 * </p>
 * 
 * <p>
 * At any point in time, a node is either "owned" by an AST or it is "free". A
 * node can be owned by at most one AST. A node starts out as free, and becomes
 * owned by an AST when an AST is created and the node is reachable from the
 * root node used to create the new AST. The nodes of an AST can become free by
 * "releasing" the AST, which essentially dissolves the AST but leaves the nodes
 * intact. Modifications to the tree structure (the parent and child relations)
 * can only occur on free nodes, hence to modify an AST it is necessary to first
 * release it. After the modifications are complete, a new AST can be formed
 * from the modified nodes.
 * </p>
 * 
 * @see #child(int)
 * @see #numChildren()
 * @see #parent()
 * @see ASTFactory#newAST(ASTNode)
 * @see #getOwner()
 * @see AST#release()
 */
public interface ASTNode {

	/**
	 * The different kind of AST nodes. Every AST node falls into one of the
	 * following categories.
	 * 
	 * @author siegel
	 * 
	 */
	public enum NodeKind {
		/**
		 * An array designator occurs in a compound initializer and specifies an index
		 * of an array. A node of this kind can be safely cast to
		 * {@link ArrayDesignatorNode}.
		 */
		ARRAY_DESIGNATOR,
		/**
		 * A node representing a CIVL-C collective assertion. Not yet implemented.
		 */
		COLLECTIVE,
		/**
		 * A node representing a contract item. A node of this kind can be safely cast
		 * to {@link ContractNode}.
		 */
		CONTRACT, DEPENDS_EVENT,
		/**
		 * A list of declarations; such a list can occur as an initializer in a
		 * <code>for</code> loop, for example. A node of this kind can be safely cast to
		 * {@link DeclarationListNode}.
		 */
		DECLARATION_LIST,
		/**
		 * A designation, which can occur in a compound initializer. A designation
		 * consists of a sequence of array or field designators to pinpoint a location
		 * within a compound structure. A node of this kind can be safely cast to
		 * {@link DesignationNode}.
		 */
		DESIGNATION,
		/**
		 * An enumerator declaration node represents the declaration of a single
		 * enumerator constant inside a complete <code>enum</code> definition. A node of
		 * this kind can be safely cast to {@link EnumeratorDeclarationNode}.
		 */
		ENUMERATOR_DECLARATION,
		/**
		 * A node representing an expression. A node of this kind can be safely cast to
		 * {@link ExpressionNode}.
		 */
		EXPRESSION,
		/**
		 * A single field declaration within a <code>struct</code> or <code>union</code>
		 * definition. A node of this kind can be safely cast to
		 * {@link FieldDeclarationNode}.
		 */
		FIELD_DECLARATION,
		/**
		 * A field designator can occur in a designation, which can occur in a compound
		 * initializer. It identifies a particular field in a structure or union. A node
		 * of this kind can be safely cast to {@link FieldDesignatorNode}.
		 */
		FIELD_DESIGNATOR,
		/**
		 * A function declaration which is not a function definition, i.e., which does
		 * not include the function body. A node of this kind can be safely cast to
		 * {@link FunctionDeclarationNode}.
		 */
		FUNCTION_DECLARATION,
		/**
		 * A function definition: this is the declaration of the function that includes
		 * the function body. A node of this kind may be safely cast to
		 * {@link FunctionDefinitionNode}.
		 */
		FUNCTION_DEFINITION,
		/**
		 * A generic association node. Represents an association (TypeNode,
		 * ExpressionNode) for use in a {@link GenericSelectionNode}. A node of this
		 * kind may be safely cast to {@link GenericAssociationNode}
		 */
		GENERIC_ASSOCIATION,
		/**
		 * An identifier node. Represents an occurrence of an identifier in the program.
		 * A node of this kind may be safely cast to {@link IdentifierNode}.
		 */
		IDENTIFIER,
		/**
		 * A node representing an OpenMP construct. May be safely cast to
		 * {@link OmpNode}.
		 */
		OMP_NODE,
		/**
		 * A node representing a reduction operator in an OpenMP <code>reduction</code>
		 * clause. May be safely cast to {@link OmpReductionNode}.
		 */
		OMP_REDUCTION_OPERATOR,
		/**
		 * A node representing a label in a labeled statement. (Does not include a
		 * <code>case</code> or <code>default</code> label.) May be safely cast to
		 * {@link OrdinaryLabelNode}.
		 */
		ORDINARY_LABEL,
		/**
		 * A pair node: a node of type {@link PairNode}<code>< S,T ></code> for some
		 * types <code>S</code> and <code>T</code> which are subtypes of
		 * {@link ASTNode}. Such a node has two children, one of type <code>S</code> and
		 * one of type <code>T</code>. A node of this kind can be safely cast to
		 * {@link PairNode}<code>< ?,? ></code>.
		 */
		PAIR,
		/**
		 * A pragma node, corresponding to a <code>#pragma</code> directive in the
		 * source code. May be safely cast to {@link PragmaNode}.
		 */
		PRAGMA,
		/**
		 * A "result"" node represents a use of the special variable
		 * <code>$result</code> in a post-condition in a CIVL-C procedure contract. It
		 * represents the value returned by the procedure. May be safely cast to
		 * {@link ResultNode}.
		 */
		RESULT,
		/**
		 * A CIVL-C scope-parameterized declaration. This is soon to be deprecated.
		 */
		SCOPE_PARAMETERIZED_DECLARATION,
		/**
		 * A node which implement the interface {@link SequenceNode} <code>< T ></code>.
		 * This is a node whose children all have type <code>T</code>, where
		 * <code>T</code> is a subtype of {@link ASTNode}.
		 */
		SEQUENCE,
		/**
		 * A node representing a statement. May be safely cast to {@link StatementNode}.
		 */
		STATEMENT,
		/**
		 * A node representing a C11 static assertion. This is a kind of assertion which
		 * can be checked at "compile time". A node of this kind may be safely cast to
		 * {@link StaticAssertionNode}.
		 */
		STATIC_ASSERTION,
		/**
		 * A switch label is either a label of the form <code>case CONSTANT:</code> or
		 * <code>default :</code> in a <code>switch</code> statement. A node of this
		 * kind may be safely cast to {@link SwitchLabelNode}.
		 */
		SWITCH_LABEL,
		/**
		 * A type node, representing any kind of type. A node of this kind may be safely
		 * cast to {@link TypeNode}.
		 */
		TYPE,
		/**
		 * A typedef node, representing a <code>typedef</code> construct in the program.
		 * A node of this kind may be safely cast to {@link TypedefDeclarationNode}.
		 */
		TYPEDEF,
		/**
		 * A variable declaration node. A node of this kind can be safely cast to
		 * {@link VariableDeclarationNode}.
		 */
		VARIABLE_DECLARATION
	};

	/**
	 * Returns the index-th child node of this AST node. The children of a node are
	 * ordered and numbered starting from 0.
	 * 
	 * @param index an integer in the range [0,n-1], where n is the number of
	 *              children of this node, i.e., the value returned by
	 *              {@link #numChildren()}
	 * @return the index-th child of this node; note that this may be
	 *         <code>null</code>.
	 * @throws NoSuchElementException if index is less than 0 or greater than or
	 *                                equal to the number of children
	 */
	ASTNode child(int index) throws NoSuchElementException;

	/**
	 * <p>
	 * Returns the index of this node among the children of its parent.
	 * </p>
	 * 
	 * <p>
	 * The children of a node are ordered and numbered from 0 to <i>n</i>-1, where
	 * <i>n</i> is the number of children. Since an AST is a tree, every node has at
	 * most one parent. If this node has a parent, this method returns the index of
	 * this node in its parent's children list. If this node does not have a parent,
	 * this method returns -1.
	 * </p>
	 * 
	 * @return the index of this node it its parent's child list, or -1 if it has no
	 *         parent
	 */
	int childIndex();

	/**
	 * Returns the sequence of children of this node as an iterable object. Do not
	 * attempt to cast the iterable to another type and/or modify it; if you do, all
	 * bets are off. Use it only to iterate over the children.
	 * 
	 * @return the (ordered) sequence of children nodes of this node; may contain
	 *         <code>null</code> values
	 */
	Iterable<ASTNode> children();

	/**
	 * Returns a deep copy of this AST node. The node and all of its descendants
	 * will be cloned. The cloning does not copy analysis or attribute information.
	 * 
	 * @return deep copy of this node
	 */
	ASTNode copy();

	/**
	 * Returns the attribute value associated to the given key, or <code>null</code>
	 * if no value has been set for that key. Note that attribute keys are generated
	 * using method {@link NodeFactory#newAttribute(String, Class)}.
	 * 
	 * @param key an attribute key
	 * @return the value associated to the key by this node, or <code>null</code>
	 */
	Object getAttribute(AttributeKey key);

	/**
	 * Returns the "owner" of this AST, i.e., the AST to which this node belongs.
	 * This can be <code>null</code>, in which case we say this node is "free".
	 * 
	 * @return the owner of this node or <code>null</code>
	 */
	AST getOwner();

	/**
	 * Gets the scope in which the syntactic element corresponding to this node
	 * occurs.
	 * 
	 * @return the scope
	 */
	Scope getScope();

	/**
	 * Returns the source object that locates the origin of this program construct
	 * in the original source code. This is used for reporting friendly messages to
	 * the user. The source element specifies a range of tokens in a token stream
	 * and can be used to display file name, line numbers, and character indexes to
	 * precisely target a source region.
	 * 
	 * @return source object for this node
	 */
	Source getSource();

	/**
	 * ID number unique within the AST to which this node belongs, or -1 if the node
	 * is free (not owned by an AST).
	 * 
	 * @return if the node is owned by an AST, the node ID number, which is unique
	 *         among all nodes in this AST; otherwise -1
	 */
	int id();

	/**
	 * <p>
	 * Removes all children that do not satisfy the predicate and applies this
	 * method recursively to the remaining children.
	 * </p>
	 * 
	 * <p>
	 * "Removing a node" is interpreted as follows: if <i>u</i> is an instance of
	 * {@link SequenceNode}, and a child of <i>u</i> does not satisfy the predicate,
	 * then the child is removed and all subsequent elements of the sequence are
	 * shifted down to remove the gap. If <i>u</i> is not an instance of
	 * {@link SequenceNode} and the child does not satisfy the predicate then the
	 * child is replaced by <code>null</code>.
	 * </p>
	 * 
	 * @param keep a node predicate specifying which nodes to keep
	 */
	void keepOnly(NodePredicate keep);

	/**
	 * Returns the node kind: this is an element of the enumerated type
	 * {@link NodeKind}, which is used to categorize the different kinds of nodes.
	 * 
	 * @return The node kind
	 */
	NodeKind nodeKind();

	/**
	 * Returns the number of child nodes of this AST node. This includes children
	 * which are <code>null</code>!
	 * 
	 * @return the number of child nodes of this node
	 */
	int numChildren();

	/**
	 * Returns the parent of this node, or <code>null</code> if this node has no
	 * parent.
	 * 
	 * @return parent node or <code>null</code>
	 */
	ASTNode parent();

	/**
	 * Prints a long-form textual representation of this node. The form usually
	 * involves multiple lines.
	 * 
	 * @param prefix        a string which should be prepended to every line of
	 *                      output; typically something like "| | " which is used to
	 *                      control indentation
	 * @param out           stream to which to print
	 * @param includeSource should the source information be included in the
	 *                      print-out? This incorporates the file name, line
	 *                      number(s), and start and end character indexes for the
	 *                      source code corresponding to this node
	 */
	void print(String prefix, PrintStream out, boolean includeSource);

	/**
	 * <p>
	 * Removes the child at given <code>index</code> from this node.
	 * </p>
	 * 
	 * <p>
	 * The index must be in the range [0,n-1], where n is the value returned by
	 * {@link #numChildren()} in the pre-state (i.e., before this method is
	 * invoked). If there is no child at the given index (i.e., child is
	 * <code>null</code>), this is a no-op.
	 * </p>
	 * 
	 * <p>
	 * If the removed child is non-<code>null</code>, its parent is set to
	 * <code>null</code>.
	 * </p>
	 * 
	 * @param index nonnegative integer in the range [0,n-1], where n is the number
	 *              of children before executing this method
	 * @return the child that was removed (may be <code>null</code>)
	 * @throws ASTException if this node is not free, or <code>index</code> is not
	 *                      in the range [0,n-1]
	 */
	ASTNode removeChild(int index);

	/**
	 * Removes this node from its parent. If the parent of this node is already
	 * <code>null</code>, this is a no-op.
	 */
	void remove();

	/**
	 * Sets the attribute value associated to the given key. This method also checks
	 * that the value belongs to the correct class. Note that attribute keys are
	 * generated by calling method {@link NodeFactory#newAttribute(String, Class)}.
	 * 
	 * @param key   the attribute key
	 * @param value the attribute value
	 */
	void setAttribute(AttributeKey key, Object value);

	/**
	 * <p>
	 * Sets the child node at the given index. This node (i.e., <code>this</code>)
	 * must be free (not owned by an AST) when this method is called.
	 * </p>
	 * 
	 * <p>
	 * The child may be <code>null</code> or non-<code>null</code>. A non-
	 * <code>null</code> child must have a <code>null</code> parent, i.e., it must
	 * not be the child of another node.
	 * </p>
	 * 
	 * <p>
	 * If there is already a non-<code>null</code> child of this node in position
	 * <code>index</code>, the old child is removed, i.e., its parent is set to
	 * <code>null</code>.
	 * </p>
	 * 
	 * <p>
	 * The caller is responsible for ensuring that the child is of the appropriate
	 * kind and type.
	 * </p>
	 * 
	 * <p>
	 * The index can be any nonnegative integer. The list of children will be
	 * expanded as necessary with <code>null</code> values in order to incorporate
	 * the index.
	 * </p>
	 * 
	 * <p>
	 * To illustrate how this method could be used, consider the case of swapping
	 * two nodes. Supposed <code>u1</code> and <code>u2</code> are nodes,
	 * <code>u1</code> has a non-<code>null</code> child in position
	 * <code>i1</code>, and <code>u2</code> has a non-<code>null</code> child in
	 * position <code>i2</code>, and we wish to swap the two children. This could be
	 * accomplished with the following code:
	 * 
	 * <pre>
	 * ASTNode v1 = u1.removeChild(i1), v2 = u2.removeChild(i2);
	 * u1.setChild(i1, v2);
	 * u2.setChild(i2, v1);
	 * </pre>
	 * 
	 * </p>
	 * 
	 * @param index any nonnegative integer
	 * @param child a node (or null) to be made the index-th child of this node
	 * @return the old child in position <code>index</code> (may be
	 *         <code>null</code>)
	 * @throws ASTException if any of the following hold: (1) this node is not free,
	 *                      (2) <code>index</code> is negative, or (3)
	 *                      <code>child</code> is not <code>null</code> and has a
	 *                      non-<code>null</code> parent.
	 */
	ASTNode setChild(int index, ASTNode child);

	/**
	 * Sets the ID number of this node.
	 * 
	 * @param id the ID number
	 */
	void setId(int id);

	/**
	 * Sets the owner of this node to the given AST.
	 * 
	 * @param owner the AST to make the owner of this node
	 */
	void setOwner(AST owner);

	/**
	 * Sets the scope of this syntactic element.
	 * 
	 * @param scope the scope
	 */
	void setScope(Scope scope);

	void addTransformAnnotation(TransformNode transform);

	void removeTransformAnnotation(int index);

	void addAllTransformAnnotations(List<TransformNode> transforms);

	List<TransformNode> transformAnnotations();

	/**
	 * Is the given AST node equivalent to me?
	 * 
	 * @param that The given AST node to be compared.
	 * @return True iff this AST node is equivalent with that AST node.
	 */
	boolean equiv(ASTNode that);

	/**
	 * Returns the first difference between this AST node and that node.
	 * 
	 * @param that The given AST node to be compared.
	 * @return The difference of this AST node and that node, null if both nodes are
	 *         equivalent.
	 */
	DifferenceObject diff(ASTNode that);

	/**
	 * Returns a short textual representation of this node only.
	 * 
	 * @return short textual representation of this node
	 */
	String toString();

	/**
	 * Finds next non-null node in AST in DFS order.
	 * 
	 * @return next non-null node in DFS order or null if there is none
	 */
	ASTNode nextDFS();

	/**
	 * Pretty-prints this AST node (and its descendants) in a form that should be
	 * similar to the actual programming language.
	 * 
	 * @param out stream to which output should be sent
	 */
	void prettyPrint(PrintStream out);

	/**
	 * Returns the pretty representation of this AST node (and its descendants) in a
	 * form that should be similar to the actual programming language.
	 * 
	 * 
	 * @return the pretty representation of this AST node (and its descendants) in a
	 *         form that should be similar to the actual programming language.
	 */
	StringBuffer prettyRepresentation();

	/**
	 * Returns the pretty representation of this AST node (and its descendants) in a
	 * form that should be similar to the actual programming language.
	 * 
	 * @param maxLength the maximal length of the string representation of this
	 *                  node; -1 if the length is unlimited
	 * @return the pretty representation of this AST node (and its descendants) in a
	 *         form that should be similar to the actual programming language.
	 */
	StringBuffer prettyRepresentation(int maxLength);
}