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.InnerTypeScope; import slangc.model.MemberModel; import slangc.model.TypeModel; import slangc.parser.Branch; import slangc.parser.Node; public class ConditionalExpression extends ExpressionModel implements ExpressionOwner { ExpressionModel leftHandSide; ExpressionModel trueBranch; ExpressionModel falseBranch; public ConditionalExpression(ExpressionOwner owner, Node source) { super(owner, source); leftHandSide = ExpressionModel.construct(this, ((Branch)source).getSubnode(0)); trueBranch = ExpressionModel.construct(this, ((Branch)source).getSubnode(2)); falseBranch = ExpressionModel.construct(this, ((Branch)source).getSubnode(4)); } @Override public void dump(Reporter reporter, String indent, String incr) { reporter.note("DUMP", indent + "> Conditional expression"); dumpResolved(reporter, indent + incr, incr); leftHandSide.dump(reporter, indent + incr, incr); trueBranch.dump(reporter, indent + incr, incr); falseBranch.dump(reporter, indent + incr, incr); } @Override public ExpressionModel[] getSubexpressions() { return new ExpressionModel[] {leftHandSide, trueBranch, falseBranch}; } @Override public TypeModel getExpectedResult(ExpressionModel e) { // TODO not sure if relevant here return null; } @Override public InnerTypeScope getTypeScope() { return getOwner().getTypeScope(); } @Override public TypeModel resolveType(Node subnode) { return getOwner().resolveType(subnode); } @Override public MemberModel getMethodOrField() { return getOwner().getMethodOrField(); } @Override protected ExpressionResult resolveResult() { if (trueBranch.getResult().resolvesToValueOrNull() && falseBranch.getResult().resolvesToValueOrNull()) { TypeModel lhs = trueBranch.getResult().getValueTypeWithNullType(null); TypeModel rhs = falseBranch.getResult().getValueTypeWithNullType(null); TypeModel res = null; if (lhs == null && rhs == null) { res = getSystem().getDefaultBaseType(); } else if (lhs == null) { res = rhs; } else if (rhs == null) { res = lhs; } else { res = BinaryExpression.resultType(lhs, ":", rhs); } if (res == null) { return ExpressionResult.INVALID; } else { return new ExpressionResult.TypedValue(res); } } return super.resolveResult(); } @Override public TypeSignature innerGenerate(BytecodeInstructionWriter w) { BytecodeInstructionWriter.Label elseLabel = w.newLabel("cond_else"); BytecodeInstructionWriter.Label endLabel = w.newLabel("cond_end"); TypeSignature xt = leftHandSide.generate(w); w.genJump(BytecodeInstructionWriter.JumpOp.IFFALSE, elseLabel); trueBranch.generate(w); w.genJump(BytecodeInstructionWriter.JumpOp.GOTO, endLabel); w.labelHere(elseLabel); falseBranch.generate(w); w.labelHere(endLabel); return getResult().getValueType().getTypeSignature(); } }