Skip to content

Commit

Permalink
Add compiler implementation, tests for Java 16 pattern matching insta…
Browse files Browse the repository at this point in the history
  • Loading branch information
vegegoku committed Feb 11, 2024
1 parent 3e84582 commit d2ad877
Show file tree
Hide file tree
Showing 4 changed files with 465 additions and 20 deletions.
68 changes: 66 additions & 2 deletions dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
import com.google.gwt.dev.jjs.ast.JUnaryOperator;
import com.google.gwt.dev.jjs.ast.JUnsafeTypeCoercion;
import com.google.gwt.dev.jjs.ast.JVariable;
import com.google.gwt.dev.jjs.ast.JVariableRef;
import com.google.gwt.dev.jjs.ast.JWhileStatement;
import com.google.gwt.dev.jjs.ast.js.JMultiExpression;
import com.google.gwt.dev.jjs.ast.js.JsniClassLiteral;
Expand Down Expand Up @@ -1095,9 +1096,71 @@ public void endVisit(Initializer x, MethodScope scope) {
public void endVisit(InstanceOfExpression x, BlockScope scope) {
try {
SourceInfo info = makeSourceInfo(x);
JExpression expr = pop(x.expression);
JExpression expr;
JDeclarationStatement jDeclarationStatement = null;
if (x.pattern != null) {
jDeclarationStatement = (JDeclarationStatement) pop();
}
expr = pop(x.expression);
JReferenceType testType = (JReferenceType) typeMap.get(x.type.resolvedType);
push(new JInstanceOf(info, testType, expr));

if (jDeclarationStatement == null) {
push(new JInstanceOf(info, testType, expr));
} else {

// If o is of type X, then
//
// rewrite (o instanceof Foo foo)
// to
// Foo foo;
// X o$instanceof_1;
// ((o$instanceof_1 = o) instanceof Foo && null != (foo = (Foo) o$instanceof_1))
//
// to avoid wrong behavior if o is a method call with side effects

// Foo foo;
String patternDeclarationName = jDeclarationStatement.getVariableRef().getTarget().getName();
if (!curMethod.instanceOfDeclarations.containsKey(patternDeclarationName)) {
curMethod.body.getBlock().addStmt(0, jDeclarationStatement);
curMethod.instanceOfDeclarations.put(patternDeclarationName, jDeclarationStatement);
}

// X o$instanceof_1;
JType expressionType = typeMap.get(x.expression.resolvedType);
JLocal local =
createLocal(info, "$instanceOfExpr", expressionType);
JDeclarationStatement expressionDeclaration =
makeDeclaration(info, local, null);
curMethod.body.getBlock().addStmt(0, expressionDeclaration);
curMethod.instanceOfDeclarations.put(local.getName(), expressionDeclaration);

// (Foo) o$instanceof_1
JVariableRef variableRef = jDeclarationStatement.getVariableRef();
JCastOperation jCastOperation =
new JCastOperation(info, variableRef.getType(), local.createRef(info));

// foo = (Foo) o$instanceof_1
JBinaryOperation assignOperation =
new JBinaryOperation(info, variableRef.getType(), JBinaryOperator.ASG, variableRef,
jCastOperation);

// null != (foo = (Foo) o$instanceof_1
JBinaryOperation nullCheckOperation =
new JBinaryOperation(info, JPrimitiveType.BOOLEAN, JBinaryOperator.NEQ,
JNullLiteral.INSTANCE, assignOperation);

// o$instanceof_1 = o
JBinaryOperation assignLocalOperation =
new JBinaryOperation(info, expressionType, JBinaryOperator.ASG, local.createRef(info),
new CloneExpressionVisitor().cloneExpression(expr));

// ((o$instanceof_1 = o) instanceof Foo && null != (foo = (Foo) o$instanceof_1))
JBinaryOperation rewrittenSwitch =
new JBinaryOperation(info, JPrimitiveType.BOOLEAN, JBinaryOperator.AND,
new JInstanceOf(info, testType, assignLocalOperation), nullCheckOperation);

push(rewrittenSwitch);
}
} catch (Throwable e) {
throw translateException(x, e);
}
Expand Down Expand Up @@ -3847,6 +3910,7 @@ static class MethodInfo {
public final Map<LocalVariableBinding, JVariable> locals = Maps.newIdentityHashMap();
public final JMethod method;
public final MethodScope scope;
public final Map<String, JStatement> instanceOfDeclarations = Maps.newHashMap();

public MethodInfo(JMethod method, JMethodBody methodBody, MethodScope methodScope) {
this.method = method;
Expand Down

0 comments on commit d2ad877

Please sign in to comment.