Merge remote-tracking branch 'origin/master'

This commit is contained in:
Krauß, Josefine 2024-06-27 09:30:43 +02:00
commit d4f98693d6
21 changed files with 175 additions and 116 deletions

View File

@ -84,7 +84,7 @@ public class MethodDecl implements Node {
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", descriptor, false); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", descriptor, false);
mv.visitCode(); mv.visitCode();
codeBlock.codeGen(mv, localVars, typeContext); codeBlock.codeGen(mv, localVars, typeContext, methodContext);
mv.visitInsn(Opcodes.RETURN); mv.visitInsn(Opcodes.RETURN);
//automatically computed max stack and max locals //automatically computed max stack and max locals
@ -96,7 +96,7 @@ public class MethodDecl implements Node {
MethodVisitor mv = cw.visitMethod(access, name, "([Ljava/lang/String;)V", null, null); MethodVisitor mv = cw.visitMethod(access, name, "([Ljava/lang/String;)V", null, null);
mv.visitCode(); mv.visitCode();
codeBlock.codeGen(mv, localVars, typeContext); codeBlock.codeGen(mv, localVars, typeContext, methodContext);
mv.visitInsn(Opcodes.RETURN); mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(0, 0); mv.visitMaxs(0, 0);
@ -106,7 +106,7 @@ public class MethodDecl implements Node {
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, name, getMethodDescriptor(methodContext), null, null); MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, name, getMethodDescriptor(methodContext), null, null);
mv.visitCode(); mv.visitCode();
codeBlock.codeGen(mv, localVars, typeContext); codeBlock.codeGen(mv, localVars, typeContext, methodContext);
// We have to check the return type to get the return opcode // 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 // For methods which return an actual value, the return opcode is created in the method body to ensure the

View File

@ -67,7 +67,7 @@ public class BinaryExpression extends AbstractType implements IExpression{
} }
@Override @Override
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) 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 {
// Label for the jump instruction // Label for the jump instruction
Label operationFalse = new Label(); //Operation is false Label operationFalse = new Label(); //Operation is false
Label operationTrue = new Label(); //Operation is true Label operationTrue = new Label(); //Operation is true
@ -77,88 +77,88 @@ public class BinaryExpression extends AbstractType implements IExpression{
// Bytecode for the binary operation // Bytecode for the binary operation
switch (operator) { switch (operator) {
case "&&": case "&&":
left.codeGen(mv, localVars, typeContext); left.codeGen(mv, localVars, typeContext, methodContext);
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // IFEQ --> "if equals to zero" (false) --> if left exp is false mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // IFEQ --> "if equals to zero" (false) --> if left exp is false
right.codeGen(mv, localVars, typeContext); right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // If right exp is false, jump to the end of the whole expression mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // If right exp is false, jump to the end of the whole expression
mv.visitJumpInsn(Opcodes.GOTO, operationTrue); // If it reaches this point, the right exp is true mv.visitJumpInsn(Opcodes.GOTO, operationTrue); // If it reaches this point, the right exp is true
break; break;
case "||": case "||":
left.codeGen(mv, localVars, typeContext); left.codeGen(mv, localVars, typeContext, methodContext);
mv.visitJumpInsn(Opcodes.IFNE, operationTrue); // IFNE --> "if not equals to zero" (true) --> if left exp is true mv.visitJumpInsn(Opcodes.IFNE, operationTrue); // IFNE --> "if not equals to zero" (true) --> if left exp is true
right.codeGen(mv, localVars, typeContext); right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitJumpInsn(Opcodes.IFNE, operationTrue); mv.visitJumpInsn(Opcodes.IFNE, operationTrue);
break; break;
case "==": case "==":
// Keep in mind that only primitive types are allowed in this case (at this time) // Keep in mind that only primitive types are allowed in this case (at this time)
left.codeGen(mv, localVars, typeContext); left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext); right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitJumpInsn(Opcodes.IF_ICMPEQ, operationTrue); // If the two values are equal, jump to the end of the expression mv.visitJumpInsn(Opcodes.IF_ICMPEQ, operationTrue); // If the two values are equal, jump to the end of the expression
break; break;
case "<": case "<":
left.codeGen(mv, localVars, typeContext); left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext); right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitJumpInsn(Opcodes.IF_ICMPLT, operationTrue); // Checks only on less than, not equal mv.visitJumpInsn(Opcodes.IF_ICMPLT, operationTrue); // Checks only on less than, not equal
break; break;
case ">": case ">":
left.codeGen(mv, localVars, typeContext); left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext); right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitJumpInsn(Opcodes.IF_ICMPGT, operationTrue); // Checks only on greater than, not equal mv.visitJumpInsn(Opcodes.IF_ICMPGT, operationTrue); // Checks only on greater than, not equal
break; break;
case "<=": case "<=":
left.codeGen(mv, localVars, typeContext); left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext); right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitJumpInsn(Opcodes.IF_ICMPLE, operationTrue); // Checks on less than OR equal mv.visitJumpInsn(Opcodes.IF_ICMPLE, operationTrue); // Checks on less than OR equal
break; break;
case ">=": case ">=":
left.codeGen(mv, localVars, typeContext); left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext); right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitJumpInsn(Opcodes.IF_ICMPGE, operationTrue); // Checks on greater than OR equal mv.visitJumpInsn(Opcodes.IF_ICMPGE, operationTrue); // Checks on greater than OR equal
break; break;
case "!=": case "!=":
left.codeGen(mv, localVars, typeContext); left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext); right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitJumpInsn(Opcodes.IF_ICMPNE, operationTrue); // Checks on not equal mv.visitJumpInsn(Opcodes.IF_ICMPNE, operationTrue); // Checks on not equal
break; break;
case "+": case "+":
left.codeGen(mv, localVars, typeContext); left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext); right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitInsn(Opcodes.IADD); mv.visitInsn(Opcodes.IADD);
break; break;
case "-": case "-":
left.codeGen(mv, localVars, typeContext); left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext); right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitInsn(Opcodes.ISUB); mv.visitInsn(Opcodes.ISUB);
break; break;
case "*": case "*":
left.codeGen(mv, localVars, typeContext); left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext); right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitInsn(Opcodes.IMUL); mv.visitInsn(Opcodes.IMUL);
break; break;
case "/": case "/":
left.codeGen(mv, localVars, typeContext); left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext); right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitInsn(Opcodes.IDIV); mv.visitInsn(Opcodes.IDIV);
break; break;

View File

@ -26,7 +26,7 @@ public class BooleanConstantExpression extends AbstractType implements IExpressi
} }
@Override @Override
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) 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 {
if (value){ if (value){
mv.visitInsn(Opcodes.ICONST_1); mv.visitInsn(Opcodes.ICONST_1);
} else { } else {

View File

@ -25,7 +25,7 @@ public class CharConstantExpression extends AbstractType implements IExpression{
} }
@Override @Override
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) 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 {
mv.visitIntInsn(Opcodes.BIPUSH, (int) value); mv.visitIntInsn(Opcodes.BIPUSH, (int) value);
} }

View File

@ -15,7 +15,7 @@ public interface IExpression extends Node {
TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException; TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException;
// visit method for code generation // visit method for code generation
void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception; void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception;
TypeCheckResult getTypeCheckResult(); TypeCheckResult getTypeCheckResult();
} }

View File

@ -42,7 +42,7 @@ public class InstVarExpression extends AbstractType implements IExpression{
@Override @Override
// typeContext: (ClassName, (FieldName, FieldType)) // typeContext: (ClassName, (FieldName, FieldType))
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) 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 {
// Load "this" onto the stack // Load "this" onto the stack
mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitVarInsn(Opcodes.ALOAD, 0);

View File

@ -27,7 +27,7 @@ public class IntConstantExpression extends AbstractType implements IExpression{
} }
@Override @Override
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) 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: When we are finished this can be done more efficiently //TODO: When we are finished this can be done more efficiently
mv.visitLdcInsn(value); mv.visitLdcInsn(value);
} }

View File

@ -45,7 +45,7 @@ public class LocalVarIdentifier extends AbstractType implements IExpression{
} }
@Override @Override
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) 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 {
// Check if the variable is in the list of local variables // Check if the variable is in the list of local variables
String type = localVars.get(identifier); String type = localVars.get(identifier);
if (type == null){ if (type == null){

View File

@ -15,8 +15,8 @@ import java.util.Objects;
public class UnaryExpression extends AbstractType implements IExpression{ public class UnaryExpression extends AbstractType implements IExpression{
public String operator; public String operator;
public IDatatype operand; public IExpression operand;
public UnaryExpression(String operator, IDatatype operand){ public UnaryExpression(String operator, IExpression operand){
this.operator = operator; this.operator = operator;
this.operand = operand; this.operand = operand;
} }
@ -24,7 +24,7 @@ public class UnaryExpression extends AbstractType implements IExpression{
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException { public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
TypeCheckResult result = new TypeCheckResult(); TypeCheckResult result = new TypeCheckResult();
TypeCheckResult operandTypeCheckResult = operand.typeCheck(); TypeCheckResult operandTypeCheckResult = operand.typeCheck(methodContext, typeContext, localVars);
String operandType = operandTypeCheckResult.type; String operandType = operandTypeCheckResult.type;
switch (operator) { switch (operator) {
@ -51,9 +51,9 @@ public class UnaryExpression extends AbstractType implements IExpression{
} }
@Override @Override
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) 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 {
operand.codeGen(mv); operand.codeGen(mv, localVars, typeContext, methodContext);
switch (operator) { switch (operator) {
case "!": case "!":

View File

@ -107,7 +107,7 @@ public class BlockStatement extends AbstractType implements IStatement {
} }
@Override @Override
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) 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 {
// Create a new HashMap for the local variables of the block // Create a new HashMap for the local variables of the block
// It has every variable of the parent block // It has every variable of the parent block
// This Map is discarded at the end of the block // This Map is discarded at the end of the block
@ -115,7 +115,7 @@ public class BlockStatement extends AbstractType implements IStatement {
LinkedHashMap<String, String> blockLocalVars = new LinkedHashMap<>(localVars); LinkedHashMap<String, String> blockLocalVars = new LinkedHashMap<>(localVars);
for (IStatement statement : statements) { for (IStatement statement : statements) {
statement.codeGen(mv, blockLocalVars, typeContext); statement.codeGen(mv, blockLocalVars, typeContext, methodContext);
} }
} }

View File

@ -20,7 +20,7 @@ public class EmptyStatement extends AbstractType implements IStatement{
} }
@Override @Override
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) 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 {
//An empty statement does not generate any code //An empty statement does not generate any code
} }

View File

@ -14,6 +14,6 @@ public interface IStatement extends Node {
TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException; TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException;
void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception; void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception;
TypeCheckResult getTypeCheckResult(); TypeCheckResult getTypeCheckResult();
} }

View File

@ -56,21 +56,21 @@ public class IfElseStatement extends AbstractType implements IStatement{
@Override @Override
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) 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 {
LinkedHashMap<String, String> blockLocalVars = new LinkedHashMap<>(localVars); LinkedHashMap<String, String> blockLocalVars = new LinkedHashMap<>(localVars);
Label conditionFalse = new Label(); Label conditionFalse = new Label();
Label statementEnd = new Label(); Label statementEnd = new Label();
condition.codeGen(mv, localVars, typeContext); condition.codeGen(mv, localVars, typeContext, methodContext);
mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); //Checks if the condition is false (0) mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); //Checks if the condition is false (0)
ifStatement.codeGen(mv, blockLocalVars, typeContext); //If the condition is true, execute the ifBlock ifStatement.codeGen(mv, blockLocalVars, typeContext, methodContext); //If the condition is true, execute the ifBlock
mv.visitJumpInsn(Opcodes.GOTO, statementEnd); //Jump to the end of the if-else statement mv.visitJumpInsn(Opcodes.GOTO, statementEnd); //Jump to the end of the if-else statement
mv.visitLabel(conditionFalse); mv.visitLabel(conditionFalse);
elseStatement.codeGen(mv, blockLocalVars, typeContext); //If the condition is false, execute the elseBlock elseStatement.codeGen(mv, blockLocalVars, typeContext, methodContext); //If the condition is false, execute the elseBlock
mv.visitLabel(statementEnd); //End of the if-else statement mv.visitLabel(statementEnd); //End of the if-else statement

View File

@ -43,16 +43,16 @@ public class IfStatement extends AbstractType implements IStatement{
} }
@Override @Override
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) 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 {
LinkedHashMap<String, String> blockLocalVars = new LinkedHashMap<>(localVars); LinkedHashMap<String, String> blockLocalVars = new LinkedHashMap<>(localVars);
Label conditionFalse = new Label(); Label conditionFalse = new Label();
condition.codeGen(mv, localVars, typeContext); condition.codeGen(mv, localVars, typeContext, methodContext);
mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); //Checks if the condition is false (0) mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); //Checks if the condition is false (0)
ifStatement.codeGen(mv, blockLocalVars, typeContext); ifStatement.codeGen(mv, blockLocalVars, typeContext, methodContext);
mv.visitLabel(conditionFalse); // If the condition is false, the Statements in the ifBlock will not be executed mv.visitLabel(conditionFalse); // If the condition is false, the Statements in the ifBlock will not be executed
} }

View File

@ -47,27 +47,40 @@ public class LocalVarDecl extends AbstractType implements IStatement{
} }
@Override @Override
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) 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 {
localVars.put(identifier, type); localVars.put(identifier, type);
int index = localVars.size() - 1;
int index = localVars.size()-1; if (expression != null) {
expression.codeGen(mv, localVars, typeContext,methodContext);
// Set a default value for the variable --> less problems // Store the result in the local variable
switch (type){ switch (type){
case "int": case "int", "char", "boolean":
mv.visitInsn(Opcodes.ICONST_0); mv.visitVarInsn(Opcodes.ISTORE, index);
mv.visitVarInsn(Opcodes.ISTORE, index); break;
break; default:
case "boolean": mv.visitVarInsn(Opcodes.ASTORE, index);
mv.visitInsn(Opcodes.ICONST_0); }
mv.visitVarInsn(Opcodes.ISTORE, index); } else {
break;
case "void": // Set a default value for the variable --> less problems
break; switch (type) {
default: case "int":
mv.visitInsn(Opcodes.ACONST_NULL); mv.visitInsn(Opcodes.ICONST_1);
mv.visitVarInsn(Opcodes.ASTORE, index); mv.visitVarInsn(Opcodes.ISTORE, index);
break;
case "boolean":
mv.visitInsn(Opcodes.ICONST_0);
mv.visitVarInsn(Opcodes.ISTORE, index);
break;
case "void":
break;
default:
mv.visitInsn(Opcodes.ACONST_NULL);
mv.visitVarInsn(Opcodes.ASTORE, index);
}
} }
} }

View File

@ -38,12 +38,11 @@ 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, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) 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 {
if (expression != null) { if (expression != null) {
expression.codeGen(mv, localVars, typeContext); expression.codeGen(mv, localVars, typeContext, methodContext);
//Get the Type of the expression //Get the Type of the expression
//TODO: Resolve how do we get the type of the expression
String type = expression.getTypeCheckResult().type; String type = expression.getTypeCheckResult().type;
if (type.equals("int") || type.equals("boolean") || type.equals("char")) { if (type.equals("int") || type.equals("boolean") || type.equals("char")) {

View File

@ -42,7 +42,7 @@ public class WhileStatement extends AbstractType implements IStatement {
} }
@Override @Override
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) 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 {
LinkedHashMap<String, String> blockLocalVars = new LinkedHashMap<>(localVars); LinkedHashMap<String, String> blockLocalVars = new LinkedHashMap<>(localVars);
@ -51,10 +51,10 @@ public class WhileStatement extends AbstractType implements IStatement {
mv.visitLabel(LoopStart); mv.visitLabel(LoopStart);
condition.codeGen(mv, localVars, typeContext); condition.codeGen(mv, localVars, typeContext, methodContext);
mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); // Checks if the condition is false (0) mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); // Checks if the condition is false (0)
statement.codeGen(mv, blockLocalVars, typeContext); statement.codeGen(mv, blockLocalVars, typeContext, methodContext);
//statement.codeGen(mv); //statement.codeGen(mv);
//TODO: If the block ends with a return statement, we might have to pop it from the stack //TODO: If the block ends with a return statement, we might have to pop it from the stack
// So the next iteration starts with a clean stack // So the next iteration starts with a clean stack

View File

@ -66,12 +66,12 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
} }
@Override @Override
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) 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: Do we need the value on the stack after assigning it?
//TODO: WE do not differentiate between InstanceVar and FieldVar //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 // Call the codeGen on the right expression which will push the value of the right expression onto the stack
right.codeGen(mv, localVars, typeContext); right.codeGen(mv, localVars, typeContext, methodContext);
if (left instanceof LocalVarIdentifier) { if (left instanceof LocalVarIdentifier) {
LocalVarIdentifier localVar = (LocalVarIdentifier) left; LocalVarIdentifier localVar = (LocalVarIdentifier) left;

View File

@ -79,51 +79,96 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
} }
//Errors occur due to the change in parameter in the RefType class //Errors occur due to the change in parameter in the RefType class
// I need the methodContext here to get the method descriptor
@Override @Override
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) 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 {
//Generate Bytecode for the receiver String owner;
if (receiver.thisExpression) {
// If the receiver is "this" then load "this" onto the stack
mv.visitVarInsn(Opcodes.ALOAD, 0);
} else if (receiver.instVarExpression != null) {
receiver.instVarExpression.codeGen(mv, localVars, typeContext);
} else if (receiver.newStatementExpression != null) { // Load the object onto the stack
receiver.newStatementExpression.codeGen(mv, localVars, typeContext); if (receiver != null) {
if (receiver.thisExpression) {
// Not sure about this part mv.visitVarInsn(Opcodes.ALOAD, 0);
} else if (receiver.identifier != null) { owner = thisClass;
// Load local variable onto the stack } else if (receiver.instVarExpression != null) {
for (String key : localVars.keySet()) { receiver.instVarExpression.codeGen(mv, localVars, typeContext, methodContext);
if (key.equals(receiver.identifier)) { owner = receiver.instVarExpression.getTypeCheckResult().type;
String type = localVars.get(key); } else if (receiver.newStatementExpression != null) {
receiver.newStatementExpression.codeGen(mv, localVars, typeContext, methodContext);
owner = receiver.newStatementExpression.getTypeCheckResult().type;
} else if (receiver.identifier != null) {
String type = localVars.get(receiver.identifier);
if (type == null) {
// If it is not a local variable, assume it is a field of the current class
type = typeContext.get(thisClass).get(receiver.identifier);
mv.visitVarInsn(Opcodes.ALOAD, 0); // Load "this" onto the stack
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, receiver.identifier, "L" + type + ";"); // Load the field onto the stack
} else {
// It's a local variable
int index = localVars.keySet().stream().toList().indexOf(receiver.identifier);
int opcode = type.equals("int") ? Opcodes.ILOAD : Opcodes.ALOAD; int opcode = type.equals("int") ? Opcodes.ILOAD : Opcodes.ALOAD;
mv.visitVarInsn(opcode, Integer.parseInt(key)); mv.visitVarInsn(opcode, index); // Load local variable onto the stack
break;
} }
owner = type;
} else {
throw new ExecutionControl.NotImplementedException("Receiver type not supported.");
}
} else {
throw new ExecutionControl.NotImplementedException("Receiver is null.");
}
/*
else {
String type = localVars.get(receiver.identifier);
if (type == null) {
type = typeContext.get(thisClass).get(receiver.identifier);
}
mv.visitVarInsn(Opcodes.ALOAD, 1);
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, receiver.identifier, "L" + type + ";");
}
*/
// Generate the code for each argument expression
for (IExpression argument : arguments) {
argument.codeGen(mv, localVars, typeContext, methodContext);
}
// Invoke the method
String descriptor = getMethodDescriptor();
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, methodName, descriptor, false);
}
private String getMethodDescriptor() {
StringBuilder descriptor = new StringBuilder("(");
for (IExpression argument : arguments) {
TypeCheckResult result = argument.getTypeCheckResult();
String type = result.type;
switch (type) {
case "int":
descriptor.append("I");
break;
case "boolean":
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(")"); // Methods always return void
// Generate Bytecode for the arguments return descriptor.toString();
for (IExpression argument : arguments) {
argument.codeGen(mv, localVars, typeContext);
}
String descriptor;
// List<MethodDecl> methodDecls = thisClass.methodDecls;
// for (MethodDecl methodDecl : methodDecls) {
// if (methodDecl.name.equals(methodName)) {
// //Get the method descriptor
// //descriptor = methodDecl.getMethodDescriptor(methodContext); //methodContext is missing
// }
// }
// Invoke the method
// String className = classThatHasTheMethodIfNotThis != null ? classThatHasTheMethodIfNotThis.name : thisClass.name;
//mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, methodName, descriptor, false);
} }
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) return true;

View File

@ -39,7 +39,7 @@ public class NewStatementExpression extends AbstractType implements IExpression,
} }
@Override @Override
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) 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 {
//Create new instance of the class //Create new instance of the class
mv.visitTypeInsn(Opcodes.NEW, className); mv.visitTypeInsn(Opcodes.NEW, className);
@ -47,7 +47,7 @@ public class NewStatementExpression extends AbstractType implements IExpression,
mv.visitInsn(Opcodes.DUP); mv.visitInsn(Opcodes.DUP);
for (IExpression argument : arguments) { for (IExpression argument : arguments) {
argument.codeGen(mv, localVars, typeContext); argument.codeGen(mv, localVars, typeContext, methodContext);
} }
String descriptor = getConstructorDescriptor(); String descriptor = getConstructorDescriptor();
@ -59,7 +59,8 @@ public class NewStatementExpression extends AbstractType implements IExpression,
} }
private String getConstructorDescriptor() { private String getConstructorDescriptor() {
StringBuilder descriptor = new StringBuilder(); StringBuilder descriptor = new StringBuilder("(");
for (IExpression parameter : arguments) { for (IExpression parameter : arguments) {
TypeCheckResult result = parameter.getTypeCheckResult(); TypeCheckResult result = parameter.getTypeCheckResult();

View File

@ -271,7 +271,8 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
} else if (ctx.value() != null) { } else if (ctx.value() != null) {
return visitValue(ctx.value()); return visitValue(ctx.value());
} else if (ctx.binaryExpr() != null) { } else if (ctx.binaryExpr() != null) {
//todo IExpression expression = (IExpression) visit(ctx.binaryExpr());
return new UnaryExpression("!", expression);
} }
return null; return null;
} }