TaggedEntityInfo.java

package edu.udel.cis.vsl.abc.program.common;

import java.util.ArrayList;
import java.util.Map;

import edu.udel.cis.vsl.abc.ast.entity.IF.ProgramEntity;
import edu.udel.cis.vsl.abc.ast.entity.IF.TaggedEntity;
import edu.udel.cis.vsl.abc.ast.type.IF.EnumerationType;
import edu.udel.cis.vsl.abc.ast.type.IF.StructureOrUnionType;
import edu.udel.cis.vsl.abc.ast.type.IF.Type;
import edu.udel.cis.vsl.abc.ast.type.IF.Type.TypeKind;
import edu.udel.cis.vsl.abc.err.IF.ABCRuntimeException;
import edu.udel.cis.vsl.abc.util.IF.Pair;

/**
 * <p>
 * A TaggedEntityInfo records information about the file-scope tagged entities
 * in different translation units sharing a common tag.
 * </p>
 * 
 * <p>
 * Once all the information has been added, the actions required to transform
 * the AST are obtained from method {@link #computeActions}. There are at least
 * two kinds of actions:
 * <ol>
 * <li>Renaming actions. These assign a new name to the entity.</li>
 * <li>Definition deletion actions. These specify nullification of the complete
 * part of the definition of a tagged entity in a translation unit.</li>
 * </ol>
 * </p>
 * 
 * @author siegel
 */
public class TaggedEntityInfo extends EntityInfo {

	/**
	 * Translation unit ID-Entity pairs for all tagged entities sharing the name
	 * corresponding to this info object.
	 */
	private ArrayList<Pair<Integer, TaggedEntity>> entityPairs = new ArrayList<>();

	/**
	 * Information about those entities using the tag and which are structs.
	 */
	private TagCategoryInfo structInfo;

	/**
	 * Information about those entities using the tag and which are unions.
	 */
	private TagCategoryInfo unionInfo;

	/**
	 * Information about those entities using the tag and which are enums.
	 */
	private TagCategoryInfo enumInfo;

	/**
	 * Creates a new tagged entity info object with the given tag. Initially,
	 * all information is empty.
	 * 
	 * @param tag
	 *            the tag, i.e., the name shared by the tagged entities this
	 *            object deals with
	 * @param numTransitionUnits
	 *            the number of translation units under consideration
	 */
	public TaggedEntityInfo(String tag, int numTranslationUnits) {
		super(tag, numTranslationUnits);
		structInfo = new TagCategoryInfo(this);
		unionInfo = new TagCategoryInfo(this);
		enumInfo = new TagCategoryInfo(this);
	}

	boolean isExclusive() {
		int numEmpty = 0;

		if (structInfo.isEmpty())
			numEmpty++;
		if (unionInfo.isEmpty())
			numEmpty++;
		if (enumInfo.isEmpty())
			numEmpty++;
		return numEmpty >= 2;
	}

	ArrayList<Pair<Integer, TaggedEntity>> getEntityPairs() {
		return entityPairs;
	}

	@Override
	protected void addEntity(int tuid, ProgramEntity entity) {
		TaggedEntity taggedEntity = (TaggedEntity) entity;
		Pair<Integer, TaggedEntity> pair = new Pair<>(tuid, taggedEntity);
		Type type = entity.getType();
		TypeKind kind = type.kind();

		entityPairs.add(pair);
		if (kind == TypeKind.STRUCTURE_OR_UNION) {
			if (((StructureOrUnionType) type).isStruct())
				structInfo.add(pair);
			else
				unionInfo.add(pair);
		} else if (kind == TypeKind.ENUMERATION)
			enumInfo.add(pair);
		else
			throw new ABCRuntimeException("Unreachable");
	}

	public void computeActions(Plan[] plans,
			Map<EnumerationType, Integer> enumMergeMap) {
		structInfo.addActions(plans);
		unionInfo.addActions(plans);
		enumInfo.addToEnumMergeMap(enumMergeMap);
		enumInfo.addActions(plans);
	}

	/**
	 * <p>
	 * This method attempts to determine which entities can be merged. Two
	 * entities can be merged if they have the same kind (enum, struct, or
	 * union), and their components can be merged. For example, for a struct,
	 * the two structs must have the same number of fields, with the same names,
	 * occurring in the same order, and the corresponding types must be the same
	 * (perhaps after merging other types). The results of this analysis are
	 * recorded in this object's internal state.
	 * </p>
	 * 
	 * @return true if at least one merge was made
	 */
	public boolean merge() {
		boolean result = false;

		result = result || enumInfo.merge();
		result = result || structInfo.merge();
		result = result || unionInfo.merge();
		return result;
	}
}