First implementation for overloaded functions and test case

This commit is contained in:
Victorious3 2022-06-17 15:15:08 +02:00
parent 0a1a596bb9
commit 29112e7bd7
6 changed files with 130 additions and 49 deletions

View File

@ -809,7 +809,7 @@ public class Codegen {
public byte[] generate() { public byte[] generate() {
cw.visit(V1_8, clazz.modifiers(), clazz.qualifiedName(), cw.visit(V1_8, clazz.modifiers(), clazz.qualifiedName(),
null, clazz.superType().getName(), null, clazz.superType() != null ? clazz.superType().getName(): "java/lang/Object",
clazz.implementingInterfaces().stream().map(TargetType::toSignature).toArray(String[]::new) clazz.implementingInterfaces().stream().map(TargetType::toSignature).toArray(String[]::new)
); );
clazz.fields().forEach(this::generateField); clazz.fields().forEach(this::generateField);

View File

@ -1,58 +1,113 @@
package de.dhbwstuttgart.target.generate; package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.exceptions.NotImplementedException;
import de.dhbwstuttgart.syntaxtree.ASTVisitor; import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.Field;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.statement.Block; import de.dhbwstuttgart.syntaxtree.statement.Block;
import de.dhbwstuttgart.syntaxtree.statement.Expression; import de.dhbwstuttgart.syntaxtree.statement.Expression;
import de.dhbwstuttgart.syntaxtree.statement.Statement;
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;
import de.dhbwstuttgart.target.tree.expression.TargetExpression; import de.dhbwstuttgart.target.tree.expression.TargetExpression;
import de.dhbwstuttgart.target.tree.type.*; import de.dhbwstuttgart.target.tree.type.*;
import de.dhbwstuttgart.typeinference.result.ResultSet; import de.dhbwstuttgart.typeinference.result.*;
import java.util.ArrayList; import java.lang.annotation.Target;
import java.util.HashMap; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class ASTToTargetAST { public class ASTToTargetAST {
protected List<HashMap<TypePlaceholder, TargetType>> all;
protected HashMap<TypePlaceholder, TargetType> sigma; protected HashMap<TypePlaceholder, TargetType> sigma;
public ASTToTargetAST(ResultSet resultSet) { private class ResultPairV implements ResultPairVisitor {
this.sigma = new HashMap<>(); @Override
public void visit(PairTPHsmallerTPH p) {
throw new NotImplementedException();
}
@Override
public void visit(PairTPHequalRefTypeOrWildcardType p) {
sigma.put(p.left, convert(p.right));
}
@Override
public void visit(PairTPHEqualTPH p) {
throw new NotImplementedException();
}
}
public ASTToTargetAST(List<ResultSet> resultSets) {
all = new ArrayList<>();
for (var set : resultSets) {
this.sigma = new HashMap<>();
for (var pair : set.results) {
var visitor = new ResultPairV();
pair.accept(visitor);
}
all.add(this.sigma);
}
this.sigma = all.get(0);
} }
public TargetClass convert(ClassOrInterface input) { public TargetClass convert(ClassOrInterface input) {
List<TargetConstructor> targetConstructors = new ArrayList<>(); return new TargetClass(input.getModifiers(),input.getClassName().toString(), convert(input.getSuperClass()),
//TODO constructor conversion -> also reduce syntactic sugar input.getSuperInterfaces().stream().map(it -> sigma.get(it)).toList(),
return new TargetClass(input.getModifiers(),input.getClassName().toString(), sigma.get(input.getSuperClass()), input.getConstructors().stream().map(it -> convert(input, it)).flatMap(List::stream).toList(),
input.getSuperInterfaces().stream().map(it -> sigma.get(it)).collect(Collectors.toList()), input.getFieldDecl().stream().map(it -> convert(input, it)).toList(),
targetConstructors, input.getMethods().stream().map(it -> convert(input, it)).flatMap(List::stream).toList()
input.getFieldDecl().stream().map(it -> convert(input, it)).collect(Collectors.toList()),
input.getMethods().stream().map(it -> convert(input, it)).collect(Collectors.toList()));
}
private TargetMethod convert(ClassOrInterface owner, Method input) {
List<MethodParameter> params = input.getParameterList().getFormalparalist().stream()
.map(param -> new MethodParameter(convert(param.getType()), param.getName())).collect(Collectors.toList());
return new TargetMethod(
input.modifier,
new TargetRefType(owner.getClassName().getClassName()),
input.name, params,
convert(input.getReturnType()),
convert(input.block)
); );
} }
private List<MethodParameter> convert(ParameterList input) {
return input.getFormalparalist().stream()
.map(param -> new MethodParameter(convert(param.getType()), param.getName())).toList();
}
private List<TargetConstructor> convert(ClassOrInterface owner, Constructor input) {
sigma = all.get(0);
List<TargetConstructor> result = new ArrayList<>();
Set<List<MethodParameter>> parameterSet = new HashSet<>();
for (var s : all) {
sigma = s;
List<MethodParameter> params = convert(input.getParameterList());
if (!parameterSet.stream().filter(p -> p.equals(params)).findFirst().isPresent()) {
result.add(new TargetConstructor(input.modifier, new TargetRefType(owner.getClassName().getClassName()), params, convert(input.block)));
parameterSet.add(params);
}
}
return result;
}
private List<TargetMethod> convert(ClassOrInterface owner, Method input) {
sigma = all.get(0);
List<TargetMethod> result = new ArrayList<>();
Set<List<MethodParameter>> parameterSet = new HashSet<>();
for (var s : all) {
sigma = s;
List<MethodParameter> params = convert(input.getParameterList());
if (!parameterSet.stream().filter(p -> p.equals(params)).findFirst().isPresent()) {
result.add(new TargetMethod(
input.modifier,
new TargetRefType(owner.getClassName().getClassName()),
input.name, params,
convert(input.getReturnType()),
convert(input.block)
));
parameterSet.add(params);
}
}
return result;
}
protected TargetBlock convert(Block block) { protected TargetBlock convert(Block block) {
return new TargetBlock(block.statements.stream().map(this::convert).collect(Collectors.toList())); return new TargetBlock(block.statements.stream().map(this::convert).toList());
} }
protected TargetExpression convert(Expression expr) { protected TargetExpression convert(Expression expr) {
@ -74,8 +129,10 @@ public class ASTToTargetAST {
return input.acceptTV(new TypeVisitor<>() { return input.acceptTV(new TypeVisitor<>() {
@Override @Override
public TargetType visit(RefType refType) { public TargetType visit(RefType refType) {
return new TargetRefType(refType.getName().toString(), var name = refType.getName().toString();
refType.getParaList().stream().map(ASTToTargetAST.this::convert).collect(Collectors.toList())); if (name.equals("void")) return null;
return new TargetRefType(name,
refType.getParaList().stream().map(ASTToTargetAST.this::convert).toList());
} }
@Override @Override

View File

@ -7,7 +7,9 @@ import de.dhbwstuttgart.syntaxtree.statement.*;
import de.dhbwstuttgart.target.tree.MethodParameter; import de.dhbwstuttgart.target.tree.MethodParameter;
import de.dhbwstuttgart.target.tree.expression.*; import de.dhbwstuttgart.target.tree.expression.*;
import de.dhbwstuttgart.target.tree.type.TargetFunNType; import de.dhbwstuttgart.target.tree.type.TargetFunNType;
import de.dhbwstuttgart.target.tree.type.TargetRefType;
import java.util.List;
import java.util.stream.StreamSupport; import java.util.stream.StreamSupport;
public class StatementToTargetExpression implements StatementVisitor { public class StatementToTargetExpression implements StatementVisitor {
@ -128,7 +130,7 @@ public class StatementToTargetExpression implements StatementVisitor {
var receiver = methodCall.receiver; var receiver = methodCall.receiver;
result = new TargetMethodCall( result = new TargetMethodCall(
converter.convert(methodCall.getType()), converter.convert(methodCall.getType()),
methodCall.argTypes.stream().map(converter::convert).toList(), methodCall.argTypes == null ? List.of() : methodCall.argTypes.stream().map(converter::convert).toList(),
converter.convert(receiver), converter.convert(receiver),
methodCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), methodCall.getArgumentList().getArguments().stream().map(converter::convert).toList(),
converter.convert(receiver.getType()), converter.convert(receiver.getType()),
@ -177,7 +179,7 @@ public class StatementToTargetExpression implements StatementVisitor {
@Override @Override
public void visit(WhileStmt whileStmt) { public void visit(WhileStmt whileStmt) {
result = new TargetWhile(converter.convert(whileStmt.expr), converter.convert(whileStmt.loopBlock));
} }
@Override @Override
@ -198,13 +200,19 @@ public class StatementToTargetExpression implements StatementVisitor {
@Override @Override
public void visit(SuperCall superCall) { public void visit(SuperCall superCall) {
this.visit((MethodCall) superCall); result = new TargetMethodCall(
converter.convert(superCall.getType()),
superCall.argTypes == null ? List.of() : superCall.argTypes.stream().map(converter::convert).toList(),
new TargetSuper(null),
superCall.getArgumentList().getArguments().stream().map(converter::convert).toList(),
null,
superCall.name, false, false
);
} }
@Override @Override
public void visit(ExpressionReceiver expressionReceiver) { public void visit(ExpressionReceiver expressionReceiver) {
// TODO What is this? result = converter.convert(expressionReceiver.expr);
throw new NotImplementedException();
} }
@Override @Override

View File

@ -1,5 +0,0 @@
package targetast;
public class ASTToTargetTest {
}

View File

@ -1,5 +1,6 @@
package targetast; package targetast;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.*;
@ -7,14 +8,14 @@ import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.target.generate.ASTToTargetAST; import de.dhbwstuttgart.target.generate.ASTToTargetAST;
import de.dhbwstuttgart.target.tree.TargetClass; import de.dhbwstuttgart.target.tree.TargetClass;
import de.dhbwstuttgart.typeinference.result.ResultSet; import de.dhbwstuttgart.typeinference.result.ResultSet;
import org.antlr.v4.runtime.Token;
import org.junit.Test; import org.junit.Test;
import java.lang.reflect.Modifier; import java.nio.file.Path;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Optional;
import static org.junit.Assert.*;
public class ASTToTypedTargetAST { public class ASTToTypedTargetAST {
@ -23,10 +24,30 @@ public class ASTToTypedTargetAST {
ClassOrInterface emptyClass = new ClassOrInterface(0, new JavaClassName("EmptyClass"), new ArrayList<>(), java.util.Optional.empty(), new ArrayList<>(), new ArrayList<>(), new GenericDeclarationList(new ArrayList<>(), new NullToken()), ClassOrInterface emptyClass = new ClassOrInterface(0, new JavaClassName("EmptyClass"), new ArrayList<>(), java.util.Optional.empty(), new ArrayList<>(), new ArrayList<>(), new GenericDeclarationList(new ArrayList<>(), new NullToken()),
new RefType(new JavaClassName("Object"), new NullToken()), false, new ArrayList<>(), new NullToken()); new RefType(new JavaClassName("Object"), new NullToken()), false, new ArrayList<>(), new NullToken());
ResultSet emptyResultSet = new ResultSet(new HashSet<>()); ResultSet emptyResultSet = new ResultSet(new HashSet<>());
TargetClass emptyTargetClass = new ASTToTargetAST(emptyResultSet).convert(emptyClass); TargetClass emptyTargetClass = new ASTToTargetAST(List.of(emptyResultSet)).convert(emptyClass);
assert emptyTargetClass.getName().equals("EmptyClass"); assert emptyTargetClass.getName().equals("EmptyClass");
assert emptyTargetClass.methods().size() == 0; assert emptyTargetClass.methods().size() == 0;
assert emptyTargetClass.fields().size() == 0; assert emptyTargetClass.fields().size() == 0;
} }
@Test
public void overloading() throws Exception {
var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/bytecode/javFiles/Overloading.jav").toFile();
var compiler = new JavaTXCompiler(file);
var resultSet = compiler.typeInference();
var converter = new ASTToTargetAST(resultSet);
var classes = compiler.sourceFiles.get(file).getClasses();
Class overloading = TestCodegen.generateClass(converter.convert(classes.get(0)));
Class overloading2 = TestCodegen.generateClass(converter.convert(classes.get(1)));
var test1 = overloading.getDeclaredMethod("test", overloading);
test1.setAccessible(true);
var test2 = overloading.getDeclaredMethod("test", overloading2);
test2.setAccessible(true);
Object overloadingInstance = overloading.getDeclaredConstructor().newInstance();
Object overloading2Instance = overloading2.getDeclaredConstructor().newInstance();
assertEquals(test1.invoke(overloadingInstance, overloadingInstance), "Overloading");
assertEquals(test2.invoke(overloadingInstance, overloading2Instance), "Overloading2");
}
} }

View File

@ -21,7 +21,7 @@ public class TestCodegen {
private static ByteArrayClassLoader loader = new ByteArrayClassLoader(); private static ByteArrayClassLoader loader = new ByteArrayClassLoader();
private static Class generateClass(TargetClass clazz) throws IOException { public static Class generateClass(TargetClass clazz) throws IOException {
var codegen = new Codegen(clazz); var codegen = new Codegen(clazz);
var bytes = codegen.generate(); var bytes = codegen.generate();
var path = Path.of(System.getProperty("user.dir"), "src/test/resources/target/"); var path = Path.of(System.getProperty("user.dir"), "src/test/resources/target/");