Compare commits

...

6 Commits

Author SHA1 Message Date
Bruder John
1441e34078 Merge branch 'main' into johns-branch 2024-05-14 11:20:44 +02:00
8e7b64c38d Merge pull request 'code-generator' (#5) from code-generator into main
Reviewed-on: #5
Reviewed-by: Johannes Ehlert <i22005@hb.dhbw-stuttgart.de>
2024-05-14 09:04:37 +00:00
d27ec0643a Add visitor for class code generation 2024-05-14 10:58:04 +02:00
79a140b683 Merge branch 'main' of https://gitea.hb.dhbw-stuttgart.de/i22005/NichtHaskell2.0 into code-generator 2024-05-14 10:01:20 +02:00
b6bbf7e1d5 Merge pull request 'johns-branch' (#4) from johns-branch into main
Reviewed-on: #4
Reviewed-by: i22035 <i22035@hb.dhbw-stuttgart.de>
2024-05-14 08:00:06 +00:00
i22007
1fbec0d754 First try with visitors 2024-05-13 20:15:17 +02:00
15 changed files with 146 additions and 26 deletions

View File

@ -37,6 +37,6 @@ public class Main {
SemanticAnalyzer.generateTast(ast);
ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator();
byteCodeGenerator.generateByteCode(ast);
byteCodeGenerator.visit(ast);
}
}

View File

@ -7,6 +7,8 @@ import ast.type.EnumAccessTypeNode;
import java.util.ArrayList;
import java.util.List;
import bytecode.visitor.ClassVisitor;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import typechecker.Visitable;
@ -40,4 +42,9 @@ public class ClassNode implements ASTNode, Visitable {
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
@Override
public void accept(ClassVisitor classVisitor) {
classVisitor.visit(this);
}
}

View File

@ -2,6 +2,8 @@ package ast;
import java.util.ArrayList;
import java.util.List;
import bytecode.visitor.ProgramVisitor;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import typechecker.Visitable;
@ -17,4 +19,9 @@ public class ProgramNode implements ASTNode, Visitable{
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
@Override
public void accept(ProgramVisitor programVisitor) {
programVisitor.visit(this);
}
}

View File

@ -1,9 +1,16 @@
package ast.member;
import ast.type.AccessTypeNode;
import bytecode.visitor.MethodVisitor;
import typechecker.Visitable;
public class ConstructorNode extends MethodNode {
public class ConstructorNode extends MethodNode implements Visitable {
public ConstructorNode(AccessTypeNode visibility, String name) {
super(visibility, name);
}
@Override
public void accept(MethodVisitor methodVisitor) {
methodVisitor.visit(this);
}
}

View File

@ -2,6 +2,7 @@ package ast.member;
import ast.type.AccessTypeNode;
import ast.type.TypeNode;
import bytecode.visitor.ClassVisitor;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import typechecker.Visitable;
@ -21,4 +22,9 @@ public class FieldNode implements MemberNode, Visitable {
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
@Override
public void accept(ClassVisitor classVisitor) {
classVisitor.visit(this);
}
}

View File

@ -7,6 +7,8 @@ import ast.type.TypeNode;
import java.util.ArrayList;
import java.util.List;
import bytecode.visitor.MethodVisitor;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import typechecker.Visitable;
@ -38,4 +40,9 @@ public class MethodNode implements MemberNode, Visitable {
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
@Override
public void accept(MethodVisitor methodVisitor) {
methodVisitor.visit(this);
}
}

View File

@ -2,13 +2,15 @@ package bytecode;
import ast.ProgramNode;
import ast.ClassNode;
import bytecode.visitor.ProgramVisitor;
public class ByteCodeGenerator {
public class ByteCodeGenerator implements ProgramVisitor {
public void generateByteCode(ProgramNode ast) {
for (ClassNode classDeclarationNode : ast.classes) {
@Override
public void visit(ProgramNode programNode) {
for (ClassNode classDeclarationNode : programNode.classes) {
ClassCodeGen classCodeGen = new ClassCodeGen();
classCodeGen.generateClassCode(classDeclarationNode);
classDeclarationNode.accept(classCodeGen);
}
}
}

View File

@ -4,6 +4,7 @@ import ast.ClassNode;
import ast.member.FieldNode;
import ast.member.MemberNode;
import ast.member.MethodNode;
import bytecode.visitor.ClassVisitor;
import java.io.File;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
@ -11,20 +12,22 @@ import org.objectweb.asm.Opcodes;
import java.io.FileOutputStream;
import java.io.IOException;
public class ClassCodeGen {
public void generateClassCode(ClassNode classNode) {
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
Mapper mapper = new Mapper();
public class ClassCodeGen implements ClassVisitor {
Mapper mapper = new Mapper();
ClassWriter classWriter;
@Override
public void visit(ClassNode classNode) {
classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
classWriter.visit(Opcodes.V1_8, mapper.mapAccesTypeToOpcode(classNode.accessType), classNode.identifier, null,
"java/lang/Object", null);
for (MemberNode memberNode : classNode.members) {
if (memberNode instanceof FieldNode) {
FieldCodeGen fieldCodeGen = new FieldCodeGen();
fieldCodeGen.generateFieldCode(classWriter, (FieldNode) memberNode);
visit((FieldNode) memberNode);
} else if (memberNode instanceof MethodNode) {
MethodCodeGen methodCodeGen = new MethodCodeGen();
methodCodeGen.generateMethodCode(classWriter, (MethodNode) memberNode);
MethodCodeGen methodCodeGen = new MethodCodeGen(classWriter);
((MethodNode) memberNode).accept(methodCodeGen);
}
}
@ -34,6 +37,12 @@ public class ClassCodeGen {
classWriter.visitEnd();
}
@Override
public void visit(FieldNode fieldNode) {
classWriter.visitField(mapper.mapAccesTypeToOpcode(fieldNode.accessTypeNode), fieldNode.identifier, mapper.getTypeChar(fieldNode.type.enumTypeNode), null, null );
classWriter.visitEnd();
}
private void printIntoClassFile(byte[] byteCode, String name) {
String directoryPath = "src/main/java/classFileOutput";
File directory = new File(directoryPath);

View File

@ -2,6 +2,8 @@ package bytecode;
import ast.type.AccessTypeNode;
import ast.type.EnumAccessTypeNode;
import ast.type.EnumTypeNode;
import ast.type.TypeNode;
import org.objectweb.asm.Opcodes;
public class Mapper {
@ -14,4 +16,26 @@ public class Mapper {
}
return 0;
}
public String generateMethodDescriptor(TypeNode typeNode) {
String descriptor = "()";
descriptor += getTypeChar(typeNode.enumTypeNode);
return descriptor;
}
public String getTypeChar(EnumTypeNode enumTypeNode) {
String typeChar = "";
switch (enumTypeNode) {
case EnumTypeNode.INT:
typeChar = "I";
break;
case EnumTypeNode.CHAR:
typeChar = "C";
break;
case EnumTypeNode.BOOLEAN:
typeChar = "Z";
break;
}
return typeChar;
}
}

View File

@ -1,17 +1,38 @@
package bytecode;
import ast.member.ConstructorNode;
import ast.member.MethodNode;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
public class MethodCodeGen {
public void generateMethodCode(ClassWriter classWriter, MethodNode methodNode) {
Mapper mapper = new Mapper();
public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
private ClassWriter classWriter;
Mapper mapper = new Mapper();
public MethodCodeGen(ClassWriter classWriter) {
this.classWriter = classWriter;
}
@Override
public void visit(ConstructorNode constructorNode) {
MethodVisitor constructor =
classWriter.visitMethod(mapper.mapAccesTypeToOpcode(methodNode.visibility),
classWriter.visitMethod(mapper.mapAccesTypeToOpcode(constructorNode.visibility),
"<init>",
"()V",
null,
null);
constructor.visitEnd();
}
@Override
public void visit(MethodNode methodNode) {
MethodVisitor method = classWriter.visitMethod(mapper.mapAccesTypeToOpcode(methodNode.visibility),
methodNode.identifier,
mapper.generateMethodDescriptor(methodNode.type),
null,
null);
method.visitEnd();
}
}

View File

@ -0,0 +1,10 @@
package bytecode.visitor;
import ast.ClassNode;
import ast.member.FieldNode;
import org.objectweb.asm.ClassWriter;
public interface ClassVisitor {
void visit(ClassNode classNode);
void visit(FieldNode fieldNode);
}

View File

@ -0,0 +1,9 @@
package bytecode.visitor;
import ast.member.ConstructorNode;
import ast.member.MethodNode;
public interface MethodVisitor {
void visit(ConstructorNode constructorNode);
void visit(MethodNode methodNode);
}

View File

@ -0,0 +1,7 @@
package bytecode.visitor;
import ast.ProgramNode;
public interface ProgramVisitor {
void visit(ProgramNode programNode);
}

View File

@ -1,16 +1,20 @@
package typechecker;
import bytecode.visitor.ClassVisitor;
import bytecode.visitor.MethodVisitor;
import bytecode.visitor.ProgramVisitor;
import semantic.SemanticVisitor;
public interface Visitable {
// default void accept(ProgramCodeVisitor visitor) {
// }
//
// default void accept(ClassCodeVisitor visitor) {
// }
//
// default void accept(MethodCodeVisitor visitor) {
// }
default void accept(ProgramVisitor programVisitor) {
}
default void accept(ClassVisitor classVisitor) {
}
default void accept(MethodVisitor methodVisitor) {
}
TypeCheckResult accept(SemanticVisitor visitor);
}