Merge remote-tracking branch 'origin/master'

This commit is contained in:
StefanZ3 2024-05-13 22:08:05 +02:00
commit 3783a1d61b
10 changed files with 128 additions and 11 deletions

View File

@ -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 + ";";
}
}
}

View File

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

View File

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

View File

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

View File

@ -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
}
}

View File

@ -15,5 +15,5 @@ public interface IStatement extends Node {
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;
}

View File

@ -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();

View File

@ -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();

View File

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

View File

@ -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();