Fixed chained instVar calls in AssignStatementExpression
This commit is contained in:
parent
edfaa93980
commit
8f55a15aef
@ -6,7 +6,7 @@ import abstractSyntaxTree.StatementExpression.NewStatementExpression;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class SubReceiver implements Node {
|
public class SubReceiver implements Node {
|
||||||
boolean thisExpression;
|
public boolean thisExpression;
|
||||||
public NewStatementExpression newStatementExpression;
|
public NewStatementExpression newStatementExpression;
|
||||||
public String identifier;
|
public String identifier;
|
||||||
|
|
||||||
|
@ -123,6 +123,8 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
|||||||
} else if (left instanceof InstVarExpression) {
|
} else if (left instanceof InstVarExpression) {
|
||||||
instVar = (InstVarExpression) left;
|
instVar = (InstVarExpression) left;
|
||||||
|
|
||||||
|
boolean isLocal = false;
|
||||||
|
|
||||||
// Load the reference onto the stack
|
// Load the reference onto the stack
|
||||||
// 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) {
|
||||||
@ -140,12 +142,90 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
|||||||
throw new Exception("Variable " + instVar.receivers.get(0).identifier + " not found");
|
throw new Exception("Variable " + instVar.receivers.get(0).identifier + " not found");
|
||||||
}
|
}
|
||||||
mv.visitVarInsn(Opcodes.ALOAD, index);
|
mv.visitVarInsn(Opcodes.ALOAD, index);
|
||||||
|
isLocal = true;
|
||||||
} else {
|
} else {
|
||||||
// Load "this" onto the stack
|
// Load "this" onto the stack
|
||||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the codeGen on the right expression which will push the value of the right expression onto the stack
|
// 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
|
||||||
|
|
||||||
|
String typeOfPrevious = "";
|
||||||
|
String currentType = "";
|
||||||
|
if (instVar.receivers.size() > 0) {
|
||||||
|
for (int i = 0; i < instVar.receivers.size(); i++) {
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
|
||||||
|
//Check if the chain is longer than 1
|
||||||
|
// If it is not, then 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() < 2) {
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
if (isLocal) {
|
||||||
|
typeOfPrevious = localVars.get(instVar.receivers.get(i).identifier);
|
||||||
|
} else {
|
||||||
|
typeOfPrevious = typeContext.get(thisClass).get(instVar.receivers.get(i).identifier);
|
||||||
|
if (typeOfPrevious == null) {
|
||||||
|
typeOfPrevious = thisClass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
currentType = typeContext.get(typeOfPrevious).get(instVar.fieldName);
|
||||||
|
|
||||||
|
String descriptor = getFieldDescriptor(currentType, typeContext, instVar.fieldName, thisClass);
|
||||||
|
mv.visitFieldInsn(Opcodes.PUTFIELD, typeOfPrevious, instVar.fieldName, descriptor);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (isLocal) {
|
||||||
|
currentType = localVars.get(instVar.receivers.get(i).identifier);
|
||||||
|
} else {
|
||||||
|
currentType = typeContext.get(thisClass).get(instVar.receivers.get(i).identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
String descriptor = getFieldDescriptor(currentType, typeContext, instVar.receivers.get(i).identifier, thisClass);
|
||||||
|
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, instVar.receivers.get(i).identifier, descriptor);
|
||||||
|
typeOfPrevious = currentType;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//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
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
String descriptor = getFieldDescriptor(currentType, typeContext, instVar.receivers.get(i).identifier, typeOfPrevious);
|
||||||
|
mv.visitFieldInsn(Opcodes.GETFIELD, typeOfPrevious, instVar.receivers.get(i).identifier, descriptor);
|
||||||
|
typeOfPrevious = currentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we have the reference of the last field in the chain on the stack
|
||||||
|
if (instVar.receivers.size() > 1) {
|
||||||
|
// We can store the value of the right expression in this field
|
||||||
|
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||||
|
|
||||||
|
currentType = typeContext.get(typeOfPrevious).get(instVar.fieldName);
|
||||||
|
String descriptor = getFieldDescriptor(currentType, typeContext, instVar.fieldName, typeOfPrevious);
|
||||||
|
mv.visitFieldInsn(Opcodes.PUTFIELD, typeOfPrevious, instVar.fieldName, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//This is finished and right
|
||||||
|
// It's for when a field is accessed directly and without a "this."
|
||||||
|
|
||||||
|
//Load the value of the right expression on the stack
|
||||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||||
|
|
||||||
// Get the field information
|
// Get the field information
|
||||||
@ -158,6 +238,60 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
|||||||
mv.visitFieldInsn(Opcodes.PUTFIELD, instVar.thisClass, instVar.fieldName, descriptor);
|
mv.visitFieldInsn(Opcodes.PUTFIELD, instVar.thisClass, instVar.fieldName, descriptor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
// 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();
|
||||||
|
Loading…
Reference in New Issue
Block a user