forked from JavaTX/JavaCompilerCore
Start implementing family of generics
This commit is contained in:
parent
3b439a49cd
commit
f00ee2598f
@ -15,6 +15,7 @@ import java.lang.invoke.MethodType;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.objectweb.asm.Opcodes.*;
|
import static org.objectweb.asm.Opcodes.*;
|
||||||
import static de.dhbwstuttgart.target.tree.expression.TargetBinaryOp.*;
|
import static de.dhbwstuttgart.target.tree.expression.TargetBinaryOp.*;
|
||||||
@ -527,7 +528,7 @@ public class Codegen {
|
|||||||
var mv = state.mv;
|
var mv = state.mv;
|
||||||
var name = "lambda$" + state.lambdaCounter;
|
var name = "lambda$" + state.lambdaCounter;
|
||||||
var impl = new TargetMethod(
|
var impl = new TargetMethod(
|
||||||
ACC_PRIVATE, new TargetRefType(clazz.qualifiedName()), name,
|
ACC_PRIVATE, name, Set.of(),
|
||||||
lambda.params(), lambda.returnType(), lambda.block()
|
lambda.params(), lambda.returnType(), lambda.block()
|
||||||
);
|
);
|
||||||
generateMethod(impl);
|
generateMethod(impl);
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
package de.dhbwstuttgart.target.generate;
|
package de.dhbwstuttgart.target.generate;
|
||||||
|
|
||||||
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
|
||||||
import de.dhbwstuttgart.syntaxtree.*;
|
import de.dhbwstuttgart.syntaxtree.*;
|
||||||
import de.dhbwstuttgart.syntaxtree.statement.Block;
|
import de.dhbwstuttgart.syntaxtree.statement.*;
|
||||||
import de.dhbwstuttgart.syntaxtree.statement.Expression;
|
|
||||||
import de.dhbwstuttgart.syntaxtree.type.*;
|
import de.dhbwstuttgart.syntaxtree.type.*;
|
||||||
import de.dhbwstuttgart.target.tree.*;
|
import de.dhbwstuttgart.target.tree.*;
|
||||||
import de.dhbwstuttgart.target.tree.expression.TargetBlock;
|
import de.dhbwstuttgart.target.tree.expression.TargetBlock;
|
||||||
@ -11,53 +10,247 @@ import de.dhbwstuttgart.target.tree.expression.TargetExpression;
|
|||||||
import de.dhbwstuttgart.target.tree.type.*;
|
import de.dhbwstuttgart.target.tree.type.*;
|
||||||
import de.dhbwstuttgart.typeinference.result.*;
|
import de.dhbwstuttgart.typeinference.result.*;
|
||||||
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public class ASTToTargetAST {
|
public class ASTToTargetAST {
|
||||||
|
|
||||||
protected List<HashMap<TypePlaceholder, TargetType>> all;
|
protected List<Sigma> all;
|
||||||
protected HashMap<TypePlaceholder, TargetType> sigma;
|
protected Sigma sigma;
|
||||||
|
|
||||||
private class ResultPairV implements ResultPairVisitor {
|
private class Sigma {
|
||||||
|
HashMap<Method, Set<TargetGeneric>> computedGenerics = new HashMap<>();
|
||||||
|
|
||||||
|
Set<PairTPHsmallerTPH> simplifiedConstraints = new HashSet<>();
|
||||||
|
Map<TypePlaceholder, TargetType> result = new HashMap<>();
|
||||||
|
Map<TypePlaceholder, TypePlaceholder> equality = new HashMap<>();
|
||||||
|
|
||||||
|
Sigma(ResultSet constraints) {
|
||||||
|
ASTToTargetAST.this.sigma = this;
|
||||||
|
|
||||||
|
Set<List<TypePlaceholder>> equalitySet = new HashSet<>();
|
||||||
|
Map<TypePlaceholder, List<TypePlaceholder>> unified = new HashMap<>();
|
||||||
|
|
||||||
|
for (var constraint : constraints.results) {
|
||||||
|
if (constraint instanceof PairTPHEqualTPH p) {
|
||||||
|
if (unified.containsKey(p.getLeft())) {
|
||||||
|
var equals = unified.get(p.getLeft());
|
||||||
|
equals.add(p.getRight());
|
||||||
|
unified.put(p.getLeft(), equals);
|
||||||
|
} else if (unified.containsKey(p.getRight())) {
|
||||||
|
var equals = unified.get(p.getRight());
|
||||||
|
equals.add(p.getLeft());
|
||||||
|
unified.put(p.getRight(), equals);
|
||||||
|
} else {
|
||||||
|
List<TypePlaceholder> equals = new ArrayList<>();
|
||||||
|
equals.add(p.getLeft());
|
||||||
|
equals.add(p.getRight());
|
||||||
|
unified.put(p.getLeft(), equals);
|
||||||
|
unified.put(p.getRight(), equals);
|
||||||
|
equalitySet.add(equals);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var constraint : constraints.results) {
|
||||||
|
if (constraint instanceof PairTPHsmallerTPH p) {
|
||||||
|
var left = p.left;
|
||||||
|
var right = p.right;
|
||||||
|
if (unified.containsKey(left))
|
||||||
|
left = unified.get(left).get(0);
|
||||||
|
if (unified.containsKey(right))
|
||||||
|
right = unified.get(right).get(0);
|
||||||
|
|
||||||
|
simplifiedConstraints.add(new PairTPHsmallerTPH(left, right));
|
||||||
|
result.put(right, new TargetGenericType(right.getName()));
|
||||||
|
result.put(left, new TargetGenericType(left.getName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println(simplifiedConstraints);
|
||||||
|
|
||||||
|
for (var equality : equalitySet) {
|
||||||
|
var first = equality.get(0);
|
||||||
|
for (var i = 1; i < equality.size(); i++)
|
||||||
|
this.equality.put(equality.get(i), first);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var constraint : constraints.results) {
|
||||||
|
if (constraint instanceof PairTPHequalRefTypeOrWildcardType p) {
|
||||||
|
result.put(p.left, convert(p.right));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Family of generated Generics
|
||||||
|
Set<TargetGeneric> generics(ClassOrInterface owner, Method method) {
|
||||||
|
if (computedGenerics.containsKey(method))
|
||||||
|
return computedGenerics.get(method);
|
||||||
|
|
||||||
|
Set<TargetGeneric> result = new HashSet<>();
|
||||||
|
computedGenerics.put(method, result);
|
||||||
|
|
||||||
|
method.block.accept(new AbstractStatementVisitor() {
|
||||||
|
// These two methods do the actual work
|
||||||
@Override
|
@Override
|
||||||
public void visit(PairTPHsmallerTPH p) {
|
public void visit(LocalVarDecl localVarDecl) {
|
||||||
throw new NotImplementedException();
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(PairTPHequalRefTypeOrWildcardType p) {
|
public void visit(MethodCall methodCall) {
|
||||||
sigma.put(p.left, convert(p.right));
|
if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver) {
|
||||||
|
if (expressionReceiver.expr instanceof This) {
|
||||||
|
// TODO This is going to fail spectacularly for overloaded methods
|
||||||
|
var optMethod = owner.getMethods().stream().filter(m -> m.name.equals(methodCall.name)).findFirst();
|
||||||
|
assert optMethod.isPresent();
|
||||||
|
var method = optMethod.get();
|
||||||
|
Set<TargetGeneric> generics = generics(owner, method);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Everything down here is just for walking the AST
|
||||||
|
@Override
|
||||||
|
public void visit(ArgumentList argumentList) {
|
||||||
|
argumentList.getArguments().forEach(expr -> expr.accept(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(PairTPHEqualTPH p) {
|
public void visit(LambdaExpression lambdaExpression) {
|
||||||
throw new NotImplementedException();
|
lambdaExpression.methodBody.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Assign assign) {
|
||||||
|
assign.rightSide.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BinaryExpr binary) {
|
||||||
|
binary.lexpr.accept(this);
|
||||||
|
binary.rexpr.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Block block) {
|
||||||
|
for (var expr : block.statements)
|
||||||
|
expr.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ForStmt forStmt) {
|
||||||
|
forStmt.body_Loop_block.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(IfStmt ifStmt) {
|
||||||
|
ifStmt.then_block.accept(this);
|
||||||
|
ifStmt.else_block.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NewClass newClass) {
|
||||||
|
newClass.arglist.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NewArray newArray) {
|
||||||
|
newArray.expr.forEach(expr -> expr.accept(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Return aReturn) {
|
||||||
|
aReturn.retexpr.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WhileStmt whileStmt) {
|
||||||
|
whileStmt.loopBlock.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(DoStmt whileStmt) {
|
||||||
|
whileStmt.loopBlock.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(UnaryExpr unaryExpr) {
|
||||||
|
unaryExpr.expr.accept(this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void findAllBounds(String name, Set<TargetGeneric> generics) {
|
||||||
|
for (var rsp : simplifiedConstraints) {
|
||||||
|
var left = equality.getOrDefault(rsp.left, rsp.left);
|
||||||
|
var right = equality.getOrDefault(rsp.right, rsp.right);
|
||||||
|
if (left.getName().equals(name)) {
|
||||||
|
generics.add(new TargetGeneric(name, new TargetGenericType(right.getName())));
|
||||||
|
findAllBounds(right.getName(), generics);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
generics.add(new TargetGeneric(name, TargetType.Object));
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<TargetGeneric> findAllBounds(TargetGenericType type) {
|
||||||
|
Set<TargetGeneric> result = new HashSet<>();
|
||||||
|
findAllBounds(type.name(), result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<TargetGeneric> generics(ClassOrInterface classOrInterface) {
|
||||||
|
Set<TargetGeneric> result = new HashSet<>();
|
||||||
|
for (var field : classOrInterface.getFieldDecl()) {
|
||||||
|
if (field.getType() instanceof TypePlaceholder tph) {
|
||||||
|
var tpe = get(tph);
|
||||||
|
switch (tpe) {
|
||||||
|
case TargetSpecializedType specializedType:
|
||||||
|
specializedType.params().stream().flatMap(targetType -> {
|
||||||
|
if (targetType instanceof TargetSpecializedType spc)
|
||||||
|
return Stream.concat(Stream.of(targetType), spc.params().stream());
|
||||||
|
return Stream.of(targetType);
|
||||||
|
}).forEach(param -> {
|
||||||
|
if (param instanceof TargetGenericType genericType) {
|
||||||
|
result.addAll(findAllBounds(genericType));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case TargetGenericType genericType:
|
||||||
|
result.addAll(findAllBounds(genericType));
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
TargetType get(TypePlaceholder tph) {
|
||||||
|
if (equality.containsKey(tph)) {
|
||||||
|
return get(equality.get(tph));
|
||||||
|
}
|
||||||
|
return result.get(tph);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ASTToTargetAST(List<ResultSet> resultSets) {
|
public ASTToTargetAST(List<ResultSet> resultSets) {
|
||||||
all = new ArrayList<>();
|
all = new ArrayList<>();
|
||||||
|
|
||||||
for (var set : resultSets) {
|
for (var set : resultSets) {
|
||||||
this.sigma = new HashMap<>();
|
all.add(new Sigma(set));
|
||||||
for (var pair : set.results) {
|
|
||||||
var visitor = new ResultPairV();
|
|
||||||
pair.accept(visitor);
|
|
||||||
}
|
}
|
||||||
all.add(this.sigma);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.sigma = all.get(0);
|
this.sigma = all.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TargetClass convert(ClassOrInterface input) {
|
public TargetClass convert(ClassOrInterface input) {
|
||||||
return new TargetClass(input.getModifiers(),input.getClassName().toString(), convert(input.getSuperClass()),
|
return new TargetClass(input.getModifiers(),input.getClassName().toString(), convert(input.getSuperClass()),
|
||||||
input.getSuperInterfaces().stream().map(it -> sigma.get(it)).toList(),
|
sigma.generics(input),
|
||||||
input.getConstructors().stream().map(it -> convert(input, it)).flatMap(List::stream).toList(),
|
input.getSuperInterfaces().stream().map(this::convert).toList(),
|
||||||
input.getFieldDecl().stream().map(it -> convert(input, it)).toList(),
|
input.getConstructors().stream().map(constructor -> this.convert(input, constructor)).flatMap(List::stream).toList(),
|
||||||
input.getMethods().stream().map(it -> convert(input, it)).flatMap(List::stream).toList()
|
input.getFieldDecl().stream().map(this::convert).toList(),
|
||||||
|
input.getMethods().stream().map(method -> this.convert(input, method)).flatMap(List::stream).toList()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +268,7 @@ public class ASTToTargetAST {
|
|||||||
sigma = s;
|
sigma = s;
|
||||||
List<MethodParameter> params = convert(input.getParameterList());
|
List<MethodParameter> params = convert(input.getParameterList());
|
||||||
if (parameterSet.stream().noneMatch(p -> p.equals(params))) {
|
if (parameterSet.stream().noneMatch(p -> p.equals(params))) {
|
||||||
result.add(new TargetConstructor(input.modifier, new TargetRefType(owner.getClassName().getClassName()), params, convert(input.block)));
|
result.add(new TargetConstructor(input.modifier, sigma.generics(owner, input), params, convert(input.block)));
|
||||||
parameterSet.add(params);
|
parameterSet.add(params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,8 +287,7 @@ public class ASTToTargetAST {
|
|||||||
if (parameterSet.stream().noneMatch(p -> p.equals(params))) {
|
if (parameterSet.stream().noneMatch(p -> p.equals(params))) {
|
||||||
result.add(new TargetMethod(
|
result.add(new TargetMethod(
|
||||||
input.modifier,
|
input.modifier,
|
||||||
new TargetRefType(owner.getClassName().getClassName()),
|
input.name, sigma.generics(owner, input), params,
|
||||||
input.name, params,
|
|
||||||
convert(input.getReturnType()),
|
convert(input.getReturnType()),
|
||||||
convert(input.block)
|
convert(input.block)
|
||||||
));
|
));
|
||||||
@ -116,10 +308,9 @@ public class ASTToTargetAST {
|
|||||||
return converter.result;
|
return converter.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TargetField convert(ClassOrInterface owner, Field input) {
|
private TargetField convert(Field input) {
|
||||||
return new TargetField(
|
return new TargetField(
|
||||||
input.modifier,
|
input.modifier,
|
||||||
new TargetRefType(owner.getClassName().getClassName()),
|
|
||||||
convert(input.getType()),
|
convert(input.getType()),
|
||||||
input.getName()
|
input.getName()
|
||||||
);
|
);
|
||||||
@ -131,8 +322,11 @@ public class ASTToTargetAST {
|
|||||||
public TargetType visit(RefType refType) {
|
public TargetType visit(RefType refType) {
|
||||||
var name = refType.getName().toString();
|
var name = refType.getName().toString();
|
||||||
if (name.equals("void")) return null;
|
if (name.equals("void")) return null;
|
||||||
return new TargetRefType(name,
|
|
||||||
refType.getParaList().stream().map(ASTToTargetAST.this::convert).toList());
|
var params = refType.getParaList().stream().map(ASTToTargetAST.this::convert).toList();
|
||||||
|
if (name.matches("Fun\\d\\$\\$")) // TODO This seems like a bad idea
|
||||||
|
return new TargetFunNType(params.size(), params);
|
||||||
|
return new TargetRefType(name, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,152 @@
|
|||||||
|
package de.dhbwstuttgart.target.generate;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.statement.*;
|
||||||
|
|
||||||
|
public abstract class AbstractStatementVisitor implements StatementVisitor {
|
||||||
|
@Override
|
||||||
|
public void visit(ArgumentList argumentList) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(LambdaExpression lambdaExpression) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Assign assign) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BinaryExpr binary) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Block block) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(CastExpr castExpr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(EmptyStmt emptyStmt) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(FieldVar fieldVar) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ForStmt forStmt) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(IfStmt ifStmt) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(InstanceOf instanceOf) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(LocalVar localVar) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(LocalVarDecl localVarDecl) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(MethodCall methodCall) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NewClass methodCall) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NewArray newArray) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Return aReturn) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ReturnVoid aReturn) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(StaticClassName staticClassName) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Super aSuper) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(This aThis) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WhileStmt whileStmt) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(DoStmt whileStmt) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(AssignToField assignLeftSide) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(AssignToLocal assignLeftSide) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(SuperCall superCall) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ExpressionReceiver expressionReceiver) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(UnaryExpr unaryExpr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Literal literal) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -6,31 +6,42 @@ import de.dhbwstuttgart.target.tree.type.TargetType;
|
|||||||
|
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public record TargetClass(int modifiers, String qualifiedName, TargetType superType, List<TargetType> implementingInterfaces,
|
public record TargetClass(int modifiers, String qualifiedName, TargetType superType, Set<TargetGeneric> generics, List<TargetType> implementingInterfaces,
|
||||||
List<TargetConstructor> constructors, List<TargetField> fields, List<TargetMethod> methods) {
|
List<TargetConstructor> constructors, List<TargetField> fields, List<TargetMethod> methods) {
|
||||||
|
|
||||||
public TargetClass(int modifiers, String qualifiedName) {
|
public TargetClass(int modifiers, String qualifiedName) {
|
||||||
this(modifiers, qualifiedName, TargetType.Object, new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>());
|
this(modifiers, qualifiedName, TargetType.Object, new HashSet<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>());
|
||||||
}
|
}
|
||||||
public TargetClass(int modifiers, String qualifiedName, List<TargetType> implementingInterfaces) {
|
public TargetClass(int modifiers, String qualifiedName, List<TargetType> implementingInterfaces) {
|
||||||
this(modifiers, qualifiedName, TargetType.Object, implementingInterfaces, new ArrayList<>(), new ArrayList<>(), new ArrayList<>());
|
this(modifiers, qualifiedName, TargetType.Object, new HashSet<>(), implementingInterfaces, new ArrayList<>(), new ArrayList<>(), new ArrayList<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return qualifiedName.replaceAll("\\.", "/");
|
return qualifiedName.replaceAll("\\.", "/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addMethod(int access, String name, Set<TargetGeneric> generics, List<MethodParameter> parameterTypes, TargetType returnType, TargetBlock block) {
|
||||||
|
this.methods.add(new TargetMethod(access, name, generics, parameterTypes, returnType, block));
|
||||||
|
}
|
||||||
|
|
||||||
public void addMethod(int access, String name, List<MethodParameter> parameterTypes, TargetType returnType, TargetBlock block) {
|
public void addMethod(int access, String name, List<MethodParameter> parameterTypes, TargetType returnType, TargetBlock block) {
|
||||||
this.methods.add(new TargetMethod(access, new TargetRefType(this.qualifiedName, List.of()), name, parameterTypes, returnType, block));
|
addMethod(access, name, Set.of(), parameterTypes, returnType, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addConstructor(int access, Set<TargetGeneric> generics, List<MethodParameter> paramterTypes, TargetBlock block) {
|
||||||
|
this.constructors.add(new TargetConstructor(access, generics, paramterTypes, block));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addConstructor(int access, List<MethodParameter> paramterTypes, TargetBlock block) {
|
public void addConstructor(int access, List<MethodParameter> paramterTypes, TargetBlock block) {
|
||||||
this.constructors.add(new TargetConstructor(access, new TargetRefType(this.qualifiedName, List.of()), paramterTypes, block));
|
addConstructor(access, Set.of(), paramterTypes, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addField(int access, TargetRefType type, String name) {
|
public void addField(int access, TargetRefType type, String name) {
|
||||||
this.fields.add(new TargetField(access, new TargetRefType(this.qualifiedName, List.of()), type, name));
|
this.fields.add(new TargetField(access, type, name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package de.dhbwstuttgart.target.tree;
|
package de.dhbwstuttgart.target.tree;
|
||||||
|
|
||||||
import de.dhbwstuttgart.target.tree.expression.TargetBlock;
|
import de.dhbwstuttgart.target.tree.expression.TargetBlock;
|
||||||
import de.dhbwstuttgart.target.tree.type.TargetRefType;
|
|
||||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public record TargetConstructor(int access, TargetType owner, List<MethodParameter> parameters, TargetBlock block) {
|
public record TargetConstructor(int access, Set<TargetGeneric> generics, List<MethodParameter> parameters, TargetBlock block) {
|
||||||
|
|
||||||
public String getDescriptor() {
|
public String getDescriptor() {
|
||||||
return TargetMethod.getDescriptor(null, parameters.stream().map(MethodParameter::type).toArray(TargetType[]::new));
|
return TargetMethod.getDescriptor(null, parameters.stream().map(MethodParameter::type).toArray(TargetType[]::new));
|
||||||
|
@ -3,7 +3,7 @@ package de.dhbwstuttgart.target.tree;
|
|||||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
public record TargetField(int access, TargetType owner, TargetType type, String name) {
|
public record TargetField(int access, TargetType type, String name) {
|
||||||
public String getDescriptor() {
|
public String getDescriptor() {
|
||||||
return type.toSignature();
|
return type.toSignature();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
|
|
||||||
|
public record TargetGeneric(String name, TargetType bound) {
|
||||||
|
}
|
@ -1,14 +1,13 @@
|
|||||||
package de.dhbwstuttgart.target.tree;
|
package de.dhbwstuttgart.target.tree;
|
||||||
|
|
||||||
import de.dhbwstuttgart.target.tree.expression.TargetBlock;
|
import de.dhbwstuttgart.target.tree.expression.TargetBlock;
|
||||||
import de.dhbwstuttgart.target.tree.type.TargetRefType;
|
|
||||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.Set;
|
||||||
|
|
||||||
public record TargetMethod(int access, TargetType owner, String name, List<MethodParameter> parameters, TargetType returnType, TargetBlock block) {
|
public record TargetMethod(int access, String name, Set<TargetGeneric> generics, List<MethodParameter> parameters, TargetType returnType, TargetBlock block) {
|
||||||
public static String getDescriptor(TargetType returnType, TargetType... parameters) {
|
public static String getDescriptor(TargetType returnType, TargetType... parameters) {
|
||||||
String ret = "(";
|
String ret = "(";
|
||||||
for (var parameterType : parameters) {
|
for (var parameterType : parameters) {
|
||||||
|
@ -2,7 +2,7 @@ package de.dhbwstuttgart.target.tree.type;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public record TargetFunNType(int N, List<TargetType> params) implements TargetType {
|
public record TargetFunNType(int N, List<TargetType> params) implements TargetSpecializedType {
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Fun" + N + "$$";
|
return "Fun" + N + "$$";
|
||||||
|
@ -7,7 +7,7 @@ public record TargetGenericType(String name) implements TargetType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public java.lang.String getName() {
|
public String getName() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import de.dhbwstuttgart.target.tree.type.TargetType;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public record TargetRefType(String name, List<TargetType> params) implements TargetType {
|
public record TargetRefType(String name, List<TargetType> params) implements TargetSpecializedType {
|
||||||
public TargetRefType(String name) {
|
public TargetRefType(String name) {
|
||||||
this(name, List.of());
|
this(name, List.of());
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
package de.dhbwstuttgart.target.tree.type;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public sealed interface TargetSpecializedType extends TargetType permits TargetFunNType, TargetRefType {
|
||||||
|
List<TargetType> params();
|
||||||
|
}
|
@ -3,7 +3,7 @@ package de.dhbwstuttgart.target.tree.type;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public sealed interface TargetType
|
public sealed interface TargetType
|
||||||
permits TargetExtendsWildcard, TargetFunNType, TargetGenericType, TargetRefType, TargetSuperWildcard {
|
permits TargetExtendsWildcard, TargetGenericType, TargetSpecializedType, TargetSuperWildcard {
|
||||||
|
|
||||||
// Builtin types
|
// Builtin types
|
||||||
TargetRefType Boolean = new TargetRefType("java.lang.Boolean");
|
TargetRefType Boolean = new TargetRefType("java.lang.Boolean");
|
||||||
|
@ -38,8 +38,8 @@ public class ASTToTypedTargetAST {
|
|||||||
var converter = new ASTToTargetAST(resultSet);
|
var converter = new ASTToTargetAST(resultSet);
|
||||||
var classes = compiler.sourceFiles.get(file).getClasses();
|
var classes = compiler.sourceFiles.get(file).getClasses();
|
||||||
|
|
||||||
Class overloading = TestCodegen.generateClass(converter.convert(classes.get(0)));
|
var overloading = TestCodegen.generateClass(converter.convert(classes.get(0)));
|
||||||
Class overloading2 = TestCodegen.generateClass(converter.convert(classes.get(1)));
|
var overloading2 = TestCodegen.generateClass(converter.convert(classes.get(1)));
|
||||||
|
|
||||||
var test1 = overloading.getDeclaredMethod("test", overloading);
|
var test1 = overloading.getDeclaredMethod("test", overloading);
|
||||||
test1.setAccessible(true);
|
test1.setAccessible(true);
|
||||||
@ -50,4 +50,15 @@ public class ASTToTypedTargetAST {
|
|||||||
assertEquals(test1.invoke(overloadingInstance, overloadingInstance), "Overloading");
|
assertEquals(test1.invoke(overloadingInstance, overloadingInstance), "Overloading");
|
||||||
assertEquals(test2.invoke(overloadingInstance, overloading2Instance), "Overloading2");
|
assertEquals(test2.invoke(overloadingInstance, overloading2Instance), "Overloading2");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void generics() throws Exception {
|
||||||
|
var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/bytecode/javFiles/TPHsAndGenerics.jav").toFile();
|
||||||
|
var compiler = new JavaTXCompiler(file);
|
||||||
|
var resultSet = compiler.typeInference();
|
||||||
|
var converter = new ASTToTargetAST(resultSet);
|
||||||
|
var classes = compiler.sourceFiles.get(file).getClasses();
|
||||||
|
|
||||||
|
converter.convert(classes.get(0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
16
src/test/resources/bytecode/javFiles/TPHsAndGenerics.jav
Normal file
16
src/test/resources/bytecode/javFiles/TPHsAndGenerics.jav
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
class TPHsAndGenerics {
|
||||||
|
id = x -> x;
|
||||||
|
|
||||||
|
id2(x) {
|
||||||
|
return id.apply(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
m(a, b) {
|
||||||
|
var c = m2(a, b);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
m2(a, b) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user