slcom/slangc/model/FieldModel.sauce

205 lines
5.2 KiB
Plaintext
Raw Permalink Normal View History

package slangc.model;
import slangc.api.Reporter;
import slangc.bytecode.FieldSignature;
import slangc.parser.Branch;
import slangc.parser.ErrorType;
import slangc.parser.Node;
import slangc.parser.NodeType;
public class FieldModel extends MemberModel implements ExpressionOwner, StorageSlot {
private Branch slotSource;
private TypeModel baseStorageType;
private ExpressionModel initialisation;
private LocalStorageModel upvalueReference;
private boolean isEnum = false;
public FieldModel(UserTypeModel owner, String name, Branch source, Branch slotSource) {
super(owner, name, source);
this.slotSource = slotSource;
baseStorageType = owner.resolveTypeReference(source.getSubnode(1));
//if (baseStorageType == null) {
// sourceFile.annotate(ErrorType.INTERNAL_ERROR, "Can't find storage type for field");
//}
if (hasInitialiser()) {
initialisation = ExpressionModel.construct(this, slotSource.getSubnode(2));
}
}
public FieldModel(UserTypeModel owner, String name, Branch source) {
super(owner, name, source);
isEnum = true;
}
public FieldModel(UserTypeModel owner, String name, LocalStorageModel upvalueReference) {
super(owner, name, null);
this.upvalueReference = upvalueReference;
baseStorageType = upvalueReference.getStorageType();
}
public Node getNameNode() {
return slotSource.getSubnode(0);
}
public String getName() {
if (isEnum) {
return super.getName();
}
if (upvalueReference != null) {
return upvalueReference.getName();
}
return UserTypeModel.plainName(getNameNode());
}
public int countAdditionalIndices() {
if (isUpvalue()) {
return 0;
}
Node n = getNameNode();
int i = 0;
while (n.getNodeType() == NodeType.INDEXED_NAME) {
n = ((Branch) n).getSubnode(0);
i++;
}
return i;
}
public TypeModel getStorageType() {
if (isEnum) {
return getOwner();
}
TypeModel effectiveType = baseStorageType;
if (effectiveType == null) {
return null;
}
for (int i = 0; i < countAdditionalIndices(); i++) {
effectiveType = effectiveType.getOrCreateArrayInstance();
}
return effectiveType;
}
@Override
public MemberCategory getCategory() {
return MemberCategory.FIELD;
}
public Branch getSlotSource() {
return slotSource;
}
public boolean hasInitialiser() {
if (isEnum) {
return false; // Kind of does have an initialiser but is treated specially.
}
if (isUpvalue()) {
return false; // Kind of does have an initialiser but is treated specially.
}
return getSlotSource().getNodeType() == NodeType.INITIALISED_SLOT;
}
//public TypeModel getStorageType() {
// return baseStorageType;
//}
public ExpressionModel getInitialisationExpression() {
return initialisation;
}
@Override
public void dump(Reporter reporter, String indent, String incr) {
super.dump(reporter, indent, incr);
if (baseStorageType != null) {
reporter.note("DUMP", indent + incr + "> Storage type is " + baseStorageType);
} else {
reporter.note("DUMP", "[no storage type information]");
}
if (hasInitialiser()) {
reporter.note("DUMP", indent + incr + "> Initialised with expression:");
initialisation.dump(reporter, indent + incr + incr, incr);
} else {
reporter.note("DUMP", indent + incr + "[this field is not initialised]");
}
}
//@Override
public TypeModel getExpectedResult(ExpressionModel e) {
return getStorageType();
}
//@Override
public InnerTypeScope getTypeScope() {
return getOwner();
}
//@Override
public TypeModel resolveType(Node typeReference) {
return ((UserTypeModel)getOwner()).resolveTypeReference(typeReference);
}
//@Override
public MemberModel getMethodOrField() {
return this;
}
//@Override
public StorageSlot.Kind getSlotKind() {
if (isStatic()) {
return StorageSlot.Kind.STATIC_FIELD;
} else {
return StorageSlot.Kind.INSTANCE_FIELD;
}
}
//@Override
public Named lookupSimpleName(String name) {
return getOwner().lookupSimpleName(name);
}
//@Override
public MethodModel[] lookupSimpleMethod(String name) {
return getOwner().lookupSimpleMethod(name);
}
@Override
public int resolveExpressions() {
if (hasInitialiser()) {
return getInitialisationExpression().resolveExpressions();
} else {
return 0;
}
}
@Override
public boolean isStatic() {
if (isEnum) { // Enum fields are always static
return true;
}
// Interface fields are assumed to be static
if (getOwner().getTypeType() == TypeType.INTERFACE || getOwner().getTypeType() == TypeType.INTERFACE_TEMPLATE) {
return true;
}
return super.isStatic();
}
public boolean isEnumField() {
return isEnum;
}
public boolean isUpvalue() {
return upvalueReference != null;
}
public LocalStorageModel getUpvalueReference() {
return upvalueReference;
}
@Override
public int getFlags() {
return super.getFlags() | (isUpvalue() ? (Flags.MASK_UPVALUE | Flags.MASK_SYNTHETIC | Flags.MASK_FINAL) : 0);
}
public FieldSignature getFieldSignature() {
return new FieldSignature(getOwner().getTypeSignature(), isStatic(), getStorageType().getTypeSignature(), getName());
}
}