Updated the codeGen Methods in FieldDecl, MethodDecl and BlockStatement
This commit is contained in:
parent
cc05c58159
commit
b5b6f763e0
@ -6,6 +6,8 @@ import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Node;
|
||||
import abstractSyntaxTree.Program;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.FieldVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@ -39,6 +41,22 @@ public class FieldDecl extends AbstractType implements IClass, Node {
|
||||
|
||||
@Override
|
||||
public void codeGen(ClassWriter cw) {
|
||||
//TODO: Do we have fields with initial values?
|
||||
FieldVisitor fv = cw.visitField(Opcodes.ACC_PUBLIC, identifier, getFieldDescriptor(), null, null);
|
||||
fv.visitEnd();
|
||||
}
|
||||
|
||||
private String getFieldDescriptor() {
|
||||
//TODO: Maybe we have to check for arrays?
|
||||
switch (type) {
|
||||
case "int":
|
||||
return "I";
|
||||
case "boolean":
|
||||
return "Z";
|
||||
case "char":
|
||||
return "C";
|
||||
default:
|
||||
return "L" + type + ";";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,25 +2,30 @@ package abstractSyntaxTree.Class;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Node;
|
||||
import abstractSyntaxTree.Parameter.Parameter;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Program;
|
||||
import abstractSyntaxTree.Statement.BlockStatement;
|
||||
import abstractSyntaxTree.Statement.IStatement;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
|
||||
public class MethodDecl implements IClass, Node {
|
||||
|
||||
//Class Name
|
||||
public String classThatContainsMethod;
|
||||
|
||||
//Method Name
|
||||
public String name;
|
||||
public ParameterList parameters;
|
||||
public String returnType;
|
||||
public BlockStatement codeBlock;
|
||||
|
||||
public Map<String, String> localVars;
|
||||
public HashMap<String, String> localVars;
|
||||
|
||||
public MethodDecl(String classThatContainsMethod, String returnType, String name, ParameterList parameters, BlockStatement codeBlock){
|
||||
this.classThatContainsMethod = classThatContainsMethod;
|
||||
@ -28,6 +33,7 @@ public class MethodDecl implements IClass, Node {
|
||||
this.name = name;
|
||||
this.parameters = parameters;
|
||||
this.codeBlock = codeBlock;
|
||||
this.localVars = new HashMap<>();
|
||||
}
|
||||
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||
@ -40,5 +46,92 @@ public class MethodDecl implements IClass, Node {
|
||||
@Override
|
||||
public void codeGen(ClassWriter cw) throws Exception {
|
||||
|
||||
localVars.put("this", classThatContainsMethod);
|
||||
for (Parameter param : parameters.parameterList) {
|
||||
localVars.put(param.identifier, param.type);
|
||||
}
|
||||
|
||||
// check if the method is a constructor
|
||||
if (classThatContainsMethod.equals(name) && returnType == null) {
|
||||
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", getMethodDescriptor(), null, null);
|
||||
|
||||
//Call the superclass constructor
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
||||
|
||||
mv.visitCode();
|
||||
codeBlock.codeGen(mv, localVars); //TODO: pass the local vars? --> codeGen for block not yet implemented
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
|
||||
//automatically computed max stack and max locals
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
} else if (name.equals("main")) { //TODO: Check how we distinguish the main method
|
||||
int access = Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC;
|
||||
|
||||
MethodVisitor mv = cw.visitMethod(access, name, "([Ljava/lang/String;)V", null, null);
|
||||
|
||||
mv.visitCode();
|
||||
codeBlock.codeGen(mv, localVars); //TODO: pass the local vars? --> codeGen for block not yet implemented
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
|
||||
} else {
|
||||
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, name, getMethodDescriptor(), null, null);
|
||||
|
||||
mv.visitCode();
|
||||
codeBlock.codeGen(mv, localVars); //TODO: pass the local vars? --> codeGen for block not yet implemented
|
||||
|
||||
// We have to check the return type to get the return opcode
|
||||
// For methods which return an actual value, the return opcode is created in the method body to ensure the
|
||||
// correct return value is on the stack
|
||||
if (returnType.equals("void")) mv.visitInsn(Opcodes.RETURN);
|
||||
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
}
|
||||
|
||||
private String getMethodDescriptor() {
|
||||
// get the method descriptor
|
||||
StringBuilder descriptor = new StringBuilder("(");
|
||||
|
||||
// Iterate over the parameters and add them to the descriptor
|
||||
for (Parameter param : parameters.parameterList) {
|
||||
switch (param.type) {
|
||||
case "int" -> descriptor.append("I");
|
||||
case "boolean" -> descriptor.append("Z");
|
||||
case "char" -> descriptor.append("C");
|
||||
case "void" -> descriptor.append("V");
|
||||
default ->
|
||||
// object
|
||||
//TODO: This is not finished
|
||||
descriptor.append("L").append(param.type).append(";");
|
||||
}
|
||||
}
|
||||
descriptor.append(")");
|
||||
|
||||
|
||||
// Get the return type
|
||||
// If the return type is null, it is a constructor and we need to append V
|
||||
if (returnType == null) {
|
||||
descriptor.append("V");
|
||||
} else {
|
||||
switch (returnType) {
|
||||
case "int" -> descriptor.append("I");
|
||||
case "boolean" -> descriptor.append("Z");
|
||||
case "char" -> descriptor.append("C");
|
||||
case "void" -> descriptor.append("V");
|
||||
|
||||
//TODO: This is not finished --> we need to append the fully qualified name of the object
|
||||
// Need to make sure what we get
|
||||
default ->
|
||||
// object
|
||||
descriptor.append("L").append(returnType).append(";");
|
||||
}
|
||||
}
|
||||
return descriptor.toString();
|
||||
}
|
||||
}
|
||||
|
@ -12,10 +12,10 @@ import java.util.List;
|
||||
|
||||
public class RefType extends AbstractType implements IClass, Node {
|
||||
|
||||
//Class Name
|
||||
public String name;
|
||||
public List<FieldDecl> fieldDecls;
|
||||
public List<MethodDecl> methodDecls;
|
||||
private boolean hasMain;
|
||||
|
||||
public RefType(String name,
|
||||
List<FieldDecl> fieldDecls,
|
||||
|
@ -46,9 +46,15 @@ public class BlockStatement extends AbstractType implements IStatement{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv) throws Exception {
|
||||
public void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception {
|
||||
// Create a new HashMap for the local variables of the block
|
||||
// It has every variable of the parent block
|
||||
// This Map is discarded at the end of the block
|
||||
//TODO: Do this for every block --> if, while, ...
|
||||
HashMap<String, String> blockLocalVars = new HashMap<>(localVars);
|
||||
|
||||
for (IStatement statement : statements) {
|
||||
statement.codeGen(mv); //TODO: I think we need to pass the symbol table here
|
||||
statement.codeGen(mv, blockLocalVars);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ public class EmptyStatement extends AbstractType implements IStatement{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv) throws Exception {
|
||||
public void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception {
|
||||
//An empty statement does not generate any code
|
||||
}
|
||||
}
|
||||
|
@ -14,5 +14,5 @@ public interface IStatement {
|
||||
|
||||
TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception;
|
||||
|
||||
void codeGen(MethodVisitor mv) throws Exception;
|
||||
void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception;
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ public class IfElseStatement extends AbstractType implements IStatement{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv) throws Exception {
|
||||
public void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception {
|
||||
|
||||
Label conditionFalse = new Label();
|
||||
Label statementEnd = new Label();
|
||||
|
@ -39,7 +39,7 @@ public class IfStatement extends AbstractType implements IStatement{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv) throws Exception {
|
||||
public void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception {
|
||||
|
||||
Label conditionFalse = new Label();
|
||||
|
||||
|
@ -39,7 +39,7 @@ public class ReturnStatement extends AbstractType implements IStatement{
|
||||
// This is a problem at "BinaryExpression" and here because we need to know the type to return
|
||||
// At this point in time we can either return reference types or have an error message
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv) throws Exception {
|
||||
public void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception {
|
||||
|
||||
if (expression != null) {
|
||||
expression.codeGen(mv);
|
||||
|
@ -39,7 +39,7 @@ public class WhileStatement extends AbstractType implements IStatement {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv) throws Exception {
|
||||
public void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception {
|
||||
Label conditionFalse = new Label();
|
||||
Label LoopStart = new Label();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user