Implemented the new codeGen for MethodCallStatementExpression

This commit is contained in:
Jochen Seyfried 2024-06-27 09:27:08 +02:00
parent eac4eb1db8
commit 377e9b3193
3 changed files with 88 additions and 3 deletions

View File

@ -18,7 +18,7 @@ public class Compiler {
public static void main(String[] args) throws Exception{
Path filePath = Paths.get("src/main/java/TestInput.java");
Path filePath = Paths.get("src/main/java/Input.java");
// todo remove this debug info

View File

@ -24,7 +24,7 @@ public class UnaryExpression extends AbstractType implements IExpression{
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
TypeCheckResult result = new TypeCheckResult();
TypeCheckResult operandTypeCheckResult = operand.typeCheck();
TypeCheckResult operandTypeCheckResult = operand.typeCheck(methodContext, typeContext, localVars);
String operandType = operandTypeCheckResult.type;
switch (operator) {
@ -53,7 +53,7 @@ public class UnaryExpression extends AbstractType implements IExpression{
@Override
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
operand.codeGen(mv);
operand.codeGen(mv, localVars, typeContext, methodContext);
switch (operator) {
case "!":

View File

@ -82,9 +82,94 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
//Errors occur due to the change in parameter in the RefType class
@Override
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
String owner;
// Load the object onto the stack
if (receiver != null) {
if (receiver.thisExpression) {
mv.visitVarInsn(Opcodes.ALOAD, 0);
owner = thisClass;
} else if (receiver.instVarExpression != null) {
receiver.instVarExpression.codeGen(mv, localVars, typeContext, methodContext);
owner = receiver.instVarExpression.getTypeCheckResult().type;
} else if (receiver.newStatementExpression != null) {
receiver.newStatementExpression.codeGen(mv, localVars, typeContext, methodContext);
owner = receiver.newStatementExpression.getTypeCheckResult().type;
} else if (receiver.identifier != null) {
String type = localVars.get(receiver.identifier);
if (type == null) {
// If it is not a local variable, assume it is a field of the current class
type = typeContext.get(thisClass).get(receiver.identifier);
mv.visitVarInsn(Opcodes.ALOAD, 0); // Load "this" onto the stack
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, receiver.identifier, "L" + type + ";"); // Load the field onto the stack
} else {
// It's a local variable
int index = localVars.keySet().stream().toList().indexOf(receiver.identifier);
int opcode = type.equals("int") ? Opcodes.ILOAD : Opcodes.ALOAD;
mv.visitVarInsn(opcode, index); // Load local variable onto the stack
}
owner = type;
} else {
throw new ExecutionControl.NotImplementedException("Receiver type not supported.");
}
} else {
throw new ExecutionControl.NotImplementedException("Receiver is null.");
}
/*
else {
String type = localVars.get(receiver.identifier);
if (type == null) {
type = typeContext.get(thisClass).get(receiver.identifier);
}
mv.visitVarInsn(Opcodes.ALOAD, 1);
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, receiver.identifier, "L" + type + ";");
}
*/
// Generate the code for each argument expression
for (IExpression argument : arguments) {
argument.codeGen(mv, localVars, typeContext, methodContext);
}
// Invoke the method
String descriptor = getMethodDescriptor();
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, methodName, descriptor, false);
}
private String getMethodDescriptor() {
StringBuilder descriptor = new StringBuilder("(");
for (IExpression argument : arguments) {
TypeCheckResult result = argument.getTypeCheckResult();
String type = result.type;
switch (type) {
case "int":
descriptor.append("I");
break;
case "boolean":
descriptor.append("Z");
break;
case "char":
descriptor.append("C");
break;
case "void":
descriptor.append("V");
break;
default:
// If it is a class reference replace the "." with "/" and return it
if (type.contains(".")) type = type.replaceAll("\\.", "/");
descriptor.append("L").append(type).append(";");
break;
}
}
descriptor.append(")"); // Methods always return void
return descriptor.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;