Merge branch 'targetBytecode' of ssh://gohorb.ba-horb.de/bahome/projekt/git/JavaCompilerCore into targetBytecode

This commit is contained in:
pl@gohorb.ba-horb.de 2023-10-07 07:24:59 +02:00
commit 9764ec6db1
6 changed files with 14318 additions and 21 deletions

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,7 @@ public class OverloadPattern {
}
Number m(Point point) {
switch(point) {
return switch(point) {
case Point(Integer x, Integer y) ->
m$Point$_$java$lang$Integer$_$java$lang$Integer$_$(point);
case Point(Float x, Float y) ->

View File

@ -59,7 +59,11 @@ public class FunNGenerator {
}
private static String applySignature(TargetType a) { return a.toSignature(); }
private static String applyNameDescriptor(TargetType a){ return a instanceof TargetGenericType ? "LTPH;" : String.format("%s;", applySignature(a)); }
private static String applyNameDescriptor(TargetType a){ return a instanceof TargetGenericType ? "LTPH;" : String.format("%s", applySignature(a)); }
public static String encodeType(TargetType type) {
return applyNameDescriptor(type).replace("/", "$").replace(";", "$_$");
}
public static byte[] generateSuperBytecode(int numberArguments) {
StringBuilder superFunNClassSignature = new StringBuilder("<");
@ -127,14 +131,12 @@ public class FunNGenerator {
public static String getSpecializedClassName(List<TargetType> argumentTypes, TargetType returnType) {
return String.format("Fun%d$$%s%s",
argumentTypes.size(),
argumentTypes
.stream()
.map(FunNGenerator::applyNameDescriptor)
.collect(Collectors.joining()),
applyNameDescriptor(returnType))
.replace('/', '$')
.replace(";", "$_$");
argumentTypes.size(),
argumentTypes
.stream()
.map(FunNGenerator::encodeType)
.collect(Collectors.joining()),
encodeType(returnType));
}
public static List<TargetType> getArguments(List<TargetType> list) {

View File

@ -67,7 +67,7 @@ public class Method extends SyntaxTreeNode implements IItemWithOffset, TypeScope
return parameterlist;
}
public Iterable<? extends GenericTypeVar> getGenerics() {
public GenericDeclarationList getGenerics() {
return generics;
}

View File

@ -4,6 +4,7 @@ import de.dhbwstuttgart.bytecode.FunNGenerator;
import de.dhbwstuttgart.environment.ByteArrayClassLoader;
import de.dhbwstuttgart.environment.IByteArrayClassLoader;
import de.dhbwstuttgart.exceptions.NotImplementedException;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.Record;
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
@ -141,7 +142,7 @@ public class ASTToTargetAST {
var superInterfaces = input.getSuperInterfaces().stream().map(clazz -> convert(clazz, generics.javaGenerics)).toList();
var constructors = input.getConstructors().stream().map(constructor -> this.convert(constructor, finalFieldInitializer)).flatMap(List::stream).toList();
var fields = input.getFieldDecl().stream().map(this::convert).toList();
var methods = input.getMethods().stream().map(this::convert).flatMap(List::stream).toList();
var methods = groupOverloads(input.getMethods()).stream().map(this::convert).flatMap(List::stream).toList();
if (input instanceof Record)
return new TargetRecord(input.getModifiers(), input.getClassName().toString(), javaGenerics, txGenerics, superInterfaces, constructors, fields, methods);
@ -199,23 +200,151 @@ public class ASTToTargetAST {
return result;
}
private List<TargetMethod> convert(Method input) {
/**
* This only considers type patterns, all other methods aren't grouped together
* @param a
* @param b
* @return
*/
private boolean signatureEquals(Method a, Method b) {
if (!a.name.equals(b.name)) return false;
var para = a.getParameterList().getFormalparalist();
var parb = b.getParameterList().getFormalparalist();
if (para.size() != parb.size()) return false;
for (var i = 0; i < para.size(); i++) {
var pa = para.get(i);
var pb = parb.get(i);
if (pa instanceof RecordPattern rpa) {
if (pb instanceof RecordPattern rpb) {
if (rpa.getType().equals(rpb.getType())) continue;
}
return false;
} else if (pa.getType().equals(pb.getType())) {
continue;
}
return false;
}
return true;
}
// TODO Nested patterns
private List<List<Method>> groupOverloads(List<Method> input) {
var done = new HashSet<Method>();
var res = new ArrayList<List<Method>>();
for (var method : input) {
if (done.contains(method)) continue;
var overloads = new ArrayList<Method>();
overloads.add(method);
done.add(method);
for (var method2 : input) {
if (!done.contains(method2) && signatureEquals(method, method2)) {
done.add(method2);
overloads.add(method2);
}
}
res.add(overloads);
}
return res;
}
private String encodeName(String name, ParameterList params) {
var res = new StringBuilder();
res.append(name);
res.append('$');
for (var param : params.getFormalparalist()) {
if (param instanceof RecordPattern rp) {
res.append(FunNGenerator.encodeType(convert(param.getType())));
for (var pattern : rp.getSubPattern()) {
res.append(FunNGenerator.encodeType(convert(pattern.getType())));
}
}
}
return res.toString();
}
private List<TargetMethod> convert(List<Method> overloadedMethods) {
if (overloadedMethods.size() == 1) {
return convert(overloadedMethods.get(0));
}
var res = new ArrayList<Method>();
for (var method : overloadedMethods) {
var newMethod = new Method(
method.modifier,
encodeName(method.name, method.getParameterList()),
method.getReturnType(),
method.getParameterList(),
method.block,
method.getGenerics(),
method.getOffset()
);
res.add(newMethod);
}
var template = overloadedMethods.get(0);
var pParams = new ArrayList<Pattern>();
var i = 0;
for (var par : template.getParameterList()) {
pParams.add(switch (par) {
case RecordPattern rp -> new RecordPattern(rp.getSubPattern(), "par" + i, rp.getType(), new NullToken());
default -> par;
});
i++;
}
var params = new ParameterList(pParams, new NullToken());
var statements = new ArrayList<Statement>();
statements.add(new Return(makeRecordSwitch(template.getReturnType(), params, res), new NullToken()));
var block = new Block(statements, new NullToken());
var entryPoint = new Method(template.modifier, template.name, template.getReturnType(), params, block, template.getGenerics(), new NullToken());
res.add(entryPoint); // TODO
return res.stream().map(this::convert).flatMap(List::stream).toList();
}
private Expression makeRecordSwitch(RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList params, List<Method> overloadedMethods) {
var param = params.getFormalparalist().get(0);
assert param instanceof RecordPattern; // TODO
var cases = new ArrayList<SwitchBlock>();
for (var method : overloadedMethods) {
var statements = new ArrayList<Statement>();
/*statements.add(new MethodCall(
method.getReturnType(), new ExpressionReceiver(new This(new NullToken())), method.name,
params,
));*/
var block = new Block(statements, new NullToken());
var labels = new ArrayList<SwitchLabel>();
cases.add(new SwitchBlock(labels, block, true, new NullToken()));
}
var swtch = new Switch(new LocalVar("par0", param.getType(), new NullToken()), cases, returnType, false, new NullToken());
return swtch;
}
private List<TargetMethod> convert(Method method) {
generics = all.get(0);
List<TargetMethod> result = new ArrayList<>();
Set<List<MethodParameter>> parameterSet = new HashSet<>();
for (var s : all) {
generics = s;
var javaGenerics = this.generics.javaGenerics.generics(currentClass, input);
var txGenerics = this.generics.txGenerics.generics(currentClass, input);
List<MethodParameter> params = convert(input.getParameterList(), this.generics.javaGenerics);
var javaGenerics = this.generics.javaGenerics.generics(currentClass, method);
var txGenerics = this.generics.txGenerics.generics(currentClass, method);
List<MethodParameter> params = convert(method.getParameterList(), this.generics.javaGenerics);
if (parameterSet.stream().noneMatch(p -> p.equals(params))) {
List<MethodParameter> txParams = convert(input.getParameterList(), this.generics.txGenerics);
List<MethodParameter> txParams = convert(method.getParameterList(), this.generics.txGenerics);
var javaMethodGenerics = collectMethodGenerics(generics.javaGenerics(), javaGenerics, input);
var txMethodGenerics = collectMethodGenerics(generics.txGenerics(), txGenerics, input);
var javaMethodGenerics = collectMethodGenerics(generics.javaGenerics(), javaGenerics, method);
var txMethodGenerics = collectMethodGenerics(generics.txGenerics(), txGenerics, method);
result.add(new TargetMethod(input.modifier, input.name, convert(input.block), new TargetMethod.Signature(javaMethodGenerics, params, convert(input.getReturnType(), this.generics.javaGenerics)), new TargetMethod.Signature(txMethodGenerics, txParams, convert(input.getReturnType(), this.generics.txGenerics))));
var javaSignature = new TargetMethod.Signature(javaMethodGenerics, params, convert(method.getReturnType(), this.generics.javaGenerics));
var txSignature = new TargetMethod.Signature(txMethodGenerics, txParams, convert(method.getReturnType(), this.generics.txGenerics));
result.add(new TargetMethod(method.modifier, method.name, convert(method.block), javaSignature, txSignature));
parameterSet.add(params);
}
}

View File

@ -58,7 +58,8 @@ public class AllgemeinTest {
//String className = "Assign";
//String className = "StreamTest";
//String className = "Iteration";
String className = "Cycle";
//String className = "Cycle";
String className = "TripleTest";
//PL 2019-10-24: genutzt fuer unterschiedliche Tests
path = System.getProperty("user.dir")+"/resources/AllgemeinTest/" + className + ".jav";
//path = System.getProperty("user.dir")+"/src/test/resources/AllgemeinTest/Overloading_Generics.jav";