package pag.node.var;

import pag.PAG;
import pag.node.GNode;
import pag.node.alloc.Alloc_Node;
import soot.AnySubType;
import soot.ArrayType;
import soot.NullType;
import soot.RefLikeType;
import soot.Type;
import soot.jimple.spark.pag.ArrayElement;
import soot.jimple.spark.pag.SparkField;

/**
 * Represents an alloc-site-dot-field node (Yellow) in the pointer assignment
 * graph.
 * 
 * @author Ondrej Lhotak
 */
public class AllocDotField_Node extends Var_Node {
	/** Returns the base AllocNode. */
	public Alloc_Node getBase() {
		return base;
	}

	/** Returns the field of this node. */
	public SparkField getField() {
		return field;
	}

	public String toString() {
		return "AllocDotField " + getNumber() + " " + base + "." + field;
	}

	/* End of public methods. */

	public AllocDotField_Node(PAG pag, Alloc_Node base, SparkField field) {
		super(pag, field, getAllocDotFieldType(base, field));
		
		this.base = base;
		this.field = field;
		base.addField(this, field);
	}

	/* End of package methods. */

	private static Type getAllocDotFieldType(Alloc_Node base, Object field) {
		Type type;
		if (field instanceof SparkField)
			if (field instanceof ArrayElement){
				Type arrType = base.getType();
				if(arrType instanceof ArrayType){
					Type elementType = ((ArrayType) arrType).getElementType();
					if (!(elementType instanceof RefLikeType) || elementType instanceof AnySubType){
						type = NullType.v();
					}else
						type = elementType; 
				}else{
					type = ((SparkField) field).getType();
				}
			}else
				type = ((SparkField) field).getType();
		else
			type = ((GNode) field).getType();
		return type;
	}

	protected Alloc_Node base;
	protected SparkField field;
}
