Fixed fields with no imminent value assignment

This commit is contained in:
Jochen Seyfried 2024-07-01 20:55:02 +02:00
parent 192dfae94b
commit cabbbdcaf3
2 changed files with 58 additions and 29 deletions

View File

@ -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

View File

@ -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;