Skip to content

Commit

Permalink
Add support for instanceof pattern matching feature (#9917)
Browse files Browse the repository at this point in the history
Add compiler implementation, tests for Java 16 pattern matching
instanceof.

JEP https://openjdk.org/jeps/394
Fixes #9893
related to #9869
  • Loading branch information
vegegoku authored Jun 4, 2024
1 parent 6cf9146 commit 0074a65
Show file tree
Hide file tree
Showing 4 changed files with 505 additions and 4 deletions.
70 changes: 67 additions & 3 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 <expr> is of type X, then
//
// rewrite (<expr> instanceof Foo foo)
// to
// Foo foo;
// X $instanceof_1;
// (($instanceof_1 = <expr>) instanceof Foo && null != (foo = (Foo) $instanceof_1))
//
// to avoid side effects from evaluating the original expression twice

// 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 $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) $instanceof_1
JVariableRef variableRef = jDeclarationStatement.getVariableRef();
JCastOperation jCastOperation =
new JCastOperation(info, variableRef.getType(), local.createRef(info));

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

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

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

// (($instanceof_1 = o) instanceof Foo && null != (foo = (Foo) $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,8 +3910,9 @@ 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) {
MethodInfo(JMethod method, JMethodBody methodBody, MethodScope methodScope) {
this.method = method;
this.body = methodBody;
this.scope = methodScope;
Expand Down
Loading

0 comments on commit 0074a65

Please sign in to comment.