package slangc.model.expressions; import slangc.api.BytecodeInstructionWriter; import slangc.api.Reporter; import slangc.bytecode.TypeSignature; import slangc.model.ExpressionModel; import slangc.model.ExpressionOwner; import slangc.model.ExpressionResult; import slangc.model.FieldModel; import slangc.model.LocalStorageModel; import slangc.model.Named; import slangc.model.StorageSlot; import slangc.model.TypeModel; import slangc.model.UserTypeModel; import slangc.parser.Branch; import slangc.parser.ErrorType; import slangc.parser.Node; public class ReferenceExpression extends ExpressionModel { private String name; private Named resolvedNamedEntity; public ReferenceExpression(ExpressionOwner owner, Node source) { super(owner, source); name = UserTypeModel.plainName(((Branch)source).getSubnode(0)); // This now waits until expressions are resolved later //resolvedNamedEntity = lookupSimpleName(name); //sourceFile.annotate(ErrorType.INTERNAL_ERROR, "Unrecognised expression (Internal error/TODO)"); } @Override public void dump(Reporter reporter, String indent, String incr) { reporter.note("DUMP", indent + "> Reference expression '" + name + "' -> " + resolvedNamedEntity); dumpResolved(reporter, indent + incr, incr); } public String getName() { return name; } public Named getResolvedNamedEntity() { return resolvedNamedEntity; } @Override public ExpressionModel[] getSubexpressions() { return NO_SUBEXPRESSIONS; } @Override protected ExpressionResult resolveResult() { if (resolvedNamedEntity == null) { resolvedNamedEntity = lookupSimpleName(name); } //System.err.println("Resolved to " + resolvedNamedEntity); if (resolvedNamedEntity == null) { if (!(getOwner() instanceof SubreferenceExpression)) { getSource().annotate(ErrorType.INTERNAL_ERROR, "Failed to resolve '" + name + "'"); } return new ExpressionResult.StartOfName(name); } else if (resolvedNamedEntity instanceof TypeModel) { return new ExpressionResult.PointsToType((TypeModel) resolvedNamedEntity); } else if (resolvedNamedEntity instanceof StorageSlot) { return new ExpressionResult.PointsToStorageSlot((StorageSlot) resolvedNamedEntity); } else { throw new Error("Reference resolved to invalid entity: " + resolvedNamedEntity); } } @Override public TypeSignature innerGenerate(BytecodeInstructionWriter w) { if (getResolvedNamedEntity() instanceof FieldModel) { FieldModel f = (FieldModel)getResolvedNamedEntity(); if (!f.isStatic()) { OuterThisExpression.generatePossibleOuterThis(w, (UserTypeModel)getMethodOrField().getOwner(), f.getOwner()); } w.genLoad(f.getFieldSignature()); return f.getFieldSignature().storageType; } else if (getResolvedNamedEntity() instanceof LocalStorageModel) { LocalStorageModel l = (LocalStorageModel)getResolvedNamedEntity(); // TODO: Handle upvalues! w.genLoadLocalOrParam(l.getStorageType().getTypeSignature(), l.getIndex()); return l.getStorageType().getTypeSignature(); } else { w.genError("TODO: innerGenerate for " + Type.of(this) + " with " + getResolvedNamedEntity()); } return null; } @Override public void generateStore(BytecodeInstructionWriter w, TypeSignature storing) { if (getResolvedNamedEntity() instanceof FieldModel) { FieldModel f = (FieldModel)getResolvedNamedEntity(); if (!f.isStatic()) { OuterThisExpression.generatePossibleOuterThis(w, (UserTypeModel)getMethodOrField().getOwner(), f.getOwner()); } w.genStore(f.getFieldSignature()); } else if (getResolvedNamedEntity() instanceof LocalStorageModel) { LocalStorageModel l = (LocalStorageModel)getResolvedNamedEntity(); // TODO: Handle upvalues! w.genStoreLocalOrParam(l.getStorageType().getTypeSignature(), l.getIndex()); } else { w.genError("TODO: generateStore for " + getResolvedNamedEntity()); } } public TypeModel resolveType(Node n) { return super.resolveType(n); // TODO: Better support for interfaces } }