Implemented NewStatementExpression and finished the return of objects (classes, methods) with fully qualified name
This commit is contained in:
parent
0d827c5f32
commit
63059994ec
@ -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) {
|
||||||
|
@ -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
|
||||||
|
@ -99,20 +99,35 @@ 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
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user