Compare commits

...

8 Commits

21 changed files with 371 additions and 98 deletions

@ -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>

@ -539,7 +539,7 @@ catchClause
;
catchType
: qualifiedName ('|' qualifiedName)*
: typeType ('|' typeType)*
;
finallyBlock

@ -10,6 +10,7 @@ import de.dhbwstuttgart.target.tree.expression.*;
import de.dhbwstuttgart.target.tree.type.*;
import org.objectweb.asm.*;
import java.lang.annotation.Target;
import java.lang.invoke.*;
import java.lang.reflect.Modifier;
import java.util.*;
@ -1158,11 +1159,48 @@ public class Codegen {
mv.visitLabel(end);
break;
}
default:
throw new CodeGenException("Unexpected value: " + expr);
case TargetPattern targetPattern:
break;
case TargetTryCatchFinally targetTryCatchFinally:
generateTryCatchFinally(targetTryCatchFinally, state);
}
}
private void generateTryCatchFinally(TargetTryCatchFinally tryCatchFinally, State state){
MethodVisitor mv = state.mv;
Label startTry = new Label();
Label endTry = new Label();
Label endOrFinally = new Label();
//Try
mv.visitLabel(startTry);
generate(state, tryCatchFinally.tryBlock());
mv.visitLabel(endTry);
mv.visitJumpInsn(GOTO, endOrFinally);
for (var catchClause : tryCatchFinally.catchClauses()){
Label startCatch = new Label();
Label endCatch = new Label();
mv.visitTryCatchBlock(startTry, endOrFinally, startCatch, "java/lang/Exception"); //ignore all exception types except the first
mv.visitLabel(startCatch);
if (!catchClause.identifier().isEmpty()) {
mv.visitFrame(F_SAME1, 0, null, 1, new Object[]{"java/lang/Exception"});
LocalVar excep = state.createVariable(catchClause.identifier(), catchClause.exceptionNames().getFirst());
mv.visitVarInsn(ASTORE, excep.index());
}
generate(state, catchClause.catchBlock());
mv.visitLabel(endCatch);
mv.visitJumpInsn(GOTO, endOrFinally);
}
if (tryCatchFinally.finallyBlock().isPresent()){
mv.visitLabel(endOrFinally);
generate(state, tryCatchFinally.finallyBlock().get());
}
else mv.visitLabel(endOrFinally);
}
private void generateForEach(TargetForEach forEach, State state) {
state.enterScope();
TargetVarDecl vd = (TargetVarDecl) forEach.vardecl();
@ -1306,16 +1344,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();
}

@ -97,7 +97,7 @@ public class JavaTXCompiler {
path.add(new File(System.getProperty("user.dir")));
}
if (outputPath != null) path.add(outputPath);
classLoader = new DirectoryClassLoader(path, ClassLoader.getSystemClassLoader());
classLoader = new DirectoryClassLoader(path, ClassLoader.getPlatformClassLoader());
environment = new CompilationEnvironment(sources, classLoader);
classPath = path;
this.outputPath = outputPath;

@ -16,7 +16,7 @@ public class DirectoryClassLoader extends URLClassLoader implements IByteArrayCl
// }
public DirectoryClassLoader(List<File> directory, java.lang.ClassLoader parent) {
super(directory.stream().map(DirectoryClassLoader::dirToURL).flatMap(List::stream).collect(Collectors.toList()).toArray(new URL[0]), parent.getParent());
super(directory.stream().map(DirectoryClassLoader::dirToURL).flatMap(List::stream).toArray(URL[]::new), parent);
}
private static URL[] generateURLArray(URL url) {

@ -1,12 +1,7 @@
package de.dhbwstuttgart.parser.SyntaxTreeGenerator;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -16,6 +11,7 @@ import de.dhbwstuttgart.syntaxtree.statement.*;
import de.dhbwstuttgart.syntaxtree.type.Void;
import de.dhbwstuttgart.target.tree.expression.TargetUnaryOp;
import de.dhbwstuttgart.target.generate.StatementToTargetExpression;
import org.antlr.v4.runtime.RuleContext;
import org.antlr.v4.runtime.Token;
import de.dhbwstuttgart.exceptions.NotImplementedException;
@ -638,8 +634,16 @@ public class StatementGenerator {
}
private Statement convert(Java17Parser.TrycatchblockContext stmt) {
// TODO
throw new NotImplementedException();
Block tryBlock = convert(stmt.block(), false);
List<CatchClause> catchClauses = stmt.catchClause().stream().
map(x ->
new CatchClause(x.catchType().typeType().stream().map(y -> TypeGenerator.convert(y, reg, generics)).toList(),
x.identifier().getText(),
convert(x.block(), false)
)).toList();
Optional<Block> finallyBlock = stmt.finallyBlock() != null ? Optional.of(convert(stmt.finallyBlock().block(), false)) : Optional.empty();
return new TryCatchFinally(tryBlock, catchClauses, finallyBlock, stmt.getStart());
}
private Statement convert(Java17Parser.TrycatchresourceContext stmt) {

@ -39,6 +39,11 @@ public class SyntacticSugar {
public void visit(LambdaExpression le) {
//PL 2024-04-09 Do nothing, as in a LambdaExpression a return could be
}
@Override
public void visit(TryCatchFinally tryCatchFinally) {
}
}
private static boolean hasReturn(Block block) {

@ -1,5 +1,6 @@
package de.dhbwstuttgart.syntaxtree;
import de.dhbwstuttgart.syntaxtree.statement.TryCatchFinally;
import de.dhbwstuttgart.syntaxtree.type.*;
public interface ASTVisitor extends StatementVisitor{
@ -40,4 +41,6 @@ public interface ASTVisitor extends StatementVisitor{
void visit(GuardedPattern aGuardedPattern);
void visit(TryCatchFinally tryCatchFinally);
}

@ -0,0 +1,19 @@
package de.dhbwstuttgart.syntaxtree;
import de.dhbwstuttgart.syntaxtree.statement.Block;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import java.util.List;
public class CatchClause {
public List<RefTypeOrTPHOrWildcardOrGeneric> exceptionTypes;
public String identifier;
public Block catchBlock;
public CatchClause(List<RefTypeOrTPHOrWildcardOrGeneric> exceptionTypes, String identifier, Block catchBlock){
this.exceptionTypes = exceptionTypes;
this.identifier = identifier;
this.catchBlock = catchBlock;
}
}

@ -85,4 +85,6 @@ public interface StatementVisitor {
void visit(Throw aThrow);
void visit(Ternary ternary);
void visit(TryCatchFinally tryCatchFinally);
}

@ -0,0 +1,30 @@
package de.dhbwstuttgart.syntaxtree.statement;
import de.dhbwstuttgart.syntaxtree.CatchClause;
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import org.antlr.v4.runtime.Token;
import de.dhbwstuttgart.syntaxtree.type.Void;
import java.util.List;
import java.util.Optional;
public class TryCatchFinally extends Statement{
public Block tryBlock;
public List<CatchClause> catchClauses;
public Optional<Block> finallyBlock;
public TryCatchFinally(Block tryBlock, List<CatchClause> catchClauses, Optional<Block> finallyBlock, Token offset){
super(new Void(offset), offset);
this.tryBlock = tryBlock;
this.catchClauses = catchClauses;
this.finallyBlock = finallyBlock;
}
@Override
public void accept(StatementVisitor visitor) {
visitor.visit(this);
}
}

@ -530,4 +530,9 @@ public class OutputGenerator implements ASTVisitor {
out.append(" with ");
aGuardedPattern.getCondition().accept(this);
}
@Override
public void visit(TryCatchFinally tryCatchFinally) {
out.append("");
}
}

@ -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;

@ -434,6 +434,11 @@ public abstract class GenerateGenerics {
whileStmt.loopBlock.accept(this);
}
@Override
public void visit(TryCatchFinally tryCatchFinally) {
}
@Override
public void visit(ArgumentList arglist) {
for (int i = 0; i < arglist.getArguments().size(); i++) {
@ -536,6 +541,11 @@ public abstract class GenerateGenerics {
super.visit(methodCall);
typeVariables.addAll(findTypeVariables(methodCall.getType()));
}
@Override
public void visit(TryCatchFinally tryCatchFinally) {
}
});
}

@ -76,6 +76,11 @@ public class StatementToTargetExpression implements ASTVisitor {
localVariables.add(varDecl.getName());
}
@Override
public void visit(TryCatchFinally tryCatchFinally) {
}
@Override
public void visit(LambdaExpression lambda) {
} // Don't look at lambda expressions
@ -591,4 +596,14 @@ public class StatementToTargetExpression implements ASTVisitor {
public void visit(GuardedPattern aGuardedPattern) {
result = new TargetGuard((TargetPattern) converter.convert(aGuardedPattern.getNestedPattern()), converter.convert(aGuardedPattern.getCondition()));
}
@Override
public void visit(TryCatchFinally tryCatchFinally) {
result = new TargetTryCatchFinally(
converter.convert(tryCatchFinally.tryBlock),
tryCatchFinally.catchClauses.stream().map(x -> new TargetCatchClause(x.exceptionTypes.stream().map(converter::convert).toList(), x.identifier, converter.convert(x.catchBlock))).toList(),
tryCatchFinally.finallyBlock.map(converter::convert)
);
}
}

@ -0,0 +1,8 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.List;
public record TargetCatchClause(List<TargetType> exceptionNames, String identifier, TargetBlock catchBlock) {
}

@ -3,7 +3,7 @@ package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.*;
public sealed interface TargetExpression
permits TargetBinaryOp, TargetBlock, TargetBreak, TargetCast, TargetClassName, TargetContinue, TargetDo, TargetFieldVar, TargetFor, TargetForEach, TargetIf, TargetInstanceOf, TargetLambdaExpression, TargetLiteral, TargetLocalVar, TargetPattern, TargetReturn, TargetStatementExpression, TargetSuper, TargetSwitch, TargetTernary, TargetThis, TargetThrow, TargetUnaryOp, TargetVarDecl, TargetWhile, TargetYield {
permits TargetBinaryOp, TargetBlock, TargetBreak, TargetCast, TargetClassName, TargetContinue, TargetDo, TargetFieldVar, TargetFor, TargetForEach, TargetIf, TargetInstanceOf, TargetLambdaExpression, TargetLiteral, TargetLocalVar, TargetPattern, TargetReturn, TargetStatementExpression, TargetSuper, TargetSwitch, TargetTernary, TargetThis, TargetThrow, TargetTryCatchFinally, TargetUnaryOp, TargetVarDecl, TargetWhile, TargetYield {
default TargetType type() {
return null;

@ -0,0 +1,7 @@
package de.dhbwstuttgart.target.tree.expression;
import java.util.List;
import java.util.Optional;
public record TargetTryCatchFinally(TargetBlock tryBlock, List<TargetCatchClause> catchClauses, Optional<TargetBlock> finallyBlock) implements TargetExpression{
}

@ -2,6 +2,7 @@ package de.dhbwstuttgart.typedeployment;
import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression;
import de.dhbwstuttgart.syntaxtree.statement.TryCatchFinally;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.target.generate.GenericsResult;
import de.dhbwstuttgart.target.generate.GenericsResultSet;
@ -32,6 +33,11 @@ public class TypeInsertPlacer extends AbstractASTWalker {
TypeInsertPlacerClass cl = new TypeInsertPlacerClass(classOrInterface, withResults, genericsResult);
this.inserts.addAll(cl.inserts);
}
@Override
public void visit(TryCatchFinally tryCatchFinally) {
}
}
class TypeInsertPlacerClass extends AbstractASTWalker{
@ -63,6 +69,11 @@ class TypeInsertPlacerClass extends AbstractASTWalker{
super.visit(method);
}
@Override
public void visit(TryCatchFinally tryCatchFinally) {
}
@Override
public void visit(Field field) {
if(field.getType() instanceof TypePlaceholder){

@ -500,6 +500,12 @@ public class TYPEStmt implements StatementVisitor {
constraintsSet.addUndConstraint(new Pair(ternary.iffalse.getType(), ternary.getType(), PairOperator.SMALLERDOT));
}
@Override
public void visit(TryCatchFinally tryCatchFinally) {
tryCatchFinally.tryBlock.accept(this);
tryCatchFinally.catchClauses.forEach(c -> c.catchBlock.accept(this));
}
@Override
public void visit(Return returnExpr) {
returnExpr.retexpr.accept(this);

@ -941,7 +941,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));
}