slcom/slangc/model/expressions/ArrayInitialiserExpression.sauce

95 lines
3.5 KiB
Plaintext

package slangc.model.expressions;
import slangc.api.BytecodeInstructionWriter;
import slangc.api.Reporter;
import slangc.bytecode.TypeSignature;
import slangc.model.ArrayTypeModel;
import slangc.model.ClauseModel;
import slangc.model.ExpressionModel;
import slangc.model.ExpressionOwner;
import slangc.model.ExpressionResult;
import slangc.model.TypeModel;
import slangc.model.clauses.Expressions;
import slangc.parser.Branch;
import slangc.parser.ErrorType;
import slangc.parser.Node;
/**
* An array initialiser is sort of a special edge case, in between an expression and a more specific clause.
* The main difference between an array initialiser and a normal expression is that the result type needs
* to be known/valid.
*
* @author Zak
*
*/
public class ArrayInitialiserExpression extends ExpressionModel implements ExpressionOwner {
private Expressions valueExpressions;
public ArrayInitialiserExpression(ExpressionOwner owner, Node source) {
super(owner, source);
if (owner.getExpectedResult(this) == null) {
source.annotate(ErrorType.INTERNAL_ERROR, "An array initialiser can only appear as an expression if the expected type is known!");
} else if (!(owner.getExpectedResult(this) instanceof ArrayTypeModel)) {
source.annotate(ErrorType.INTERNAL_ERROR, "Array initialiser type is invalid");
}
valueExpressions = (Expressions)ClauseModel.construct(this, ((Branch)source).getSubnode(1));
//sourceFile.annotate(ErrorType.INTERNAL_ERROR, "Unrecognised expression (Internal error/TODO)");
}
@Override
public void dump(Reporter reporter, String indent, String incr) {
reporter.note("DUMP", indent + "> Array initialiser of: (element type " + getExpectedResult(null) + ")");
dumpResolved(reporter, indent + incr, incr);
valueExpressions.dump(reporter, indent + incr, incr);
}
@Override
protected ExpressionResult resolveResult() {
TypeModel et = getOwner().getExpectedResult(this);
if (et == null) {
return ExpressionResult.INVALID;
} else {
return new ExpressionResult.TypedValue(et);
}
}
@Override
public TypeModel getExpectedResult(ExpressionModel e) {
if (getOwner().getExpectedResult(this) == null || !(getOwner().getExpectedResult(this) instanceof ArrayTypeModel)) {
return null;
}
return ((ArrayTypeModel)getOwner().getExpectedResult(this)).getElementType();
}
public Expressions getArguments() {
return valueExpressions;
}
@Override
public ExpressionModel[] getSubexpressions() {
return valueExpressions.getSubexpressions();
}
@Override
public TypeSignature innerGenerate(BytecodeInstructionWriter w) {
w.genConst(w.getTarget().getHeap().getConstInt32("" + valueExpressions.countExpressions()));
w.genNewArray(getResult().getValueType().getTypeSignature());
for (int i = 0; i < valueExpressions.countExpressions(); i++) {
w.genDup(getResult().getValueType().getTypeSignature()); // TODO: Wrong dup type?
ExpressionModel e = valueExpressions.getExpression(i);
TypeSignature et = e.generate(w);
w.genSwap(et, getResult().getValueType().getTypeSignature());
w.genConst(w.getTarget().getHeap().getConstInt32("" + i));
//w.genSwap(getSystem().getDefaultInt32Type().getTypeSignature(), getResult().getValueType().getTypeSignature());
w.genArrayStore(((ArrayTypeModel)getResult().getValueType()).getElementType().getTypeSignature());
}
return getResult().getValueType().getTypeSignature();
}
public TypeModel resolveType(Node n) {
return super.resolveType(n); // TODO: Better support for interfaces
}
}