Updated the codeGen Methods in FieldDecl, MethodDecl and BlockStatement
This commit is contained in:
parent
cc05c58159
commit
b5b6f763e0
@ -6,6 +6,8 @@ import TypeCheck.TypeCheckResult;
|
|||||||
import abstractSyntaxTree.Node;
|
import abstractSyntaxTree.Node;
|
||||||
import abstractSyntaxTree.Program;
|
import abstractSyntaxTree.Program;
|
||||||
import org.objectweb.asm.ClassWriter;
|
import org.objectweb.asm.ClassWriter;
|
||||||
|
import org.objectweb.asm.FieldVisitor;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -39,6 +41,22 @@ public class FieldDecl extends AbstractType implements IClass, Node {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(ClassWriter cw) {
|
public void codeGen(ClassWriter cw) {
|
||||||
|
//TODO: Do we have fields with initial values?
|
||||||
|
FieldVisitor fv = cw.visitField(Opcodes.ACC_PUBLIC, identifier, getFieldDescriptor(), null, null);
|
||||||
|
fv.visitEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getFieldDescriptor() {
|
||||||
|
//TODO: Maybe we have to check for arrays?
|
||||||
|
switch (type) {
|
||||||
|
case "int":
|
||||||
|
return "I";
|
||||||
|
case "boolean":
|
||||||
|
return "Z";
|
||||||
|
case "char":
|
||||||
|
return "C";
|
||||||
|
default:
|
||||||
|
return "L" + type + ";";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,25 +2,30 @@ package abstractSyntaxTree.Class;
|
|||||||
|
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Node;
|
import abstractSyntaxTree.Node;
|
||||||
|
import abstractSyntaxTree.Parameter.Parameter;
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import abstractSyntaxTree.Program;
|
import abstractSyntaxTree.Program;
|
||||||
import abstractSyntaxTree.Statement.BlockStatement;
|
import abstractSyntaxTree.Statement.BlockStatement;
|
||||||
import abstractSyntaxTree.Statement.IStatement;
|
import abstractSyntaxTree.Statement.IStatement;
|
||||||
import org.objectweb.asm.ClassWriter;
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
public class MethodDecl implements IClass, Node {
|
public class MethodDecl implements IClass, Node {
|
||||||
|
|
||||||
|
//Class Name
|
||||||
public String classThatContainsMethod;
|
public String classThatContainsMethod;
|
||||||
|
|
||||||
|
//Method Name
|
||||||
public String name;
|
public String name;
|
||||||
public ParameterList parameters;
|
public ParameterList parameters;
|
||||||
public String returnType;
|
public String returnType;
|
||||||
public BlockStatement codeBlock;
|
public BlockStatement codeBlock;
|
||||||
|
|
||||||
public Map<String, String> localVars;
|
public HashMap<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){
|
||||||
this.classThatContainsMethod = classThatContainsMethod;
|
this.classThatContainsMethod = classThatContainsMethod;
|
||||||
@ -28,6 +33,7 @@ public class MethodDecl implements IClass, Node {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
this.parameters = parameters;
|
this.parameters = parameters;
|
||||||
this.codeBlock = codeBlock;
|
this.codeBlock = codeBlock;
|
||||||
|
this.localVars = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||||
@ -40,5 +46,92 @@ public class MethodDecl implements IClass, Node {
|
|||||||
@Override
|
@Override
|
||||||
public void codeGen(ClassWriter cw) throws Exception {
|
public void codeGen(ClassWriter cw) throws Exception {
|
||||||
|
|
||||||
|
localVars.put("this", classThatContainsMethod);
|
||||||
|
for (Parameter param : parameters.parameterList) {
|
||||||
|
localVars.put(param.identifier, param.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the method is a constructor
|
||||||
|
if (classThatContainsMethod.equals(name) && returnType == null) {
|
||||||
|
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", getMethodDescriptor(), null, null);
|
||||||
|
|
||||||
|
//Call the superclass constructor
|
||||||
|
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
||||||
|
|
||||||
|
mv.visitCode();
|
||||||
|
codeBlock.codeGen(mv, localVars); //TODO: pass the local vars? --> codeGen for block not yet implemented
|
||||||
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
|
|
||||||
|
//automatically computed max stack and max locals
|
||||||
|
mv.visitMaxs(0, 0);
|
||||||
|
mv.visitEnd();
|
||||||
|
} else if (name.equals("main")) { //TODO: Check how we distinguish the main method
|
||||||
|
int access = Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC;
|
||||||
|
|
||||||
|
MethodVisitor mv = cw.visitMethod(access, name, "([Ljava/lang/String;)V", null, null);
|
||||||
|
|
||||||
|
mv.visitCode();
|
||||||
|
codeBlock.codeGen(mv, localVars); //TODO: pass the local vars? --> codeGen for block not yet implemented
|
||||||
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
|
|
||||||
|
mv.visitMaxs(0, 0);
|
||||||
|
mv.visitEnd();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, name, getMethodDescriptor(), null, null);
|
||||||
|
|
||||||
|
mv.visitCode();
|
||||||
|
codeBlock.codeGen(mv, localVars); //TODO: pass the local vars? --> codeGen for block not yet implemented
|
||||||
|
|
||||||
|
// We have to check the return type to get the return opcode
|
||||||
|
// For methods which return an actual value, the return opcode is created in the method body to ensure the
|
||||||
|
// correct return value is on the stack
|
||||||
|
if (returnType.equals("void")) mv.visitInsn(Opcodes.RETURN);
|
||||||
|
|
||||||
|
mv.visitMaxs(0, 0);
|
||||||
|
mv.visitEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getMethodDescriptor() {
|
||||||
|
// get the method descriptor
|
||||||
|
StringBuilder descriptor = new StringBuilder("(");
|
||||||
|
|
||||||
|
// Iterate over the parameters and add them to the descriptor
|
||||||
|
for (Parameter param : parameters.parameterList) {
|
||||||
|
switch (param.type) {
|
||||||
|
case "int" -> descriptor.append("I");
|
||||||
|
case "boolean" -> descriptor.append("Z");
|
||||||
|
case "char" -> descriptor.append("C");
|
||||||
|
case "void" -> descriptor.append("V");
|
||||||
|
default ->
|
||||||
|
// object
|
||||||
|
//TODO: This is not finished
|
||||||
|
descriptor.append("L").append(param.type).append(";");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
descriptor.append(")");
|
||||||
|
|
||||||
|
|
||||||
|
// Get the return type
|
||||||
|
// If the return type is null, it is a constructor and we need to append V
|
||||||
|
if (returnType == null) {
|
||||||
|
descriptor.append("V");
|
||||||
|
} else {
|
||||||
|
switch (returnType) {
|
||||||
|
case "int" -> descriptor.append("I");
|
||||||
|
case "boolean" -> descriptor.append("Z");
|
||||||
|
case "char" -> descriptor.append("C");
|
||||||
|
case "void" -> descriptor.append("V");
|
||||||
|
|
||||||
|
//TODO: This is not finished --> we need to append the fully qualified name of the object
|
||||||
|
// Need to make sure what we get
|
||||||
|
default ->
|
||||||
|
// object
|
||||||
|
descriptor.append("L").append(returnType).append(";");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return descriptor.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,10 +12,10 @@ import java.util.List;
|
|||||||
|
|
||||||
public class RefType extends AbstractType implements IClass, Node {
|
public class RefType extends AbstractType implements IClass, Node {
|
||||||
|
|
||||||
|
//Class Name
|
||||||
public String name;
|
public String name;
|
||||||
public List<FieldDecl> fieldDecls;
|
public List<FieldDecl> fieldDecls;
|
||||||
public List<MethodDecl> methodDecls;
|
public List<MethodDecl> methodDecls;
|
||||||
private boolean hasMain;
|
|
||||||
|
|
||||||
public RefType(String name,
|
public RefType(String name,
|
||||||
List<FieldDecl> fieldDecls,
|
List<FieldDecl> fieldDecls,
|
||||||
|
@ -46,9 +46,15 @@ public class BlockStatement extends AbstractType implements IStatement{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv) throws Exception {
|
public void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception {
|
||||||
|
// Create a new HashMap for the local variables of the block
|
||||||
|
// It has every variable of the parent block
|
||||||
|
// This Map is discarded at the end of the block
|
||||||
|
//TODO: Do this for every block --> if, while, ...
|
||||||
|
HashMap<String, String> blockLocalVars = new HashMap<>(localVars);
|
||||||
|
|
||||||
for (IStatement statement : statements) {
|
for (IStatement statement : statements) {
|
||||||
statement.codeGen(mv); //TODO: I think we need to pass the symbol table here
|
statement.codeGen(mv, blockLocalVars);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ public class EmptyStatement extends AbstractType implements IStatement{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv) throws Exception {
|
public void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception {
|
||||||
//An empty statement does not generate any code
|
//An empty statement does not generate any code
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,5 +14,5 @@ public interface IStatement {
|
|||||||
|
|
||||||
TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception;
|
TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception;
|
||||||
|
|
||||||
void codeGen(MethodVisitor mv) throws Exception;
|
void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception;
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ public class IfElseStatement extends AbstractType implements IStatement{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv) throws Exception {
|
public void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception {
|
||||||
|
|
||||||
Label conditionFalse = new Label();
|
Label conditionFalse = new Label();
|
||||||
Label statementEnd = new Label();
|
Label statementEnd = new Label();
|
||||||
|
@ -39,7 +39,7 @@ public class IfStatement extends AbstractType implements IStatement{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv) throws Exception {
|
public void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception {
|
||||||
|
|
||||||
Label conditionFalse = new Label();
|
Label conditionFalse = new Label();
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ public class ReturnStatement extends AbstractType implements IStatement{
|
|||||||
// This is a problem at "BinaryExpression" and here because we need to know the type to return
|
// This is a problem at "BinaryExpression" and here because we need to know the type to return
|
||||||
// At this point in time we can either return reference types or have an error message
|
// At this point in time we can either return reference types or have an error message
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv) throws Exception {
|
public void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception {
|
||||||
|
|
||||||
if (expression != null) {
|
if (expression != null) {
|
||||||
expression.codeGen(mv);
|
expression.codeGen(mv);
|
||||||
|
@ -39,7 +39,7 @@ public class WhileStatement extends AbstractType implements IStatement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv) throws Exception {
|
public void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception {
|
||||||
Label conditionFalse = new Label();
|
Label conditionFalse = new Label();
|
||||||
Label LoopStart = new Label();
|
Label LoopStart = new Label();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user