mirror of
https://github.com/JonathanFleischmann/CompilerULTIMATE.git
synced 2024-12-27 09:28:03 +00:00
Add the exception to the list
This commit is contained in:
parent
371480a790
commit
a259aa3a51
@ -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<byte[]> 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<String> sourcePaths) {
|
||||
List<byte[]> 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);
|
||||
|
@ -0,0 +1,10 @@
|
||||
package de.maishai.typedast.ExceptionHandler;
|
||||
|
||||
public class FieldAlreadyDeclaredException extends RuntimeException{
|
||||
|
||||
public FieldAlreadyDeclaredException(String name) {
|
||||
super("Field " + name + " already declared");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,7 @@
|
||||
package de.maishai.typedast.ExceptionHandler;
|
||||
|
||||
public class LocalVariableAlreadDeclaredException extends RuntimeException {
|
||||
public LocalVariableAlreadDeclaredException(String name){
|
||||
super("local Variable " + name + " already declared");
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package de.maishai.typedast.ExceptionHandler;
|
||||
|
||||
public class NotFoundMethodOrConstructor extends RuntimeException {
|
||||
|
||||
public NotFoundMethodOrConstructor() {
|
||||
super("Method or constructor not found in class");
|
||||
}
|
||||
|
||||
}
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package de.maishai.typedast.ExceptionHandler;
|
||||
|
||||
public class TypeMismatchException extends RuntimeException{
|
||||
|
||||
public TypeMismatchException(String operator) {
|
||||
super("Type mismatch in operator: " + operator);
|
||||
}
|
||||
|
||||
}
|
@ -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");
|
||||
}
|
||||
}
|
@ -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 + "'");
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<Type> findMatchingMethod(TypedClass ownerChain, String methodName) {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<TypedClass> typedClasses = new ArrayList<>();
|
||||
public static Map<String, Exception> 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<String, Exception> 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;
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user