From 9fa9dfdfb6ae5582fa33a4748cfcffc7a313795a Mon Sep 17 00:00:00 2001 From: Jochen Seyfried Date: Fri, 31 May 2024 10:26:47 +0200 Subject: [PATCH 1/2] Fixed missing parameters in Program, MethodDecl, and RefType --- src/main/java/abstractSyntaxTree/Class/MethodDecl.java | 8 ++++---- src/main/java/abstractSyntaxTree/Class/RefType.java | 6 ++++-- src/main/java/abstractSyntaxTree/Program.java | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/java/abstractSyntaxTree/Class/MethodDecl.java b/src/main/java/abstractSyntaxTree/Class/MethodDecl.java index fc074c7..6b95799 100644 --- a/src/main/java/abstractSyntaxTree/Class/MethodDecl.java +++ b/src/main/java/abstractSyntaxTree/Class/MethodDecl.java @@ -46,7 +46,7 @@ public class MethodDecl implements Node { //Need to get the returnType of the method if it is an object // methodContext (class, (returnType, (identifier, parameter))) - public void codeGen(ClassWriter cw, HashMap>> methodContext) throws Exception { + public void codeGen(ClassWriter cw, HashMap>> methodContext, HashMap> typeContext) throws Exception { localVars.put("this", classThatContainsMethod); for (Parameter param : parameters.parameterList) { @@ -75,7 +75,7 @@ public class MethodDecl implements Node { mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "", descriptor, false); mv.visitCode(); - codeBlock.codeGen(mv, localVars); + codeBlock.codeGen(mv, localVars, typeContext); mv.visitInsn(Opcodes.RETURN); //automatically computed max stack and max locals @@ -87,7 +87,7 @@ public class MethodDecl implements Node { MethodVisitor mv = cw.visitMethod(access, name, "([Ljava/lang/String;)V", null, null); mv.visitCode(); - codeBlock.codeGen(mv, localVars); + codeBlock.codeGen(mv, localVars, typeContext); mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(0, 0); @@ -97,7 +97,7 @@ public class MethodDecl implements Node { MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, name, getMethodDescriptor(methodContext), null, null); mv.visitCode(); - codeBlock.codeGen(mv, localVars); + codeBlock.codeGen(mv, localVars, typeContext); // 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 diff --git a/src/main/java/abstractSyntaxTree/Class/RefType.java b/src/main/java/abstractSyntaxTree/Class/RefType.java index 19bc5f6..5c858fa 100644 --- a/src/main/java/abstractSyntaxTree/Class/RefType.java +++ b/src/main/java/abstractSyntaxTree/Class/RefType.java @@ -2,6 +2,7 @@ package abstractSyntaxTree.Class; import TypeCheck.AbstractType; import TypeCheck.TypeCheckResult; +import abstractSyntaxTree.Expression.IExpression; import abstractSyntaxTree.Node; import abstractSyntaxTree.Parameter.ParameterList; import org.objectweb.asm.ClassWriter; @@ -29,6 +30,7 @@ public class RefType extends AbstractType implements Node { this.fieldDecls = fieldDecls; this.methodDecls = methodDecls; this.hasMain = hasMain; + } public TypeCheckResult typeCheck(HashMap>> methodContext, @@ -75,7 +77,7 @@ public class RefType extends AbstractType implements Node { // Method for code generation which iterates over all the field declarations // and method declarations and calls their CodeGen methods - public void codeGen(ClassWriter cw, HashMap>> methodContext) throws Exception { + public void codeGen(ClassWriter cw, HashMap>> methodContext, HashMap> typeContext) throws Exception { cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, name, null, "java/lang/Object", null); @@ -85,7 +87,7 @@ public class RefType extends AbstractType implements Node { } for (MethodDecl method : methodDecls) { - method.codeGen(cw, methodContext); + method.codeGen(cw, methodContext, typeContext); } cw.visitEnd(); } diff --git a/src/main/java/abstractSyntaxTree/Program.java b/src/main/java/abstractSyntaxTree/Program.java index 58c1d24..0c330ce 100644 --- a/src/main/java/abstractSyntaxTree/Program.java +++ b/src/main/java/abstractSyntaxTree/Program.java @@ -68,7 +68,7 @@ public class Program implements Node { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, oneClass.name, null, "java/lang/Object", null); - // oneClass.codeGen(cw); + oneClass.codeGen(cw, methodContext, typeContext); cw.visitEnd(); byte[] bytecode = cw.toByteArray(); From 21dff015b560dddb9bec72dcd29363a10242cc00 Mon Sep 17 00:00:00 2001 From: Jochen Seyfried Date: Fri, 31 May 2024 10:42:14 +0200 Subject: [PATCH 2/2] Changed the order of arguments --- .../Expression/BinaryExpression.java | 50 +++++++++---------- .../Expression/IExpression.java | 2 +- .../Expression/InstVarExpression.java | 2 +- .../Expression/LocalVarIdentifier.java | 2 +- .../Expression/UnaryExpression.java | 2 +- .../Statement/IfElseStatement.java | 2 +- .../Statement/IfStatement.java | 2 +- .../Statement/ReturnStatement.java | 2 +- .../Statement/WhileStatement.java | 2 +- .../AssignStatementExpression.java | 44 ++++++++-------- .../MethodCallStatementExpression.java | 13 +++-- .../NewStatementExpression.java | 7 +-- 12 files changed, 63 insertions(+), 67 deletions(-) diff --git a/src/main/java/abstractSyntaxTree/Expression/BinaryExpression.java b/src/main/java/abstractSyntaxTree/Expression/BinaryExpression.java index 938c503..c4b92a7 100644 --- a/src/main/java/abstractSyntaxTree/Expression/BinaryExpression.java +++ b/src/main/java/abstractSyntaxTree/Expression/BinaryExpression.java @@ -67,7 +67,7 @@ public class BinaryExpression extends AbstractType implements IExpression{ } @Override - public void codeGen(MethodVisitor mv, HashMap> typeContext, LinkedHashMap localVars) throws Exception { + public void codeGen(MethodVisitor mv, LinkedHashMap localVars, HashMap> typeContext) throws Exception { // Label for the jump instruction Label operationFalse = new Label(); //Operation is false Label operationTrue = new Label(); //Operation is true @@ -77,88 +77,88 @@ public class BinaryExpression extends AbstractType implements IExpression{ // Bytecode for the binary operation switch (operator) { case "&&": - left.codeGen(mv, typeContext, localVars); + left.codeGen(mv, localVars, typeContext); mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // IFEQ --> "if equals to zero" (false) --> if left exp is false - right.codeGen(mv, typeContext, localVars); + right.codeGen(mv, localVars, typeContext); 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 break; case "||": - left.codeGen(mv, typeContext, localVars); + left.codeGen(mv, localVars, typeContext); mv.visitJumpInsn(Opcodes.IFNE, operationTrue); // IFNE --> "if not equals to zero" (true) --> if left exp is true - right.codeGen(mv, typeContext, localVars); + right.codeGen(mv, localVars, typeContext); mv.visitJumpInsn(Opcodes.IFNE, operationTrue); break; case "==": // Keep in mind that only primitive types are allowed in this case (at this time) - left.codeGen(mv, typeContext, localVars); - right.codeGen(mv, typeContext, localVars); + left.codeGen(mv, localVars, typeContext); + right.codeGen(mv, localVars, typeContext); mv.visitJumpInsn(Opcodes.IF_ICMPEQ, operationTrue); // If the two values are equal, jump to the end of the expression break; case "<": - left.codeGen(mv, typeContext, localVars); - right.codeGen(mv, typeContext, localVars); + left.codeGen(mv, localVars, typeContext); + right.codeGen(mv, localVars, typeContext); mv.visitJumpInsn(Opcodes.IF_ICMPLT, operationTrue); // Checks only on less than, not equal break; case ">": - left.codeGen(mv, typeContext, localVars); - right.codeGen(mv, typeContext, localVars); + left.codeGen(mv, localVars, typeContext); + right.codeGen(mv, localVars, typeContext); mv.visitJumpInsn(Opcodes.IF_ICMPGT, operationTrue); // Checks only on greater than, not equal break; case "<=": - left.codeGen(mv, typeContext, localVars); - right.codeGen(mv, typeContext, localVars); + left.codeGen(mv, localVars, typeContext); + right.codeGen(mv, localVars, typeContext); mv.visitJumpInsn(Opcodes.IF_ICMPLE, operationTrue); // Checks on less than OR equal break; case ">=": - left.codeGen(mv, typeContext, localVars); - right.codeGen(mv, typeContext, localVars); + left.codeGen(mv, localVars, typeContext); + right.codeGen(mv, localVars, typeContext); mv.visitJumpInsn(Opcodes.IF_ICMPGE, operationTrue); // Checks on greater than OR equal break; case "!=": - left.codeGen(mv, typeContext, localVars); - right.codeGen(mv, typeContext, localVars); + left.codeGen(mv, localVars, typeContext); + right.codeGen(mv, localVars, typeContext); mv.visitJumpInsn(Opcodes.IF_ICMPNE, operationTrue); // Checks on not equal break; case "+": - left.codeGen(mv, typeContext, localVars); - right.codeGen(mv, typeContext, localVars); + left.codeGen(mv, localVars, typeContext); + right.codeGen(mv, localVars, typeContext); mv.visitInsn(Opcodes.IADD); break; case "-": - left.codeGen(mv, typeContext, localVars); - right.codeGen(mv, typeContext, localVars); + left.codeGen(mv, localVars, typeContext); + right.codeGen(mv, localVars, typeContext); mv.visitInsn(Opcodes.ISUB); break; case "*": - left.codeGen(mv, typeContext, localVars); - right.codeGen(mv, typeContext, localVars); + left.codeGen(mv, localVars, typeContext); + right.codeGen(mv, localVars, typeContext); mv.visitInsn(Opcodes.IMUL); break; case "/": - left.codeGen(mv, typeContext, localVars); - right.codeGen(mv, typeContext, localVars); + left.codeGen(mv, localVars, typeContext); + right.codeGen(mv, localVars, typeContext); mv.visitInsn(Opcodes.IDIV); break; diff --git a/src/main/java/abstractSyntaxTree/Expression/IExpression.java b/src/main/java/abstractSyntaxTree/Expression/IExpression.java index 2379268..9730648 100644 --- a/src/main/java/abstractSyntaxTree/Expression/IExpression.java +++ b/src/main/java/abstractSyntaxTree/Expression/IExpression.java @@ -14,5 +14,5 @@ public interface IExpression extends Node { TypeCheckResult typeCheck(HashMap>> methodContext, HashMap> typeContext, HashMap localVars) throws Exception; // visit method for code generation - void codeGen(MethodVisitor mv, HashMap> typeContext, LinkedHashMap localVars) throws Exception; + void codeGen(MethodVisitor mv, LinkedHashMap localVars, HashMap> typeContext) throws Exception; } diff --git a/src/main/java/abstractSyntaxTree/Expression/InstVarExpression.java b/src/main/java/abstractSyntaxTree/Expression/InstVarExpression.java index 3e0daf2..25e8fe2 100644 --- a/src/main/java/abstractSyntaxTree/Expression/InstVarExpression.java +++ b/src/main/java/abstractSyntaxTree/Expression/InstVarExpression.java @@ -35,7 +35,7 @@ public class InstVarExpression implements IExpression{ @Override // typeContext: (ClassName, (FieldName, FieldType)) - public void codeGen(MethodVisitor mv, HashMap> typeContext, LinkedHashMap localVars) throws Exception { + public void codeGen(MethodVisitor mv, LinkedHashMap localVars, HashMap> typeContext) throws Exception { // Load "this" onto the stack mv.visitVarInsn(Opcodes.ALOAD, 0); diff --git a/src/main/java/abstractSyntaxTree/Expression/LocalVarIdentifier.java b/src/main/java/abstractSyntaxTree/Expression/LocalVarIdentifier.java index da3f7ea..f00ff46 100644 --- a/src/main/java/abstractSyntaxTree/Expression/LocalVarIdentifier.java +++ b/src/main/java/abstractSyntaxTree/Expression/LocalVarIdentifier.java @@ -28,7 +28,7 @@ public class LocalVarIdentifier implements IExpression{ } @Override - public void codeGen(MethodVisitor mv, HashMap> typeContext, LinkedHashMap localVars) throws Exception { + public void codeGen(MethodVisitor mv, LinkedHashMap localVars, HashMap> typeContext) throws Exception { // Check if the variable is in the list of local variables String type = localVars.get(identifier); if (type == null){ diff --git a/src/main/java/abstractSyntaxTree/Expression/UnaryExpression.java b/src/main/java/abstractSyntaxTree/Expression/UnaryExpression.java index be1367c..0b8d5da 100644 --- a/src/main/java/abstractSyntaxTree/Expression/UnaryExpression.java +++ b/src/main/java/abstractSyntaxTree/Expression/UnaryExpression.java @@ -50,7 +50,7 @@ public class UnaryExpression extends AbstractType implements IExpression{ } @Override - public void codeGen(MethodVisitor mv, HashMap> typeContext, LinkedHashMap localVars) throws Exception { + public void codeGen(MethodVisitor mv, LinkedHashMap localVars, HashMap> typeContext) throws Exception { operand.codeGen(mv); diff --git a/src/main/java/abstractSyntaxTree/Statement/IfElseStatement.java b/src/main/java/abstractSyntaxTree/Statement/IfElseStatement.java index 4c2c2ed..5fb5f31 100644 --- a/src/main/java/abstractSyntaxTree/Statement/IfElseStatement.java +++ b/src/main/java/abstractSyntaxTree/Statement/IfElseStatement.java @@ -51,7 +51,7 @@ public class IfElseStatement extends AbstractType implements IStatement{ Label conditionFalse = new Label(); Label statementEnd = new Label(); - condition.codeGen(mv, typeContext, localVars); + condition.codeGen(mv, localVars, typeContext); 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 diff --git a/src/main/java/abstractSyntaxTree/Statement/IfStatement.java b/src/main/java/abstractSyntaxTree/Statement/IfStatement.java index d53737d..0598c91 100644 --- a/src/main/java/abstractSyntaxTree/Statement/IfStatement.java +++ b/src/main/java/abstractSyntaxTree/Statement/IfStatement.java @@ -43,7 +43,7 @@ public class IfStatement extends AbstractType implements IStatement{ Label conditionFalse = new Label(); - condition.codeGen(mv, typeContext, localVars); + condition.codeGen(mv, localVars, typeContext); mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); //Checks if the condition is false (0) ifStatement.codeGen(mv, blockLocalVars, typeContext); diff --git a/src/main/java/abstractSyntaxTree/Statement/ReturnStatement.java b/src/main/java/abstractSyntaxTree/Statement/ReturnStatement.java index 87782c4..d0b44ee 100644 --- a/src/main/java/abstractSyntaxTree/Statement/ReturnStatement.java +++ b/src/main/java/abstractSyntaxTree/Statement/ReturnStatement.java @@ -38,7 +38,7 @@ public class ReturnStatement extends AbstractType implements IStatement{ public void codeGen(MethodVisitor mv, LinkedHashMap localVars, HashMap> typeContext) throws Exception { if (expression != null) { - expression.codeGen(mv, typeContext, localVars); + expression.codeGen(mv, localVars, typeContext); //Get the Type of the expression //TODO: Resolve how do we get the type of the expression String type = expression.typeCheck(null, null, null).type; diff --git a/src/main/java/abstractSyntaxTree/Statement/WhileStatement.java b/src/main/java/abstractSyntaxTree/Statement/WhileStatement.java index 1b7b577..9872d8d 100644 --- a/src/main/java/abstractSyntaxTree/Statement/WhileStatement.java +++ b/src/main/java/abstractSyntaxTree/Statement/WhileStatement.java @@ -45,7 +45,7 @@ public class WhileStatement extends AbstractType implements IStatement { mv.visitLabel(LoopStart); - condition.codeGen(mv, typeContext, localVars); + condition.codeGen(mv, localVars, typeContext); mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); // Checks if the condition is false (0) statement.codeGen(mv, blockLocalVars, typeContext); diff --git a/src/main/java/abstractSyntaxTree/StatementExpression/AssignStatementExpression.java b/src/main/java/abstractSyntaxTree/StatementExpression/AssignStatementExpression.java index b2f1e53..7809a69 100644 --- a/src/main/java/abstractSyntaxTree/StatementExpression/AssignStatementExpression.java +++ b/src/main/java/abstractSyntaxTree/StatementExpression/AssignStatementExpression.java @@ -12,6 +12,7 @@ import org.objectweb.asm.*; import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.Objects; public class AssignStatementExpression extends AbstractType implements IExpression, IStatement { public String operator; @@ -50,42 +51,34 @@ public class AssignStatementExpression extends AbstractType implements IExpressi return result; } - @Override - public void codeGen(MethodVisitor mv, HashMap localVars) throws Exception { - if (left instanceof VarRefExpression varRef) { - - } - - } - public TypeCheckResult typeCheck() throws Exception { return null; } @Override - public void codeGen(MethodVisitor mv, HashMap> typeContext, LinkedHashMap localVars) throws Exception { + public void codeGen(MethodVisitor mv, LinkedHashMap localVars, HashMap> typeContext) 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, typeContext, localVars); + right.codeGen(mv, localVars, typeContext); - if (left instanceof LocalVarIdentifier) { + if (left instanceof LocalVarIdentifier) { LocalVarIdentifier localVar = (LocalVarIdentifier) left; String varName = localVar.getIdentifier(); //Get the index of the local variable int index = -1; int counter = 0; - for (String key : localVars.keySet()){ - if (key.equals(varName)){ + for (String key : localVars.keySet()) { + if (key.equals(varName)) { index = counter; break; } counter++; } - if (index == -1){ + if (index == -1) { throw new Exception("Variable " + varName + " not found"); } @@ -100,20 +93,23 @@ public class AssignStatementExpression extends AbstractType implements IExpressi break; } - } else if (left instanceof InstVarExpression){ + } else if (left instanceof InstVarExpression) { instVar = (InstVarExpression) left; // Load "this" onto the stack mv.visitVarInsn(Opcodes.ALOAD, 0); + } + /* + 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); -// 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); -// -// // We now again need the owner (class reference), name (of the Field in the owner) and type of the field -// //mv.visitFieldInsn(Opcodes.PUTFIELD, instVar.className, instVar.varName, instVar.type); -// } + // We now again need the owner (class reference), name (of the Field in the owner) and type of the field + //mv.visitFieldInsn(Opcodes.PUTFIELD, instVar.className, instVar.varName, instVar.type); + } + } + */ } } diff --git a/src/main/java/abstractSyntaxTree/StatementExpression/MethodCallStatementExpression.java b/src/main/java/abstractSyntaxTree/StatementExpression/MethodCallStatementExpression.java index 7a8498c..cf526f9 100644 --- a/src/main/java/abstractSyntaxTree/StatementExpression/MethodCallStatementExpression.java +++ b/src/main/java/abstractSyntaxTree/StatementExpression/MethodCallStatementExpression.java @@ -51,11 +51,10 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr return null; } - //Errors occur due to the change in parameter in the RefType class // I need the methodContext here to get the method descriptor @Override - public void codeGen(MethodVisitor mv, HashMap> typeContext, LinkedHashMap localVars) throws Exception { + public void codeGen(MethodVisitor mv, LinkedHashMap localVars, HashMap> typeContext) throws Exception { //Generate Bytecode for the receiver if(classThatHasTheMethodIfNotThis != null){ //TODO: classThatHasTheMethodIfNotThis must be an object --> instance of the class not the class itself @@ -66,10 +65,10 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr for (MethodDecl methodDecl : methodDecls) { if (methodDecl.name.equals(methodName)) { //Get the method descriptor - descriptor = methodDecl.getMethodDescriptor(methodContext); + //descriptor = methodDecl.getMethodDescriptor(methodContext); } } - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, classThatHasTheMethodIfNotThis.name, methodName, descriptor, false); + //mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, classThatHasTheMethodIfNotThis.name, methodName, descriptor, false); } else { // Load this onto the stack @@ -77,7 +76,7 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr } for (IExpression argument : arguments) { - argument.codeGen(mv, typeContext, localVars); + argument.codeGen(mv, localVars, typeContext); } // Get the method descriptor @@ -86,9 +85,9 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr for (MethodDecl methodDecl : methodDecls) { if (methodDecl.name.equals(methodName)) { //Get the method descriptor - descriptor = methodDecl.getMethodDescriptor(methodContext); + //descriptor = methodDecl.getMethodDescriptor(methodContext); } } - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, thisClass.name, methodName, descriptor, false); + //mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, thisClass.name, methodName, descriptor, false); } } diff --git a/src/main/java/abstractSyntaxTree/StatementExpression/NewStatementExpression.java b/src/main/java/abstractSyntaxTree/StatementExpression/NewStatementExpression.java index 7938552..0aee650 100644 --- a/src/main/java/abstractSyntaxTree/StatementExpression/NewStatementExpression.java +++ b/src/main/java/abstractSyntaxTree/StatementExpression/NewStatementExpression.java @@ -8,6 +8,7 @@ import abstractSyntaxTree.Statement.IStatement; import org.objectweb.asm.MethodVisitor; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; public class NewStatementExpression extends AbstractType implements IExpression, IStatement { @@ -19,12 +20,12 @@ public class NewStatementExpression extends AbstractType implements IExpression, } @Override - public void codeGen(MethodVisitor mv, HashMap localVars) throws Exception { + public void codeGen(MethodVisitor mv, LinkedHashMap localVars, HashMap> typeContext) throws Exception { } @Override - public void codeGen(MethodVisitor mv) throws Exception { - throw new Exception("CodeGen not implemented for NewStatementExpression"); + public void codeGen(MethodVisitor mv, HashMap> typeContext, LinkedHashMap localVars) throws Exception { + } }