Added Exceptions to the map and printed all collected Exceptions after compiling

This commit is contained in:
Ahmad 2024-06-22 21:59:59 +02:00
parent 0e035aac8b
commit 44b0f0a330
18 changed files with 147 additions and 68 deletions

View File

@ -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");
}
}

View File

@ -1,6 +1,8 @@
package de.maishai.typedast.typedclass; package de.maishai.typedast.typedclass;
import de.maishai.ast.records.Assignment; 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.MethodContext;
import de.maishai.typedast.TypedExpression; import de.maishai.typedast.TypedExpression;
import de.maishai.typedast.TypedStatement; import de.maishai.typedast.TypedStatement;
@ -35,11 +37,15 @@ public class TypedAssignment implements TypedStatement {
Type typeLeft = getTypeLeft(typedProgram); Type typeLeft = getTypeLeft(typedProgram);
Type typeRight = value.typeCheck(typedProgram); Type typeRight = value.typeCheck(typedProgram);
if (typeLeft.equals(typeRight)) { // so because of the collection of exceptions
type = typeLeft; if(typeLeft != null && typeRight != null){
return typeLeft; if (typeLeft.equals(typeRight)) {
type = typeLeft;
return typeLeft;
}
} }
throw new RuntimeException("type of left not equals with type of right"); TypedProgram.addException("Type Not Match", new TypeMismatchException(typeRight.getKind().toString()));
return Type.VOID;
} }
private Type getTypeLeft(TypedProgram typedProgram) { private Type getTypeLeft(TypedProgram typedProgram) {
@ -58,7 +64,8 @@ public class TypedAssignment implements TypedStatement {
return getTypeFromConstructorOrField(currentClass.getCurrentConstructor(), name, currentClass); 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) { private Type getTypeFromMethodOrField(TypedMethod currentMethod, String name, TypedClass currentClass) {
@ -67,7 +74,8 @@ public class TypedAssignment implements TypedStatement {
} else if (currentClass.isThereField(name)) { } else if (currentClass.isThereField(name)) {
return currentClass.getFieldType(name); return currentClass.getFieldType(name);
} else { } else {
throw new RuntimeException("Variable " + name + " not declared in method"); TypedProgram.addException(name, new VariableNotDeclaredException(name));
return null;
} }
} }
@ -77,7 +85,8 @@ public class TypedAssignment implements TypedStatement {
} else if (currentClass.isThereField(name)) { } else if (currentClass.isThereField(name)) {
return currentClass.getFieldType(name); return currentClass.getFieldType(name);
} else { } else {
throw new RuntimeException("Variable " + name + " not declared in constructor"); TypedProgram.addException(name, new VariableNotDeclaredException(name));
return null;
} }
} }
@ -99,14 +108,14 @@ public class TypedAssignment implements TypedStatement {
receiver = location.getRecursiveOwnerChain().getType().getReference(); receiver = location.getRecursiveOwnerChain().getType().getReference();
} }
ctx.getMv().visitFieldInsn(Opcodes.PUTFIELD, receiver, location.getName(), value.getType().getDescriptor()); ctx.getMv().visitFieldInsn(Opcodes.PUTFIELD, receiver, location.getName(), value.getType().getDescriptor());
System.out.println("PUTFIELD: " + receiver + " " + location.getName() + " " + value.getType().getDescriptor()); // System.out.println("PUTFIELD: " + receiver + " " + location.getName() + " " + value.getType().getDescriptor());
ctx.popStack(); ctx.popStack();
} else { } else {
if(value.getType().getKind() == Type.Kind.REFERENCE) { if(value.getType().getKind() == Type.Kind.REFERENCE) {
System.out.println("ASTORE " + ctx.getLocalVar(location.getName()).get().index()); //System.out.println("ASTORE " + ctx.getLocalVar(location.getName()).get().index());
ctx.getMv().visitVarInsn(Opcodes.ASTORE, ctx.getLocalVar(location.getName()).get().index()); ctx.getMv().visitVarInsn(Opcodes.ASTORE, ctx.getLocalVar(location.getName()).get().index());
} else { } else {
System.out.println("ISTORE " + ctx.getLocalVar(location.getName()).get().index()); // System.out.println("ISTORE " + ctx.getLocalVar(location.getName()).get().index());
ctx.getMv().visitVarInsn(Opcodes.ISTORE, ctx.getLocalVar(location.getName()).get().index()); ctx.getMv().visitVarInsn(Opcodes.ISTORE, ctx.getLocalVar(location.getName()).get().index());
} }
} }

View File

@ -2,6 +2,7 @@ package de.maishai.typedast.typedclass;
import de.maishai.ast.Operator; import de.maishai.ast.Operator;
import de.maishai.ast.records.Binary; import de.maishai.ast.records.Binary;
import de.maishai.typedast.ExceptionHandler.TypeMismatchException;
import de.maishai.typedast.MethodContext; import de.maishai.typedast.MethodContext;
import de.maishai.typedast.TypedExpression; import de.maishai.typedast.TypedExpression;
import de.maishai.typedast.Type; import de.maishai.typedast.Type;
@ -9,11 +10,8 @@ import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.objectweb.asm.Label; import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import java.util.Map;
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression; import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
@Data @Data
@ -46,21 +44,24 @@ public class TypedBinary implements TypedExpression {
type = Type.INT; type = Type.INT;
return Type.INT; return Type.INT;
} else { } 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) { } else if (op == Operator.GT || op == Operator.LT || op == Operator.GE || op == Operator.LE) {
if (leftType == Type.INT && rightType == Type.INT) { if (leftType == Type.INT && rightType == Type.INT) {
type = Type.BOOL; type = Type.BOOL;
return Type.BOOL; return Type.BOOL;
} else { } 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) { } else if (op == Operator.AND || op == Operator.OR) {
if (leftType == Type.BOOL && rightType == Type.BOOL) { if (leftType == Type.BOOL && rightType == Type.BOOL) {
type = Type.BOOL; type = Type.BOOL;
return Type.BOOL; return Type.BOOL;
} else { } else {
throw new RuntimeException("Type mismatch in " + op); TypedProgram.addException(op.name(), new TypeMismatchException(op.toString()));
return null;
} }
} }
@ -68,7 +69,8 @@ public class TypedBinary implements TypedExpression {
type = rightType; type = rightType;
return type; return type;
} }
throw new RuntimeException("Void can not be compared with Void"); TypedProgram.addException("Void", new RuntimeException("Void can not be compared with Void"));
return null;
} }
@Override @Override

View File

@ -3,6 +3,7 @@ package de.maishai.typedast.typedclass;
import de.maishai.ast.records.Constructor; import de.maishai.ast.records.Constructor;
import de.maishai.ast.records.Parameter; import de.maishai.ast.records.Parameter;
import de.maishai.typedast.*; import de.maishai.typedast.*;
import de.maishai.typedast.ExceptionHandler.ParameterAlreadyExistsException;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -63,7 +64,7 @@ public class TypedConstructor implements TypedNode {
public void checkIfParameterExists(String paraName) { public void checkIfParameterExists(String paraName) {
if (typedParameters.stream().anyMatch(parameter -> parameter.getParaName().equals(paraName))) { if (typedParameters.stream().anyMatch(parameter -> parameter.getParaName().equals(paraName))) {
throw new RuntimeException("Parameter " + paraName + " already exists"); TypedProgram.addException(paraName, new ParameterAlreadyExistsException(paraName));
} }
} }
@ -79,7 +80,8 @@ public class TypedConstructor implements TypedNode {
public Type typeCheck(TypedProgram typedProgram) { public Type typeCheck(TypedProgram typedProgram) {
type = typedBlock.typeCheck(typedProgram); type = typedBlock.typeCheck(typedProgram);
if (type != Type.VOID) { 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; return type;
@ -89,13 +91,13 @@ public class TypedConstructor implements TypedNode {
public void codeGen(ClassContext ctx) { public void codeGen(ClassContext ctx) {
int accessModifier = Opcodes.ACC_PUBLIC; // ist laut Andi ok int accessModifier = Opcodes.ACC_PUBLIC; // ist laut Andi ok
MethodVisitor mv = ctx.getCw().visitMethod(accessModifier, "<init>", CodeGenUtils.generateDescriptor(typedParameters.stream().map(TypedParameter::getType).toList(), Type.VOID), null, null); MethodVisitor mv = ctx.getCw().visitMethod(accessModifier, "<init>", CodeGenUtils.generateDescriptor(typedParameters.stream().map(TypedParameter::getType).toList(), Type.VOID), null, null);
System.out.println("Visiting method: " + "<init>" + CodeGenUtils.generateDescriptor(typedParameters.stream().map(TypedParameter::getType).toList(), Type.VOID)); //System.out.println("Visiting method: " + "<init>" + CodeGenUtils.generateDescriptor(typedParameters.stream().map(TypedParameter::getType).toList(), Type.VOID));
MethodContext mctx = new MethodContext(ctx, mv); MethodContext mctx = new MethodContext(ctx, mv);
typedParameters.forEach(param -> mctx.registerVariable(param.getParaName(), param.getType())); typedParameters.forEach(param -> mctx.registerVariable(param.getParaName(), param.getType()));
//super(); //super();
mctx.pushStack("this"); mctx.pushStack("this");
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
System.out.println("INVOKESPECIAL: " + "java/lang/Object" + " " + "<init>" + " " + "()V"); //System.out.println("INVOKESPECIAL: " + "java/lang/Object" + " " + "<init>" + " " + "()V");
mctx.popStack(); mctx.popStack();
typedBlock.codeGen(mctx); typedBlock.codeGen(mctx);

View File

@ -1,6 +1,7 @@
package de.maishai.typedast.typedclass; package de.maishai.typedast.typedclass;
import de.maishai.ast.records.Declaration; import de.maishai.ast.records.Declaration;
import de.maishai.typedast.ExceptionHandler.FieldAlreadyDeclaredException;
import de.maishai.typedast.TypedNode; import de.maishai.typedast.TypedNode;
import de.maishai.typedast.Type; import de.maishai.typedast.Type;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
@ -31,11 +32,13 @@ public final class TypedDeclaration implements TypedNode {
public Type typeCheck(TypedProgram typedProgram) { public Type typeCheck(TypedProgram typedProgram) {
if (type.getReference() != null && !typedProgram.getCurrentClass().getClassName().equals(type.getReference())) { if (type.getReference() != null && !typedProgram.getCurrentClass().getClassName().equals(type.getReference())) {
if (!typedProgram.isTypedClassPresent(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 (typedProgram.getCurrentClass().isThereField(name)) { if (typedProgram.getCurrentClass().isThereField(name)) {
throw new RuntimeException("Field " + name + " already declared"); TypedProgram.addException(name, new FieldAlreadyDeclaredException(name));
return null;
} }
return type; return type;
} }

View File

@ -29,7 +29,8 @@ public class TypedDoWhile implements TypedStatement {
@Override @Override
public Type typeCheck(TypedProgram typedProgram) { public Type typeCheck(TypedProgram typedProgram) {
if (cond.typeCheck(typedProgram) != Type.BOOL) { 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); typedBlock.typeCheck(typedProgram);
this.type = Type.VOID; this.type = Type.VOID;

View File

@ -1,17 +1,15 @@
package de.maishai.typedast.typedclass; package de.maishai.typedast.typedclass;
import de.maishai.ast.records.*; import de.maishai.ast.records.*;
import de.maishai.typedast.ExceptionHandler.VariableNotDeclaredException;
import de.maishai.typedast.MethodContext; import de.maishai.typedast.MethodContext;
import de.maishai.typedast.TypedExpression; import de.maishai.typedast.TypedExpression;
import de.maishai.typedast.Type; import de.maishai.typedast.Type;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import java.util.Map;
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression; import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
@Data @Data
@ -56,7 +54,8 @@ public class TypedFieldVarAccess implements TypedExpression {
type = typedProgram.getCurrentClass().getFieldType(typedFieldVarAccess.getName()); type = typedProgram.getCurrentClass().getFieldType(typedFieldVarAccess.getName());
return type; return type;
} else { } else {
throw new RuntimeException("Field " + name + " not declared"); TypedProgram.addException(name,new RuntimeException("Field " + name + " not declared") );
return null;
} }
} }
@ -66,7 +65,8 @@ public class TypedFieldVarAccess implements TypedExpression {
} else if (typedProgram.getCurrentClass().isCurrentMethodPresent()) { } else if (typedProgram.getCurrentClass().isCurrentMethodPresent()) {
return checkMethodVariableType(typedProgram); return checkMethodVariableType(typedProgram);
} else { } else {
throw new RuntimeException("Variable " + name + " not declared"); TypedProgram.addException(name, new VariableNotDeclaredException(name));
return null;
} }
} }
@ -100,7 +100,7 @@ public class TypedFieldVarAccess implements TypedExpression {
} else if (recursiveOwnerChain instanceof TypedFieldVarAccess typedFieldVarAccess) { } else if (recursiveOwnerChain instanceof TypedFieldVarAccess typedFieldVarAccess) {
type = typedProgram.getCurrentClass().getFieldType(typedFieldVarAccess.getName()); type = typedProgram.getCurrentClass().getFieldType(typedFieldVarAccess.getName());
} else { } else {
throw new RuntimeException("Variable " + name + " not declared"); TypedProgram.addException(name, new VariableNotDeclaredException(name));
} }
return type; return type;
} }
@ -130,7 +130,7 @@ public class TypedFieldVarAccess implements TypedExpression {
} else { } else {
int loadOpcode = type.getKind() == Type.Kind.REFERENCE ? Opcodes.ALOAD : Opcodes.ILOAD; int loadOpcode = type.getKind() == Type.Kind.REFERENCE ? Opcodes.ALOAD : Opcodes.ILOAD;
ctx.getMv().visitVarInsn(loadOpcode, ctx.getLocalVar(name).get().index()); ctx.getMv().visitVarInsn(loadOpcode, ctx.getLocalVar(name).get().index());
System.out.println(loadOpcode == Opcodes.ALOAD ? "ALOAD " + ctx.getLocalVar(name).get().index() : "ILOAD " + ctx.getLocalVar(name).get().index()); //System.out.println(loadOpcode == Opcodes.ALOAD ? "ALOAD " + ctx.getLocalVar(name).get().index() : "ILOAD " + ctx.getLocalVar(name).get().index());
} }
ctx.pushAnonToStack(); ctx.pushAnonToStack();
} }

View File

@ -36,7 +36,8 @@ public class TypedFor implements TypedStatement {
public Type typeCheck(TypedProgram typedProgram) { public Type typeCheck(TypedProgram typedProgram) {
assign.typeCheck(typedProgram); assign.typeCheck(typedProgram);
if (!cond.typeCheck(typedProgram).equals(Type.BOOL)) { 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); inc.typeCheck(typedProgram);
type = typedBlock.typeCheck(typedProgram); type = typedBlock.typeCheck(typedProgram);

View File

@ -7,11 +7,8 @@ import de.maishai.typedast.Type;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import java.util.Map;
@Data @Data
@AllArgsConstructor @AllArgsConstructor
@RequiredArgsConstructor @RequiredArgsConstructor
@ -43,13 +40,13 @@ public class TypedIntLiteral implements TypedExpression {
public void codeGen(MethodContext ctx) { public void codeGen(MethodContext ctx) {
if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) { if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
ctx.getMv().visitIntInsn(Opcodes.BIPUSH, value); ctx.getMv().visitIntInsn(Opcodes.BIPUSH, value);
System.out.println("BIPUSH " + value); // System.out.println("BIPUSH " + value);
} else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) { } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
ctx.getMv().visitIntInsn(Opcodes.SIPUSH, value); ctx.getMv().visitIntInsn(Opcodes.SIPUSH, value);
System.out.println("SIPUSH " + value); // System.out.println("SIPUSH " + value);
} else { } else {
ctx.getMv().visitLdcInsn(value); ctx.getMv().visitLdcInsn(value);
System.out.println("LDC " + value); // System.out.println("LDC " + value);
} }
ctx.pushInstantToStack(); ctx.pushInstantToStack();
} }

View File

@ -1,6 +1,8 @@
package de.maishai.typedast.typedclass; package de.maishai.typedast.typedclass;
import de.maishai.ast.records.Declaration; 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.MethodContext;
import de.maishai.typedast.TypedNode; import de.maishai.typedast.TypedNode;
import de.maishai.typedast.Type; import de.maishai.typedast.Type;
@ -30,19 +32,22 @@ public final class TypedLocalVariable implements TypedNode {
public Type typeCheck(TypedProgram typedProgram) { public Type typeCheck(TypedProgram typedProgram) {
if (typedProgram.getCurrentClass().isCurrentMethodPresent() && !typedProgram.getCurrentClass().isCurrentConstructorPresent()) { if (typedProgram.getCurrentClass().isCurrentMethodPresent() && !typedProgram.getCurrentClass().isCurrentConstructorPresent()) {
if (typedProgram.getCurrentClass().getCurrentMethod().isLocalVariableInMethod(name)) { if (typedProgram.getCurrentClass().getCurrentMethod().isLocalVariableInMethod(name)) {
throw new RuntimeException("Variable " + name + " already declared"); TypedProgram.addException(name, new LocalVariableAlreadDeclaredException(name));
return null;
} }
typedProgram.getCurrentClass().getCurrentMethod().getLocalVariables().add(this); typedProgram.getCurrentClass().getCurrentMethod().getLocalVariables().add(this);
return type; return type;
} }
if (!typedProgram.getCurrentClass().isCurrentMethodPresent() && typedProgram.getCurrentClass().isCurrentConstructorPresent()) { if (!typedProgram.getCurrentClass().isCurrentMethodPresent() && typedProgram.getCurrentClass().isCurrentConstructorPresent()) {
if (typedProgram.getCurrentClass().getCurrentConstructor().isLocalVariableInConstructor(name)) { if (typedProgram.getCurrentClass().getCurrentConstructor().isLocalVariableInConstructor(name)) {
throw new RuntimeException("Variable " + name + " already declared"); TypedProgram.addException(name, new LocalVariableAlreadDeclaredException(name));
return null;
} }
typedProgram.getCurrentClass().getCurrentConstructor().getLocalVariables().add(this); typedProgram.getCurrentClass().getCurrentConstructor().getLocalVariables().add(this);
return type; 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) { public void codeGen(MethodVisitor mv, MethodContext ctx) {

View File

@ -2,6 +2,7 @@ package de.maishai.typedast.typedclass;
import de.maishai.ast.records.Method; import de.maishai.ast.records.Method;
import de.maishai.typedast.*; import de.maishai.typedast.*;
import de.maishai.typedast.ExceptionHandler.ParameterAlreadyExistsException;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@ -38,14 +39,14 @@ public class TypedMethod implements TypedNode {
typedProgram.getCurrentClass().getTypedMethods().stream().filter(method -> method.equals(this)).findFirst().ifPresentOrElse( typedProgram.getCurrentClass().getTypedMethods().stream().filter(method -> method.equals(this)).findFirst().ifPresentOrElse(
method -> { method -> {
throw new RuntimeException("Method " + name + " already exists"); TypedProgram.addException(name, new RuntimeException("Method " + name + " already exists"));
}, () -> { }, () -> {
}); });
} }
public void checkIfParameterExists(String parameterName) { public void checkIfParameterExists(String parameterName) {
if (typedParameters.stream().anyMatch(parameter -> parameter.getParaName().equals(parameterName))) { if (typedParameters.stream().anyMatch(parameter -> parameter.getParaName().equals(parameterName))) {
throw new RuntimeException("Parameter " + parameterName + " already exists"); TypedProgram.addException(parameterName, new ParameterAlreadyExistsException(parameterName));
} }
} }
@ -101,9 +102,11 @@ public class TypedMethod implements TypedNode {
if (returnType != Type.VOID && !hasEvenReturnsInIfElseBlocks()) { if (returnType != Type.VOID && !hasEvenReturnsInIfElseBlocks()) {
if (typedBlock.typeCheck(typedProgram).getKind() != returnType.getKind()) { if (typedBlock.typeCheck(typedProgram).getKind() != returnType.getKind()) {
if (hasEvenReturnsInIfElseBlocks()) { if (hasEvenReturnsInIfElseBlocks()) {
throw new RuntimeException("Method " + name + " must have even returns in if else blocks"); TypedProgram.addException(name, new RuntimeException("Method " + name + " must have even returns in if else blocks"));
return null;
} else { } else {
throw new RuntimeException("Method " + name + " must return " + returnType.getKind()); TypedProgram.addException(name, new RuntimeException("Method " + name + " must return " + returnType.getKind()));
return null;
} }
} }
} }

View File

@ -59,7 +59,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) { public Optional<Type> findMatchingMethod(TypedClass ownerChain, String methodName) {
@ -99,7 +100,7 @@ public class TypedMethodCall implements TypedExpression, TypedStatement {
methodOwnerClass = recipient.getRecursiveOwnerChain().getType().getReference(); methodOwnerClass = recipient.getRecursiveOwnerChain().getType().getReference();
} }
ctx.getMv().visitMethodInsn(Opcodes.INVOKEVIRTUAL, methodOwnerClass, recipient.getName(), descriptor, false); ctx.getMv().visitMethodInsn(Opcodes.INVOKEVIRTUAL, methodOwnerClass, recipient.getName(), descriptor, false);
System.out.println("INVOKEVIRTUAL " + methodOwnerClass + " " + recipient.getName() + " " + descriptor); //System.out.println("INVOKEVIRTUAL " + methodOwnerClass + " " + recipient.getName() + " " + descriptor);
ctx.popStack(); // pop the owner ctx.popStack(); // pop the owner
for (TypedExpression arg : args) { for (TypedExpression arg : args) {
ctx.popStack(); ctx.popStack();

View File

@ -3,9 +3,9 @@ package de.maishai.typedast.typedclass;
import de.maishai.ast.records.Expression; import de.maishai.ast.records.Expression;
import de.maishai.ast.records.New; import de.maishai.ast.records.New;
import de.maishai.typedast.*; import de.maishai.typedast.*;
import de.maishai.typedast.ExceptionHandler.NotMatchConstructorException;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import java.util.ArrayList; import java.util.ArrayList;
@ -52,17 +52,18 @@ public class TypedNew implements TypedExpression, TypedStatement {
} }
} }
} }
throw new RuntimeException("No matching constructor found"); TypedProgram.addException("notMatchConstructor", new NotMatchConstructorException());
return null;
} }
@Override @Override
public void codeGen(MethodContext ctx) { public void codeGen(MethodContext ctx) {
ctx.getMv().visitTypeInsn(Opcodes.NEW, type.getReference()); ctx.getMv().visitTypeInsn(Opcodes.NEW, type.getReference());
System.out.println("NEW " + type.getReference()); //System.out.println("NEW " + type.getReference());
ctx.pushAnonToStack(); ctx.pushAnonToStack();
ctx.getMv().visitInsn(Opcodes.DUP); ctx.getMv().visitInsn(Opcodes.DUP);
System.out.println("DUP"); // System.out.println("DUP");
ctx.pushAnonToStack(); ctx.pushAnonToStack();
for (TypedExpression arg : args) { for (TypedExpression arg : args) {
arg.codeGen(ctx); arg.codeGen(ctx);
@ -71,6 +72,6 @@ public class TypedNew implements TypedExpression, TypedStatement {
for (TypedExpression arg : args) { for (TypedExpression arg : args) {
ctx.popStack(); ctx.popStack();
} }
System.out.println("INVOKESPECIAL " + type.getReference() + "<init> " + CodeGenUtils.generateDescriptor(args.stream().map(TypedExpression::getType).toList(), Type.VOID)); //System.out.println("INVOKESPECIAL " + type.getReference() + "<init> " + CodeGenUtils.generateDescriptor(args.stream().map(TypedExpression::getType).toList(), Type.VOID));
} }
} }

View File

@ -1,6 +1,7 @@
package de.maishai.typedast.typedclass; package de.maishai.typedast.typedclass;
import de.maishai.ast.records.Parameter; import de.maishai.ast.records.Parameter;
import de.maishai.typedast.ExceptionHandler.ParameterAlreadyExistsException;
import de.maishai.typedast.Type; import de.maishai.typedast.Type;
import de.maishai.typedast.TypedNode; import de.maishai.typedast.TypedNode;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
@ -36,11 +37,13 @@ public class TypedParameter implements TypedNode {
if (typedProgram.getCurrentClass().isCurrentMethodPresent()) { if (typedProgram.getCurrentClass().isCurrentMethodPresent()) {
if (typedProgram.getCurrentClass().isParameterWitNameInMethod(paraName)) { if (typedProgram.getCurrentClass().isParameterWitNameInMethod(paraName)) {
throw new RuntimeException("Parameter " + paraName + " already exists"); TypedProgram.addException(paraName, new ParameterAlreadyExistsException(paraName));
return null;
} }
} else if (typedProgram.getCurrentClass().isCurrentConstructorPresent()) { } else if (typedProgram.getCurrentClass().isCurrentConstructorPresent()) {
if (typedProgram.getCurrentClass().isParameterWitNameInConstructor(paraName)) { if (typedProgram.getCurrentClass().isParameterWitNameInConstructor(paraName)) {
throw new RuntimeException("Parameter " + paraName + " already exists"); TypedProgram.addException(paraName, new ParameterAlreadyExistsException(paraName));
return null;
} }
} }

View File

@ -5,12 +5,15 @@ import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public class TypedProgram { public class TypedProgram {
private List<TypedClass> typedClasses = new ArrayList<>(); private List<TypedClass> typedClasses = new ArrayList<>();
public static Map<String, Exception> EXCEPTIONS = new HashMap<>();
private TypedClass currentClass; private TypedClass currentClass;
public TypedProgram(Program program) { public TypedProgram(Program program) {
@ -41,6 +44,21 @@ public class TypedProgram {
exitCurrentClass(); exitCurrentClass();
i++; i++;
} }
if(EXCEPTIONS.isEmpty()){
System.out.println("Es wurde erfolgreich kompiliert.");
}else{
System.out.println("Es wurden insgesamt " + EXCEPTIONS.size() + " Fehlern gefunden:");
int counter = 0;
for(Map.Entry<String, Exception> entry : EXCEPTIONS.entrySet()){
System.out.println("["+ counter + "] Fehler: " +
"\n Schlüssel: " + entry.getKey() +
"\n Exception: " + entry.getValue().getClass().getSimpleName() +
"\n Message: " + entry.getValue().getMessage()
);
counter++;
}
}
} }
public TypedClass getTypedClass(String className) { public TypedClass getTypedClass(String className) {
@ -59,6 +77,12 @@ public class TypedProgram {
currentClass = null; currentClass = null;
} }
public static void addException(String name, Exception ex){
if(!EXCEPTIONS.containsKey(name)){
EXCEPTIONS.put(name, ex);
}
}
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) return true; if (this == obj) return true;
@ -69,7 +93,7 @@ public class TypedProgram {
|| currentClass.equals(other.currentClass))) { || currentClass.equals(other.currentClass))) {
return true; return true;
} else { } else {
System.out.println("TypedPrograms are not equal:\n" + this.typedClasses + "\n" + other.typedClasses + "\n"); //System.out.println("TypedPrograms are not equal:\n" + this.typedClasses + "\n" + other.typedClasses + "\n");
return false; return false;
} }
} }

View File

@ -3,6 +3,7 @@ package de.maishai.typedast.typedclass;
import de.maishai.ast.records.*; import de.maishai.ast.records.*;
import de.maishai.typedast.*; import de.maishai.typedast.*;
import de.maishai.typedast.ExceptionHandler.TypeOfReturnNotMatchException;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@ -35,12 +36,17 @@ public class TypedReturn implements TypedStatement {
public Type typeCheck(TypedProgram typedProgram) { public Type typeCheck(TypedProgram typedProgram) {
if (typedProgram.getCurrentClass().isCurrentMethodPresent()) { if (typedProgram.getCurrentClass().isCurrentMethodPresent()) {
if (typedProgram.getCurrentClass().getCurrentMethod().getReturnType().getKind() != this.type.getKind()) { if (typedProgram.getCurrentClass().getCurrentMethod().getReturnType().getKind() != this.type.getKind()) {
StringBuilder exp = new StringBuilder(); String key = "Type of return in " + typedProgram.getCurrentClass().getCurrentMethod().getName();
exp.append("\nMismatched return type: "); TypeOfReturnNotMatchException ex = new TypeOfReturnNotMatchException(
exp.append("\nExpected: ").append(typedProgram.getCurrentClass().getCurrentMethod().getReturnType().getKind()); typedProgram.getCurrentClass().getCurrentMethod().getReturnType().getKind().name(),
exp.append("\nActual: ").append(this.type.getKind()); this.type.getKind().name(),
exp.append("\nMethod name: ").append(typedProgram.getCurrentClass().getCurrentMethod().getName()); typedProgram.getCurrentClass().getCurrentMethod().getName());
throw new RuntimeException(exp.toString()); 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; return type;
@ -50,15 +56,15 @@ public class TypedReturn implements TypedStatement {
public void codeGen(MethodContext ctx) { public void codeGen(MethodContext ctx) {
if (ret == null) { if (ret == null) {
ctx.getMv().visitInsn(Opcodes.RETURN); ctx.getMv().visitInsn(Opcodes.RETURN);
System.out.println("RETURN"); //System.out.println("RETURN");
} else { } else {
ret.codeGen(ctx); ret.codeGen(ctx);
if (ret.getType().getKind() != Type.Kind.REFERENCE) { if (ret.getType().getKind() != Type.Kind.REFERENCE) {
ctx.getMv().visitInsn(Opcodes.IRETURN); ctx.getMv().visitInsn(Opcodes.IRETURN);
System.out.println("IRETURN"); // System.out.println("IRETURN");
} else { } else {
ctx.getMv().visitInsn(Opcodes.ARETURN); ctx.getMv().visitInsn(Opcodes.ARETURN);
System.out.println("ARETURN"); // System.out.println("ARETURN");
} }
} }

View File

@ -31,18 +31,21 @@ public class TypedUnary implements TypedExpression {
if (op == UnaryOperator.NOT) { if (op == UnaryOperator.NOT) {
if (right.typeCheck(typedProgram) != Type.BOOL) { 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;
} }
return Type.BOOL; return Type.BOOL;
} }
if (op == UnaryOperator.SUB) { if (op == UnaryOperator.SUB) {
if (right.typeCheck(typedProgram) != Type.INT) { 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;
} }
return Type.INT; return Type.INT;
} }
throw new RuntimeException("Unknown unary operator"); TypedProgram.addException("UnknownUnary",new RuntimeException("Unknown unary operator") );
return null;
} }
@Override @Override

View File

@ -28,7 +28,8 @@ public class TypedWhile implements TypedStatement {
@Override @Override
public Type typeCheck(TypedProgram typedProgram) { public Type typeCheck(TypedProgram typedProgram) {
if (cond.typeCheck(typedProgram) != Type.BOOL) { 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); type = typedBlock.typeCheck(typedProgram);
return type; return type;