forked from JavaTX/JavaCompilerCore
First implementation for overloaded functions and test case
This commit is contained in:
parent
0a1a596bb9
commit
29112e7bd7
@ -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);
|
||||||
|
@ -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 {
|
||||||
|
@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<>();
|
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) {
|
private List<MethodParameter> convert(ParameterList input) {
|
||||||
List<MethodParameter> params = input.getParameterList().getFormalparalist().stream()
|
return input.getFormalparalist().stream()
|
||||||
.map(param -> new MethodParameter(convert(param.getType()), param.getName())).collect(Collectors.toList());
|
.map(param -> new MethodParameter(convert(param.getType()), param.getName())).toList();
|
||||||
return new TargetMethod(
|
}
|
||||||
|
|
||||||
|
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,
|
input.modifier,
|
||||||
new TargetRefType(owner.getClassName().getClassName()),
|
new TargetRefType(owner.getClassName().getClassName()),
|
||||||
input.name, params,
|
input.name, params,
|
||||||
convert(input.getReturnType()),
|
convert(input.getReturnType()),
|
||||||
convert(input.block)
|
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
|
||||||
|
@ -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
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
package targetast;
|
|
||||||
|
|
||||||
public class ASTToTargetTest {
|
|
||||||
|
|
||||||
}
|
|
@ -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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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/");
|
||||||
|
Loading…
Reference in New Issue
Block a user