diff --git a/Source/abstractSyntaxTree/Expression/InstVarExpression.java b/Source/abstractSyntaxTree/Expression/InstVarExpression.java index 8eee374..4cefa0c 100644 --- a/Source/abstractSyntaxTree/Expression/InstVarExpression.java +++ b/Source/abstractSyntaxTree/Expression/InstVarExpression.java @@ -1,10 +1,32 @@ package abstractSyntaxTree.Expression; import TypeCheck.TypeCheckResult; +import abstractSyntaxTree.Datatype.RefType; +import jdk.jshell.spi.ExecutionControl; +import org.objectweb.asm.MethodVisitor; 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 + private RefType classRef; + private String fieldName; + +/* public InstVarExpression(RefType classRef, String fieldName){ + this.classRef = classRef; + this.fieldName = fieldName; + }*/ @Override public TypeCheckResult typeCheck() throws Exception { return null; } + + @Override + public void CodeGen(MethodVisitor mv) throws Exception { + throw new ExecutionControl.NotImplementedException("CodeGen not implemented for InstVarExpression"); + + //ALOAD the index of the var + //GETFIELD the field + //visitFieldInsn(Opcodes.GETFIELD, "class reference", "field name", type); + } } diff --git a/Source/abstractSyntaxTree/Expression/UnaryExpression.java b/Source/abstractSyntaxTree/Expression/UnaryExpression.java index 73e880b..890a43a 100644 --- a/Source/abstractSyntaxTree/Expression/UnaryExpression.java +++ b/Source/abstractSyntaxTree/Expression/UnaryExpression.java @@ -4,6 +4,8 @@ import TypeCheck.AbstractType; import TypeCheck.TypeCheckHelper; import TypeCheck.TypeCheckResult; import abstractSyntaxTree.Datatype.IDatatype; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; import java.util.Objects; @@ -38,4 +40,26 @@ public class UnaryExpression extends AbstractType implements IExpression{ setTypeCheckResult(result); return result; } + + @Override + public void CodeGen(MethodVisitor mv) throws Exception { + + operand.CodeGen(mv); + + switch (operator) { + case "!": + //XOR with 1 to get the negation + mv.visitInsn(Opcodes.ICONST_1); + mv.visitInsn(Opcodes.IXOR); + break; + case "-": + mv.visitInsn(Opcodes.INEG); + break; + case "+": + break; + + default: throw new Exception("Unknown operator :" + operator); + } + + } } diff --git a/Source/abstractSyntaxTree/Expression/VarRefExpression.java b/Source/abstractSyntaxTree/Expression/VarRefExpression.java index 2361d68..b94b166 100644 --- a/Source/abstractSyntaxTree/Expression/VarRefExpression.java +++ b/Source/abstractSyntaxTree/Expression/VarRefExpression.java @@ -1,10 +1,23 @@ package abstractSyntaxTree.Expression; import TypeCheck.TypeCheckResult; +import org.objectweb.asm.MethodVisitor; + +import java.util.Map; public class VarRefExpression implements IExpression{ + + //Parameters that are needed here + private String varName; + private Map localVars; + @Override public TypeCheckResult typeCheck() throws Exception { return null; } + + @Override + public void CodeGen(MethodVisitor mv) throws Exception { + throw new Exception("CodeGen not implemented for VarRefExpression"); + } } diff --git a/Source/abstractSyntaxTree/Modifier/IModifier.java b/Source/abstractSyntaxTree/Modifier/IModifier.java index e201d50..e8c98ab 100644 --- a/Source/abstractSyntaxTree/Modifier/IModifier.java +++ b/Source/abstractSyntaxTree/Modifier/IModifier.java @@ -1,6 +1,10 @@ package abstractSyntaxTree.Modifier; public interface IModifier { + + //TODO: Maybe we can just use an enum for the Modifier + // if there is no typeCheck and no CodeGen + // not type or type check // visit method for code generation diff --git a/Source/abstractSyntaxTree/Statement/BlockStatement.java b/Source/abstractSyntaxTree/Statement/BlockStatement.java index f1fdc4e..3fb36e4 100644 --- a/Source/abstractSyntaxTree/Statement/BlockStatement.java +++ b/Source/abstractSyntaxTree/Statement/BlockStatement.java @@ -3,10 +3,13 @@ package abstractSyntaxTree.Statement; import TypeCheck.TypeCheckResult; import TypeCheck.AbstractType; import abstractSyntaxTree.Expression.IExpression; +import org.objectweb.asm.MethodVisitor; import java.util.List; public class BlockStatement extends AbstractType implements IStatement{ + + //We will need a parameter which holds the symbol table List statements; public BlockStatement(List statements){ this.statements = statements; @@ -31,4 +34,11 @@ public class BlockStatement extends AbstractType implements IStatement{ } return result; } + + @Override + public void CodeGen(MethodVisitor mv) throws Exception { + for (IStatement statement : statements) { + statement.CodeGen(mv); //TODO: I think we need to pass the symbol table here + } + } } diff --git a/Source/abstractSyntaxTree/Statement/EmptyStatement.java b/Source/abstractSyntaxTree/Statement/EmptyStatement.java index 43dd155..b6ce18e 100644 --- a/Source/abstractSyntaxTree/Statement/EmptyStatement.java +++ b/Source/abstractSyntaxTree/Statement/EmptyStatement.java @@ -2,6 +2,7 @@ package abstractSyntaxTree.Statement; import TypeCheck.TypeCheckResult; import TypeCheck.AbstractType; +import org.objectweb.asm.MethodVisitor; public class EmptyStatement extends AbstractType implements IStatement{ @Override @@ -10,4 +11,9 @@ public class EmptyStatement extends AbstractType implements IStatement{ result.type = "void"; return result; } + + @Override + public void CodeGen(MethodVisitor mv) throws Exception { + //An empty statement does not generate any code + } } diff --git a/Source/abstractSyntaxTree/Statement/IStatement.java b/Source/abstractSyntaxTree/Statement/IStatement.java index daa669a..65a2cb0 100644 --- a/Source/abstractSyntaxTree/Statement/IStatement.java +++ b/Source/abstractSyntaxTree/Statement/IStatement.java @@ -1,10 +1,11 @@ package abstractSyntaxTree.Statement; import TypeCheck.TypeCheckResult; +import org.objectweb.asm.MethodVisitor; public interface IStatement { TypeCheckResult typeCheck() throws Exception; - // visit method for code generation + void CodeGen(MethodVisitor mv) throws Exception; } diff --git a/Source/abstractSyntaxTree/Statement/IfElseStatement.java b/Source/abstractSyntaxTree/Statement/IfElseStatement.java index 2f19499..55f7619 100644 --- a/Source/abstractSyntaxTree/Statement/IfElseStatement.java +++ b/Source/abstractSyntaxTree/Statement/IfElseStatement.java @@ -3,6 +3,7 @@ package abstractSyntaxTree.Statement; import TypeCheck.TypeCheckResult; import TypeCheck.AbstractType; import abstractSyntaxTree.Expression.IExpression; +import org.objectweb.asm.*; public class IfElseStatement extends AbstractType implements IStatement{ IExpression condition; @@ -35,4 +36,23 @@ public class IfElseStatement extends AbstractType implements IStatement{ result.type = elseStatementType.type; return result; } + + @Override + public void CodeGen(MethodVisitor mv) throws Exception { + + Label conditionFalse = new Label(); + Label statementEnd = new Label(); + + condition.CodeGen(mv); + + mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); //Checks if the condition is false (0) + ifStatement.CodeGen(mv); //If the condition is true, execute the ifBlock + mv.visitJumpInsn(Opcodes.GOTO, statementEnd); //Jump to the end of the if-else statement + + mv.visitLabel(conditionFalse); + elseStatement.CodeGen(mv); //If the condition is false, execute the elseBlock + + mv.visitLabel(statementEnd); //End of the if-else statement + + } } diff --git a/Source/abstractSyntaxTree/Statement/IfStatement.java b/Source/abstractSyntaxTree/Statement/IfStatement.java index 0c19016..c1a915d 100644 --- a/Source/abstractSyntaxTree/Statement/IfStatement.java +++ b/Source/abstractSyntaxTree/Statement/IfStatement.java @@ -3,9 +3,12 @@ package abstractSyntaxTree.Statement; import TypeCheck.TypeCheckResult; import TypeCheck.AbstractType; import abstractSyntaxTree.Expression.IExpression; +import org.objectweb.asm.*; public class IfStatement extends AbstractType implements IStatement{ IExpression condition; + + //Do we need a block statement here? IStatement ifStatement; public IfStatement(IExpression condition, IStatement ifStatement) { @@ -27,6 +30,18 @@ public class IfStatement extends AbstractType implements IStatement{ return result; } + @Override + public void CodeGen(MethodVisitor mv) throws Exception { + + Label conditionFalse = new Label(); + + condition.CodeGen(mv); + + mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); //Checks if the condition is false (0) + ifStatement.CodeGen(mv); + + mv.visitLabel(conditionFalse); // If the condition is false, the Statements in the ifBlock will not be executed + } } diff --git a/Source/abstractSyntaxTree/Statement/ReturnStatement.java b/Source/abstractSyntaxTree/Statement/ReturnStatement.java index 10b92df..2ee7536 100644 --- a/Source/abstractSyntaxTree/Statement/ReturnStatement.java +++ b/Source/abstractSyntaxTree/Statement/ReturnStatement.java @@ -3,6 +3,7 @@ package abstractSyntaxTree.Statement; import TypeCheck.TypeCheckResult; import TypeCheck.AbstractType; import abstractSyntaxTree.Expression.IExpression; +import org.objectweb.asm.*; public class ReturnStatement extends AbstractType implements IStatement{ IExpression expression; @@ -24,4 +25,27 @@ public class ReturnStatement extends AbstractType implements IStatement{ return result; } + + + //TODO: We do not differentiate between primitive types and reference types + // 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 + @Override + public void CodeGen(MethodVisitor mv) throws Exception { + + if (expression != null) { + expression.CodeGen(mv); + //Get the Type of the expression + String type = expression.typeCheck().type; + + if (type.equals("int") || type.equals("bool")) { + mv.visitInsn(Opcodes.IRETURN); + } else { + mv.visitInsn(Opcodes.ARETURN); + + } + } else { + mv.visitInsn(Opcodes.RETURN); + } + } } diff --git a/Source/abstractSyntaxTree/Statement/WhileStatement.java b/Source/abstractSyntaxTree/Statement/WhileStatement.java index 288bcec..128660e 100644 --- a/Source/abstractSyntaxTree/Statement/WhileStatement.java +++ b/Source/abstractSyntaxTree/Statement/WhileStatement.java @@ -3,14 +3,17 @@ package abstractSyntaxTree.Statement; import TypeCheck.TypeCheckResult; import TypeCheck.AbstractType; import abstractSyntaxTree.Expression.IExpression; +import org.objectweb.asm.*; -public class WhileStatement extends AbstractType implements IStatement{ +public class WhileStatement extends AbstractType implements IStatement { IExpression condition; IStatement statement; + public WhileStatement(IExpression condition, IStatement statement) { this.condition = condition; this.statement = statement; } + @Override public TypeCheckResult typeCheck() throws Exception { TypeCheckResult result = new TypeCheckResult(); @@ -26,4 +29,22 @@ public class WhileStatement extends AbstractType implements IStatement{ result.type = statementType.type; return result; } -} + + @Override + public void CodeGen(MethodVisitor mv) throws Exception { + Label conditionFalse = new Label(); + Label LoopStart = new Label(); + + mv.visitLabel(LoopStart); + + condition.CodeGen(mv); + mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); // Checks if the condition is false (0) + + statement.CodeGen(mv); + //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 + mv.visitJumpInsn(Opcodes.GOTO, LoopStart); // Jump to the start of the while loop + + mv.visitLabel(conditionFalse); + } +} \ No newline at end of file diff --git a/Source/abstractSyntaxTree/StatementExpression/AssignStatementExpression.java b/Source/abstractSyntaxTree/StatementExpression/AssignStatementExpression.java index 520370b..11c7fb1 100644 --- a/Source/abstractSyntaxTree/StatementExpression/AssignStatementExpression.java +++ b/Source/abstractSyntaxTree/StatementExpression/AssignStatementExpression.java @@ -4,7 +4,10 @@ import TypeCheck.AbstractType; import TypeCheck.TypeCheckHelper; import TypeCheck.TypeCheckResult; import abstractSyntaxTree.Expression.IExpression; +import abstractSyntaxTree.Expression.InstVarExpression; +import abstractSyntaxTree.Expression.VarRefExpression; import abstractSyntaxTree.Statement.IStatement; +import org.objectweb.asm.*; import java.util.Objects; @@ -28,4 +31,20 @@ public class AssignStatementExpression extends AbstractType implements IExpressi setTypeCheckResult(result); return result; } + + @Override + public void CodeGen(MethodVisitor mv) throws Exception { + left.CodeGen(mv); + right.CodeGen(mv); + + if (left instanceof VarRefExpression varRef) { + //TODO: Implement the handling of a variable reference --> I need a lis 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); + } + } } diff --git a/Source/abstractSyntaxTree/StatementExpression/MethodCallStatementExpression.java b/Source/abstractSyntaxTree/StatementExpression/MethodCallStatementExpression.java index ee428d6..bffaa94 100644 --- a/Source/abstractSyntaxTree/StatementExpression/MethodCallStatementExpression.java +++ b/Source/abstractSyntaxTree/StatementExpression/MethodCallStatementExpression.java @@ -6,6 +6,8 @@ import abstractSyntaxTree.Class.MethodDecl; import abstractSyntaxTree.Datatype.RefType; import abstractSyntaxTree.Expression.IExpression; import abstractSyntaxTree.Statement.IStatement; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; import java.util.List; @@ -39,4 +41,22 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr return result; } + + @Override + public void CodeGen(MethodVisitor mv) throws Exception { + //Generate Bytecode for the receiver + if(classThatHasTheMethodIfNotThis != null){ + classThatHasTheMethodIfNotThis.CodeGen(mv); + } else { + mv.visitVarInsn(Opcodes.ALOAD, 0); + } + + for (IExpression argument : arguments) { + argument.CodeGen(mv); + } + + //We need the class reference and the return type of the method + //mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, thisClass.name, methodName, return type); + + } } diff --git a/Source/abstractSyntaxTree/StatementExpression/NewStatementExpression.java b/Source/abstractSyntaxTree/StatementExpression/NewStatementExpression.java index 915ee84..9992585 100644 --- a/Source/abstractSyntaxTree/StatementExpression/NewStatementExpression.java +++ b/Source/abstractSyntaxTree/StatementExpression/NewStatementExpression.java @@ -4,10 +4,16 @@ import TypeCheck.AbstractType; import TypeCheck.TypeCheckResult; import abstractSyntaxTree.Expression.IExpression; import abstractSyntaxTree.Statement.IStatement; +import org.objectweb.asm.MethodVisitor; public class NewStatementExpression extends AbstractType implements IExpression, IStatement { @Override public TypeCheckResult typeCheck() throws Exception { return null; } + + @Override + public void CodeGen(MethodVisitor mv) throws Exception { + throw new Exception("CodeGen not implemented for NewStatementExpression"); + } }