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{
|
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
|
// 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 {
|
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 result = new TypeCheckResult();
|
||||||
|
|
||||||
TypeCheckResult operandTypeCheckResult = operand.typeCheck();
|
TypeCheckResult operandTypeCheckResult = operand.typeCheck(methodContext, typeContext, localVars);
|
||||||
String operandType = operandTypeCheckResult.type;
|
String operandType = operandTypeCheckResult.type;
|
||||||
|
|
||||||
switch (operator) {
|
switch (operator) {
|
||||||
@ -53,7 +53,7 @@ public class UnaryExpression extends AbstractType implements IExpression{
|
|||||||
@Override
|
@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 {
|
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) {
|
switch (operator) {
|
||||||
case "!":
|
case "!":
|
||||||
|
@ -82,9 +82,94 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
|
|||||||
//Errors occur due to the change in parameter in the RefType class
|
//Errors occur due to the change in parameter in the RefType class
|
||||||
@Override
|
@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 {
|
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
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
|
Loading…
Reference in New Issue
Block a user