From 1fbec0d754e62b33ec51a718562885e6469f360b Mon Sep 17 00:00:00 2001 From: i22007 Date: Mon, 13 May 2024 20:15:17 +0200 Subject: [PATCH 1/2] First try with visitors --- src/main/java/Main.java | 2 +- src/main/java/ast/ClassNode.java | 9 ++++++++- src/main/java/ast/ProgramNode.java | 9 ++++++++- src/main/java/bytecode/ByteCodeGenerator.java | 10 ++++++---- src/main/java/bytecode/ClassCodeGen.java | 11 ++++++++--- src/main/java/bytecode/visitor/ClassVisitor.java | 7 +++++++ src/main/java/bytecode/visitor/ProgramVisitor.java | 7 +++++++ src/main/java/bytecode/visitor/Visitable.java | 11 +++++++++++ 8 files changed, 56 insertions(+), 10 deletions(-) create mode 100644 src/main/java/bytecode/visitor/ClassVisitor.java create mode 100644 src/main/java/bytecode/visitor/ProgramVisitor.java create mode 100644 src/main/java/bytecode/visitor/Visitable.java diff --git a/src/main/java/Main.java b/src/main/java/Main.java index bcb48c5..fd3f22a 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -48,6 +48,6 @@ public class Main { semanticAnalyzer.analyze(ast); ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator(); - byteCodeGenerator.generateByteCode(ast); + byteCodeGenerator.visit(ast); } } \ No newline at end of file diff --git a/src/main/java/ast/ClassNode.java b/src/main/java/ast/ClassNode.java index 2f27d08..a8e5516 100644 --- a/src/main/java/ast/ClassNode.java +++ b/src/main/java/ast/ClassNode.java @@ -5,10 +5,12 @@ 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; -public class ClassNode extends ASTNode{ +public class ClassNode extends ASTNode implements Visitable { public IdentifierNode identifier; public AccessTypeNode accessType; public String name; @@ -33,4 +35,9 @@ public class ClassNode extends ASTNode{ members.add(0,constructor); } } + + @Override + public void accept(ClassVisitor classVisitor) { + classVisitor.visit(this); + } } diff --git a/src/main/java/ast/ProgramNode.java b/src/main/java/ast/ProgramNode.java index 1fcc193..85c0682 100644 --- a/src/main/java/ast/ProgramNode.java +++ b/src/main/java/ast/ProgramNode.java @@ -1,12 +1,19 @@ package ast; +import bytecode.visitor.ProgramVisitor; +import bytecode.visitor.Visitable; import java.util.ArrayList; import java.util.List; -public class ProgramNode extends ASTNode { +public class ProgramNode extends ASTNode implements Visitable { public List classes = new ArrayList<>(); public void addClass(ClassNode classNode) { classes.add(classNode); } + + @Override + public void accept(ProgramVisitor programVisitor) { + programVisitor.visit(this); + } } \ No newline at end of file diff --git a/src/main/java/bytecode/ByteCodeGenerator.java b/src/main/java/bytecode/ByteCodeGenerator.java index 0846386..5494255 100644 --- a/src/main/java/bytecode/ByteCodeGenerator.java +++ b/src/main/java/bytecode/ByteCodeGenerator.java @@ -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); } } } diff --git a/src/main/java/bytecode/ClassCodeGen.java b/src/main/java/bytecode/ClassCodeGen.java index 1e931c0..d278901 100644 --- a/src/main/java/bytecode/ClassCodeGen.java +++ b/src/main/java/bytecode/ClassCodeGen.java @@ -1,9 +1,12 @@ 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; @@ -11,12 +14,14 @@ import org.objectweb.asm.Opcodes; import java.io.FileOutputStream; import java.io.IOException; -public class ClassCodeGen { - public void generateClassCode(ClassNode classNode) { +public class ClassCodeGen implements ClassVisitor { + + @Override + public void visit(ClassNode classNode) { ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); Mapper mapper = new Mapper(); classWriter.visit(Opcodes.V1_8, mapper.mapAccesTypeToOpcode(classNode.accessType), classNode.name, null, - "java/lang/Object", null); + "java/lang/Object", null); for (MemberNode memberNode : classNode.members) { if (memberNode instanceof FieldNode) { diff --git a/src/main/java/bytecode/visitor/ClassVisitor.java b/src/main/java/bytecode/visitor/ClassVisitor.java new file mode 100644 index 0000000..85d1c15 --- /dev/null +++ b/src/main/java/bytecode/visitor/ClassVisitor.java @@ -0,0 +1,7 @@ +package bytecode.visitor; + +import ast.ClassNode; + +public interface ClassVisitor { + void visit(ClassNode classNode); +} diff --git a/src/main/java/bytecode/visitor/ProgramVisitor.java b/src/main/java/bytecode/visitor/ProgramVisitor.java new file mode 100644 index 0000000..d569ec6 --- /dev/null +++ b/src/main/java/bytecode/visitor/ProgramVisitor.java @@ -0,0 +1,7 @@ +package bytecode.visitor; + +import ast.ProgramNode; + +public interface ProgramVisitor { + void visit(ProgramNode programNode); +} diff --git a/src/main/java/bytecode/visitor/Visitable.java b/src/main/java/bytecode/visitor/Visitable.java new file mode 100644 index 0000000..af7a369 --- /dev/null +++ b/src/main/java/bytecode/visitor/Visitable.java @@ -0,0 +1,11 @@ +package bytecode.visitor; + +public interface Visitable { + + default void accept(ProgramVisitor programVisitor) { + + } + default void accept(ClassVisitor classVisitor) { + + } +} From d27ec0643ae85466a120d2fcafb3100f200e443d Mon Sep 17 00:00:00 2001 From: i22007 Date: Tue, 14 May 2024 10:58:04 +0200 Subject: [PATCH 2/2] Add visitor for class code generation --- src/main/java/ast/ClassNode.java | 9 ++++-- src/main/java/ast/ProgramNode.java | 11 +++++-- src/main/java/ast/member/ConstructorNode.java | 9 +++++- src/main/java/ast/member/FieldNode.java | 6 ++++ src/main/java/ast/member/MethodNode.java | 7 +++++ src/main/java/bytecode/ClassCodeGen.java | 20 +++++++----- src/main/java/bytecode/Mapper.java | 24 +++++++++++++++ src/main/java/bytecode/MethodCodeGen.java | 29 +++++++++++++++--- .../java/bytecode/visitor/ClassVisitor.java | 3 ++ .../java/bytecode/visitor/MethodVisitor.java | 9 ++++++ src/main/java/bytecode/visitor/Visitable.java | 11 ------- src/main/java/classFileOutput/Example.class | Bin 111 -> 132 bytes src/main/java/typechecker/Visitable.java | 20 +++++++----- 13 files changed, 121 insertions(+), 37 deletions(-) create mode 100644 src/main/java/bytecode/visitor/MethodVisitor.java delete mode 100644 src/main/java/bytecode/visitor/Visitable.java diff --git a/src/main/java/ast/ClassNode.java b/src/main/java/ast/ClassNode.java index b7cde2e..654b745 100644 --- a/src/main/java/ast/ClassNode.java +++ b/src/main/java/ast/ClassNode.java @@ -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); + } } diff --git a/src/main/java/ast/ProgramNode.java b/src/main/java/ast/ProgramNode.java index c76ce42..cdfdd34 100644 --- a/src/main/java/ast/ProgramNode.java +++ b/src/main/java/ast/ProgramNode.java @@ -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 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); + } } \ No newline at end of file diff --git a/src/main/java/ast/member/ConstructorNode.java b/src/main/java/ast/member/ConstructorNode.java index b411ff1..c729dc1 100644 --- a/src/main/java/ast/member/ConstructorNode.java +++ b/src/main/java/ast/member/ConstructorNode.java @@ -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); + } } diff --git a/src/main/java/ast/member/FieldNode.java b/src/main/java/ast/member/FieldNode.java index cfefdfc..cbb70d4 100644 --- a/src/main/java/ast/member/FieldNode.java +++ b/src/main/java/ast/member/FieldNode.java @@ -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); + } } diff --git a/src/main/java/ast/member/MethodNode.java b/src/main/java/ast/member/MethodNode.java index 122eb5e..3bc7732 100644 --- a/src/main/java/ast/member/MethodNode.java +++ b/src/main/java/ast/member/MethodNode.java @@ -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); + } } diff --git a/src/main/java/bytecode/ClassCodeGen.java b/src/main/java/bytecode/ClassCodeGen.java index dfdf2c6..59be9ee 100644 --- a/src/main/java/bytecode/ClassCodeGen.java +++ b/src/main/java/bytecode/ClassCodeGen.java @@ -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); diff --git a/src/main/java/bytecode/Mapper.java b/src/main/java/bytecode/Mapper.java index 168e1e2..7f1b219 100644 --- a/src/main/java/bytecode/Mapper.java +++ b/src/main/java/bytecode/Mapper.java @@ -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; + } } diff --git a/src/main/java/bytecode/MethodCodeGen.java b/src/main/java/bytecode/MethodCodeGen.java index 066905f..fd8a29a 100644 --- a/src/main/java/bytecode/MethodCodeGen.java +++ b/src/main/java/bytecode/MethodCodeGen.java @@ -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), "", "()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(); } } diff --git a/src/main/java/bytecode/visitor/ClassVisitor.java b/src/main/java/bytecode/visitor/ClassVisitor.java index 85d1c15..98ef25c 100644 --- a/src/main/java/bytecode/visitor/ClassVisitor.java +++ b/src/main/java/bytecode/visitor/ClassVisitor.java @@ -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); } diff --git a/src/main/java/bytecode/visitor/MethodVisitor.java b/src/main/java/bytecode/visitor/MethodVisitor.java new file mode 100644 index 0000000..70177ce --- /dev/null +++ b/src/main/java/bytecode/visitor/MethodVisitor.java @@ -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); +} diff --git a/src/main/java/bytecode/visitor/Visitable.java b/src/main/java/bytecode/visitor/Visitable.java deleted file mode 100644 index af7a369..0000000 --- a/src/main/java/bytecode/visitor/Visitable.java +++ /dev/null @@ -1,11 +0,0 @@ -package bytecode.visitor; - -public interface Visitable { - - default void accept(ProgramVisitor programVisitor) { - - } - default void accept(ClassVisitor classVisitor) { - - } -} diff --git a/src/main/java/classFileOutput/Example.class b/src/main/java/classFileOutput/Example.class index c0d9270e1638a12598a097c3a813e0adcc1b821b..e2994804a9b99ea9c567e9caec4c6109835e84dc 100644 GIT binary patch delta 67 zcmd0AVdOgXZ`VEs1_l!b?ulG_YAhO>!C{OH>?NtiC1Ht0j0}vPj0{{Lo^NVNMt%w- T1G9!^)I?8tc1{K^pf&~oVSo>n delta 46 zcmZo+%;!4wZ`VEs1_l!b&WT)lg3KD4VT=syC8@