Add Ternary, fix #324
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 2m48s

This commit is contained in:
Daniel Holle 2024-04-22 12:17:53 +02:00
parent 9358130468
commit b774281cbb
12 changed files with 106 additions and 2 deletions

View File

@ -0,0 +1,9 @@
import java.lang.Boolean;
import java.lang.String;
import java.lang.Integer;
public class Ternary {
public main(x) {
return x > 10 ? "big" : "small";
}
}

View File

@ -1108,6 +1108,20 @@ public class Codegen {
mv.visitInsn(ATHROW);
break;
}
case TargetTernary ternary: {
generate(state, ternary.cond());
var iffalse = new Label();
var end = new Label();
mv.visitJumpInsn(IFEQ, iffalse);
generate(state, ternary.iftrue());
convertTo(state, ternary.iftrue().type(), ternary.type());
mv.visitJumpInsn(GOTO, end);
mv.visitLabel(iffalse);
generate(state, ternary.iffalse());
convertTo(state, ternary.iffalse().type(), ternary.type());
mv.visitLabel(end);
break;
}
default:
throw new CodeGenException("Unexpected value: " + expr);
}

View File

@ -832,7 +832,13 @@ public class StatementGenerator {
}
private Expression convert(Java17Parser.ConditionalassignexpressionContext expression) {
throw new NotImplementedException();
return new Ternary(TypePlaceholder.fresh(
expression.getStart()),
convert(expression.expression(0)),
convert(expression.expression(1)),
convert(expression.expression(2)),
expression.getStart()
);
}
private Expression convert(Java17Parser.OrexpressionContext expression) {

View File

@ -332,4 +332,11 @@ public abstract class AbstractASTWalker implements ASTVisitor {
public void visit(GuardedPattern aGuardedPattern) {
}
@Override
public void visit(Ternary ternary) {
ternary.cond.accept(this);
ternary.iftrue.accept(this);
ternary.iffalse.accept(this);
}
}

View File

@ -80,4 +80,6 @@ public interface StatementVisitor {
void visit(Literal literal);
void visit(Throw aThrow);
void visit(Ternary ternary);
}

View File

@ -0,0 +1,24 @@
package de.dhbwstuttgart.syntaxtree.statement;
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import org.antlr.v4.runtime.Token;
public class Ternary extends Expression {
public final Expression cond;
public final Expression iftrue;
public final Expression iffalse;
public Ternary(RefTypeOrTPHOrWildcardOrGeneric type, Expression cond, Expression iftrue, Expression iffalse, Token offset) {
super(type, offset);
this.cond = cond;
this.iftrue = iftrue;
this.iffalse = iffalse;
}
@Override
public void accept(StatementVisitor visitor) {
visitor.visit(this);
}
}

View File

@ -427,6 +427,18 @@ public class OutputGenerator implements ASTVisitor {
// TODO implement
}
@Override
public void visit(Ternary ternary) {
out.append("(");
ternary.cond.accept(this);
out.append(" ? ");
ternary.iftrue.accept(this);
out.append(" : ");
ternary.iffalse.accept(this);
out.append(")::");
ternary.getType().accept(this);
}
@Override
public void visit(Switch switchStmt) {
out.append("switch(");

View File

@ -359,6 +359,11 @@ public class StatementToTargetExpression implements ASTVisitor {
result = new TargetThrow(converter.convert(aThrow.expr));
}
@Override
public void visit(Ternary ternary) {
result = new TargetTernary(converter.convert(ternary.getType()), converter.convert(ternary.cond), converter.convert(ternary.iftrue), converter.convert(ternary.iffalse));
}
@Override
public void visit(Switch switchStmt) {
var cases = switchStmt.getBlocks().stream().filter(s -> !s.isDefault()).map(converter::convert).toList();

View File

@ -203,4 +203,11 @@ public abstract class TracingStatementVisitor implements StatementVisitor {
public void visit(Yield aYield) {
}
@Override
public void visit(Ternary ternary) {
ternary.cond.accept(this);
ternary.iftrue.accept(this);
ternary.iffalse.accept(this);
}
}

View File

@ -2,5 +2,5 @@ package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetTernary(TargetType type, TargetExpression cond, TargetExpression ifTrue, TargetExpression ifFalse) implements TargetExpression {
public record TargetTernary(TargetType type, TargetExpression cond, TargetExpression iftrue, TargetExpression iffalse) implements TargetExpression {
}

View File

@ -488,6 +488,16 @@ public class TYPEStmt implements StatementVisitor {
aThrow.expr.accept(this);
}
@Override
public void visit(Ternary ternary) {
ternary.cond.accept(this);
ternary.iftrue.accept(this);
ternary.iffalse.accept(this);
constraintsSet.addUndConstraint(new Pair(ternary.cond.getType(), bool, PairOperator.EQUALSDOT));
constraintsSet.addUndConstraint(new Pair(ternary.iftrue.getType(), ternary.getType(), PairOperator.SMALLERDOT));
constraintsSet.addUndConstraint(new Pair(ternary.iffalse.getType(), ternary.getType(), PairOperator.SMALLERDOT));
}
@Override
public void visit(Return returnExpr) {
returnExpr.retexpr.accept(this);

View File

@ -916,6 +916,14 @@ public class TestComplete {
var instance = clazz.getDeclaredConstructor().newInstance();
}
@Test
public void testTernary() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Ternary.jav");
var clazz = classFiles.get("Ternary");
var instance = clazz.getDeclaredConstructor().newInstance();
assertEquals(clazz.getDeclaredMethod("main", Integer.class).invoke(instance, 5), "small");
}
@Test
public void testBug122() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug122.jav");