Second step of codeGen refactoring in which other methods were refactored to use the methods in CodeGenHelper

This commit is contained in:
Jochen Seyfried 2024-07-04 18:48:34 +02:00
parent 3e908293ee
commit 32353b9a37
5 changed files with 11 additions and 102 deletions

View File

@ -1,9 +1,6 @@
package CodeGen; package CodeGen;
import abstractSyntaxTree.Expression.SubReceiver;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List;
public class CodeGenHelper { public class CodeGenHelper {

View File

@ -1,5 +1,6 @@
package abstractSyntaxTree.Statement; package abstractSyntaxTree.Statement;
import CodeGen.CodeGenHelper;
import TypeCheck.AbstractType; import TypeCheck.AbstractType;
import TypeCheck.TypeCheckException; import TypeCheck.TypeCheckException;
import TypeCheck.TypeCheckHelper; import TypeCheck.TypeCheckHelper;
@ -59,15 +60,8 @@ public class LocalVarDecl extends AbstractType implements IStatement{
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 {
localVars.put(identifier, type); localVars.put(identifier, type);
int index = -1;
int counter = 0; int index = CodeGenHelper.GetLocalVarIndex(localVars, identifier);
for (String key : localVars.keySet()){
if (key.equals(identifier)){
index = counter+1; // +1 because the first local variable is at index 1, 0 is used for "this"
break;
}
counter++;
}
if (index == -1){ if (index == -1){
throw new Exception("Variable " + identifier + " not found"); throw new Exception("Variable " + identifier + " not found");

View File

@ -1,5 +1,6 @@
package abstractSyntaxTree.Statement; package abstractSyntaxTree.Statement;
import CodeGen.CodeGenHelper;
import TypeCheck.AbstractType; import TypeCheck.AbstractType;
import TypeCheck.TypeCheckException; import TypeCheck.TypeCheckException;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
@ -51,15 +52,8 @@ public class PrintStatement extends AbstractType implements IStatement {
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
// Load the value of the variable onto the stack // Load the value of the variable onto the stack
int index = -1; int index = CodeGenHelper.GetLocalVarIndex(localVars, variableName);
int counter = 0;
for (String key : localVars.keySet()){
if (key.equals(variableName)){
index = counter+1; // +1 because the first local variable is at index 1, 0 is used for "this"
break;
}
counter++;
}
// If not a localVar, maybe a class field of this class // If not a localVar, maybe a class field of this class
if (index == -1){ if (index == -1){
String typeOfField = typeContext.get(thisClass).get(variableName); String typeOfField = typeContext.get(thisClass).get(variableName);

View File

@ -1,5 +1,6 @@
package abstractSyntaxTree.StatementExpression; package abstractSyntaxTree.StatementExpression;
import CodeGen.CodeGenHelper;
import TypeCheck.AbstractType; import TypeCheck.AbstractType;
import TypeCheck.TypeCheckException; import TypeCheck.TypeCheckException;
import TypeCheck.TypeCheckHelper; import TypeCheck.TypeCheckHelper;
@ -84,15 +85,7 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
String varName = localVar.getIdentifier(); String varName = localVar.getIdentifier();
//Get the index of the local variable //Get the index of the local variable
int index = -1; int index = CodeGenHelper.GetLocalVarIndex(localVars, varName);
int counter = 0;
for (String key : localVars.keySet()) {
if (key.equals(varName)) {
index = counter + 1;
break;
}
counter++;
}
if (index == -1) { if (index == -1) {
String fieldType = typeContext.get(thisClass).get(varName); String fieldType = typeContext.get(thisClass).get(varName);
@ -132,15 +125,8 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
// Determine if the reference is this or another object // Determine if the reference is this or another object
if (instVar.receivers.get(0).identifier != null) { if (instVar.receivers.get(0).identifier != null) {
// Load the local variable (another object) onto the stack // Load the local variable (another object) onto the stack
int index = -1; int index = CodeGenHelper.GetLocalVarIndex(localVars, instVar.receivers.get(0).identifier);
int counter = 0;
for (String key : localVars.keySet()) {
if (key.equals(instVar.receivers.get(0).identifier)) {
index = counter + 1; // Local variables start at index 1, 0 is "this"
break;
}
counter++;
}
if (index == -1) { if (index == -1) {
throw new Exception("Variable " + instVar.receivers.get(0).identifier + " not found"); throw new Exception("Variable " + instVar.receivers.get(0).identifier + " not found");
} }
@ -152,10 +138,6 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
} }
// Call the codeGen on the right expression which will push the value of the right expression onto the stack
//right.codeGen(mv, localVars, typeContext, methodContext);
//Now that the base ref is on the stack, I need to get the next field(s) and store the value in the last field //Now that the base ref is on the stack, I need to get the next field(s) and store the value in the last field
String typeOfPrevious = ""; String typeOfPrevious = "";
@ -205,9 +187,6 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
//Now we have to implement the logic for the following fields in the chain as the above code //Now we have to implement the logic for the following fields in the chain as the above code
// only handles the first field in the chain // only handles the first field in the chain
// For the following fields I only have to call GETFIELD so I load the next reference onto the stack
// The fields must be present in "typeOfPrevious"
currentType = typeContext.get(typeOfPrevious).get(instVar.receivers.get(i).identifier); currentType = typeContext.get(typeOfPrevious).get(instVar.receivers.get(i).identifier);
String descriptor = getFieldDescriptor(currentType, typeContext, instVar.receivers.get(i).identifier, typeOfPrevious); String descriptor = getFieldDescriptor(currentType, typeContext, instVar.receivers.get(i).identifier, typeOfPrevious);
mv.visitFieldInsn(Opcodes.GETFIELD, typeOfPrevious, instVar.receivers.get(i).identifier, descriptor); mv.visitFieldInsn(Opcodes.GETFIELD, typeOfPrevious, instVar.receivers.get(i).identifier, descriptor);
@ -225,8 +204,7 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
} }
} else { } else {
//This is finished and right // When a field is accessed directly and without a "this."
// It's for when a field is accessed directly and without a "this."
//Load the value of the right expression on the stack //Load the value of the right expression on the stack
right.codeGen(mv, localVars, typeContext, methodContext); right.codeGen(mv, localVars, typeContext, methodContext);
@ -243,59 +221,6 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
} }
} }
/*
// Field is called with "this.xxx"
if (instVar.receivers.get(0).thisExpression) {
// If the chain is only 1 long we can directly store the value in the field
// If not we have to load the reference of the field on the stack
if(instVar.receivers.size() > 1) {
// If first receiver is not this check local then fields of thisClass
if (isLocal) {
currentType = localVars.get(instVar.receivers.get(i).identifier);
} else {
currentType = typeContext.get(thisClass).get(instVar.receivers.get(i).identifier);
}
currentType = typeContext.get(thisClass).get(instVar.fieldName);
String descriptor = getFieldDescriptor(currentType, typeContext, instVar.fieldName, thisClass);
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, instVar.fieldName, descriptor);
continue;
} else {
// Chain is only 1 long, so we can call PUTFIELD directly
//Load the value of the right expression on the stack
right.codeGen(mv, localVars, typeContext, methodContext);
currentType = typeContext.get(thisClass).get(instVar.fieldName);
String descriptor = getFieldDescriptor(currentType, typeContext, instVar.fieldName, thisClass);
mv.visitFieldInsn(Opcodes.PUTFIELD, thisClass, instVar.fieldName, descriptor);
continue;
}
}
// If first receiver is not this check local then fields of thisClass
if (isLocal) {
currentType = localVars.get(instVar.receivers.get(i).identifier);
} else {
currentType = typeContext.get(thisClass).get(instVar.receivers.get(i).identifier);
}
currentType = typeContext.get(typeOfPrevious).get(instVar.fieldName);
String descriptor = getFieldDescriptor(currentType, typeContext, instVar.fieldName, typeOfPrevious);
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, instVar.fieldName, descriptor);
continue;
}
currentType = typeContext.get(typeOfPrevious).get(instVar.receivers.get(i).identifier);
String descriptor = getFieldDescriptor(currentType, typeContext, instVar.receivers.get(i).identifier, typeOfPrevious);
mv.visitFieldInsn(Opcodes.GETFIELD, typeOfPrevious, instVar.receivers.get(i).identifier, descriptor);
typeOfPrevious = currentType;
} */
private String getFieldDescriptor(String type, HashMap<String, HashMap<String, String>> typeContext, String varName, String classToSearchFieldIn) { private String getFieldDescriptor(String type, HashMap<String, HashMap<String, String>> typeContext, String varName, String classToSearchFieldIn) {
StringBuilder descriptor = new StringBuilder(); StringBuilder descriptor = new StringBuilder();
switch (type) { switch (type) {

View File

@ -145,7 +145,6 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
owner = returnOfPreviousMethod; owner = returnOfPreviousMethod;
} }
String descriptor = getMethodDescriptor(methodName, localVars, methodContext, arguments, returnOfPreviousMethod, owner); String descriptor = getMethodDescriptor(methodName, localVars, methodContext, arguments, returnOfPreviousMethod, owner);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, methodName, descriptor, false); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, methodName, descriptor, false);