After merge fixes Codegen.java
This commit is contained in:
parent
124313cb16
commit
1fb431ab36
@ -691,16 +691,7 @@ public class Codegen {
|
|||||||
var parameters = new ArrayList<>(lambda.captures());
|
var parameters = new ArrayList<>(lambda.captures());
|
||||||
parameters.addAll(lambda.params().stream().map(param -> param.type() instanceof TargetGenericType ? new MethodParameter(TargetType.Object, param.name()) : param).toList());
|
parameters.addAll(lambda.params().stream().map(param -> param.type() instanceof TargetGenericType ? new MethodParameter(TargetType.Object, param.name()) : param).toList());
|
||||||
|
|
||||||
impl = new TargetMethod(
|
impl = new TargetMethod(0, name, lambda.block(), new TargetMethod.Signature(Set.of(), parameters, lambda.returnType() instanceof TargetGenericType ? TargetType.Object : lambda.returnType()), null);
|
||||||
0, name,
|
|
||||||
lambda.block(),
|
|
||||||
new TargetMethod.Signature(
|
|
||||||
Set.of(),
|
|
||||||
parameters,
|
|
||||||
lambda.returnType() instanceof TargetGenericType ? TargetType.Object : lambda.returnType()
|
|
||||||
),
|
|
||||||
null
|
|
||||||
);
|
|
||||||
generateMethod(impl);
|
generateMethod(impl);
|
||||||
lambdas.put(lambda, impl);
|
lambdas.put(lambda, impl);
|
||||||
}
|
}
|
||||||
@ -729,10 +720,7 @@ public class Codegen {
|
|||||||
for (var capture : lambda.captures())
|
for (var capture : lambda.captures())
|
||||||
mv.visitVarInsn(ALOAD, state.scope.get(capture.name()).index);
|
mv.visitVarInsn(ALOAD, state.scope.get(capture.name()).index);
|
||||||
|
|
||||||
mv.visitInvokeDynamicInsn("apply", descriptor,
|
mv.visitInvokeDynamicInsn("apply", descriptor, bootstrap, Type.getType(desugared), handle, Type.getType(TargetMethod.getDescriptor(impl.signature().returnType(), lambda.params().stream().map(MethodParameter::type).toArray(TargetType[]::new))));
|
||||||
bootstrap, Type.getType(desugared), handle,
|
|
||||||
Type.getType(TargetMethod.getDescriptor(impl.signature().returnType(), lambda.params().stream().map(MethodParameter::type).toArray(TargetType[]::new)))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generate(State state, TargetExpression expr) {
|
private void generate(State state, TargetExpression expr) {
|
||||||
@ -793,42 +781,7 @@ public class Codegen {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TargetBinaryOp op:
|
|
||||||
generateBinaryOp(state, op);
|
|
||||||
break;
|
|
||||||
case TargetUnaryOp op:
|
|
||||||
generateUnaryOp(state, op);
|
|
||||||
break;
|
|
||||||
case TargetAssign assign: {
|
|
||||||
switch (assign.left()) {
|
|
||||||
case TargetLocalVar localVar: {
|
|
||||||
generate(state, assign.right());
|
|
||||||
convertTo(state, assign.right().type(), localVar.type());
|
|
||||||
boxPrimitive(state, localVar.type());
|
|
||||||
var local = state.scope.get(localVar.name());
|
|
||||||
mv.visitInsn(DUP);
|
|
||||||
mv.visitVarInsn(ASTORE, local.index());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TargetFieldVar dot: {
|
|
||||||
var fieldType = dot.type();
|
|
||||||
generate(state, dot.left());
|
|
||||||
generate(state, assign.right());
|
|
||||||
convertTo(state, assign.right().type(), fieldType);
|
|
||||||
boxPrimitive(state, fieldType);
|
|
||||||
if (dot.isStatic())
|
|
||||||
mv.visitInsn(DUP);
|
|
||||||
else mv.visitInsn(DUP_X1);
|
|
||||||
mv.visitFieldInsn(dot.isStatic() ? PUTSTATIC : PUTFIELD, dot.owner().getInternalName(), dot.right(), fieldType.toSignature());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
throw new CodeGenException("Invalid assignment");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case TargetBinaryOp op:
|
case TargetBinaryOp op:
|
||||||
generateBinaryOp(state, op);
|
generateBinaryOp(state, op);
|
||||||
break;
|
break;
|
||||||
@ -839,7 +792,8 @@ public class Codegen {
|
|||||||
switch (assign.left()) {
|
switch (assign.left()) {
|
||||||
case TargetLocalVar localVar: {
|
case TargetLocalVar localVar: {
|
||||||
generate(state, assign.right());
|
generate(state, assign.right());
|
||||||
boxPrimitive(state, assign.right().type());
|
convertTo(state, assign.right().type(), localVar.type());
|
||||||
|
boxPrimitive(state, localVar.type());
|
||||||
var local = state.scope.get(localVar.name());
|
var local = state.scope.get(localVar.name());
|
||||||
mv.visitInsn(DUP);
|
mv.visitInsn(DUP);
|
||||||
mv.visitVarInsn(ASTORE, local.index());
|
mv.visitVarInsn(ASTORE, local.index());
|
||||||
@ -1024,7 +978,7 @@ public class Codegen {
|
|||||||
|
|
||||||
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);
|
||||||
for (var param: method.signature().parameters())
|
for (var param : method.signature().parameters())
|
||||||
state.createVariable(param.name(), param.type());
|
state.createVariable(param.name(), param.type());
|
||||||
generate(state, method.block());
|
generate(state, method.block());
|
||||||
if (method.signature().returnType() == null)
|
if (method.signature().returnType() == null)
|
||||||
@ -1048,10 +1002,7 @@ public class Codegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public byte[] generate() {
|
public byte[] generate() {
|
||||||
cw.visit(V1_8, clazz.modifiers() | ACC_PUBLIC | ACC_SUPER, clazz.qualifiedName(),
|
cw.visit(V1_8, clazz.modifiers() | ACC_PUBLIC | ACC_SUPER, clazz.qualifiedName(), generateSignature(clazz, clazz.generics()), clazz.superType() != null ? clazz.superType().getInternalName() : "java/lang/Object", clazz.implementingInterfaces().stream().map(TargetType::toSignature).toArray(String[]::new));
|
||||||
generateSignature(clazz, clazz.generics()), clazz.superType() != null ? clazz.superType().getInternalName(): "java/lang/Object",
|
|
||||||
clazz.implementingInterfaces().stream().map(TargetType::toSignature).toArray(String[]::new)
|
|
||||||
);
|
|
||||||
if (clazz.txGenerics() != null)
|
if (clazz.txGenerics() != null)
|
||||||
cw.visitAttribute(new JavaTXSignatureAttribute(generateSignature(clazz, clazz.txGenerics())));
|
cw.visitAttribute(new JavaTXSignatureAttribute(generateSignature(clazz, clazz.txGenerics())));
|
||||||
|
|
||||||
|
@ -382,7 +382,7 @@ public class JavaTXCompiler {
|
|||||||
SourceFile sf = source.getValue();
|
SourceFile sf = source.getValue();
|
||||||
allClasses.addAll(getAvailableClasses(sf));
|
allClasses.addAll(getAvailableClasses(sf));
|
||||||
allClasses.addAll(sf.getClasses());
|
allClasses.addAll(sf.getClasses());
|
||||||
var newClasses = CompilationEnvironment.loadDefaultPackageClasses(f, classLoader).stream().map(ASTFactory::createClass).collect(Collectors.toList());
|
var newClasses = CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), source.getKey(), classLoader).stream().map(ASTFactory::createClass).collect(Collectors.toList());
|
||||||
for (var clazz : newClasses) {
|
for (var clazz : newClasses) {
|
||||||
var found = false;
|
var found = false;
|
||||||
for (var old : allClasses) {
|
for (var old : allClasses) {
|
||||||
|
@ -36,29 +36,32 @@ public class TestCodegen {
|
|||||||
Files.write(outputPath.resolve(name + ".class"), code);
|
Files.write(outputPath.resolve(name + ".class"), code);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<String, ? extends Class<?>> generateClassFiles(IByteArrayClassLoader classLoader, String... files) throws IOException, ClassNotFoundException {
|
public static Map<String, ? extends Class<?>> generateClassFiles(IByteArrayClassLoader classLoader, String... files) throws IOException, ClassNotFoundException {
|
||||||
var path = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/");
|
var path = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/");
|
||||||
var filenames = Arrays.stream(files).map(filename -> Path.of(path.toString(), filename).toFile()).toList();
|
var filenames = Arrays.stream(files).map(filename -> Path.of(path.toString(), filename).toFile()).toList();
|
||||||
var compiler = new JavaTXCompiler(filenames, List.of(path.toFile(), outputPath.toFile()));
|
var compiler = new JavaTXCompiler(filenames, List.of(path.toFile(), outputPath.toFile()));
|
||||||
var resultSet = compiler.typeInference();
|
var resultSet = compiler.typeInference();
|
||||||
|
|
||||||
var result = new HashMap<String, Class<?>>();
|
var result = new HashMap<String, Class<?>>();
|
||||||
for (var file : filenames) {
|
for (var file : filenames) {
|
||||||
var sourceFile = compiler.sourceFiles.get(file);
|
var sourceFile = compiler.sourceFiles.get(file);
|
||||||
var converter = new ASTToTargetAST(resultSet, sourceFile, classLoader);
|
var converter = new ASTToTargetAST(resultSet, sourceFile, classLoader);
|
||||||
var classes = compiler.sourceFiles.get(file).getClasses();
|
var classes = compiler.sourceFiles.get(file).getClasses();
|
||||||
|
|
||||||
result.putAll(classes.stream().map(cli -> {
|
result.putAll(classes.stream().map(cli -> {
|
||||||
try {
|
try {
|
||||||
return generateClass(converter.convert(cli), classLoader);
|
return generateClass(converter.convert(cli), classLoader);
|
||||||
} catch (IOException exception) {
|
} catch (IOException exception) {
|
||||||
throw new RuntimeException(exception);
|
throw new RuntimeException(exception);
|
||||||
|
}
|
||||||
|
}).collect(Collectors.toMap(Class::getName, Function.identity())));
|
||||||
|
|
||||||
|
for (var entry : converter.auxiliaries.entrySet()) {
|
||||||
|
writeClassFile(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}).collect(Collectors.toMap(Class::getName, Function.identity())));
|
|
||||||
|
|
||||||
for (var entry : converter.auxiliaries.entrySet()) {
|
return result;
|
||||||
writeClassFile(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Class<?> generateClass(TargetClass clazz, IByteArrayClassLoader classLoader) throws IOException {
|
public static Class<?> generateClass(TargetClass clazz, IByteArrayClassLoader classLoader) throws IOException {
|
||||||
@ -200,25 +203,6 @@ public class TestCodegen {
|
|||||||
// var fun = classLoader.loadClass(Path.of(System.getProperty("user.dir"), "src/test/java/targetast/Fun1$$.class"));
|
// var fun = classLoader.loadClass(Path.of(System.getProperty("user.dir"), "src/test/java/targetast/Fun1$$.class"));
|
||||||
var interfaceType = TargetFunNType.fromParams(List.of(TargetType.Integer));
|
var interfaceType = TargetFunNType.fromParams(List.of(TargetType.Integer));
|
||||||
|
|
||||||
var mainTarget = new TargetClass(Opcodes.ACC_PUBLIC, "New");
|
|
||||||
mainTarget.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "makePoint", List.of(new MethodParameter(TargetType.Integer, "x"), new MethodParameter(TargetType.Integer, "y")), pointType, new TargetBlock(List.of(new TargetReturn(new TargetNew(pointType, List.of(new TargetLocalVar(TargetType.Integer, "x"), new TargetLocalVar(TargetType.Integer, "y")))))));
|
|
||||||
|
|
||||||
var classLoader = new ByteArrayClassLoader();
|
|
||||||
var pointClass = generateClass(pointTarget, classLoader);
|
|
||||||
var mainClass = generateClass(mainTarget, classLoader);
|
|
||||||
|
|
||||||
var point = mainClass.getDeclaredMethod("makePoint", Integer.class, Integer.class).invoke(null, 10, 20);
|
|
||||||
assertEquals(point.getClass().getDeclaredField("x").get(point), 10);
|
|
||||||
assertEquals(point.getClass().getDeclaredField("y").get(point), 20);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Ignore("The lambda class is not generated because we don't call ASTToTargetAST")
|
|
||||||
public void testLambda() throws Exception {
|
|
||||||
var classLoader = new ByteArrayClassLoader();
|
|
||||||
// var fun = classLoader.loadClass(Path.of(System.getProperty("user.dir"), "src/test/java/targetast/Fun1$$.class"));
|
|
||||||
var interfaceType = new TargetFunNType(1, List.of(TargetType.Integer));
|
|
||||||
|
|
||||||
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "CGLambda");
|
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "CGLambda");
|
||||||
targetClass.addConstructor(Opcodes.ACC_PUBLIC, List.of(), new TargetBlock(List.of(new TargetMethodCall(null, new TargetSuper(TargetType.Object), List.of(), TargetType.Object, "<init>", false, false))));
|
targetClass.addConstructor(Opcodes.ACC_PUBLIC, List.of(), new TargetBlock(List.of(new TargetMethodCall(null, new TargetSuper(TargetType.Object), List.of(), TargetType.Object, "<init>", false, false))));
|
||||||
targetClass.addMethod(Opcodes.ACC_PUBLIC, "lambda", List.of(), TargetType.Integer, new TargetBlock(List.of(new TargetVarDecl(interfaceType, "by2", new TargetLambdaExpression(interfaceType, List.of(), List.of(new MethodParameter(TargetType.Integer, "num")), TargetType.Integer, new TargetBlock(List.of(new TargetReturn(new TargetBinaryOp.Mul(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "num"), new TargetLiteral.IntLiteral(2))))))), new TargetReturn(new TargetCast(TargetType.Integer, new TargetMethodCall(TargetType.Object, TargetType.Object, List.of(TargetType.Object), new TargetLocalVar(interfaceType, "by2"), List.of(new TargetLiteral.IntLiteral(10)), interfaceType, "apply", false, true))))));
|
targetClass.addMethod(Opcodes.ACC_PUBLIC, "lambda", List.of(), TargetType.Integer, new TargetBlock(List.of(new TargetVarDecl(interfaceType, "by2", new TargetLambdaExpression(interfaceType, List.of(), List.of(new MethodParameter(TargetType.Integer, "num")), TargetType.Integer, new TargetBlock(List.of(new TargetReturn(new TargetBinaryOp.Mul(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "num"), new TargetLiteral.IntLiteral(2))))))), new TargetReturn(new TargetCast(TargetType.Integer, new TargetMethodCall(TargetType.Object, TargetType.Object, List.of(TargetType.Object), new TargetLocalVar(interfaceType, "by2"), List.of(new TargetLiteral.IntLiteral(10)), interfaceType, "apply", false, true))))));
|
||||||
|
Loading…
Reference in New Issue
Block a user