Compare commits

...

8 Commits

5 changed files with 274 additions and 160 deletions
.gitea/workflows
pom.xml
src
main
java
de
dhbwstuttgart
bytecode
target
test

@ -15,7 +15,7 @@ jobs:
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '22'
java-version: '23'
cache: 'maven'
- name: Compile project
run: |

@ -54,8 +54,8 @@ http://maven.apache.org/maven-v4_0_0.xsd">
<version>3.11.0</version>
<configuration>
<compilerArgs>--enable-preview</compilerArgs>
<source>22</source>
<target>22</target>
<source>23</source>
<target>23</target>
</configuration>
</plugin>
<plugin>

@ -1306,16 +1306,17 @@ public class Codegen {
var mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, Object[].class);
var bootstrap = new Handle(H_INVOKESTATIC, "java/lang/runtime/SwitchBootstraps", "typeSwitch", mt.toMethodDescriptorString(), false);
var types = new ArrayList<Object>(aSwitch.cases().size());
var types = new ArrayList<>(aSwitch.cases().size());
for (var cse : aSwitch.cases()) for (var label : cse.labels()) {
if (label instanceof TargetTypePattern || label instanceof TargetComplexPattern)
types.add(Type.getObjectType(label.type().getInternalName()));
else if (label instanceof TargetLiteral lit)
if (label instanceof TargetTypePattern || label instanceof TargetComplexPattern) {
if (label.type() instanceof TargetGenericType) types.add(Type.getType(Object.class));
else types.add(Type.getObjectType(label.type().getInternalName()));
} else if (label instanceof TargetLiteral lit) {
types.add(lit.value());
else if (label instanceof TargetGuard guard)
} else if (label instanceof TargetGuard guard) {
types.add(Type.getObjectType(guard.inner().type().getInternalName()));
// TODO Same here we need to evaluate constant;
else {
// TODO Same here we need to evaluate constant;
} else {
System.out.println(label);
throw new NotImplementedException();
}

@ -17,7 +17,6 @@ import de.dhbwstuttgart.target.tree.expression.*;
import de.dhbwstuttgart.target.tree.type.*;
import de.dhbwstuttgart.typeinference.result.*;
import java.lang.annotation.Target;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -145,49 +144,25 @@ public class ASTToTargetAST {
return ret;
}
// This is used to serve as a custom equality to signature that performs a weak check without going into record patterns.
// The two signatures are considered equal if all the argument types match.
// This also turns equal if both types implement a sealed super interface
class PatternSignature {
final TargetMethod.Signature signature;
final String name;
PatternSignature(String name, TargetMethod.Signature signature) {
this.signature = signature;
this.name = name;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof PatternSignature other)) return false;
if (!this.name.equals(other.name)) return false;
if (other.signature.parameters().size() != signature.parameters().size()) return false;
for (var i = 0; i < signature.parameters().size(); i++) {
var p1 = signature.parameters().get(i).pattern().type();
var p2 = other.signature.parameters().get(i).pattern().type();
if (p1 instanceof TargetGenericType && p2 instanceof TargetGenericType) continue;
if (!p1.equals(p2) && commonSuperInterfaceTypes(p1, p2).isEmpty()) return false;
}
return true;
}
@Override
public int hashCode() {
return signature.parameters().size();
}
}
// This finds a common sealed interface type to group together methods that use different records
private List<ClassOrInterface> commonSuperInterfaceTypes(TargetType a, TargetType b) {
if (a instanceof TargetGenericType && b instanceof TargetGenericType) return List.of(ASTFactory.createClass(Object.class));
if (a instanceof TargetGenericType && b instanceof TargetGenericType) return List.of(ASTFactory.createObjectClass());
if (a instanceof TargetRefType ta && b instanceof TargetGenericType)
return List.of(compiler.getClass(new JavaClassName(ta.name())));
if (b instanceof TargetRefType tb && a instanceof TargetGenericType)
return List.of(compiler.getClass(new JavaClassName(tb.name())));
if (a instanceof TargetRefType ta && b instanceof TargetRefType tb) {
var res = new HashSet<ClassOrInterface>();
var cla = compiler.getClass(new JavaClassName(ta.name()));
var clb = compiler.getClass(new JavaClassName(tb.name()));
while (!cla.equals(ASTFactory.createClass(Object.class))) {
if (cla.equals(clb)) return List.of(cla);
while (!cla.equals(ASTFactory.createObjectClass())) {
var clb2 = clb;
while (!clb2.equals(ASTFactory.createClass(Object.class))) {
while (!clb2.equals(ASTFactory.createObjectClass())) {
for (var intfa : cla.getSuperInterfaces()) {
for (var intfb : clb.getSuperInterfaces()) {
if (intfa.equals(intfb)) {
@ -207,48 +182,167 @@ public class ASTToTargetAST {
return List.of();
}
// TODO This is ugly and probably doesn't work right
private boolean patternStrictlyEquals(TargetComplexPattern a, TargetComplexPattern b) {
if (!a.name().equals(b.name())) return false;
if (a.subPatterns().size() != b.subPatterns().size()) return false;
for (var i = 0; i < a.subPatterns().size(); i++) {
var p1 = a.subPatterns().get(i);
var p2 = b.subPatterns().get(i);
if (p1 instanceof TargetComplexPattern pc1 && p2 instanceof TargetComplexPattern pc2 &&
patternStrictlyEquals(pc1, pc2)) return false;
if (p1 instanceof TargetTypePattern pt1 && p2 instanceof TargetTypePattern pt2) {
if (pt1.type() instanceof TargetGenericType && pt2.type() instanceof TargetGenericType) continue;
}
if (!p1.type().equals(p2.type()) && commonSuperInterfaceTypes(p1.type(), p2.type()).isEmpty()) return false;
}
return true;
}
private boolean canCombine(TargetMethod m1, TargetMethod m2) {
if (!m1.name().equals(m2.name())) return false;
var s1 = m1.signature();
var s2 = m2.signature();
if (s1.parameters().size() != s2.parameters().size()) return false;
if (s1.parameters().isEmpty()) return false;
for (var i = 0; i < s1.parameters().size(); i++) {
var p1 = s1.parameters().get(i).pattern();
var p2 = s2.parameters().get(i).pattern();
if (p1.type() instanceof TargetGenericType || p2.type() instanceof TargetGenericType) continue;
if (p1 instanceof TargetComplexPattern pc1 && p2 instanceof TargetComplexPattern pc2 &&
patternStrictlyEquals(pc1, pc2)) return false;
if (!p1.equals(p2) && commonSuperInterfaceTypes(p1.type(), p2.type()).isEmpty()) return false;
}
return true;
}
private record Combination(TargetMethod a, TargetMethod b) {
@Override
public boolean equals(Object o) {
if (!(o instanceof Combination(TargetMethod a1, TargetMethod b1))) return false;
return this.a.equals(a1) && this.b.equals(b1) ||
this.a.equals(b1) && this.b.equals(a1);
}
@Override
public int hashCode() {
return Objects.hashCode(a) + Objects.hashCode(b);
}
}
public List<List<TargetMethod>> groupOverloads(ClassOrInterface input, List<Method> methods) {
var mapOfSignatures = new HashMap<PatternSignature, List<TargetMethod>>();
for (var method : methods) {
var mapOfTargetMethods = new HashMap<Generics, TargetMethod[]>();
for (var generics : all) {
mapOfTargetMethods.put(generics, new TargetMethod[methods.size()]);
}
for (var i = 0; i < methods.size(); i++) {
var method = methods.get(i);
// Convert all methods
var methodsWithTphs = convert(input, method);
// Then check for methods with the same signature
var resMethods = new HashSet<MethodWithTphs>();
for (var m1 : methodsWithTphs) {
System.out.println(m1.method.name() + " -> " + m1.method.signature().parameters().stream().map(m -> m.pattern().type()).toList());
for (var m : methodsWithTphs) {
var resultMethods = mapOfTargetMethods.get(m.generics);
resultMethods[i] = m.method;
}
}
/*System.out.println("============== INPUT ==============");
for (var m : mapOfTargetMethods.values()) {
for (var v : m) System.out.println(v.name() + " " + v.getSignature());
System.out.println();
}*/
outer:
for (var m1 : methodsWithTphs) {
for (var m2 : methodsWithTphs) {
for (var i = 0; i < m1.args.size(); i++) {
var arg1 = m1.args.get(i);
var arg2 = m2.args.get(i);
if (arg1.parameter.equals(arg2.parameter)) {
if (isSupertype(arg1.signature, arg2.signature) &&
!arg1.signature.equals(arg2.signature)) continue outer;
var allCombinations = new HashSet<Set<Combination>>();
// Combine methods based on their signature and position in the result set
for (var g1 : all) {
var resMeth1 = mapOfTargetMethods.get(g1);
for (var i = 0; i < methods.size(); i++) {
var m1 = resMeth1[i];
if (m1 == null) continue;
for (var g2 : all) {
if (g1 == g2) continue; // No need to combine the same method
var resMeth2 = mapOfTargetMethods.get(g2);
var m2 = resMeth2[i];
if (m2 == null) continue;
var combinations = new HashSet<Combination>();
if (canCombine(m1, m2)) {
//System.out.println(" Combining " + m1.getSignature() + " and " + m2.getSignature());
combinations.add(new Combination(m1, m2));
for (var j = 0; j < methods.size(); j++) {
if (j == i) continue;
var m3 = resMeth2[j];
if (m3 == null) continue;
var m4 = resMeth1[j];
if (m4 == null) continue;
combinations.add(new Combination(m4, m3));
//System.out.println("Also Combining " + m4.getSignature() + " and " + m3.getSignature());
}
} else {
//System.out.println(" Not Combining " + m1.getSignature() + " and " + m2.getSignature());
}
if (!combinations.isEmpty()) allCombinations.add(combinations);
}
resMethods.add(m1);
}
for (var m : resMethods) {
var signature = new PatternSignature(m.method.name(), m.method.signature());
var methodsWithSameSignature = mapOfSignatures.getOrDefault(signature, new ArrayList<>());
methodsWithSameSignature.add(m.method);
mapOfSignatures.put(signature, methodsWithSameSignature);
}
}
mapOfSignatures.values().forEach(e -> {
e.forEach(e2 -> {
System.out.println(e2.name() + " -> " + e2.signature().parameters().stream().map(m -> m.pattern().type()).toList());
});
if (allCombinations.isEmpty()) allCombinations.add(new HashSet<>());
// Combine back into output format
var r0 = new HashSet<Set<TargetMethod>>();
for (var combinations : allCombinations) {
var r1 = new HashSet<Set<TargetMethod>>();
// This is used to weed out duplicates
var uniqued = new HashSet<TargetMethod>();
// We go over all methods in the result
for (var g : all) for (var i = 0; i < methods.size(); i++) {
var r2 = new HashSet<TargetMethod>();
var m = mapOfTargetMethods.get(g)[i];
if (m == null) continue;
if (!uniqued.contains(m)) {
// Add the method to r2
r2.add(m);
uniqued.add(m);
} else continue;
// Find all combinations that contain the method and add them to the result
// if not filtered out by uniqued
for (var c : combinations) {
if (c.a.equals(m) || c.b.equals(m)) {
if (!uniqued.contains(c.a)) {
r2.add(c.a);
uniqued.add(c.a);
}
if (!uniqued.contains(c.b)) {
r2.add(c.b);
uniqued.add(c.b);
}
}
}
r1.add(r2);
}
outer: for (var s1 : r1) {
for (var s2 : new HashSet<>(r0)) {
if (s2.containsAll(s1)) {
continue outer;
} else if (s1.containsAll(s2)) {
r0.remove(s2);
r0.add(s1);
continue outer;
}
}
r0.add(s1);
}
}
var result = r0.stream().map(l -> l.stream().toList()).toList();
System.out.println("============== OUTPUT ==============");
for (var l : result) {
for (var m : l) System.out.println(m.name() + " " + m.getSignature());
System.out.println();
});
return mapOfSignatures.values().stream().toList();
}
return result;
}
public TargetStructure convert(ClassOrInterface input) {
@ -281,7 +375,8 @@ public class ASTToTargetAST {
var superInterfaces = input.getSuperInterfaces().stream().map(clazz -> convert(clazz, generics.javaGenerics)).toList();
var constructors = input.getConstructors().stream().map(constructor -> this.convert(input, constructor, finalFieldInitializer)).flatMap(List::stream).toList();
var fields = input.getFieldDecl().stream().map(this::convert).toList();
var methods = groupOverloads(input, input.getMethods()).stream().map(m -> generatePatternOverloads(input, m)).flatMap(List::stream).toList();
var methods = groupOverloads(input, input.getMethods()).stream().map(m -> generatePatternOverloads(input, m)).flatMap(List::stream)
.collect(Collectors.toSet()).stream().toList(); // Unique generated methods
TargetMethod staticConstructor = null;
if (input.getStaticInitializer().isPresent())
@ -403,7 +498,7 @@ public class ASTToTargetAST {
}
var cases = new ArrayList<TargetSwitch.Case>();
var usedPatterns = new HashSet<TargetType>();
var usedPatterns = new HashSet<TargetPattern>();
for (var method : methods) {
var patternsRec = new ArrayList<>(patterns);
@ -423,9 +518,8 @@ public class ASTToTargetAST {
}
var lastPattern = patternsRec.getLast();
var type = unwrap(lastPattern.type());
if (usedPatterns.contains(type)) continue;
usedPatterns.add(type);
if (usedPatterns.contains(lastPattern)) continue;
usedPatterns.add(lastPattern);
var candidates = methods.stream().filter(m -> {
var j = 0;
@ -471,9 +565,12 @@ public class ASTToTargetAST {
var t3 = m.signature().parameters().get(i).pattern().type();
commonSubTypes.retainAll(commonSuperInterfaceTypes(t1, t3));
}
if (commonSubTypes.size() != 1) throw new DebugException("Invalid overload");
if (commonSubTypes.size() > 1) throw new DebugException("Invalid overload");
// TODO accept multiple types
var superType = commonSubTypes.iterator().next();
var superType = ASTFactory.createObjectClass();
if (!commonSubTypes.isEmpty())
superType = commonSubTypes.iterator().next();
String name;
if (p1 instanceof TargetComplexPattern) name = "__var" + i;
else name = p1.name();
@ -543,7 +640,19 @@ public class ASTToTargetAST {
}).findFirst();
}
record MethodWithTphs(TargetMethod method, List<SignaturePairTarget> args) {}
record MethodWithTphs(TargetMethod method, Generics generics, List<SignaturePairTarget> args) {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MethodWithTphs that)) return false;
return Objects.equals(method, that.method) && Objects.equals(args, that.args);
}
@Override
public int hashCode() {
return Objects.hash(method, args);
}
}
record Signature(TargetMethod.Signature java, TargetMethod.Signature tx, Generics generics) {}
@ -592,7 +701,7 @@ public class ASTToTargetAST {
var newMethod = new TargetMethod(method.modifier, method.name, convert(method.block), signature.java, signature.tx);
var concreteParams = tphsInMethods.getOrDefault(method, new HashSet<>()).stream().map(sig -> new SignaturePairTarget(convert(sig.signature), convert(sig.parameter))).toList();
result.add(new MethodWithTphs(newMethod, concreteParams));
result.add(new MethodWithTphs(newMethod, generics, concreteParams));
}
return result;

@ -303,7 +303,7 @@ public class TestComplete {
var result = mul.invoke(instanceOfClass_s1, instanceOfClass_s2);
System.out.println(instanceOfClass_s1.toString() + " * " + instanceOfClass_s2.toString() + " = " + result.toString());
assertEquals(result, 8);
assertEquals(8, result);
}
@Test
@ -444,8 +444,8 @@ public class TestComplete {
var O = Arrays.stream(typeParaTypes).filter(t -> t.equals(paraTypes[0])).findFirst().get();
var N2 = Arrays.stream(typeParaTypes).filter(t -> t.equals(paraTypes[1])).findFirst().get();
assertEquals(N, N2);
assertEquals(N.getBounds()[0], Object.class);
assertEquals(O.getBounds()[0], Object.class);
assertEquals(Object.class, N.getBounds()[0]);
assertEquals(Object.class, O.getBounds()[0]);
var m2 = tph4.getDeclaredMethod("m2", Object.class);
@ -500,8 +500,8 @@ public class TestComplete {
var P = Arrays.stream(typeParaTypes).filter(t -> t.equals(paraTypes[0])).findFirst().get();
var O = Arrays.stream(typeParaTypes).filter(t -> t.equals(paraTypes[1])).findFirst().get();
assertEquals(P.getBounds()[0], Object.class);
assertEquals(O.getBounds()[0], Object.class);
assertEquals(Object.class, P.getBounds()[0]);
assertEquals(Object.class, O.getBounds()[0]);
var m2 = tph5.getDeclaredMethod("m2", Object.class);
@ -605,7 +605,7 @@ public class TestComplete {
var fac1 = classFiles.get("Fac1");
var instance = fac1.getDeclaredConstructor().newInstance();
var fac = fac1.getDeclaredMethod("fac", Integer.class);
assertEquals(fac.invoke(instance, 10), 3628800);
assertEquals(3628800, fac.invoke(instance, 10));
}
@Test
@ -676,16 +676,16 @@ public class TestComplete {
var r2 = ctor.newInstance(10, 20f);
var r3 = ctor.newInstance(10, r1);
assertEquals(swtch.invoke(instance, r1), 30);
assertEquals(swtch.invoke(instance, r2), 20);
assertEquals(swtch.invoke(instance, r3), 40);
assertEquals(swtch.invoke(instance, 50), 50);
assertEquals(30, swtch.invoke(instance, r1));
assertEquals(20, swtch.invoke(instance, r2));
assertEquals(40, swtch.invoke(instance, r3));
assertEquals(50, swtch.invoke(instance, 50));
try {
assertEquals(swtch.invoke(instance, "Some string"), 0);
assertEquals(0, swtch.invoke(instance, "Some string"));
fail("No assertion thrown!");
} catch (InvocationTargetException exception) {
assertTrue(exception.getCause() instanceof IllegalArgumentException);
assertEquals(exception.getCause().getMessage(), "Unhandled case value");
assertEquals("Unhandled case value", exception.getCause().getMessage());
}
}
@ -702,7 +702,7 @@ public class TestComplete {
var r1 = ctor.newInstance("asd", "asb");
assertEquals(swtch.invoke(instance, r1), "asd");
assertEquals("asd", swtch.invoke(instance, r1));
}
@Test
@ -753,8 +753,8 @@ public class TestComplete {
var r2 = ctor.newInstance(1, clazzNumber.getConstructor().newInstance());
assertEquals(swtch.invoke(instance, r1), "Second Element is a Text");
assertEquals(swtch.invoke(instance, r2), "Second Element is a Number");
assertEquals("Second Element is a Text", swtch.invoke(instance, r1));
assertEquals("Second Element is a Number", swtch.invoke(instance, r2));
}
@Test
public void testSwitchListRecord() throws Exception {
@ -776,10 +776,10 @@ public class TestComplete {
var listWithMoreThanOneElement = constructorLinkedElem.newInstance(5, constructorLinkedElem.newInstance(1, constructorElem.newInstance(5)));
assertEquals(swtch.invoke(instance, listWithMoreThanOneElement), 11);
assertEquals(11, swtch.invoke(instance, listWithMoreThanOneElement));
var listWithOneElement = constructorLinkedElem.newInstance(5, constructorElem.newInstance(5));
assertEquals(swtch.invoke(instance, listWithOneElement), 10);
assertEquals(10, swtch.invoke(instance, listWithOneElement));
}
@Test
@ -795,9 +795,9 @@ public class TestComplete {
var r2 = ctor.newInstance(20);
var r3 = ctor.newInstance(30);
assertEquals(m.invoke(instance, r1), 1);
assertEquals(m.invoke(instance, r2), 2);
assertEquals(m.invoke(instance, r3), 3);
assertEquals(1, m.invoke(instance, r1));
assertEquals(2, m.invoke(instance, r2));
assertEquals(3, m.invoke(instance, r3));
}
@Test
@ -820,10 +820,10 @@ public class TestComplete {
var listWithMoreThanOneElement = constructorLinkedElem.newInstance(5, constructorLinkedElem.newInstance(1, constructorElem.newInstance(5)));
assertEquals(swtch.invoke(instance, listWithMoreThanOneElement), 5);
assertEquals(5, swtch.invoke(instance, listWithMoreThanOneElement));
var listWithOneElement = constructorLinkedElem.newInstance(5, constructorElem.newInstance(5));
assertEquals(swtch.invoke(instance, listWithOneElement), 5);
assertEquals(5, swtch.invoke(instance, listWithOneElement));
}
@ -835,6 +835,7 @@ public class TestComplete {
var instance = clazz.getDeclaredConstructor().newInstance();
}
@Ignore("Not implemented")
@Test
public void testStringSwitch() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "SwitchString.jav");
@ -842,11 +843,11 @@ public class TestComplete {
var instance = clazz.getDeclaredConstructor().newInstance();
var main = clazz.getDeclaredMethod("main", String.class);
assertEquals(main.invoke(instance, "AaAaAa"), 1);
assertEquals(main.invoke(instance, "AaAaBB"), 2);
assertEquals(main.invoke(instance, "test"), 3);
assertEquals(main.invoke(instance, "TEST"), 3);
assertEquals(main.invoke(instance, "awawa"), 4);
assertEquals(1, main.invoke(instance, "AaAaAa"));
assertEquals(2, main.invoke(instance, "AaAaBB"));
assertEquals(3, main.invoke(instance, "test"));
assertEquals(3, main.invoke(instance, "TEST"));
assertEquals(4, main.invoke(instance, "awawa"));
}
@Test
@ -856,6 +857,7 @@ public class TestComplete {
var instance = clazz.getDeclaredConstructor().newInstance();
}
@Ignore("Not implemented")
@Test
public void testOverloadPattern() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "OverloadPattern.jav");
@ -870,17 +872,18 @@ public class TestComplete {
var ptInt = rec.getDeclaredConstructor(Number.class, Number.class).newInstance(1, 2);
var ptFlt = rec.getDeclaredConstructor(Number.class, Number.class).newInstance(1f, 2f);
assertEquals(m1.invoke(instance, ptInt, ptFlt), 1);
assertEquals(m1.invoke(instance, ptInt, ptInt), 2);
assertEquals(m1.invoke(instance, ptFlt, ptInt), 3);
assertEquals(m1.invoke(instance, ptFlt, ptFlt), 4);
assertEquals(1, m1.invoke(instance, ptInt, ptFlt));
assertEquals(2, m1.invoke(instance, ptInt, ptInt));
assertEquals(3, m1.invoke(instance, ptFlt, ptInt));
assertEquals(4, m1.invoke(instance, ptFlt, ptFlt));
assertEquals(m2.invoke(instance, ptInt), 5);
assertEquals(m2.invoke(instance, ptFlt), 6);
assertEquals(5, m2.invoke(instance, ptInt));
assertEquals(6, m2.invoke(instance, ptFlt));
assertEquals(m3.invoke(instance, 10), 10);
assertEquals(10, m3.invoke(instance, 10));
}
@Ignore("Not implemented")
@Test
public void testOverloadNestedPattern() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "OverloadNestedPattern.jav");
@ -893,16 +896,16 @@ public class TestComplete {
var r2 = ctor.newInstance(r1);
var m = clazz.getDeclaredMethod("m", rec, rec);
assertEquals(m.invoke(instance, r2, r1), 1);
assertEquals(1, m.invoke(instance, r2, r1));
var r3 = ctor.newInstance(2f);
var r4 = ctor.newInstance(r3);
assertEquals(m.invoke(instance, r4, r3), 2);
assertEquals(2, m.invoke(instance, r4, r3));
assertEquals(m.invoke(instance, r1, r1), 3);
assertEquals(3, m.invoke(instance, r1, r1));
}
//@Ignore("Not implemented")
@Ignore("Not implemented")
@Test
public void testPatternMatchingHaskellStyle() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "PatternMatchingHaskellStyle.jav");
@ -920,11 +923,12 @@ public class TestComplete {
var x = rctor.newInstance(rctor.newInstance(0, rctor.newInstance(0, r2ctor.newInstance(0))), r2ctor.newInstance(0));
var y = rctor.newInstance(r2ctor.newInstance(0), r2ctor.newInstance(0));
assertEquals(m.invoke(instance, x, y), null);
assertEquals(m.invoke(instance, y, y), null);
assertNull(m.invoke(instance, x, y));
assertNull(m.invoke(instance, y, y));
}
@Ignore("Not implemented")
@Test
public void testPatternMatchingListAppend() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "PatternMatchingListAppend.jav");
@ -941,7 +945,7 @@ public class TestComplete {
var list1 = ConsCtor.newInstance(1, ConsCtor.newInstance(2, ConsCtor.newInstance(3, EmptyCtor.newInstance())));
var list2 = ConsCtor.newInstance(4, ConsCtor.newInstance(5, ConsCtor.newInstance(6, EmptyCtor.newInstance())));
var append = clazz.getDeclaredMethod("append", List, List);
var append = clazz.getDeclaredMethod("append", Cons, Cons);
System.out.println(append.invoke(instance, list1, list2));
}
@ -959,8 +963,8 @@ public class TestComplete {
var x = rctor.newInstance(10);
var d = rctor.newInstance(20.0);
assertEquals(m.invoke(instance, x, 0), 50);
assertEquals(m.invoke(instance, d, 0), 40.0);
assertEquals(50, m.invoke(instance, x, 0));
assertEquals(40.0, m.invoke(instance, d, 0));
}
@Test
@ -975,7 +979,7 @@ public class TestComplete {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Static.jav");
var clazz = classFiles.get("Static");
var m = clazz.getDeclaredMethod("m");
assertEquals(m.invoke(null), 50);
assertEquals(50, m.invoke(null));
}
@Test
@ -984,7 +988,7 @@ public class TestComplete {
var clazz = classFiles.get("For");
var instance = clazz.getDeclaredConstructor().newInstance();
var m = clazz.getDeclaredMethod("m", Integer.class);
assertEquals(m.invoke(instance, 10), 60);
assertEquals(60, m.invoke(instance, 10));
}
@Test
@ -993,7 +997,7 @@ public class TestComplete {
var clazz = classFiles.get("ForEach");
var instance = clazz.getDeclaredConstructor().newInstance();
var m = clazz.getDeclaredMethod("m");
assertEquals(m.invoke(instance), 6);
assertEquals(6, m.invoke(instance));
}
@Test
@ -1011,7 +1015,7 @@ public class TestComplete {
var clazz = classFiles.get("FunctionalInterface");
var instance = clazz.getDeclaredConstructor().newInstance();
var m = clazz.getDeclaredMethod("m");
assertEquals(m.invoke(instance), 200);
assertEquals(200, m.invoke(instance));
}
@Test
@ -1020,7 +1024,7 @@ public class TestComplete {
var clazz = classFiles.get("Chain");
var instance = clazz.getDeclaredConstructor().newInstance();
var m = clazz.getDeclaredMethod("m");
assertEquals(m.invoke(instance), 5);
assertEquals(5, m.invoke(instance));
}
@Test
@ -1073,9 +1077,9 @@ public class TestComplete {
var instance = clazz.getDeclaredConstructor().newInstance();
assertNull(clazz.getDeclaredMethod("m").invoke(instance));
assertEquals(clazz.getDeclaredMethod("m2").invoke(instance), 'C');
assertEquals(clazz.getDeclaredMethod("m3").invoke(instance), 10L);
assertEquals(clazz.getDeclaredMethod("m4").invoke(instance), 10.5F);
assertEquals('C', clazz.getDeclaredMethod("m2").invoke(instance));
assertEquals(10L, clazz.getDeclaredMethod("m3").invoke(instance));
assertEquals(10.5F, clazz.getDeclaredMethod("m4").invoke(instance));
}
@Test
@ -1083,7 +1087,7 @@ public class TestComplete {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "OLConstructor.jav");
var clazz = classFiles.get("Child");
var instance = clazz.getDeclaredConstructor().newInstance();
assertEquals(clazz.getSuperclass().getDeclaredField("x").get(instance), 3);
assertEquals(3, clazz.getSuperclass().getDeclaredField("x").get(instance));
}
@Test
@ -1091,11 +1095,11 @@ public class TestComplete {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Op1.jav");
var clazz = classFiles.get("Op1");
var instance = clazz.getDeclaredConstructor().newInstance();
assertEquals(clazz.getDeclaredMethod("not").invoke(instance), true);
assertEquals(clazz.getDeclaredMethod("or").invoke(instance), 10 | 20);
assertEquals(clazz.getDeclaredMethod("and").invoke(instance), 10 & 20);
assertEquals(clazz.getDeclaredMethod("xor").invoke(instance), 10 ^ 20);
assertEquals(clazz.getDeclaredMethod("mod").invoke(instance), 10 % 2);
assertEquals(true, clazz.getDeclaredMethod("not").invoke(instance));
assertEquals(10 | 20, clazz.getDeclaredMethod("or").invoke(instance));
assertEquals(10 & 20, clazz.getDeclaredMethod("and").invoke(instance));
assertEquals(10 ^ 20, clazz.getDeclaredMethod("xor").invoke(instance));
assertEquals(10 % 2, clazz.getDeclaredMethod("mod").invoke(instance));
}
@Ignore("Not implemented")
@ -1112,18 +1116,18 @@ public class TestComplete {
var clazzPublic = classFiles.get("Access");
var clazzDefault = classFiles.get("AccessDefault");
assertEquals(clazzPublic.getModifiers(), Modifier.PUBLIC);
assertEquals(clazzDefault.getModifiers(), 0);
assertEquals(Modifier.PUBLIC, clazzPublic.getModifiers());
assertEquals(0, clazzDefault.getModifiers());
assertEquals(clazzPublic.getDeclaredMethod("mPublic").getModifiers(), Modifier.PUBLIC);
assertEquals(clazzPublic.getDeclaredMethod("mProtected").getModifiers(), Modifier.PROTECTED);
assertEquals(clazzPublic.getDeclaredMethod("mDefault").getModifiers(), 0);
assertEquals(clazzPublic.getDeclaredMethod("mPrivate").getModifiers(), Modifier.PRIVATE);
assertEquals(Modifier.PUBLIC, clazzPublic.getDeclaredMethod("mPublic").getModifiers());
assertEquals(Modifier.PROTECTED, clazzPublic.getDeclaredMethod("mProtected").getModifiers());
assertEquals(0, clazzPublic.getDeclaredMethod("mDefault").getModifiers());
assertEquals(Modifier.PRIVATE, clazzPublic.getDeclaredMethod("mPrivate").getModifiers());
assertEquals(clazzPublic.getDeclaredField("fPublic").getModifiers(), Modifier.PUBLIC);
assertEquals(clazzPublic.getDeclaredField("fProtected").getModifiers(), Modifier.PROTECTED);
assertEquals(clazzPublic.getDeclaredField("fDefault").getModifiers(), 0);
assertEquals(clazzPublic.getDeclaredField("fPrivate").getModifiers(), Modifier.PRIVATE);
assertEquals(Modifier.PUBLIC, clazzPublic.getDeclaredField("fPublic").getModifiers());
assertEquals(Modifier.PROTECTED, clazzPublic.getDeclaredField("fProtected").getModifiers());
assertEquals(0, clazzPublic.getDeclaredField("fDefault").getModifiers());
assertEquals(Modifier.PRIVATE, clazzPublic.getDeclaredField("fPrivate").getModifiers());
}
@Test
@ -1161,7 +1165,7 @@ public class TestComplete {
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");
assertEquals("small", clazz.getDeclaredMethod("main", Integer.class).invoke(instance, 5));
}
@Test
@ -1169,8 +1173,8 @@ public class TestComplete {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "While.jav");
var clazz = classFiles.get("While");
var instance = clazz.getDeclaredConstructor().newInstance();
assertEquals(clazz.getDeclaredMethod("m", Integer.class).invoke(instance, 5), 5);
assertEquals(clazz.getDeclaredMethod("m2").invoke(instance), 10);
assertEquals(5, clazz.getDeclaredMethod("m", Integer.class).invoke(instance, 5));
assertEquals(10, clazz.getDeclaredMethod("m2").invoke(instance));
}
@Test
@ -1186,7 +1190,7 @@ public class TestComplete {
var clazz = classFiles.get("Assign");
var instance = clazz.getDeclaredConstructor().newInstance();
var m = clazz.getDeclaredMethod("m");
assertEquals(m.invoke(instance), 20);
assertEquals(20, m.invoke(instance));
}
@Test
@ -1243,9 +1247,9 @@ public class TestComplete {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug295.jav");
var clazz = classFiles.get("Bug295");
var instance = clazz.getDeclaredConstructor(Integer.class, Integer.class, Integer.class).newInstance(1, 2, 3);
assertEquals(clazz.getDeclaredField("a").get(instance), 1);
assertEquals(clazz.getDeclaredField("b").get(instance), 2);
assertEquals(clazz.getDeclaredField("c").get(instance), 3);
assertEquals(1, clazz.getDeclaredField("a").get(instance));
assertEquals(2, clazz.getDeclaredField("b").get(instance));
assertEquals(3, clazz.getDeclaredField("c").get(instance));
}
@Test
@ -1275,7 +1279,7 @@ public class TestComplete {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug300.jav");
var clazz = classFiles.get("Bug300");
var instance = clazz.getDeclaredConstructor().newInstance();
assertEquals(clazz.getDeclaredMethod("m").invoke(instance), "Base");
assertEquals("Base", clazz.getDeclaredMethod("m").invoke(instance));
}
@Test
@ -1320,7 +1324,7 @@ public class TestComplete {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug310.jav");
var clazz = classFiles.get("Bug310");
var instance = clazz.getDeclaredConstructor().newInstance();
assertEquals(clazz.getDeclaredMethod("toString").invoke(instance), "3");
assertEquals("3", clazz.getDeclaredMethod("toString").invoke(instance));
}
@Test