95 lines
3.5 KiB
Plaintext
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
|
|
}
|
|
}
|