Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support match all pattern #230

Closed
wants to merge 14 commits into from
Original file line number Diff line number Diff line change
@@ -2896,13 +2896,21 @@ final class Record<T> implements Pattern {
}
}

final class MatchAll implements Pattern {
MatchAll() {
}
}

// @@@ Pattern types

JavaType PATTERN_BINDING_TYPE = JavaType.type(ClassDesc.of(Pattern_CLASS_NAME +
"$" + Type.class.getSimpleName()));
JavaType PATTERN_RECORD_TYPE = JavaType.type(ClassDesc.of(Pattern_CLASS_NAME +
"$" + Pattern.Record.class.getSimpleName()));

JavaType PATTERN_MATCH_ALL_TYPE = JavaType.type(ClassDesc.of(Pattern_CLASS_NAME +
"$" + Pattern.MatchAll.class.getSimpleName()));

static JavaType bindingType(TypeElement t) {
return parameterized(PATTERN_BINDING_TYPE, (JavaType) t);
}
@@ -2911,6 +2919,10 @@ static JavaType recordType(TypeElement t) {
return parameterized(PATTERN_RECORD_TYPE, (JavaType) t);
}

static JavaType MatchAllType() {
return PATTERN_MATCH_ALL_TYPE;
}

static TypeElement targetType(TypeElement t) {
return ((ClassType) t).typeArguments().get(0);
}
@@ -3080,6 +3092,38 @@ public TypeElement resultType() {
}
}

@OpFactory.OpDeclaration(MatchAllPatternOp.NAME)
public static final class MatchAllPatternOp extends PatternOp {

public static final String NAME = "pattern.match.all";

MatchAllPatternOp(ExternalizedOp def) {
super(def);
}

MatchAllPatternOp(MatchAllPatternOp that, CopyContext cc) {
super(that, cc);
}

MatchAllPatternOp() {
super(NAME, List.of());
}

public static MatchAllPatternOp create(ExternalizedOp def) {
return new MatchAllPatternOp(def);
}

@Override
public Op transform(CopyContext cc, OpTransformer ot) {
return new MatchAllPatternOp(this, cc);
}

@Override
public TypeElement resultType() {
return Pattern.MatchAllType();
}
}

/**
* The match operation, that can model Java language pattern matching.
*/
@@ -3209,6 +3253,9 @@ static Block.Builder lowerRecordPattern(Block.Builder endNoMatchBlock, Block.Bui
List<Value> dArgs = rpOp.operands();
for (int i = 0; i < dArgs.size(); i++) {
Op.Result nestedPattern = (Op.Result) dArgs.get(i);
if (nestedPattern.op() instanceof MatchAllPatternOp) {
continue;
}
// @@@ Handle exceptions?
Value nestedTarget = currentBlock.op(CoreOp.invoke(rpOp.recordDescriptor().methodForComponent(i), target));

@@ -3712,4 +3759,8 @@ public static PatternOps.RecordPatternOp recordPattern(RecordTypeRef recordDescr
return new PatternOps.RecordPatternOp(recordDescriptor, nestedPatterns);
}

public static PatternOps.MatchAllPatternOp matchAllPattern() {
return new PatternOps.MatchAllPatternOp();
}

}
Original file line number Diff line number Diff line change
@@ -1244,7 +1244,7 @@ public void visitRecordPattern(JCTree.JCRecordPattern record) {

@Override
public void visitAnyPattern(JCTree.JCAnyPattern anyPattern) {
result = append(ExtendedOp.typePattern(typeToTypeElement(anyPattern.type), null));
result = append(ExtendedOp.matchAllPattern());
}

Value toValue(JCTree tree) {
20 changes: 7 additions & 13 deletions test/jdk/java/lang/reflect/code/TestPatterns.java
Original file line number Diff line number Diff line change
@@ -105,9 +105,11 @@ public void testRecordPatterns() {
}
}

record R(Number n) {}

@CodeReflection
static String recordPatterns2(Object o) {
return o instanceof Rectangle(_, _) ? "match" : "no-match";
static boolean recordPatterns2(Object o) {
return o instanceof R(_);
}

@Test
@@ -119,17 +121,9 @@ void testRecordPattern2() {
CoreOp.FuncOp lf = f.transform(OpTransformer.LOWERING_TRANSFORMER);
lf.writeTo(System.out);

{
Rectangle r = new Rectangle(
new ColoredPoint(new ConcretePoint(1, 2), Color.BLUE),
new ConcretePoint(3, 4)
);
Assert.assertEquals(Interpreter.invoke(MethodHandles.lookup(), lf, r), recordPatterns2(r));
}

{
Number n = 99;
Assert.assertEquals(Interpreter.invoke(MethodHandles.lookup(), lf, n), recordPatterns2(n));
Object[] objects = {new R(1), "str", null};
for (Object o : objects) {
Assert.assertEquals(Interpreter.invoke(MethodHandles.lookup(), lf, o), recordPatterns2(o));
}
}

19 changes: 11 additions & 8 deletions test/langtools/tools/javac/reflect/PatternsTest.java
Original file line number Diff line number Diff line change
@@ -375,21 +375,24 @@ boolean test8(Object o) {
func @"test9" (%0 : PatternsTest, %1 : java.lang.Object)boolean -> {
%2 : Var<java.lang.Object> = var %1 @"o";
%3 : java.lang.Object = var.load %2;
%4 : boolean = pattern.match %3
%4 : PatternsTest$ConcretePoint = constant @null;
%5 : Var<PatternsTest$ConcretePoint> = var %4 @"cp";
%6 : boolean = pattern.match %3
()java.lang.reflect.code.ExtendedOp$Pattern$Record<PatternsTest$Rectangle> -> {
%5 : java.lang.reflect.code.ExtendedOp$Pattern$Type<PatternsTest$Point> = pattern.type;
%6 : java.lang.reflect.code.ExtendedOp$Pattern$Type<PatternsTest$Point> = pattern.type;
%7 : java.lang.reflect.code.ExtendedOp$Pattern$Record<PatternsTest$Rectangle> = pattern.record %5 %6 @"(PatternsTest$Point upperLeft, PatternsTest$Point lowerRight)PatternsTest$Rectangle";
yield %7;
%7 : java.lang.reflect.code.ExtendedOp$Pattern$MatchAll = pattern.match.all;
%8 : java.lang.reflect.code.ExtendedOp$Pattern$Type<PatternsTest$ConcretePoint> = pattern.type @"cp";
%9 : java.lang.reflect.code.ExtendedOp$Pattern$Record<PatternsTest$Rectangle> = pattern.record %7 %8 @"(PatternsTest$Point upperLeft, PatternsTest$Point lowerRight)PatternsTest$Rectangle";
yield %9;
}
()void -> {
(%10 : PatternsTest$ConcretePoint)void -> {
var.store %5 %10;
yield;
};
return %4;
return %6;
};
""")
@CodeReflection
boolean test9(Object o) {
return o instanceof Rectangle(_, _);
return o instanceof Rectangle(_, ConcretePoint cp);
}
}