Fixed fields with no imminent value assignment
This commit is contained in:
parent
192dfae94b
commit
cabbbdcaf3
@ -77,18 +77,31 @@ public class MethodDecl implements Node {
|
|||||||
HashMap<String, String> classFields = typeContext.get(classThatContainsMethod);
|
HashMap<String, String> classFields = typeContext.get(classThatContainsMethod);
|
||||||
|
|
||||||
//Set the fields of the class
|
//Set the fields of the class
|
||||||
|
boolean fieldFound = false;
|
||||||
for (Map.Entry<String, String> entry : classFields.entrySet()) {
|
for (Map.Entry<String, String> entry : classFields.entrySet()) {
|
||||||
String fieldName = entry.getKey();
|
String fieldName = entry.getKey();
|
||||||
for (FieldDecl field : fieldDecls) {
|
for (FieldDecl field : fieldDecls) {
|
||||||
if (field.identifier.equals(fieldName)) {
|
if (field.identifier.equals(fieldName)) {
|
||||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||||
field.expression.codeGen(mv, localVars, typeContext, methodContext);
|
if (field.expression != null) {
|
||||||
|
field.expression.codeGen(mv, localVars, typeContext, methodContext);
|
||||||
|
} else {
|
||||||
|
// If the field is not initialized, we need to load a default value onto the stack
|
||||||
|
switch (field.type) {
|
||||||
|
case "int", "boolean", "char" -> mv.visitInsn(Opcodes.ICONST_0);
|
||||||
|
default -> mv.visitInsn(Opcodes.ACONST_NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
descriptor = getFieldDescriptor(field.type);
|
descriptor = getFieldDescriptor(field.type);
|
||||||
mv.visitFieldInsn(Opcodes.PUTFIELD, classThatContainsMethod, fieldName, descriptor);
|
mv.visitFieldInsn(Opcodes.PUTFIELD, classThatContainsMethod, fieldName, descriptor);
|
||||||
} else {
|
fieldFound = true;
|
||||||
throw new Exception("Field " + fieldName + " not found");
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!fieldFound){
|
||||||
|
throw new Exception("Field " + fieldName + " not found");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Load the parameters onto the stack
|
//Load the parameters onto the stack
|
||||||
|
@ -67,11 +67,6 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
|||||||
|
|
||||||
@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 {
|
||||||
//TODO: Do we need the value on the stack after assigning it?
|
|
||||||
//TODO: WE do not differentiate between InstanceVar and FieldVar
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
if (left instanceof LocalVarIdentifier) {
|
if (left instanceof LocalVarIdentifier) {
|
||||||
LocalVarIdentifier localVar = (LocalVarIdentifier) left;
|
LocalVarIdentifier localVar = (LocalVarIdentifier) left;
|
||||||
@ -89,10 +84,25 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
throw new Exception("Variable " + varName + " not found");
|
String fieldType = typeContext.get(thisClass).get(varName);
|
||||||
|
if (fieldType != null) {
|
||||||
|
// Load "this" onto the stack
|
||||||
|
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||||
|
// 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);
|
||||||
|
// Get the field descriptor
|
||||||
|
String descriptor = getFieldDescriptor(fieldType, typeContext);
|
||||||
|
// Store the value in the field
|
||||||
|
mv.visitFieldInsn(Opcodes.PUTFIELD, thisClass, varName, descriptor);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
throw new Exception("Variable " + varName + " not found");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String type = localVars.get(localVar.getIdentifier());
|
String type = localVars.get(localVar.getIdentifier());
|
||||||
|
// 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);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "int", "char", "boolean":
|
case "int", "char", "boolean":
|
||||||
mv.visitVarInsn(Opcodes.ISTORE, index);
|
mv.visitVarInsn(Opcodes.ISTORE, index);
|
||||||
@ -108,35 +118,41 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
|||||||
// Load "this" onto the stack
|
// Load "this" onto the stack
|
||||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||||
|
|
||||||
// Duplicate the top of the stack as we'll need it for both the PUTFIELD and subsequent expressions
|
// Call the codeGen on the right expression which will push the value of the right expression onto the stack
|
||||||
mv.visitInsn(Opcodes.DUP_X1);
|
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||||
|
|
||||||
// Get the field information
|
// Get the field information
|
||||||
String fieldType = typeContext.get(instVar.thisClass).get(instVar.fieldName);
|
String fieldType = typeContext.get(instVar.thisClass).get(instVar.fieldName);
|
||||||
|
|
||||||
StringBuilder descriptor = new StringBuilder();
|
// Get the field descriptor
|
||||||
|
String descriptor = getFieldDescriptor(fieldType, typeContext);
|
||||||
switch (fieldType) {
|
|
||||||
case "int":
|
|
||||||
descriptor.append("I");
|
|
||||||
break;
|
|
||||||
case "boolean":
|
|
||||||
descriptor.append("Z");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
String fullReturnType = typeContext.get(instVar.thisClass).get(instVar.fieldName);
|
|
||||||
|
|
||||||
// If it is a class reference replace the "." with "/" and return it
|
|
||||||
if (fieldType.contains(".")) fullReturnType = fullReturnType.replaceAll("\\.", "/");
|
|
||||||
if (fullReturnType != null) descriptor.append("L").append(fullReturnType).append(";");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store the value in the field
|
// Store the value in the field
|
||||||
mv.visitFieldInsn(Opcodes.PUTFIELD, instVar.thisClass, instVar.fieldName, descriptor.toString());
|
mv.visitFieldInsn(Opcodes.PUTFIELD, instVar.thisClass, instVar.fieldName, descriptor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getFieldDescriptor(String type, HashMap<String, HashMap<String, String>> typeContext) {
|
||||||
|
StringBuilder descriptor = new StringBuilder();
|
||||||
|
switch (type) {
|
||||||
|
case "int":
|
||||||
|
return "I";
|
||||||
|
case "boolean":
|
||||||
|
return "Z";
|
||||||
|
case "char":
|
||||||
|
return "C";
|
||||||
|
default: {
|
||||||
|
String fullReturnType = typeContext.get(instVar.thisClass).get(instVar.fieldName);
|
||||||
|
|
||||||
|
// If it is a class reference replace the "." with "/" and return it
|
||||||
|
if (type.contains(".")) fullReturnType = fullReturnType.replaceAll("\\.", "/");
|
||||||
|
if (fullReturnType != null) descriptor.append("L").append(fullReturnType).append(";");
|
||||||
|
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