/**
 * MicroJava Type Structures:
 * A type structure stores the type attributes of a declared type.
 */
package ppdz;

public class Struct {
	public static final int None = 0, Int = 1, Char = 2, Arr = 3, Class = 4;
	
	public int kind;		// None, Int, Char, Arr, Class
	public Struct elemType;	// Arr: type of array elements
	public int n;			// Class: # of fields
	public Obj fields;		// Class: reference to list of local variables
	
	public Struct (int kind) { this.kind = kind; }
	public Struct (int kind, Struct elemType) {
		this.kind = kind;
		if (kind == Arr) this.elemType = elemType;
	}
	
	public boolean equals (Object o) {
		if (super.equals(o)) return true;	// same object
		
		if (!(o instanceof Struct)) return false;
		
		return equals((Struct) o);		
	}
	
	public boolean isRefType () {
		return kind == Class || kind == Arr;
	}

	public boolean equals (Struct other) {
		if (kind == Arr) 
			return other.kind == Arr && elemType.equals(other.elemType);
		
		if (kind == Class)
			return other.kind == Class && n == other.n && 
			       Obj.equalsCompleteList(fields, other.fields);
		
		return this == other;	// must be same type Obj node
	}
	
	public boolean compatibleWith (Struct other) {
		return this.equals(other) ||
		       this == Tab.nullType && other.isRefType() ||
		       other == Tab.nullType && this.isRefType();
	}

	public boolean assignableTo (Struct dest) {
		return this.equals(dest) || 
		       this == Tab.nullType && dest.isRefType() ||
		       this.kind == Arr && 
		       dest.kind == Arr && dest.elemType == Tab.noType;
	}
}
