Implemented the new codeGen for MethodCallStatementExpression
This commit is contained in:
parent
eac4eb1db8
commit
377e9b3193
@ -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
|
||||
|
@ -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 "!":
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user