Merge remote-tracking branch 'origin/master'

This commit is contained in:
StefanZ3 2024-05-14 14:23:55 +02:00
commit 0a81315366
2 changed files with 37 additions and 30 deletions

View File

@ -1,16 +0,0 @@
package abstractSyntaxTree.Class;
import TypeCheck.TypeCheckResult;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.TypeReference;
import java.util.HashMap;
import java.util.List;
public interface IClass {
// visit method for code generation
void codeGen(ClassWriter cw) throws Exception;
}

View File

@ -44,6 +44,7 @@ public class MethodDecl implements Node {
} }
//Need to get the returnType of the method if it is an object
// methodContext (class, (returnType, (identifier, parameter))) // methodContext (class, (returnType, (identifier, parameter)))
public void codeGen(ClassWriter cw, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception { public void codeGen(ClassWriter cw, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
@ -54,11 +55,24 @@ public class MethodDecl implements Node {
// check if the method is a constructor // check if the method is a constructor
if (classThatContainsMethod.equals(name) && returnType == null) { if (classThatContainsMethod.equals(name) && returnType == null) {
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", getMethodDescriptor(), null, null); String descriptor = getMethodDescriptor(methodContext);
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", descriptor, null, null);
//Call the superclass constructor //Call the superclass constructor
mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
//Load the parameters onto the stack
int localVarIndex = 1;
for (Parameter param : parameters.parameterList) {
String paramType = param.type;
switch(paramType) {
case "int", "boolean", "char" -> mv.visitVarInsn(Opcodes.ILOAD, localVarIndex);
default -> mv.visitVarInsn(Opcodes.ALOAD, localVarIndex);
}
localVarIndex++;
}
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", descriptor, false);
mv.visitCode(); mv.visitCode();
codeBlock.codeGen(mv, localVars); codeBlock.codeGen(mv, localVars);
@ -66,7 +80,7 @@ public class MethodDecl implements Node {
//automatically computed max stack and max locals //automatically computed max stack and max locals
mv.visitMaxs(0, 0); mv.visitMaxs(0, 0);
mv.visitEnd();
} else if (name.equals("main")) { } else if (name.equals("main")) {
int access = Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC; int access = Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC;
@ -80,7 +94,7 @@ public class MethodDecl implements Node {
mv.visitEnd(); mv.visitEnd();
} else { } else {
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, name, getMethodDescriptor(), null, null); MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, name, getMethodDescriptor(methodContext), null, null);
mv.visitCode(); mv.visitCode();
codeBlock.codeGen(mv, localVars); codeBlock.codeGen(mv, localVars);
@ -95,7 +109,7 @@ public class MethodDecl implements Node {
} }
} }
private String getMethodDescriptor() { private String getMethodDescriptor(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) {
// get the method descriptor // get the method descriptor
StringBuilder descriptor = new StringBuilder("("); StringBuilder descriptor = new StringBuilder("(");
@ -106,17 +120,18 @@ public class MethodDecl implements Node {
case "boolean" -> descriptor.append("Z"); case "boolean" -> descriptor.append("Z");
case "char" -> descriptor.append("C"); case "char" -> descriptor.append("C");
case "void" -> descriptor.append("V"); case "void" -> descriptor.append("V");
default -> default -> {
// object // object
//TODO: This is not finished //TODO: This is not finished for objects --> classes and methods
descriptor.append("L").append(param.type).append(";"); if (returnType != null) descriptor.append("L").append(returnType).append(";");
}
} }
} }
descriptor.append(")"); descriptor.append(")");
// Get the return type // Get the return type
// If the return type is null, it is a constructor and we need to append V // If the return type is null, it is a constructor, and we need to append V
if (returnType == null) { if (returnType == null) {
descriptor.append("V"); descriptor.append("V");
} else { } else {
@ -125,12 +140,20 @@ public class MethodDecl implements Node {
case "boolean" -> descriptor.append("Z"); case "boolean" -> descriptor.append("Z");
case "char" -> descriptor.append("C"); case "char" -> descriptor.append("C");
case "void" -> descriptor.append("V"); case "void" -> descriptor.append("V");
default -> {
//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 // object
descriptor.append("L").append(returnType).append(";"); HashMap<String, HashMap<String, ParameterList>> classMethods = methodContext.get(classThatContainsMethod);
HashMap<String, ParameterList> methodDetails = classMethods.get(name);
String fullReturnType = null;
for (Map.Entry<String, ParameterList> entry : methodDetails.entrySet()) {
fullReturnType = entry.getKey();
}
// If it is a class reference replace the "." with "/" and return it
if (returnType.contains(".")) fullReturnType = fullReturnType.replaceAll("\\.", "/");
if (fullReturnType != null) descriptor.append("L").append(fullReturnType).append(";");
}
} }
} }
return descriptor.toString(); return descriptor.toString();