Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
biboudis committed May 23, 2023
1 parent ca02e6f commit b65664f
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,12 @@ public boolean isMatcher() {
return (flags() & MATCHER) != 0;
}

/** Is this symbol a deconstructor?
*/
public boolean isDeconstructor() {
return isMatcher() && name == owner.name;
}

public boolean isDynamic() {
return false;
}
Expand Down Expand Up @@ -2059,14 +2065,6 @@ protected Name toName() {
}
}

public boolean isMatcher() {
return (flags() & MATCHER) != 0;
}

public boolean isDeconstructor() {
return isMatcher() && name == owner.name;
}

public MethodHandleSymbol asHandle() {
return new MethodHandleSymbol(this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3018,7 +3018,7 @@ public void visitAssert(JCAssert tree) {

public void visitApply(JCMethodInvocation tree) {
Symbol meth = TreeInfo.symbol(tree.meth);
List<Type> argtypes = meth.isMatcher() ? List.of(tree.args.head.type)
List<Type> argtypes = meth.isDeconstructor() ? List.of(tree.args.head.type)
: meth.type.getParameterTypes();
if (meth.name == names.init && meth.owner == syms.enumSym)
argtypes = argtypes.tail.tail;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Attribute.RetentionPolicy;
import com.sun.tools.javac.code.Directive.*;
import com.sun.tools.javac.code.Source.Feature;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.Types.SignatureGenerator.InvalidSignatureException;
Expand All @@ -58,7 +57,6 @@
import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
import static com.sun.tools.javac.code.TypeTag.*;
import static com.sun.tools.javac.main.Option.*;
import java.util.stream.Collectors;

import static javax.tools.StandardLocation.CLASS_OUTPUT;

Expand Down Expand Up @@ -358,25 +356,28 @@ int writeFlagAttrs(long flags) {
/** Write member (field or method) attributes;
* return number of attributes written.
*/
int writeMemberAttrs(Symbol sym, boolean isRecordComponent) {
int writeMemberAttrs(Symbol sym, boolean isRecordComponent, boolean isMatcher) {
int acount = 0;
if (!isRecordComponent) {
acount = writeFlagAttrs(sym.flags());
}
long flags = sym.flags();
if ((flags & (SYNTHETIC | BRIDGE)) != SYNTHETIC &&
if (((flags & (SYNTHETIC | BRIDGE)) != SYNTHETIC &&
(flags & ANONCONSTR) == 0 &&
(!types.isSameType(sym.type, sym.erasure(types)) ||
poolWriter.signatureGen.hasTypeVar(sym.type.getThrownTypes()))) {
poolWriter.signatureGen.hasTypeVar(sym.type.getThrownTypes())) &&
!sym.isDeconstructor()) || isMatcher) {
// note that a local class with captured variables
// will get a signature attribute
int alenIdx = writeAttr(names.Signature);
databuf.appendChar(poolWriter.putSignature(sym));
endAttr(alenIdx);
acount++;
}
acount += writeJavaAnnotations(sym.getRawAttributes());
acount += writeTypeAnnotations(sym.getRawTypeAttributes(), false);
if (!isMatcher) {
acount += writeJavaAnnotations(sym.getRawAttributes());
acount += writeTypeAnnotations(sym.getRawTypeAttributes(), false);
}
return acount;
}

Expand Down Expand Up @@ -857,7 +858,7 @@ int writeRecordAttribute(ClassSymbol csym) {
databuf.appendChar(poolWriter.putDescriptor(v));
int acountIdx = beginAttrs();
int acount = 0;
acount += writeMemberAttrs(v, true);
acount += writeMemberAttrs(v, true, false);
endAttrs(acountIdx, acount);
}
endAttr(alenIdx);
Expand All @@ -877,10 +878,11 @@ int writeMatcherAttribute(MethodSymbol m) {
int acountIdx = beginAttrs();
int acount = 0;

if (target.hasMethodParameters() && (options.isSet(PARAMETERS))) {
if (m.isMatcher() && target.hasMethodParameters() && (options.isSet(PARAMETERS))) {
acount += writeMethodParametersAttr(m);
}
// acount += writeMemberAttrs(m, false); // TODO: which do we need?

acount += writeMemberAttrs(m, false, true);
acount += writeParameterAttrs(m.params);

endAttrs(acountIdx, acount);
Expand Down Expand Up @@ -992,7 +994,7 @@ void writeField(VarSymbol v) {
endAttr(alenIdx);
acount++;
}
acount += writeMemberAttrs(v, false);
acount += writeMemberAttrs(v, false, false);
acount += writeExtraAttributes(v);
endAttrs(acountIdx, acount);
}
Expand Down Expand Up @@ -1034,11 +1036,11 @@ void writeMethod(MethodSymbol m) {
endAttr(alenIdx);
acount++;
}
if (target.hasMethodParameters() && (options.isSet(PARAMETERS) || m.isConstructor() && (m.flags_field & RECORD) != 0)) {
if (!m.isDeconstructor() && target.hasMethodParameters() && (options.isSet(PARAMETERS) || m.isConstructor() && (m.flags_field & RECORD) != 0)) {
if (!m.isLambdaMethod()) // Per JDK-8138729, do not emit parameters table for lambda bodies.
acount += writeMethodParametersAttr(m);
}
acount += writeMemberAttrs(m, false);
acount += writeMemberAttrs(m, false, false);
if (!m.isLambdaMethod())
acount += writeParameterAttrs(m.params);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,13 +380,11 @@ public Void visitMatcher(Matcher_attribute attr, Void unused) {
if (options.showDescriptors) {
println("pattern_descriptor: " + getValue(attr.pattern_descriptor));
}
if (options.showAllAttrs) {
if (options.showAllAttrs && attr.attributes.size() > 0) {
for (Attribute matcherAttribute: attr.attributes)
write(attr, matcherAttribute, constant_pool);
println();
}
indent(-1);

indent(-1);
return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
/**
* @test
* @enablePreview
* @compile Matcher.java
* @run main Matcher
* @compile Point.java
* @run main Point
*/
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.template.Carriers;
import java.util.Objects;

public record Matcher(String s, int i) {
public record Point(Integer x, Integer y) {
/*
TODO
ask about exceptions on matchers
Expand All @@ -31,33 +30,32 @@ test switch with the record Matcher
*/

public static void main(String... args) {
assertEquals("a", test(new Matcher("a", 0)));
assertEquals(2, test2(new Matcher("a", 42)));
assertEquals(1, test(new Point(1, 2)));
assertEquals(2, test2(new Point(42, 4)));
}

public static String test(Object o) {
if (o instanceof Matcher(String os, int oi)) {
return os;
public static Integer test(Object o) {
if (o instanceof Point(Integer x, Integer y)) {
return x;
}
return "error";
return -1;
}

public static int test2(Matcher o) {
public static int test2(Point o) {
return switch (o) {
case Matcher(String s, int i) when s.isEmpty() -> 1;
case Matcher(String s, int i) when i == 42 -> 2;
case Matcher mm -> 3;
case Point(Integer x, Integer y) when x == 42 -> 2;
case Point mm -> 3;
};
}

//original code:
@MyCustomAnnotation(annotField = 42)
public __matcher Matcher(String s, int i) throws Throwable { //XXX: exceptions?
MethodType returnType = MethodType.methodType(Object.class, String.class, int.class); //TODO: return type of the Carrier constructor?
return Carriers.factory(returnType).invoke(this.s, this.i);

public __matcher Point(Integer x, Integer y) throws Throwable { //XXX: exceptions?
// s = this.s;
// i = this.i;

MethodType returnType = MethodType.methodType(Object.class, Integer.class, Integer.class); //TODO: return type of the Carrier constructor?
return Carriers.factory(returnType).invoke(this.x, this.y);
}

@Target(ElementType.METHOD) // TODO: element type must target matchers
Expand Down
45 changes: 45 additions & 0 deletions test/langtools/tools/javac/patterns/Points.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* @test
* @enablePreview
* @compile -parameters Points.java
* @run main Points
*/
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.invoke.MethodType;
import java.lang.template.Carriers;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

public record Points(Collection<Integer> is) {
public static void main(String... args) {
assertEquals(List.of(1), test(new Points(List.of(1))));
}

public static List<Integer> test(Object o) {
if (o instanceof Points(List<Integer> ss)) {
return ss;
}
return List.of(-1);
}

public __matcher Points(@Foo Collection<Integer> is) throws Throwable {
// is = this.is;

MethodType returnType = MethodType.methodType(Object.class, Collection.class);
return Carriers.factory(returnType).invoke(this.is);
}

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Foo { }

private static <T> void assertEquals(T expected, T actual) {
if (!Objects.equals(expected, actual)) {
throw new AssertionError("Expected: " + expected + ", but got: " + actual);
}
}
}

0 comments on commit b65664f

Please sign in to comment.