Add visitor for class code generation

This commit is contained in:
i22007 2024-05-14 10:58:04 +02:00
parent 79a140b683
commit d27ec0643a
13 changed files with 121 additions and 37 deletions

View File

@ -5,10 +5,10 @@ import ast.member.MemberNode;
import ast.type.AccessTypeNode;
import ast.type.EnumAccessTypeNode;
import bytecode.visitor.ClassVisitor;
import bytecode.visitor.Visitable;
import java.util.ArrayList;
import java.util.List;
import bytecode.visitor.ClassVisitor;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import typechecker.Visitable;
@ -42,4 +42,9 @@ public class ClassNode extends ASTNode implements Visitable {
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.typeCheck(this);
}
@Override
public void accept(ClassVisitor classVisitor) {
classVisitor.visit(this);
}
}

View File

@ -1,14 +1,14 @@
package ast;
import bytecode.visitor.ProgramVisitor;
import bytecode.visitor.Visitable;
import java.util.ArrayList;
import java.util.List;
import bytecode.visitor.ProgramVisitor;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import typechecker.Visitable;
public class ProgramNode extends ASTNode implements Visitable{
public class ProgramNode extends ASTNode implements Visitable {
public List<ClassNode> classes = new ArrayList<>();
public void addClass(ClassNode classNode) {
@ -19,4 +19,9 @@ public class ProgramNode extends ASTNode implements Visitable{
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.typeCheck(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 extends MemberNode implements Visitable {
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.typeCheck(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 extends MemberNode implements Visitable {
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.typeCheck(this);
}
@Override
public void accept(MethodVisitor methodVisitor) {
methodVisitor.visit(this);
}
}

View File

@ -1,12 +1,10 @@
package bytecode;
import ast.ClassNode;
import ast.ProgramNode;
import ast.member.FieldNode;
import ast.member.MemberNode;
import ast.member.MethodNode;
import bytecode.visitor.ClassVisitor;
import bytecode.visitor.ProgramVisitor;
import java.io.File;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
@ -15,21 +13,21 @@ import java.io.FileOutputStream;
import java.io.IOException;
public class ClassCodeGen implements ClassVisitor {
Mapper mapper = new Mapper();
ClassWriter classWriter;
@Override
public void visit(ClassNode classNode) {
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
Mapper mapper = new Mapper();
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);
}
}
@ -39,6 +37,12 @@ public class ClassCodeGen implements ClassVisitor {
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

@ -1,7 +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

@ -1,11 +0,0 @@
package bytecode.visitor;
public interface Visitable {
default void accept(ProgramVisitor programVisitor) {
}
default void accept(ClassVisitor classVisitor) {
}
}

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);
}