From a259aa3a51d7173add8424adc932b48c629ed7ae Mon Sep 17 00:00:00 2001 From: ahmad Date: Thu, 4 Jul 2024 16:55:54 +0200 Subject: [PATCH] Add the exception to the list --- src/main/java/de/maishai/Compiler.java | 14 ++++++-- .../FieldAlreadyDeclaredException.java | 10 ++++++ .../LocalVariableAlreadDeclaredException.java | 7 ++++ .../NotFoundMethodOrConstructor.java | 9 +++++ .../NotMatchConstructorException.java | 13 ++++++++ .../ParameterAlreadyExistsException.java | 14 ++++++++ .../TypeMismatchException.java | 9 +++++ .../TypeOfReturnNotMatchException.java | 17 ++++++++++ .../VariableNotDeclaredException.java | 13 ++++++++ .../typedast/typedclass/TypedAssignment.java | 33 ++++++++++++------- .../typedast/typedclass/TypedBinary.java | 16 ++++++--- .../typedast/typedclass/TypedClass.java | 1 - .../typedast/typedclass/TypedConstructor.java | 8 +++-- .../typedast/typedclass/TypedDeclaration.java | 7 ++-- .../typedast/typedclass/TypedDoWhile.java | 3 +- .../typedclass/TypedFieldVarAccess.java | 11 +++++-- .../maishai/typedast/typedclass/TypedFor.java | 3 +- .../typedclass/TypedLocalVariable.java | 11 +++++-- .../typedast/typedclass/TypedMethod.java | 3 +- .../typedast/typedclass/TypedMethodCall.java | 3 +- .../maishai/typedast/typedclass/TypedNew.java | 4 ++- .../typedast/typedclass/TypedParameter.java | 7 ++-- .../typedast/typedclass/TypedProgram.java | 27 +++++++++++++++ .../typedast/typedclass/TypedReturn.java | 27 +++++++++++---- .../typedast/typedclass/TypedUnary.java | 9 +++-- .../typedast/typedclass/TypedWhile.java | 3 +- 26 files changed, 233 insertions(+), 49 deletions(-) create mode 100644 src/main/java/de/maishai/typedast/ExceptionHandler/FieldAlreadyDeclaredException.java create mode 100644 src/main/java/de/maishai/typedast/ExceptionHandler/LocalVariableAlreadDeclaredException.java create mode 100644 src/main/java/de/maishai/typedast/ExceptionHandler/NotFoundMethodOrConstructor.java create mode 100644 src/main/java/de/maishai/typedast/ExceptionHandler/NotMatchConstructorException.java create mode 100644 src/main/java/de/maishai/typedast/ExceptionHandler/ParameterAlreadyExistsException.java create mode 100644 src/main/java/de/maishai/typedast/ExceptionHandler/TypeMismatchException.java create mode 100644 src/main/java/de/maishai/typedast/ExceptionHandler/TypeOfReturnNotMatchException.java create mode 100644 src/main/java/de/maishai/typedast/ExceptionHandler/VariableNotDeclaredException.java diff --git a/src/main/java/de/maishai/Compiler.java b/src/main/java/de/maishai/Compiler.java index ec54be2..fcdb805 100644 --- a/src/main/java/de/maishai/Compiler.java +++ b/src/main/java/de/maishai/Compiler.java @@ -13,6 +13,7 @@ import org.apache.commons.cli.*; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.logging.Formatter; import java.util.logging.Handler; @@ -81,14 +82,21 @@ public class Compiler { Program program = generateASTFromFiles(sourcePaths); TypedProgram typedAST = generateTypedASTFromAst(program); List byteCode = new ArrayList<>(); - for (TypedClass c : typedAST.getTypedClasses()) { - byteCode.add(generateByteCodeArrayFromTypedAst(c)); + if(TypedProgram.EXCEPTIONS.isEmpty()){ + for (TypedClass c : typedAST.getTypedClasses()) { + byteCode.add(generateByteCodeArrayFromTypedAst(c)); + } + return byteCode; + }else{ + return Collections.emptyList(); } - return byteCode; } public static void generateByteCodeFilesFromFiles(List sourcePaths) { List bytes = generateByteCodeArrayFromFiles(sourcePaths); + if(bytes.isEmpty()){ + return; + } for (int i = 0; i < bytes.size(); i++) { String targetPath = sourcePaths.get(i).replace(JAVA_FILE_EXTENSION, ".class"); CodeGenUtils.writeClassfile(bytes.get(i), targetPath); diff --git a/src/main/java/de/maishai/typedast/ExceptionHandler/FieldAlreadyDeclaredException.java b/src/main/java/de/maishai/typedast/ExceptionHandler/FieldAlreadyDeclaredException.java new file mode 100644 index 0000000..57d4323 --- /dev/null +++ b/src/main/java/de/maishai/typedast/ExceptionHandler/FieldAlreadyDeclaredException.java @@ -0,0 +1,10 @@ +package de.maishai.typedast.ExceptionHandler; + +public class FieldAlreadyDeclaredException extends RuntimeException{ + + public FieldAlreadyDeclaredException(String name) { + super("Field " + name + " already declared"); + } + +} + diff --git a/src/main/java/de/maishai/typedast/ExceptionHandler/LocalVariableAlreadDeclaredException.java b/src/main/java/de/maishai/typedast/ExceptionHandler/LocalVariableAlreadDeclaredException.java new file mode 100644 index 0000000..a11a7ab --- /dev/null +++ b/src/main/java/de/maishai/typedast/ExceptionHandler/LocalVariableAlreadDeclaredException.java @@ -0,0 +1,7 @@ +package de.maishai.typedast.ExceptionHandler; + +public class LocalVariableAlreadDeclaredException extends RuntimeException { + public LocalVariableAlreadDeclaredException(String name){ + super("local Variable " + name + " already declared"); + } +} diff --git a/src/main/java/de/maishai/typedast/ExceptionHandler/NotFoundMethodOrConstructor.java b/src/main/java/de/maishai/typedast/ExceptionHandler/NotFoundMethodOrConstructor.java new file mode 100644 index 0000000..64f69e7 --- /dev/null +++ b/src/main/java/de/maishai/typedast/ExceptionHandler/NotFoundMethodOrConstructor.java @@ -0,0 +1,9 @@ +package de.maishai.typedast.ExceptionHandler; + +public class NotFoundMethodOrConstructor extends RuntimeException { + + public NotFoundMethodOrConstructor() { + super("Method or constructor not found in class"); + } + +} diff --git a/src/main/java/de/maishai/typedast/ExceptionHandler/NotMatchConstructorException.java b/src/main/java/de/maishai/typedast/ExceptionHandler/NotMatchConstructorException.java new file mode 100644 index 0000000..d0474c0 --- /dev/null +++ b/src/main/java/de/maishai/typedast/ExceptionHandler/NotMatchConstructorException.java @@ -0,0 +1,13 @@ +package de.maishai.typedast.ExceptionHandler; + +public class NotMatchConstructorException extends RuntimeException { + + public NotMatchConstructorException(String constructorName) { + super(constructorName); + } + + public NotMatchConstructorException() { + super("Not matching constructor found"); + } + +} diff --git a/src/main/java/de/maishai/typedast/ExceptionHandler/ParameterAlreadyExistsException.java b/src/main/java/de/maishai/typedast/ExceptionHandler/ParameterAlreadyExistsException.java new file mode 100644 index 0000000..4d9a6d8 --- /dev/null +++ b/src/main/java/de/maishai/typedast/ExceptionHandler/ParameterAlreadyExistsException.java @@ -0,0 +1,14 @@ +package de.maishai.typedast.ExceptionHandler; + +public class ParameterAlreadyExistsException extends RuntimeException{ + public ParameterAlreadyExistsException(String paraName) { + super("Parameter '" + paraName + "' already exists"); + } + public ParameterAlreadyExistsException(String paraName, String methodOrConstructorName) { + super("Parameter '" + paraName + "' already exists in " + methodOrConstructorName); + } + public ParameterAlreadyExistsException() { + super("Parameter already exists"); + } + +} \ No newline at end of file diff --git a/src/main/java/de/maishai/typedast/ExceptionHandler/TypeMismatchException.java b/src/main/java/de/maishai/typedast/ExceptionHandler/TypeMismatchException.java new file mode 100644 index 0000000..30b7c05 --- /dev/null +++ b/src/main/java/de/maishai/typedast/ExceptionHandler/TypeMismatchException.java @@ -0,0 +1,9 @@ +package de.maishai.typedast.ExceptionHandler; + +public class TypeMismatchException extends RuntimeException{ + + public TypeMismatchException(String operator) { + super("Type mismatch in operator: " + operator); + } + +} \ No newline at end of file diff --git a/src/main/java/de/maishai/typedast/ExceptionHandler/TypeOfReturnNotMatchException.java b/src/main/java/de/maishai/typedast/ExceptionHandler/TypeOfReturnNotMatchException.java new file mode 100644 index 0000000..64c93dc --- /dev/null +++ b/src/main/java/de/maishai/typedast/ExceptionHandler/TypeOfReturnNotMatchException.java @@ -0,0 +1,17 @@ +package de.maishai.typedast.ExceptionHandler; + +import de.maishai.typedast.Type; + +public class TypeOfReturnNotMatchException extends RuntimeException{ + + public TypeOfReturnNotMatchException(String excepted, String actual, String name){ + super("Mismatched return type: " + + " Expected: " + excepted + + " Actual: " + actual + + " Method name: " + name + ); + } + public TypeOfReturnNotMatchException(String name){ + super("Constructor " + name + " must not have a return"); + } +} diff --git a/src/main/java/de/maishai/typedast/ExceptionHandler/VariableNotDeclaredException.java b/src/main/java/de/maishai/typedast/ExceptionHandler/VariableNotDeclaredException.java new file mode 100644 index 0000000..741e4ef --- /dev/null +++ b/src/main/java/de/maishai/typedast/ExceptionHandler/VariableNotDeclaredException.java @@ -0,0 +1,13 @@ +package de.maishai.typedast.ExceptionHandler; + +public class VariableNotDeclaredException extends RuntimeException{ + + public VariableNotDeclaredException(String variableName) { + super("Variable '" + variableName + "' not declared"); + } + public VariableNotDeclaredException(String variableName, String methodName) { + super("Variable '" + variableName + "' not declared in method '" + methodName + "'"); + } + + +} diff --git a/src/main/java/de/maishai/typedast/typedclass/TypedAssignment.java b/src/main/java/de/maishai/typedast/typedclass/TypedAssignment.java index 18ed031..ec5dfac 100644 --- a/src/main/java/de/maishai/typedast/typedclass/TypedAssignment.java +++ b/src/main/java/de/maishai/typedast/typedclass/TypedAssignment.java @@ -1,6 +1,8 @@ package de.maishai.typedast.typedclass; import de.maishai.ast.records.Assignment; +import de.maishai.typedast.ExceptionHandler.TypeMismatchException; +import de.maishai.typedast.ExceptionHandler.VariableNotDeclaredException; import de.maishai.typedast.MethodContext; import de.maishai.typedast.Type; import de.maishai.typedast.TypedExpression; @@ -37,17 +39,23 @@ public class TypedAssignment implements TypedStatement { TypedClass currentClass = typedProgram.getCurrentClass(); if (currentClass.isCurrentMainMethodPresent() && location.getField() && location.getRecursiveOwnerChain() == null) { - throw new RuntimeException("Main Method, is not allowed to have fields, they are not static"); + TypedProgram.addException("Main Method", new RuntimeException("Main Method, is not allowed to have fields, they are not static")); + return null; } Type typeLeft = getTypeLeft(typedProgram); Type typeRight = value.typeCheck(typedProgram); - if (typeLeft.equals(typeRight)) { - type = typeLeft; - return typeLeft; - } - throw new RuntimeException("type of left not equals with type of right"); + // improve fallowing code + + if(typeLeft != null && typeLeft.equals(typeRight)) { + type = typeLeft; + return typeLeft; + } + + assert typeLeft != null; + TypedProgram.addException("Type Not Match", new TypeMismatchException(typeLeft.getKind().toString())); + return null; } private Type getTypeLeft(TypedProgram typedProgram) { @@ -66,16 +74,18 @@ public class TypedAssignment implements TypedStatement { return getTypeFromConstructorOrField(currentClass.getCurrentConstructor(), name, currentClass); } - throw new RuntimeException("Variable " + name + " not declared"); + TypedProgram.addException(name, new VariableNotDeclaredException(name)); + return null; } private Type getTypeFromMethodOrField(TypedMethod currentMethod, String name, TypedClass currentClass) { if (currentMethod.isLocalVariableInMethod(name)) { return currentMethod.getLocalVariableType(name); } else if (currentClass.isThereField(name)) { - throw new RuntimeException("Field Variable " + name + " should be used with `this´"); + throw new RuntimeException("Field Variable "+ name + " should be used with `this´"); } else { - throw new RuntimeException("Variable " + name + " not declared in method"); + TypedProgram.addException(name, new VariableNotDeclaredException(name)); + return null; } } @@ -83,9 +93,10 @@ public class TypedAssignment implements TypedStatement { if (currentConstructor.isLocalVariableInConstructor(name)) { return currentConstructor.getLocalVariableType(name); } else if (currentClass.isThereField(name)) { - throw new RuntimeException("Field Variable " + name + " should be used with `this´"); + throw new RuntimeException("Field Variable "+ name+ " should be used with `this´"); } else { - throw new RuntimeException("Variable " + name + " not declared in constructor"); + TypedProgram.addException(name, new VariableNotDeclaredException(name)); + return null; } } diff --git a/src/main/java/de/maishai/typedast/typedclass/TypedBinary.java b/src/main/java/de/maishai/typedast/typedclass/TypedBinary.java index 457df79..72fb651 100644 --- a/src/main/java/de/maishai/typedast/typedclass/TypedBinary.java +++ b/src/main/java/de/maishai/typedast/typedclass/TypedBinary.java @@ -2,6 +2,7 @@ package de.maishai.typedast.typedclass; import de.maishai.ast.Operator; import de.maishai.ast.records.Binary; +import de.maishai.typedast.ExceptionHandler.TypeMismatchException; import de.maishai.typedast.MethodContext; import de.maishai.typedast.Type; import de.maishai.typedast.TypedExpression; @@ -43,28 +44,32 @@ public class TypedBinary implements TypedExpression { type = Type.INT; return Type.INT; } else { - throw new RuntimeException("Type mismatch in " + op); + TypedProgram.addException(op.name(), new TypeMismatchException(op.toString())); + return null; } } else if (op == Operator.GT || op == Operator.LT || op == Operator.GE || op == Operator.LE) { if (leftType == Type.INT && rightType == Type.INT) { type = Type.BOOL; return Type.BOOL; } else { - throw new RuntimeException("Type mismatch in " + op); + TypedProgram.addException(op.name(), new TypeMismatchException(op.toString())); + return null; } } else if (op == Operator.EQ || op == Operator.NE ) { if (leftType == Type.INT && rightType == Type.INT || leftType == Type.BOOL && rightType == Type.BOOL) { type = Type.BOOL; return Type.BOOL; } else { - throw new RuntimeException("Type mismatch in " + op); + TypedProgram.addException(op.name(), new TypeMismatchException(op.toString())); + return null; } } else if (op == Operator.AND || op == Operator.OR ){ if (leftType == Type.BOOL && rightType == Type.BOOL) { type = Type.BOOL; return Type.BOOL; } else { - throw new RuntimeException("Type mismatch in " + op); + TypedProgram.addException(op.name(), new TypeMismatchException(op.toString())); + return null; } } @@ -72,7 +77,8 @@ public class TypedBinary implements TypedExpression { type = rightType; return type; } - throw new RuntimeException("Void can not be compared with Void"); + TypedProgram.addException(op.name(), new TypeMismatchException(op.toString())); + return null; } @Override diff --git a/src/main/java/de/maishai/typedast/typedclass/TypedClass.java b/src/main/java/de/maishai/typedast/typedclass/TypedClass.java index a1c1dcd..1d84aa3 100644 --- a/src/main/java/de/maishai/typedast/typedclass/TypedClass.java +++ b/src/main/java/de/maishai/typedast/typedclass/TypedClass.java @@ -6,7 +6,6 @@ import de.maishai.ast.records.Declaration; import de.maishai.ast.records.Method; import de.maishai.typedast.ClassContext; import de.maishai.typedast.Type; -import de.maishai.typedast.TypedExpression; import de.maishai.typedast.TypedNode; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/src/main/java/de/maishai/typedast/typedclass/TypedConstructor.java b/src/main/java/de/maishai/typedast/typedclass/TypedConstructor.java index f7e4d43..962b1eb 100644 --- a/src/main/java/de/maishai/typedast/typedclass/TypedConstructor.java +++ b/src/main/java/de/maishai/typedast/typedclass/TypedConstructor.java @@ -3,6 +3,7 @@ package de.maishai.typedast.typedclass; import de.maishai.ast.records.Constructor; import de.maishai.ast.records.Parameter; import de.maishai.typedast.*; +import de.maishai.typedast.ExceptionHandler.ParameterAlreadyExistsException; import lombok.AllArgsConstructor; import lombok.Data; import lombok.RequiredArgsConstructor; @@ -38,7 +39,7 @@ public class TypedConstructor implements TypedNode { public void convertToTypedConstructor(TypedProgram typedProgram, Constructor unTypedConstructor, String className) { if(!unTypedConstructor.className().equals(className)) { - throw new RuntimeException("Constructor name "+ unTypedConstructor.className() +" must be the same as class name" + className); + TypedProgram.addException("ConstructorNameNotMatch " + unTypedConstructor.className(), new RuntimeException("Constructor name must be the same as class name " + className)); } name = unTypedConstructor.className(); convertToTypedParameter(typedProgram, unTypedConstructor.params()); @@ -58,7 +59,8 @@ public class TypedConstructor implements TypedNode { public Type typeCheck(TypedProgram typedProgram) { type = typedBlock.typeCheck(typedProgram); if (type != Type.VOID) { - throw new RuntimeException("Constructor must not habe a return statement"); + TypedProgram.addException("ConstructorContainsReturn",new RuntimeException("Constructor must not habe a return statement")); + return null; } return type; @@ -84,7 +86,7 @@ public class TypedConstructor implements TypedNode { private void checkIfParameterExists(String paraName) { if (typedParameters.stream().anyMatch(parameter -> parameter.getParaName().equals(paraName))) { - throw new RuntimeException("Parameter " + paraName + " already exists"); + TypedProgram.addException(paraName, new ParameterAlreadyExistsException(paraName)); } } diff --git a/src/main/java/de/maishai/typedast/typedclass/TypedDeclaration.java b/src/main/java/de/maishai/typedast/typedclass/TypedDeclaration.java index 33281c1..c54d923 100644 --- a/src/main/java/de/maishai/typedast/typedclass/TypedDeclaration.java +++ b/src/main/java/de/maishai/typedast/typedclass/TypedDeclaration.java @@ -1,6 +1,7 @@ package de.maishai.typedast.typedclass; import de.maishai.ast.records.Declaration; +import de.maishai.typedast.ExceptionHandler.FieldAlreadyDeclaredException; import de.maishai.typedast.TypedNode; import de.maishai.typedast.Type; import lombok.AllArgsConstructor; @@ -33,12 +34,14 @@ public final class TypedDeclaration implements TypedNode { if (type.getReference() != null && !currentClass.getClassName().equals(type.getReference())) { if (!typedProgram.isTypedClassPresent(type.getReference())) { - throw new RuntimeException("Type " + type.getReference() + " not found"); + TypedProgram.addException(type.getReference(), new RuntimeException("Type " + type.getReference() + " not found")); + return null; } } if (currentClass.isThereField(name)) { - throw new RuntimeException("Field " + name + " already declared"); + TypedProgram.addException(name, new FieldAlreadyDeclaredException(name)); + return null; } return type; } diff --git a/src/main/java/de/maishai/typedast/typedclass/TypedDoWhile.java b/src/main/java/de/maishai/typedast/typedclass/TypedDoWhile.java index 4f6827c..a6721e8 100644 --- a/src/main/java/de/maishai/typedast/typedclass/TypedDoWhile.java +++ b/src/main/java/de/maishai/typedast/typedclass/TypedDoWhile.java @@ -29,7 +29,8 @@ public class TypedDoWhile implements TypedStatement { @Override public Type typeCheck(TypedProgram typedProgram) { if (cond.typeCheck(typedProgram) != Type.BOOL) { - throw new RuntimeException("Condition must be boolean"); + TypedProgram.addException("ConditionError", new RuntimeException("Condition must be boolean")); + return null; } typedBlock.typeCheck(typedProgram); this.type = Type.VOID; diff --git a/src/main/java/de/maishai/typedast/typedclass/TypedFieldVarAccess.java b/src/main/java/de/maishai/typedast/typedclass/TypedFieldVarAccess.java index 982565e..e4c2dd8 100644 --- a/src/main/java/de/maishai/typedast/typedclass/TypedFieldVarAccess.java +++ b/src/main/java/de/maishai/typedast/typedclass/TypedFieldVarAccess.java @@ -1,6 +1,8 @@ package de.maishai.typedast.typedclass; import de.maishai.ast.records.FieldVarAccess; +import de.maishai.ast.records.*; +import de.maishai.typedast.ExceptionHandler.VariableNotDeclaredException; import de.maishai.typedast.MethodContext; import de.maishai.typedast.Type; import de.maishai.typedast.TypedExpression; @@ -68,7 +70,8 @@ public class TypedFieldVarAccess implements TypedExpression { type = currentClass.getFieldType(typedFieldVarAccess.getName()); return type; } else { - throw new RuntimeException("Field " + name + " not declared"); + TypedProgram.addException(name,new RuntimeException("Field " + name + " not declared") ); + return null; } } @@ -80,7 +83,8 @@ public class TypedFieldVarAccess implements TypedExpression { } else if (currentClass.isCurrentMethodPresent()) { return checkMethodVariableType(typedProgram); } else { - throw new RuntimeException("Variable " + name + " not declared"); + TypedProgram.addException(name, new VariableNotDeclaredException(name)); + return null; } } @@ -122,7 +126,8 @@ public class TypedFieldVarAccess implements TypedExpression { } else if (recursiveOwnerChain instanceof TypedFieldVarAccess typedFieldVarAccess) { type = currentClass.getFieldType(typedFieldVarAccess.getName()); } else { - throw new RuntimeException("Variable " + name + " not declared"); + TypedProgram.addException(name, new VariableNotDeclaredException(name)); + return null; } return type; } diff --git a/src/main/java/de/maishai/typedast/typedclass/TypedFor.java b/src/main/java/de/maishai/typedast/typedclass/TypedFor.java index 0b1181f..2e00dc6 100644 --- a/src/main/java/de/maishai/typedast/typedclass/TypedFor.java +++ b/src/main/java/de/maishai/typedast/typedclass/TypedFor.java @@ -36,7 +36,8 @@ public class TypedFor implements TypedStatement { public Type typeCheck(TypedProgram typedProgram) { assign.typeCheck(typedProgram); if (!cond.typeCheck(typedProgram).equals(Type.BOOL)) { - throw new RuntimeException("Condition must be a boolean"); + TypedProgram.addException("ConditionError", new RuntimeException("Condition must be boolean")); + return null; } inc.typeCheck(typedProgram); type = typedBlock.typeCheck(typedProgram); diff --git a/src/main/java/de/maishai/typedast/typedclass/TypedLocalVariable.java b/src/main/java/de/maishai/typedast/typedclass/TypedLocalVariable.java index 710cc1c..9f5475d 100644 --- a/src/main/java/de/maishai/typedast/typedclass/TypedLocalVariable.java +++ b/src/main/java/de/maishai/typedast/typedclass/TypedLocalVariable.java @@ -1,6 +1,8 @@ package de.maishai.typedast.typedclass; import de.maishai.ast.records.Declaration; +import de.maishai.typedast.ExceptionHandler.LocalVariableAlreadDeclaredException; +import de.maishai.typedast.ExceptionHandler.NotFoundMethodOrConstructor; import de.maishai.typedast.MethodContext; import de.maishai.typedast.TypedNode; import de.maishai.typedast.Type; @@ -34,19 +36,22 @@ public final class TypedLocalVariable implements TypedNode { if (currentClass.isCurrentMethodPresent() && !currentClass.isCurrentConstructorPresent()) { if (currentMethod.isLocalVariableInMethod(name)) { - throw new RuntimeException("Variable " + name + " already declared"); + TypedProgram.addException(name, new LocalVariableAlreadDeclaredException(name)); + return null; } currentMethod.getLocalVariables().add(this); return type; } if (!currentClass.isCurrentMethodPresent() && currentClass.isCurrentConstructorPresent()) { if (currentConstructor.isLocalVariableInConstructor(name)) { - throw new RuntimeException("Variable " + name + " already declared"); + TypedProgram.addException(name, new LocalVariableAlreadDeclaredException(name)); + return null; } currentConstructor.getLocalVariables().add(this); return type; } - throw new RuntimeException("not found method or constructor in class"); + TypedProgram.addException("NotFoundMethodOrConstructor", new NotFoundMethodOrConstructor()); + return null; } public void codeGen(MethodVisitor mv, MethodContext ctx) { diff --git a/src/main/java/de/maishai/typedast/typedclass/TypedMethod.java b/src/main/java/de/maishai/typedast/typedclass/TypedMethod.java index 2048b53..f50ec48 100644 --- a/src/main/java/de/maishai/typedast/typedclass/TypedMethod.java +++ b/src/main/java/de/maishai/typedast/typedclass/TypedMethod.java @@ -3,6 +3,7 @@ package de.maishai.typedast.typedclass; import de.maishai.ast.records.Method; import de.maishai.ast.records.Parameter; import de.maishai.typedast.*; +import de.maishai.typedast.ExceptionHandler.ParameterAlreadyExistsException; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -46,7 +47,7 @@ public class TypedMethod implements TypedNode { public void checkIfParameterExists(String parameterName) { if (typedParameters.stream().anyMatch(parameter -> parameter.getParaName().equals(parameterName))) { - throw new RuntimeException("Parameter " + parameterName + " already exists"); + TypedProgram.addException(parameterName, new ParameterAlreadyExistsException(parameterName)); } } diff --git a/src/main/java/de/maishai/typedast/typedclass/TypedMethodCall.java b/src/main/java/de/maishai/typedast/typedclass/TypedMethodCall.java index cf893ad..997726f 100644 --- a/src/main/java/de/maishai/typedast/typedclass/TypedMethodCall.java +++ b/src/main/java/de/maishai/typedast/typedclass/TypedMethodCall.java @@ -64,7 +64,8 @@ public class TypedMethodCall implements TypedExpression, TypedStatement { } } - throw new RuntimeException("Method not found"); + TypedProgram.addException("MethodNotFound", new RuntimeException("Method not found") ); + return null; } public Optional findMatchingMethod(TypedClass ownerChain, String methodName) { diff --git a/src/main/java/de/maishai/typedast/typedclass/TypedNew.java b/src/main/java/de/maishai/typedast/typedclass/TypedNew.java index 0ef32e5..bfea7b3 100644 --- a/src/main/java/de/maishai/typedast/typedclass/TypedNew.java +++ b/src/main/java/de/maishai/typedast/typedclass/TypedNew.java @@ -3,6 +3,7 @@ package de.maishai.typedast.typedclass; import de.maishai.ast.records.Expression; import de.maishai.ast.records.New; import de.maishai.typedast.*; +import de.maishai.typedast.ExceptionHandler.NotMatchConstructorException; import lombok.AllArgsConstructor; import lombok.Data; import org.objectweb.asm.Opcodes; @@ -59,7 +60,8 @@ public class TypedNew implements TypedExpression, TypedStatement { } } } - throw new RuntimeException("No matching constructor found"); + TypedProgram.addException("notMatchConstructor", new NotMatchConstructorException()); + return null; } @Override diff --git a/src/main/java/de/maishai/typedast/typedclass/TypedParameter.java b/src/main/java/de/maishai/typedast/typedclass/TypedParameter.java index 67d106b..28c4a8f 100644 --- a/src/main/java/de/maishai/typedast/typedclass/TypedParameter.java +++ b/src/main/java/de/maishai/typedast/typedclass/TypedParameter.java @@ -1,6 +1,7 @@ package de.maishai.typedast.typedclass; import de.maishai.ast.records.Parameter; +import de.maishai.typedast.ExceptionHandler.ParameterAlreadyExistsException; import de.maishai.typedast.Type; import de.maishai.typedast.TypedNode; import lombok.AllArgsConstructor; @@ -36,11 +37,13 @@ public class TypedParameter implements TypedNode { if (typedProgram.getCurrentClass().isCurrentMethodPresent()) { if (typedProgram.getCurrentClass().isParameterWitNameInCurrentMethod(paraName)) { - throw new RuntimeException("Parameter " + paraName + " already exists"); + TypedProgram.addException(paraName, new ParameterAlreadyExistsException(paraName)); + return null; } } else if (typedProgram.getCurrentClass().isCurrentConstructorPresent()) { if (typedProgram.getCurrentClass().isParameterWitNameInCurrentConstructor(paraName)) { - throw new RuntimeException("Parameter " + paraName + " already exists"); + TypedProgram.addException(paraName, new ParameterAlreadyExistsException(paraName)); + return null; } } diff --git a/src/main/java/de/maishai/typedast/typedclass/TypedProgram.java b/src/main/java/de/maishai/typedast/typedclass/TypedProgram.java index e7daa7e..a1f5cf1 100644 --- a/src/main/java/de/maishai/typedast/typedclass/TypedProgram.java +++ b/src/main/java/de/maishai/typedast/typedclass/TypedProgram.java @@ -6,12 +6,15 @@ import lombok.AllArgsConstructor; import lombok.Getter; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; @Getter @AllArgsConstructor public class TypedProgram { private List typedClasses = new ArrayList<>(); + public static Map EXCEPTIONS = new HashMap<>(); private TypedClass currentClass; public TypedProgram(Program program) { @@ -42,6 +45,24 @@ public class TypedProgram { exitCurrentClass(); i++; } + + if(EXCEPTIONS.isEmpty()){ + System.out.println("Es wurde erfolgreich kompiliert."); + }else{ + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("Es wurden mindestens " + EXCEPTIONS.size() + " Fehlermeldungen gefunden"); + stringBuilder.append("\nDie bekannte Fehlermeldungen: "); + int counter = 0; + for(Map.Entry entry : EXCEPTIONS.entrySet()){ + stringBuilder.append("\n["+ counter + "] Fehler: " + + "\n Schlüssel: " + entry.getKey() + + "\n Exception: " + entry.getValue().getClass().getSimpleName() + + "\n Message: " + entry.getValue().getMessage() + ); + counter++; + } + throw new RuntimeException(stringBuilder.toString()); + } } public boolean isClassWithNamePresent(String className) { @@ -68,6 +89,12 @@ public class TypedProgram { currentClass = null; } + public static void addException(String name, Exception ex){ + if(!EXCEPTIONS.containsKey(name)){ + EXCEPTIONS.put(name, ex); + } + } + @Override public boolean equals(Object obj) { if (this == obj) return true; diff --git a/src/main/java/de/maishai/typedast/typedclass/TypedReturn.java b/src/main/java/de/maishai/typedast/typedclass/TypedReturn.java index ef190f8..54cdd6c 100644 --- a/src/main/java/de/maishai/typedast/typedclass/TypedReturn.java +++ b/src/main/java/de/maishai/typedast/typedclass/TypedReturn.java @@ -1,22 +1,25 @@ package de.maishai.typedast.typedclass; - import de.maishai.ast.records.Return; import de.maishai.typedast.MethodContext; import de.maishai.typedast.Type; import de.maishai.typedast.TypedExpression; import de.maishai.typedast.TypedStatement; +import de.maishai.typedast.ExceptionHandler.TypeOfReturnNotMatchException; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.objectweb.asm.Opcodes; +import java.util.logging.Logger; + import static de.maishai.typedast.Util.TypedExpressionUtil.convertExpression; @Data @NoArgsConstructor @AllArgsConstructor public class TypedReturn implements TypedStatement { + private static final Logger LOGGER = Logger.getLogger(TypedReturn.class.getName()); private TypedExpression ret; private Type type; @@ -41,14 +44,21 @@ public class TypedReturn implements TypedStatement { if (currentClass.isCurrentMethodPresent()) { if (currentMethod.getReturnType().getKind() != this.type.getKind()) { - StringBuilder exp = new StringBuilder(); - exp.append("\nMismatched return type: "); - exp.append("\nExpected: ").append(currentMethod.getReturnType().getKind()); - exp.append("\nActual: ").append(this.type.getKind()); - exp.append("\nMethod name: ").append(currentMethod.getName()); - throw new RuntimeException(exp.toString()); + String key = "Type of return in " + typedProgram.getCurrentClass().getCurrentMethod().getName(); + TypeOfReturnNotMatchException ex = new TypeOfReturnNotMatchException( + typedProgram.getCurrentClass().getCurrentMethod().getReturnType().getKind().name(), + this.type.getKind().name(), + typedProgram.getCurrentClass().getCurrentMethod().getName()); + TypedProgram.addException(key, ex); } } + /* + if (typedProgram.getCurrentClass().isCurrentConstructorPresent()) { + if (typedProgram.getCurrentClass().getCurrentConstructor().getType().getKind() != this.type.getKind()) { + TypedProgram.addException(typedProgram.getCurrentClass().getCurrentConstructor().getName(), new TypeOfReturnNotMatchException(typedProgram.getCurrentClass().getCurrentConstructor().getName())); + } + } + */ return type; } @@ -56,12 +66,15 @@ public class TypedReturn implements TypedStatement { public void codeGen(MethodContext ctx) { if (ret == null) { ctx.getMv().visitInsn(Opcodes.RETURN); + LOGGER.finest("RETURN"); } else { ret.codeGen(ctx); if (ret.getType().getKind() != Type.Kind.REFERENCE) { ctx.getMv().visitInsn(Opcodes.IRETURN); + LOGGER.finest("IRETURN"); } else { ctx.getMv().visitInsn(Opcodes.ARETURN); + LOGGER.finest("ARETURN"); } } diff --git a/src/main/java/de/maishai/typedast/typedclass/TypedUnary.java b/src/main/java/de/maishai/typedast/typedclass/TypedUnary.java index 8ee358e..cae71d2 100644 --- a/src/main/java/de/maishai/typedast/typedclass/TypedUnary.java +++ b/src/main/java/de/maishai/typedast/typedclass/TypedUnary.java @@ -33,7 +33,8 @@ public class TypedUnary implements TypedExpression { if (op == UnaryOperator.NOT) { if (right.typeCheck(typedProgram) != Type.BOOL) { - throw new RuntimeException("Not operator must be applied to boolean"); + TypedProgram.addException(UnaryOperator.NOT.name(), new RuntimeException("Not operator must be applied to boolean")); + return null; } type = Type.BOOL; return type; @@ -41,12 +42,14 @@ public class TypedUnary implements TypedExpression { if (op == UnaryOperator.SUB) { if (right.typeCheck(typedProgram) != Type.INT) { - throw new RuntimeException("Minus operator must be applied to int"); + TypedProgram.addException(UnaryOperator.SUB.name(),new RuntimeException("Minus operator must be applied to int") ); + return null; } type = Type.INT; return type; } - throw new RuntimeException("Unknown unary operator"); + TypedProgram.addException("UnknownUnary",new RuntimeException("Unknown unary operator") ); + return null; } @Override diff --git a/src/main/java/de/maishai/typedast/typedclass/TypedWhile.java b/src/main/java/de/maishai/typedast/typedclass/TypedWhile.java index f26c8d8..8e2dbff 100644 --- a/src/main/java/de/maishai/typedast/typedclass/TypedWhile.java +++ b/src/main/java/de/maishai/typedast/typedclass/TypedWhile.java @@ -32,7 +32,8 @@ public class TypedWhile implements TypedStatement { @Override public Type typeCheck(TypedProgram typedProgram) { if (cond.typeCheck(typedProgram) != Type.BOOL) { - throw new RuntimeException("While condition must be a boolean"); + TypedProgram.addException("ConditionError",new RuntimeException("While condition must be a boolean") ); + return null; } type = typedBlock.typeCheck(typedProgram); return type;