Merge pull request 'code-generator' (#5) from code-generator into main
Reviewed-on: #5 Reviewed-by: Johannes Ehlert <i22005@hb.dhbw-stuttgart.de>
This commit is contained in:
commit
8e7b64c38d
@ -37,6 +37,6 @@ public class Main {
|
||||
SemanticAnalyzer.generateTast(ast);
|
||||
|
||||
ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator();
|
||||
byteCodeGenerator.generateByteCode(ast);
|
||||
byteCodeGenerator.visit(ast);
|
||||
}
|
||||
}
|
@ -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 extends ASTNode implements Visitable {
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.typeCheck(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(ClassVisitor classVisitor) {
|
||||
classVisitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
@ -2,11 +2,13 @@ package ast;
|
||||
|
||||
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) {
|
||||
@ -17,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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
10
src/main/java/bytecode/visitor/ClassVisitor.java
Normal file
10
src/main/java/bytecode/visitor/ClassVisitor.java
Normal 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);
|
||||
}
|
9
src/main/java/bytecode/visitor/MethodVisitor.java
Normal file
9
src/main/java/bytecode/visitor/MethodVisitor.java
Normal 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);
|
||||
}
|
7
src/main/java/bytecode/visitor/ProgramVisitor.java
Normal file
7
src/main/java/bytecode/visitor/ProgramVisitor.java
Normal file
@ -0,0 +1,7 @@
|
||||
package bytecode.visitor;
|
||||
|
||||
import ast.ProgramNode;
|
||||
|
||||
public interface ProgramVisitor {
|
||||
void visit(ProgramNode programNode);
|
||||
}
|
Binary file not shown.
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user