package rs.etf.pp1.symboltable.concepts;
import java.util.Collection;
import rs.etf.pp1.symboltable.Tab;
import rs.etf.pp1.symboltable.structure.HashTableDataStructure;
import rs.etf.pp1.symboltable.structure.SymbolDataStructure;
import rs.etf.pp1.symboltable.visitors.SymbolTableVisitor;
/**
* Struktura tipa u MikroJavi.
*
* @author ETF
*
*/
public class Struct {
// kodiranje tipova
public static final int None = 0;
public static final int Int = 1;
public static final int Char = 2;
public static final int Array = 3;
public static final int Class = 4;
private int kind; // None, Int, Char, Array, Class
private Struct elemType; // niz: tip elementa niza
// klasa: broj bolja klase
private int numOfFields;
// klasa: referenca na hes tabelu u kojoj se nalaze polja klase
private SymbolDataStructure members;
public void setMembers(SymbolDataStructure symbols) {
members = symbols;
numOfFields = 0;
if (symbols != null) {
for (Obj s : symbols.symbols()) {
if (s.getKind() == Obj.Fld)
numOfFields++;
}
}
}
public Struct(int kind) {
this.kind = kind;
}
public Struct(int kind, Struct elemType) {
this.kind = kind;
if (kind == Array) this.elemType = elemType;
}
public Struct(int kind, SymbolDataStructure members) {
this.kind = kind;
setMembers(members);
}
public int getKind() {
return kind;
}
public Struct getElemType() {
return elemType;
}
public int getNumberOfFields() {
return numOfFields;
}
public SymbolDataStructure getMembers() {
if (members == null)
members = new HashTableDataStructure();
return members;
}
public boolean equals(Object o) {
// najpre provera da li su reference jednake
if (super.equals(o)) return true;
if (!(o instanceof Struct)) return false;
return equals((Struct) o);
}
public boolean isRefType() {
return kind == Class || kind == Array;
}
public boolean equals(Struct other) {
if (kind == Array) return other.kind == Array
&& elemType.equals(other.elemType);
if (kind == Class) return other.kind == Class && numOfFields == other.numOfFields
&& Obj.equalsCompleteHash(members, other.members);
// mora biti isti Struct cvor
return this == other;
}
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 == Array && dest.kind == Array && dest.elemType == Tab.noType);
}
public void accept(SymbolTableVisitor stv) {
stv.visitStructNode(this);
}
}