Work on pattern matching in function headers
This commit is contained in:
parent
6ccf2a3df6
commit
89bbbdacd8
@ -2,16 +2,16 @@ import java.lang.Integer;
|
|||||||
import java.lang.Number;
|
import java.lang.Number;
|
||||||
import java.lang.Float;
|
import java.lang.Float;
|
||||||
|
|
||||||
record Point(Number x, Number y) {}
|
public record Point(Number x, Number y) {}
|
||||||
|
|
||||||
public class OverloadPattern {
|
public class OverloadPattern {
|
||||||
public m(Point(Integer x, Integer y)) {
|
public m(Point(x, y), Point(z, a)) {
|
||||||
return x + y;
|
return x + y + z + a;
|
||||||
}
|
}
|
||||||
|
|
||||||
public m(Point(Float x, Float y)) {
|
/*public m(Point(Float x, Float y)) {
|
||||||
return x * y;
|
return x * y;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
public m(Integer x) {
|
public m(Integer x) {
|
||||||
return x;
|
return x;
|
||||||
|
@ -9,9 +9,13 @@ public class SwitchOverload {
|
|||||||
Number f(Double d) { return d * 2; }
|
Number f(Double d) { return d * 2; }
|
||||||
Number f(Integer i) { return i * 5; }
|
Number f(Integer i) { return i * 5; }
|
||||||
|
|
||||||
public m(r) {
|
public m(r, x) {
|
||||||
|
x = x + x;
|
||||||
return switch(r) {
|
return switch(r) {
|
||||||
case R(o) -> f(o);
|
case R(o) -> {
|
||||||
|
x = x + x;
|
||||||
|
yield f(o);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,6 +13,7 @@ import de.dhbwstuttgart.target.generate.StatementToTargetExpression;
|
|||||||
import de.dhbwstuttgart.target.tree.*;
|
import de.dhbwstuttgart.target.tree.*;
|
||||||
import de.dhbwstuttgart.target.tree.expression.*;
|
import de.dhbwstuttgart.target.tree.expression.*;
|
||||||
import de.dhbwstuttgart.target.tree.type.*;
|
import de.dhbwstuttgart.target.tree.type.*;
|
||||||
|
import org.antlr.v4.codegen.Target;
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
import java.lang.invoke.*;
|
import java.lang.invoke.*;
|
||||||
@ -1521,29 +1522,26 @@ public class Codegen {
|
|||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int bindLocalVariables(State state, TargetPattern pattern, int offset, int field) {
|
private void bindLocalVariables(State state, TargetComplexPattern cp, int offset) {
|
||||||
if (pattern instanceof TargetComplexPattern cp) {
|
state.mv.visitVarInsn(ALOAD, offset);
|
||||||
state.mv.visitVarInsn(ALOAD, offset);
|
|
||||||
|
|
||||||
var clazz = findClass(new JavaClassName(cp.type().name()));
|
var clazz = findClass(new JavaClassName(cp.type().name()));
|
||||||
if (clazz == null) throw new CodeGenException("Class definition for '" + cp.type().name() + "' not found");
|
if (clazz == null) throw new CodeGenException("Class definition for '" + cp.type().name() + "' not found");
|
||||||
|
|
||||||
for (var i = 0; i < cp.subPatterns().size(); i++) {
|
for (var i = 0; i < cp.subPatterns().size(); i++) {
|
||||||
var subPattern = cp.subPatterns().get(i);
|
var subPattern = cp.subPatterns().get(i);
|
||||||
|
|
||||||
if (i < cp.subPatterns().size() - 1)
|
if (i < cp.subPatterns().size() - 1)
|
||||||
state.mv.visitInsn(DUP);
|
state.mv.visitInsn(DUP);
|
||||||
|
|
||||||
extractField(state, cp.type(), i, clazz);
|
extractField(state, cp.type(), i, clazz);
|
||||||
state.mv.visitTypeInsn(CHECKCAST, subPattern.type().getInternalName());
|
state.mv.visitTypeInsn(CHECKCAST, subPattern.type().getInternalName());
|
||||||
state.mv.visitVarInsn(ASTORE, offset);
|
offset = state.createVariable(subPattern.name(), subPattern.type()).index;
|
||||||
offset = bindLocalVariables(state, subPattern, offset, i);
|
state.mv.visitVarInsn(ASTORE, offset);
|
||||||
|
if (subPattern instanceof TargetComplexPattern cp2) {
|
||||||
|
bindLocalVariables(state, cp2, offset);
|
||||||
}
|
}
|
||||||
} else if (pattern instanceof TargetTypePattern tp) {
|
}
|
||||||
offset++;
|
|
||||||
state.createVariable(tp.name(), tp.type());
|
|
||||||
} else throw new NotImplementedException();
|
|
||||||
return offset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateMethod(TargetMethod method) {
|
private void generateMethod(TargetMethod method) {
|
||||||
@ -1562,8 +1560,14 @@ public class Codegen {
|
|||||||
if (method.block() != null) {
|
if (method.block() != null) {
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
var state = new State(method.signature().returnType(), mv, method.isStatic() ? 0 : 1);
|
var state = new State(method.signature().returnType(), mv, method.isStatic() ? 0 : 1);
|
||||||
|
var offset = 1;
|
||||||
for (var param : method.signature().parameters()) {
|
for (var param : method.signature().parameters()) {
|
||||||
bindLocalVariables(state, param.pattern(), 1, 0);
|
state.createVariable(param.pattern().name(), param.pattern().type());
|
||||||
|
}
|
||||||
|
for (var param : method.signature().parameters()) {
|
||||||
|
if (param.pattern() instanceof TargetComplexPattern cp)
|
||||||
|
bindLocalVariables(state, cp, offset);
|
||||||
|
offset++;
|
||||||
}
|
}
|
||||||
generate(state, method.block());
|
generate(state, method.block());
|
||||||
if (method.signature().returnType() == null)
|
if (method.signature().returnType() == null)
|
||||||
|
@ -17,6 +17,7 @@ import de.dhbwstuttgart.target.tree.expression.*;
|
|||||||
import de.dhbwstuttgart.target.tree.type.*;
|
import de.dhbwstuttgart.target.tree.type.*;
|
||||||
import de.dhbwstuttgart.typeinference.result.*;
|
import de.dhbwstuttgart.typeinference.result.*;
|
||||||
|
|
||||||
|
import java.sql.Array;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
@ -206,7 +207,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(input, constructor, finalFieldInitializer)).flatMap(List::stream).toList();
|
var constructors = input.getConstructors().stream().map(constructor -> this.convert(input, 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 = groupOverloads(input, input.getMethods()).stream().flatMap(List::stream).toList();
|
var methods = groupOverloads(input, input.getMethods()).stream().map(m -> generatePatternOverloads(input, m)).flatMap(List::stream).toList();
|
||||||
|
|
||||||
TargetMethod staticConstructor = null;
|
TargetMethod staticConstructor = null;
|
||||||
if (input.getStaticInitializer().isPresent())
|
if (input.getStaticInitializer().isPresent())
|
||||||
@ -271,69 +272,42 @@ public class ASTToTargetAST {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String encodeName(String name, ParameterList params) {
|
private String encodeName(String name, TargetMethod.Signature params) {
|
||||||
var res = new StringBuilder();
|
var res = new StringBuilder();
|
||||||
res.append(name);
|
res.append(name);
|
||||||
res.append('$');
|
res.append('$');
|
||||||
for (var param : params.getFormalparalist()) {
|
for (var param : params.parameters()) {
|
||||||
if (param instanceof RecordPattern rp) {
|
encodeName(param.pattern(), res);
|
||||||
res.append(FunNGenerator.encodeType(convert(param.getType())));
|
|
||||||
for (var pattern : rp.getSubPattern()) {
|
|
||||||
res.append(FunNGenerator.encodeType(convert(pattern.getType())));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return res.toString();
|
return res.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<TargetMethod> convert(ClassOrInterface clazz, List<Method> overloadedMethods) {
|
private void encodeName(TargetPattern pattern, StringBuilder res) {
|
||||||
if (overloadedMethods.size() == 1) {
|
if (pattern instanceof TargetComplexPattern cp) {
|
||||||
return convert(clazz, overloadedMethods.getFirst()).stream().map(m -> m.method()).toList();
|
res.append(FunNGenerator.encodeType(cp.type()));
|
||||||
}
|
for (var pat : cp.subPatterns()) {
|
||||||
var methods = new ArrayList<Method>();
|
encodeName(pat, res);
|
||||||
for (var method : overloadedMethods) {
|
|
||||||
var newMethod = new Method(
|
|
||||||
method.modifier,
|
|
||||||
method.name,
|
|
||||||
//encodeName(method.name, method.getParameterList()),
|
|
||||||
method.getReturnType(),
|
|
||||||
method.getParameterList(),
|
|
||||||
method.block,
|
|
||||||
method.getGenerics(),
|
|
||||||
method.getOffset()
|
|
||||||
);
|
|
||||||
methods.add(newMethod);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO Record overloading
|
|
||||||
/*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*/
|
|
||||||
var res = new ArrayList<TargetMethod>();
|
|
||||||
for (var method : methods) {
|
|
||||||
var overloads = convert(clazz, method);
|
|
||||||
for (var m : overloads) {
|
|
||||||
var overload = m.method;
|
|
||||||
if (res.contains(overload)) throw new CodeGenException("Duplicate method found: " + overload.name() + " with signature " + overload.signature().getSignature());
|
|
||||||
res.add(overload);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
res.append(FunNGenerator.encodeType(pattern.type()));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<TargetMethod> generatePatternOverloads(ClassOrInterface clazz, List<TargetMethod> overloadedMethods) {
|
||||||
|
if (overloadedMethods.size() <= 1) return overloadedMethods;
|
||||||
|
// Check if we have a pattern as a parameter
|
||||||
|
var firstMethod = overloadedMethods.getFirst();
|
||||||
|
if (firstMethod.signature().parameters().stream().noneMatch(mp -> mp.pattern() instanceof TargetComplexPattern)) return overloadedMethods;
|
||||||
|
// Rename existing methods
|
||||||
|
|
||||||
|
var res = new ArrayList<TargetMethod>();
|
||||||
|
for (var method : overloadedMethods) {
|
||||||
|
var name = encodeName(method.name(), method.signature());
|
||||||
|
res.add(new TargetMethod(method.access(), name, method.block(), method.signature(), method.txSignature()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate dispatch method
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user