diff --git a/src/main/java/Compiler.java b/src/main/java/Compiler.java index 0a0ff90..3f197ab 100644 --- a/src/main/java/Compiler.java +++ b/src/main/java/Compiler.java @@ -28,7 +28,7 @@ public class Compiler { public static void main(String[] args) throws Exception{ - Path filePath = Paths.get("src/main/java/Input.java"); + Path filePath = Paths.get("src/main/java/InputTest.java"); // todo remove this debug info diff --git a/src/main/java/TypeCheck/TypeCheckHelper.java b/src/main/java/TypeCheck/TypeCheckHelper.java index 173a21e..b9a4cb3 100644 --- a/src/main/java/TypeCheck/TypeCheckHelper.java +++ b/src/main/java/TypeCheck/TypeCheckHelper.java @@ -24,7 +24,7 @@ public class TypeCheckHelper { } public static boolean typeExists(String type, List customTypeslist) { - if(type.equals("int") || type.equals("bool") || type.equals("char")){ + if(type.equals("int") || type.equals("boolean") || type.equals("char")){ return true; } return customTypeslist.contains(type); diff --git a/src/main/java/abstractSyntaxTree/Class/MethodDecl.java b/src/main/java/abstractSyntaxTree/Class/MethodDecl.java index 04c7525..b4cfcab 100644 --- a/src/main/java/abstractSyntaxTree/Class/MethodDecl.java +++ b/src/main/java/abstractSyntaxTree/Class/MethodDecl.java @@ -125,7 +125,7 @@ public class MethodDecl implements Node { for (Parameter param : parameters.parameterList) { switch (param.type) { case "int" -> descriptor.append("I"); - case "bool" -> descriptor.append("Z"); + case "boolean" -> descriptor.append("Z"); case "char" -> descriptor.append("C"); case "void" -> descriptor.append("V"); default -> { @@ -144,11 +144,12 @@ public class MethodDecl implements Node { } else { switch (returnType) { case "int" -> descriptor.append("I"); - case "bool" -> descriptor.append("Z"); + case "boolean" -> descriptor.append("Z"); case "char" -> descriptor.append("C"); case "void" -> descriptor.append("V"); default -> { // object + // methodContext (class, (returnType, (identifier, parameter))) HashMap> classMethods = methodContext.get(classThatContainsMethod); HashMap methodDetails = classMethods.get(name); diff --git a/src/main/java/abstractSyntaxTree/Expression/BooleanConstantExpression.java b/src/main/java/abstractSyntaxTree/Expression/BooleanConstantExpression.java index ffc7198..da0e925 100644 --- a/src/main/java/abstractSyntaxTree/Expression/BooleanConstantExpression.java +++ b/src/main/java/abstractSyntaxTree/Expression/BooleanConstantExpression.java @@ -5,6 +5,7 @@ import TypeCheck.TypeCheckException; import TypeCheck.TypeCheckResult; import abstractSyntaxTree.Parameter.ParameterList; import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; import java.util.HashMap; import java.util.LinkedHashMap; @@ -26,7 +27,11 @@ public class BooleanConstantExpression extends AbstractType implements IExpressi @Override public void codeGen(MethodVisitor mv, LinkedHashMap localVars, HashMap> typeContext) throws Exception { - + if (value){ + mv.visitInsn(Opcodes.ICONST_1); + } else { + mv.visitInsn(Opcodes.ICONST_0); + } } @Override public TypeCheckResult getTypeCheckResult() { diff --git a/src/main/java/abstractSyntaxTree/Expression/CharConstantExpression.java b/src/main/java/abstractSyntaxTree/Expression/CharConstantExpression.java index ecc0b4f..1485cd5 100644 --- a/src/main/java/abstractSyntaxTree/Expression/CharConstantExpression.java +++ b/src/main/java/abstractSyntaxTree/Expression/CharConstantExpression.java @@ -4,6 +4,7 @@ import TypeCheck.AbstractType; import TypeCheck.TypeCheckResult; import abstractSyntaxTree.Parameter.ParameterList; import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; import java.util.HashMap; import java.util.LinkedHashMap; @@ -25,7 +26,7 @@ public class CharConstantExpression extends AbstractType implements IExpression{ @Override public void codeGen(MethodVisitor mv, LinkedHashMap localVars, HashMap> typeContext) throws Exception { - + mv.visitIntInsn(Opcodes.BIPUSH, (int) value); } @Override diff --git a/src/main/java/abstractSyntaxTree/Expression/IntConstantExpression.java b/src/main/java/abstractSyntaxTree/Expression/IntConstantExpression.java index c10e36c..fd1fb24 100644 --- a/src/main/java/abstractSyntaxTree/Expression/IntConstantExpression.java +++ b/src/main/java/abstractSyntaxTree/Expression/IntConstantExpression.java @@ -4,6 +4,7 @@ import TypeCheck.AbstractType; import TypeCheck.TypeCheckResult; import abstractSyntaxTree.Parameter.ParameterList; import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; import java.util.HashMap; import java.util.LinkedHashMap; @@ -27,7 +28,8 @@ public class IntConstantExpression extends AbstractType implements IExpression{ @Override public void codeGen(MethodVisitor mv, LinkedHashMap localVars, HashMap> typeContext) throws Exception { - + //TODO: When we are finished this can be done more efficiently + mv.visitLdcInsn(value); } @Override diff --git a/src/main/java/abstractSyntaxTree/Expression/LocalVarIdentifier.java b/src/main/java/abstractSyntaxTree/Expression/LocalVarIdentifier.java index 69c115f..aa8345e 100644 --- a/src/main/java/abstractSyntaxTree/Expression/LocalVarIdentifier.java +++ b/src/main/java/abstractSyntaxTree/Expression/LocalVarIdentifier.java @@ -45,12 +45,12 @@ public class LocalVarIdentifier extends AbstractType implements IExpression{ throw new Exception("Variable " + identifier + " not declared"); } - // Load the variable onto the stack + // Find the index of the variable int index = -1; int counter = 0; for (String key : localVars.keySet()){ if (key.equals(identifier)){ - index = counter; + index = counter+1; // +1 because the first local variable is at index 1, 0 is used for "this" break; } counter++; @@ -65,7 +65,7 @@ public class LocalVarIdentifier extends AbstractType implements IExpression{ case "int": mv.visitVarInsn(Opcodes.ILOAD, index); break; - case "bool": + case "boolean": mv.visitVarInsn(Opcodes.ILOAD, index); break; case "void": diff --git a/src/main/java/abstractSyntaxTree/Statement/LocalVarDecl.java b/src/main/java/abstractSyntaxTree/Statement/LocalVarDecl.java index fd748c3..44338f2 100644 --- a/src/main/java/abstractSyntaxTree/Statement/LocalVarDecl.java +++ b/src/main/java/abstractSyntaxTree/Statement/LocalVarDecl.java @@ -43,15 +43,16 @@ public class LocalVarDecl extends AbstractType implements IStatement{ public void codeGen(MethodVisitor mv, LinkedHashMap localVars, HashMap> typeContext) throws Exception { localVars.put(identifier, type); - // Set a default value for the variable --> less problems + int index = localVars.size()-1; + // Set a default value for the variable --> less problems switch (type){ case "int": mv.visitInsn(Opcodes.ICONST_0); mv.visitVarInsn(Opcodes.ISTORE, index); break; - case "bool": + case "boolean": mv.visitInsn(Opcodes.ICONST_0); mv.visitVarInsn(Opcodes.ISTORE, index); break; diff --git a/src/main/java/abstractSyntaxTree/Statement/ReturnStatement.java b/src/main/java/abstractSyntaxTree/Statement/ReturnStatement.java index f6dfd8c..b9a64e4 100644 --- a/src/main/java/abstractSyntaxTree/Statement/ReturnStatement.java +++ b/src/main/java/abstractSyntaxTree/Statement/ReturnStatement.java @@ -50,7 +50,6 @@ public class ReturnStatement extends AbstractType implements IStatement{ mv.visitInsn(Opcodes.IRETURN); } else { mv.visitInsn(Opcodes.ARETURN); - } } else { mv.visitInsn(Opcodes.RETURN); diff --git a/src/main/java/abstractSyntaxTree/StatementExpression/AssignStatementExpression.java b/src/main/java/abstractSyntaxTree/StatementExpression/AssignStatementExpression.java index e8975f8..917aa8e 100644 --- a/src/main/java/abstractSyntaxTree/StatementExpression/AssignStatementExpression.java +++ b/src/main/java/abstractSyntaxTree/StatementExpression/AssignStatementExpression.java @@ -46,7 +46,7 @@ public class AssignStatementExpression extends AbstractType implements IExpressi String upperbound = TypeCheckHelper.upperBound(leftType.type, rightType.type); if(Objects.equals(leftType.type, "boolean")) - leftType.type = "bool"; + leftType.type = "boolean"; if (!Objects.equals(upperbound, leftType.type)) { throw new TypeCheckException("The upper bound of assignment is not the left type."); } @@ -77,7 +77,7 @@ public class AssignStatementExpression extends AbstractType implements IExpressi int counter = 0; for (String key : localVars.keySet()) { if (key.equals(varName)) { - index = counter; + index = counter+1; break; } counter++; @@ -89,8 +89,7 @@ public class AssignStatementExpression extends AbstractType implements IExpressi String type = localVars.get(localVar.getIdentifier()); switch (type) { - case "int": - case "bool": + case "int", "char", "boolean": mv.visitVarInsn(Opcodes.ISTORE, index); break; default: @@ -116,7 +115,7 @@ public class AssignStatementExpression extends AbstractType implements IExpressi case "int": descriptor.append("I"); break; - case "bool": + case "boolean": descriptor.append("Z"); break; default: diff --git a/src/main/java/abstractSyntaxTree/StatementExpression/MethodCallStatementExpression.java b/src/main/java/abstractSyntaxTree/StatementExpression/MethodCallStatementExpression.java index bfbe742..92646c0 100644 --- a/src/main/java/abstractSyntaxTree/StatementExpression/MethodCallStatementExpression.java +++ b/src/main/java/abstractSyntaxTree/StatementExpression/MethodCallStatementExpression.java @@ -65,41 +65,45 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr @Override 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 - // This is not finished - // Need to call codeGen so it pushes the instance onto the stack, which will be popped of - //classThatHasTheMethodIfNotThis.codeGen(); - - String descriptor; - List methodDecls = thisClass.methodDecls; - for (MethodDecl methodDecl : methodDecls) { - if (methodDecl.name.equals(methodName)) { - //Get the method descriptor - // descriptor = methodDecl.getMethodDescriptor(methodContext); - } - } - // mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, classThatHasTheMethodIfNotThis.name, methodName, descriptor, false); - - } else { - // Load this onto the stack + 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); - for (IExpression argument : arguments) { - argument.codeGen(mv, localVars, typeContext); - } + } else if (receiver.newStatementExpression != null) { + receiver.newStatementExpression.codeGen(mv, localVars, typeContext); - // Get the method descriptor - String descriptor; - List methodDecls = thisClass.methodDecls; - for (MethodDecl methodDecl : methodDecls) { - if (methodDecl.name.equals(methodName)) { - //Get the method descriptor - //descriptor = methodDecl.getMethodDescriptor(methodContext); + // Not sure about this part + } else if (receiver.identifier != null) { + // Load local variable onto the stack + for (String key : localVars.keySet()) { + if (key.equals(receiver.identifier)) { + String type = localVars.get(key); + int opcode = type.equals("int") ? Opcodes.ILOAD : Opcodes.ALOAD; + mv.visitVarInsn(opcode, Integer.parseInt(key)); + break; } } - // mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, thisClass.name, methodName, descriptor, false); } + + // Generate Bytecode for the arguments + for (IExpression argument : arguments) { + argument.codeGen(mv, localVars, typeContext); + } + + + String descriptor; + List 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 diff --git a/src/main/java/abstractSyntaxTree/StatementExpression/NewStatementExpression.java b/src/main/java/abstractSyntaxTree/StatementExpression/NewStatementExpression.java index a868c0e..4188fbd 100644 --- a/src/main/java/abstractSyntaxTree/StatementExpression/NewStatementExpression.java +++ b/src/main/java/abstractSyntaxTree/StatementExpression/NewStatementExpression.java @@ -53,6 +53,9 @@ public class NewStatementExpression extends AbstractType implements IExpression, //Call the constructor mv.visitMethodInsn(Opcodes.INVOKESPECIAL, className, "", descriptor, false); + + // One instance of the class remains now on the stack + // Which will then be used in an assignment or method call } private String getConstructorDescriptor() { @@ -66,7 +69,7 @@ public class NewStatementExpression extends AbstractType implements IExpression, case "int": descriptor.append("I"); break; - case "bool": + case "boolean": descriptor.append("Z"); break; case "char":