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

This commit is contained in:
Daniel Holle 2023-10-17 12:27:52 +02:00
commit f10e7e6d72
8 changed files with 14368 additions and 23 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
import java.lang.Integer; import java.lang.Integer;
import java.lang.Float;
import java.lang.Number; import java.lang.Number;
import java.lang.Float;
record Point(Number x, Number y) {} record Point(Number x, Number y) {}
@ -17,3 +17,34 @@ public class OverloadPattern {
return x; return x;
} }
} }
/*
public class OverloadPattern {
Integer m$Point$_$java$lang$Integer$_$java$lang$Integer$_$(Point point) {
var x = point.x();
var y = point.y();
return x + y;
}
Float m$Point$_$java$lang$Float$_$java$lang$Float$_$(Point point) {
var x = point.x();
var y = point.y();
return x * y;
}
Number m(Point 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) ->
m$Point$_$java$lang$Float$_$java$lang$Float$_$(point);
default -> throw new IllegalArgumentException();
}
}
Integer m(Integer x) {
return x;
}
}
*/

View File

@ -59,7 +59,11 @@ public class FunNGenerator {
} }
private static String applySignature(TargetType a) { return a.toSignature(); } 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) { public static byte[] generateSuperBytecode(int numberArguments) {
StringBuilder superFunNClassSignature = new StringBuilder("<"); StringBuilder superFunNClassSignature = new StringBuilder("<");
@ -130,11 +134,9 @@ public class FunNGenerator {
argumentTypes.size(), argumentTypes.size(),
argumentTypes argumentTypes
.stream() .stream()
.map(FunNGenerator::applyNameDescriptor) .map(FunNGenerator::encodeType)
.collect(Collectors.joining()), .collect(Collectors.joining()),
applyNameDescriptor(returnType)) encodeType(returnType));
.replace('/', '$')
.replace(";", "$_$");
} }
public static List<TargetType> getArguments(List<TargetType> list) { public static List<TargetType> getArguments(List<TargetType> list) {

View File

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

View File

@ -4,6 +4,7 @@ import de.dhbwstuttgart.bytecode.FunNGenerator;
import de.dhbwstuttgart.environment.ByteArrayClassLoader; import de.dhbwstuttgart.environment.ByteArrayClassLoader;
import de.dhbwstuttgart.environment.IByteArrayClassLoader; import de.dhbwstuttgart.environment.IByteArrayClassLoader;
import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.exceptions.NotImplementedException;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.Record; import de.dhbwstuttgart.syntaxtree.Record;
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; 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 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 constructors = input.getConstructors().stream().map(constructor -> this.convert(constructor, finalFieldInitializer)).flatMap(List::stream).toList();
var fields = input.getFieldDecl().stream().map(this::convert).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) if (input instanceof Record)
return new TargetRecord(input.getModifiers(), input.getClassName().toString(), javaGenerics, txGenerics, superInterfaces, constructors, fields, methods); return new TargetRecord(input.getModifiers(), input.getClassName().toString(), javaGenerics, txGenerics, superInterfaces, constructors, fields, methods);
@ -199,23 +200,151 @@ public class ASTToTargetAST {
return result; 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); generics = all.get(0);
List<TargetMethod> result = new ArrayList<>(); List<TargetMethod> result = new ArrayList<>();
Set<List<MethodParameter>> parameterSet = new HashSet<>(); Set<List<MethodParameter>> parameterSet = new HashSet<>();
for (var s : all) { for (var s : all) {
generics = s; generics = s;
var javaGenerics = this.generics.javaGenerics.generics(currentClass, input); var javaGenerics = this.generics.javaGenerics.generics(currentClass, method);
var txGenerics = this.generics.txGenerics.generics(currentClass, input); var txGenerics = this.generics.txGenerics.generics(currentClass, method);
List<MethodParameter> params = convert(input.getParameterList(), this.generics.javaGenerics); List<MethodParameter> params = convert(method.getParameterList(), this.generics.javaGenerics);
if (parameterSet.stream().noneMatch(p -> p.equals(params))) { 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 javaMethodGenerics = collectMethodGenerics(generics.javaGenerics(), javaGenerics, method);
var txMethodGenerics = collectMethodGenerics(generics.txGenerics(), txGenerics, input); 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); parameterSet.add(params);
} }
} }

View File

@ -371,6 +371,23 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
do { do {
eq0Prime = eqSubst.get(); eq0Prime = eqSubst.get();
eq0 = applyTypeUnificationRules(eq0Prime, fc); eq0 = applyTypeUnificationRules(eq0Prime, fc);
/* In commit dfd91b5f8b7fca1cb5f302eec4b0ba3330271c9b eingefuegt ANFANG */
Set<UnifyPair> occurcheck = new HashSet<>(eq0);
occurcheck.removeAll(eq0Prime);
ocurrPairs = occurcheck.stream().filter(x -> {
UnifyType lhs, rhs;
return (lhs = x.getLhsType()) instanceof PlaceholderType
&& !((rhs = x.getRhsType()) instanceof PlaceholderType)
&& rhs.getTypeParams().occurs((PlaceholderType)lhs);})
.map(x -> { x.setUndefinedPair(); return x;})
.collect(Collectors.toCollection(HashSet::new));
writeLog("ocurrPairs: " + ocurrPairs);
if (ocurrPairs.size() > 0) {
Set<Set<UnifyPair>> ret = new HashSet<>();
ret.add(ocurrPairs);
return ret;
}
/* In commit dfd91b5f8b7fca1cb5f302eec4b0ba3330271c9b eingefuegt ENDE */
eqSubst = rules.subst(eq0, oderConstraints); eqSubst = rules.subst(eq0, oderConstraints);
} while (eqSubst.isPresent()); } while (eqSubst.isPresent());

View File

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