diff --git a/src/main/java/Main.java b/src/main/java/Main.java index e1673c1..9b803ca 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -37,6 +37,6 @@ public class Main { SemanticAnalyzer.generateTast(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 dacd4b4..2f09f41 100644 --- a/src/main/java/ast/ClassNode.java +++ b/src/main/java/ast/ClassNode.java @@ -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); + } } diff --git a/src/main/java/ast/ProgramNode.java b/src/main/java/ast/ProgramNode.java index 44b1ad2..116c5a2 100644 --- a/src/main/java/ast/ProgramNode.java +++ b/src/main/java/ast/ProgramNode.java @@ -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); + } } \ 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 2525171..70880c5 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 implements MemberNode, Visitable { public TypeCheckResult accept(SemanticVisitor visitor) { return visitor.analyze(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 ae6ef68..88ed182 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 implements MemberNode, Visitable { public TypeCheckResult accept(SemanticVisitor visitor) { return visitor.analyze(this); } + + @Override + public void accept(MethodVisitor methodVisitor) { + methodVisitor.visit(this); + } } 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 3b10586..59be9ee 100644 --- a/src/main/java/bytecode/ClassCodeGen.java +++ b/src/main/java/bytecode/ClassCodeGen.java @@ -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); 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 new file mode 100644 index 0000000..98ef25c --- /dev/null +++ b/src/main/java/bytecode/visitor/ClassVisitor.java @@ -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); +} 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/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/classFileOutput/Example.class b/src/main/java/classFileOutput/Example.class index c0d9270..e299480 100644 Binary files a/src/main/java/classFileOutput/Example.class and b/src/main/java/classFileOutput/Example.class differ diff --git a/src/main/java/typechecker/Visitable.java b/src/main/java/typechecker/Visitable.java index 99694b7..111c58f 100644 --- a/src/main/java/typechecker/Visitable.java +++ b/src/main/java/typechecker/Visitable.java @@ -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); }