Implemented NewStatementExpression and finished the return of objects (classes, methods) with fully qualified name

This commit is contained in:
Jochen Seyfried 2024-05-31 13:53:06 +02:00
parent 0d827c5f32
commit 63059994ec
4 changed files with 81 additions and 25 deletions

View File

@ -22,7 +22,6 @@ public class MethodDecl implements Node {
public String returnType; public String returnType;
public BlockStatement codeBlock; public BlockStatement codeBlock;
//TODO: Can this be a linked hash map? --> need it to be to get the index of local variables
public LinkedHashMap<String, String> localVars; public LinkedHashMap<String, String> localVars;
public MethodDecl(String classThatContainsMethod, String returnType, String name, ParameterList parameters, BlockStatement codeBlock){ public MethodDecl(String classThatContainsMethod, String returnType, String name, ParameterList parameters, BlockStatement codeBlock){
@ -43,7 +42,6 @@ public class MethodDecl implements Node {
return result; return result;
} }
//Need to get the returnType of the method if it is an object //Need to get the returnType of the method if it is an object
// methodContext (class, (returnType, (identifier, parameter))) // methodContext (class, (returnType, (identifier, parameter)))
public void codeGen(ClassWriter cw, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception { public void codeGen(ClassWriter cw, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
@ -129,7 +127,6 @@ public class MethodDecl implements Node {
} }
descriptor.append(")"); descriptor.append(")");
// Get the return type // Get the return type
// If the return type is null, it is a constructor, and we need to append V // If the return type is null, it is a constructor, and we need to append V
if (returnType == null) { if (returnType == null) {

View File

@ -3,17 +3,17 @@ package abstractSyntaxTree.Expression;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import abstractSyntaxTree.Class.RefType; import abstractSyntaxTree.Class.RefType;
import abstractSyntaxTree.Parameter.ParameterList; import abstractSyntaxTree.Parameter.ParameterList;
import gen.DecafParser;
import jdk.jshell.spi.ExecutionControl; import jdk.jshell.spi.ExecutionControl;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Objects;
public class InstVarExpression implements IExpression{ public class InstVarExpression implements IExpression{
//TODO: We have to decide upon more parameters and where they come from, for
// example here we need the index of the field, the class reference and the field name
public RefType classRef; public RefType classRef;
public String fieldName; public String fieldName;
@ -22,7 +22,6 @@ public class InstVarExpression implements IExpression{
this.fieldName = fieldName; this.fieldName = fieldName;
} }
@Override @Override
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception { public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
@ -42,26 +41,30 @@ public class InstVarExpression implements IExpression{
//Get the field information //Get the field information
String fieldType = typeContext.get(classRef.name).get(fieldName); String fieldType = typeContext.get(classRef.name).get(fieldName);
String fieldDescriptor; StringBuilder descriptor = new StringBuilder();
switch (fieldType) { switch (fieldType) {
case "int": case "int":
fieldDescriptor = "I"; descriptor.append("I");
break; break;
case "boolean": case "boolean":
fieldDescriptor = "Z"; descriptor.append("Z");
break; break;
case "char": case "char":
fieldDescriptor = "C"; descriptor.append("C");
break; break;
default: default:
//TODO: We need the fully qualified name of the class here in field type String fullReturnType = typeContext.get(classRef.name).get(fieldName);
fieldDescriptor = "L" + fieldType + ";";
// 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; break;
} }
// Load the variable onto the stack // Load the variable onto the stack
mv.visitFieldInsn(Opcodes.GETFIELD, classRef.name, fieldName, fieldDescriptor); mv.visitFieldInsn(Opcodes.GETFIELD, classRef.name, fieldName, descriptor.toString());
} }
@Override @Override

View File

@ -99,19 +99,34 @@ 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
if (left instanceof VarRefExpression varRef) {
//TODO: Implement the handling of a variable reference --> I need a list of local variables
// for that to determine if the variable is a local or field variable
} else if (left instanceof InstVarExpression instVar) {
mv.visitInsn(Opcodes.DUP_X1); mv.visitInsn(Opcodes.DUP_X1);
// We now again need the owner (class reference), name (of the Field in the owner) and type of the field // Get the field information
//mv.visitFieldInsn(Opcodes.PUTFIELD, instVar.className, instVar.varName, instVar.type); String fieldType = typeContext.get(instVar.classRef.name).get(instVar.fieldName);
StringBuilder descriptor = new StringBuilder();
switch (fieldType) {
case "int":
descriptor.append("I");
break;
case "bool":
descriptor.append("Z");
break;
default:
String fullReturnType = typeContext.get(instVar.classRef.name).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
mv.visitFieldInsn(Opcodes.PUTFIELD, instVar.classRef.name, instVar.fieldName, descriptor.toString());
} }
*/
} }
@Override @Override

View File

@ -4,6 +4,7 @@ import TypeCheck.AbstractType;
import TypeCheck.TypeCheckHelper; import TypeCheck.TypeCheckHelper;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import abstractSyntaxTree.Expression.IExpression; import abstractSyntaxTree.Expression.IExpression;
import abstractSyntaxTree.Parameter.Parameter;
import abstractSyntaxTree.Parameter.ParameterList; import abstractSyntaxTree.Parameter.ParameterList;
import abstractSyntaxTree.Statement.IStatement; import abstractSyntaxTree.Statement.IStatement;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
@ -17,9 +18,11 @@ import java.util.List;
public class NewStatementExpression extends AbstractType implements IExpression, IStatement { public class NewStatementExpression extends AbstractType implements IExpression, IStatement {
private String className; private String className;
private List<IExpression> arguments;
public NewStatementExpression(String className) { public NewStatementExpression(String className, List<IExpression> arguments) {
this.className = className; this.className = className;
this.arguments = arguments;
} }
@Override @Override
@ -40,7 +43,45 @@ public class NewStatementExpression extends AbstractType implements IExpression,
//Duplicate the reference, so I can use it after the INVOKE consumes one //Duplicate the reference, so I can use it after the INVOKE consumes one
mv.visitInsn(Opcodes.DUP); mv.visitInsn(Opcodes.DUP);
for (IExpression argument : arguments) {
argument.codeGen(mv, localVars, typeContext);
}
String descriptor = getConstructorDescriptor();
//Call the constructor //Call the constructor
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, className, "<init>", "()V", false); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, className, "<init>", descriptor, false);
}
private String getConstructorDescriptor() {
StringBuilder descriptor = new StringBuilder();
for (IExpression parameter : arguments) {
TypeCheckResult result = parameter.getTypeCheckResult();
String type = result.type;
switch (type) {
case "int":
descriptor.append("I");
break;
case "bool":
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(")V"); // Constructors always return void
return descriptor.toString();
} }
} }