mostly refactoring und now using "typecheckexception"

This commit is contained in:
Krauß, Josefine 2024-06-20 11:03:27 +02:00
parent 5220a65a92
commit fdae734452
32 changed files with 113 additions and 110 deletions

View File

@ -79,40 +79,6 @@ public class Compiler {
System.out.println(refType.name); System.out.println(refType.name);
} }
//
// List<FieldDecl> fieldDecls = new ArrayList<>();
//
// FieldDecl fieldDecl = new FieldDecl("int", "i");
// fieldDecls.add(fieldDecl);
//
//// FieldDecl fieldDecl2 = new FieldDecl("char", "i");
//// fieldDecls.add(fieldDecl2);
//
// List<MethodDecl> methodDecls = new ArrayList<>();
//
//
// MethodDecl methodDecl = new MethodDecl("ClassA", "int", "m", new ParameterList(new ArrayList<>()), new BlockStatement(new ArrayList<>(), "void"));
// methodDecls.add(methodDecl);
//
//// MethodDecl methodDecl2 = new MethodDecl("ClassA", "int", "m", new ArrayList<>(), new ArrayList<>());
//// methodDecls.add(methodDecl2);
//
// abstractSyntaxTree.classes.add(new RefType("MyClass", fieldDecls, methodDecls, false));
//
// System.out.println("Parsed " + abstractSyntaxTree.classes.size() + " classes with identifiers/names:");
// for (RefType refType : abstractSyntaxTree.classes) {
// System.out.println(refType.name);
// }
IfElseStatement c = (IfElseStatement) abstractSyntaxTree.classes.get(0).methodDecls.get(0).codeBlock.statements.get(2);
InstVarExpression d = (InstVarExpression) c.condition;
d.classRef = abstractSyntaxTree.classes.get(0);
AssignStatementExpression a = (AssignStatementExpression) abstractSyntaxTree.classes.get(0).methodDecls.get(0).codeBlock.statements.get(1);
InstVarExpression b = (InstVarExpression) a.left;
b.classRef = abstractSyntaxTree.classes.get(0);
abstractSyntaxTree.typeCheck(); abstractSyntaxTree.typeCheck();
abstractSyntaxTree.codeGen(); abstractSyntaxTree.codeGen();

View File

@ -1,15 +1,24 @@
class Example { class Example1 {
int i; int i;
boolean b; boolean b;
char c; char c;
int m(int n){ int m(int n){
int localA; Example e = new Example();
this.b = true; e.m(1);
if(this.b){ return 0;
}
}
class Example {
int i;
boolean b;
char c;
int m(int a){
int localA = 0;
boolean localB = true;
if(localB){
localA = 7; localA = 7;
}else{ }else{}
localA = 5;
}
return localA; return localA;
} }
} }

View File

@ -0,0 +1,7 @@
package TypeCheck;
public class TypeCheckException extends Exception {
public TypeCheckException(String message) {
super(message);
}
}

View File

@ -4,23 +4,19 @@ import java.util.List;
import java.util.Objects; import java.util.Objects;
public class TypeCheckHelper { public class TypeCheckHelper {
public String upperBound(String type1, String type2) throws Exception{ public String upperBound(String type1, String type2) throws TypeCheckException{
if(Objects.equals(type1, "boolean")) boolean type1Primitiv = Objects.equals(type1, "boolean") || Objects.equals(type1, "int") || Objects.equals(type1, "char");
type1 = "bool"; boolean type2Primitiv = Objects.equals(type2, "boolean") || Objects.equals(type2, "int") || Objects.equals(type2, "char");
if (Objects.equals(type2, "boolean"))
type2 = "bool";
boolean type1Primitiv = Objects.equals(type1, "bool") || Objects.equals(type1, "int") || Objects.equals(type1, "char");
boolean type2Primitiv = Objects.equals(type2, "bool") || Objects.equals(type2, "int") || Objects.equals(type2, "char");
String result; String result;
if(type1Primitiv && type2Primitiv){ if(type1Primitiv && type2Primitiv){
if(Objects.equals(type1, type2)){ if(Objects.equals(type1, type2)){
result = type1; result = type1;
}else{ }else{
throw new Exception("no upper bound"); throw new TypeCheckException("There is no upper bound.");
} }
}else if(type1Primitiv || type2Primitiv){ }else if(type1Primitiv || type2Primitiv){
throw new Exception("no upper bound"); throw new TypeCheckException("There is no upper bound.");
}else{ }else{
result = "class"; result = "class";
} }

View File

@ -1,6 +1,7 @@
package abstractSyntaxTree.Class; package abstractSyntaxTree.Class;
import TypeCheck.AbstractType; import TypeCheck.AbstractType;
import TypeCheck.TypeCheckException;
import TypeCheck.TypeCheckHelper; import TypeCheck.TypeCheckHelper;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import abstractSyntaxTree.Node; import abstractSyntaxTree.Node;
@ -23,7 +24,7 @@ public class FieldDecl extends AbstractType implements Node {
this.type = type; this.type = type;
this.identifier = identifier; this.identifier = identifier;
} }
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, String>> typeContext) throws Exception { public TypeCheckResult typeCheck(HashMap<String, HashMap<String, String>> typeContext) throws TypeCheckException {
TypeCheckResult result = new TypeCheckResult(); TypeCheckResult result = new TypeCheckResult();

View File

@ -1,5 +1,6 @@
package abstractSyntaxTree.Class; package abstractSyntaxTree.Class;
import TypeCheck.TypeCheckException;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import abstractSyntaxTree.Node; import abstractSyntaxTree.Node;
import abstractSyntaxTree.Parameter.Parameter; import abstractSyntaxTree.Parameter.Parameter;
@ -33,7 +34,7 @@ public class MethodDecl implements Node {
this.localVars = new LinkedHashMap<>(); this.localVars = new LinkedHashMap<>();
} }
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception { public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws TypeCheckException {
// jede methode als block statement aufrufen und jede neue locale varibale in localvars schreiben // jede methode als block statement aufrufen und jede neue locale varibale in localvars schreiben
List<Parameter> parametersList = parameters.parameterList; List<Parameter> parametersList = parameters.parameterList;
for(Parameter parameter : parametersList){ for(Parameter parameter : parametersList){
@ -43,7 +44,7 @@ public class MethodDecl implements Node {
TypeCheckResult result = new TypeCheckResult(); TypeCheckResult result = new TypeCheckResult();
String CodeBlockType = codeBlock.typeCheck(methodContext, typeContext, localVars).type; String CodeBlockType = codeBlock.typeCheck(methodContext, typeContext, localVars).type;
if(!Objects.equals(this.returnType, CodeBlockType)) if(!Objects.equals(this.returnType, CodeBlockType))
throw new Exception("TypeCheck Exception: Method retruns wrong type"); throw new TypeCheckException("Method returns " + CodeBlockType + ", but should retrun " + this.returnType + ". ");
result.type = codeBlock.returnType; result.type = codeBlock.returnType;
return result; return result;
} }

View File

@ -1,6 +1,7 @@
package abstractSyntaxTree.Class; package abstractSyntaxTree.Class;
import TypeCheck.AbstractType; import TypeCheck.AbstractType;
import TypeCheck.TypeCheckException;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import abstractSyntaxTree.Expression.IExpression; import abstractSyntaxTree.Expression.IExpression;
import abstractSyntaxTree.Node; import abstractSyntaxTree.Node;
@ -34,14 +35,14 @@ public class RefType extends AbstractType implements Node {
} }
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext,
HashMap<String, HashMap<String, String>> typeContext) throws Exception { HashMap<String, HashMap<String, String>> typeContext) throws TypeCheckException {
TypeCheckResult result = new TypeCheckResult(); TypeCheckResult result = new TypeCheckResult();
// check if field with the same identifier is defined more than once // check if field with the same identifier is defined more than once
List<String> discoveredFieldIdentifiers = new ArrayList<>(); List<String> discoveredFieldIdentifiers = new ArrayList<>();
for (FieldDecl fieldDecl : fieldDecls) { for (FieldDecl fieldDecl : fieldDecls) {
if(discoveredFieldIdentifiers.contains(fieldDecl.identifier)){ if(discoveredFieldIdentifiers.contains(fieldDecl.identifier)){
throw new Exception("A field with the identifier " + fieldDecl.identifier + " was defined more than once in the same class."); throw new TypeCheckException("A field with the identifier " + fieldDecl.identifier + " was defined more than once in the class " + this.name + ". ");
} }
discoveredFieldIdentifiers.add(fieldDecl.identifier); discoveredFieldIdentifiers.add(fieldDecl.identifier);
} }
@ -58,7 +59,7 @@ public class RefType extends AbstractType implements Node {
if (discoveredMethods.containsKey(methodDecl.returnType)) { if (discoveredMethods.containsKey(methodDecl.returnType)) {
if(discoveredMethods.get(methodDecl.returnType).equals(methodDecl.name)){ if(discoveredMethods.get(methodDecl.returnType).equals(methodDecl.name)){
throw new Exception("A method with the name " + methodDecl.name + " and return type " + methodDecl.returnType + " was defined more than once in the same class."); throw new TypeCheckException("A method with the name " + methodDecl.name + " and return type " + methodDecl.returnType + " was defined more than once in the same class.");
} }
} }
discoveredMethods.put(methodDecl.returnType, methodDecl.name); discoveredMethods.put(methodDecl.returnType, methodDecl.name);

View File

@ -17,10 +17,10 @@ public class BoolDatatype extends AbstractType implements IDatatype{
return (Objects.equals(value, boolDatatype.value)); return (Objects.equals(value, boolDatatype.value));
} }
@Override @Override
public TypeCheckResult typeCheck() throws Exception { public TypeCheckResult typeCheck() {
TypeCheckResult result = new TypeCheckResult(); TypeCheckResult result = new TypeCheckResult();
result.type = "bool"; result.type = "boolean";
setTypeCheckResult(result); setTypeCheckResult(result);
return result; return result;

View File

@ -10,7 +10,7 @@ public class CharDatatype extends AbstractType implements IDatatype{
char value; char value;
@Override @Override
public TypeCheckResult typeCheck() throws Exception { public TypeCheckResult typeCheck() {
TypeCheckResult result = new TypeCheckResult(); TypeCheckResult result = new TypeCheckResult();
result.type = "char"; result.type = "char";

View File

@ -1,11 +1,12 @@
package abstractSyntaxTree.Datatype; package abstractSyntaxTree.Datatype;
import TypeCheck.TypeCheckException;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
public interface IDatatype { public interface IDatatype {
// typeCheck method // typeCheck method
TypeCheckResult typeCheck() throws Exception; TypeCheckResult typeCheck() throws TypeCheckException;
// visit method for code generation // visit method for code generation

View File

@ -10,7 +10,7 @@ import java.util.Objects;
public class IntDatatype extends AbstractType implements IDatatype{ public class IntDatatype extends AbstractType implements IDatatype{
int value; int value;
@Override @Override
public TypeCheckResult typeCheck() throws Exception { public TypeCheckResult typeCheck() {
TypeCheckResult result = new TypeCheckResult(); TypeCheckResult result = new TypeCheckResult();
result.type = "int"; result.type = "int";
@ -19,9 +19,6 @@ public class IntDatatype extends AbstractType implements IDatatype{
return result; return result;
} }
// visit method for code generation
@Override @Override
public void codeGen(MethodVisitor mv) throws Exception { public void codeGen(MethodVisitor mv) throws Exception {

View File

@ -1,5 +1,6 @@
package abstractSyntaxTree.Expression; package abstractSyntaxTree.Expression;
import TypeCheck.TypeCheckException;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import TypeCheck.TypeCheckHelper; import TypeCheck.TypeCheckHelper;
import TypeCheck.AbstractType; import TypeCheck.AbstractType;
@ -24,7 +25,7 @@ public class BinaryExpression extends AbstractType implements IExpression{
} }
@Override @Override
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception { public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
TypeCheckHelper helper = new TypeCheckHelper(); TypeCheckHelper helper = new TypeCheckHelper();
TypeCheckResult result = new TypeCheckResult(); TypeCheckResult result = new TypeCheckResult();
@ -163,7 +164,7 @@ public class BinaryExpression extends AbstractType implements IExpression{
break; break;
default: default:
throw new Exception("Unknown operator: " + operator); throw new TypeCheckException("The operator " + operator + " is not known.");
} }
mv.visitLabel(operationFalse); mv.visitLabel(operationFalse);

View File

@ -1,6 +1,7 @@
package abstractSyntaxTree.Expression; package abstractSyntaxTree.Expression;
import TypeCheck.AbstractType; import TypeCheck.AbstractType;
import TypeCheck.TypeCheckException;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import abstractSyntaxTree.Parameter.ParameterList; import abstractSyntaxTree.Parameter.ParameterList;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
@ -16,9 +17,9 @@ public class BooleanConstantExpression extends AbstractType implements IExpressi
} }
@Override @Override
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception { public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) {
TypeCheckResult result = new TypeCheckResult(); TypeCheckResult result = new TypeCheckResult();
result.type = "bool"; result.type = "boolean";
setTypeCheckResult(result); setTypeCheckResult(result);
return result; return result;
} }

View File

@ -16,7 +16,7 @@ public class CharConstantExpression extends AbstractType implements IExpression{
} }
@Override @Override
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception { public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) {
TypeCheckResult result = new TypeCheckResult(); TypeCheckResult result = new TypeCheckResult();
result.type = "char"; result.type = "char";
setTypeCheckResult(result); setTypeCheckResult(result);

View File

@ -1,5 +1,6 @@
package abstractSyntaxTree.Expression; package abstractSyntaxTree.Expression;
import TypeCheck.TypeCheckException;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import abstractSyntaxTree.Node; import abstractSyntaxTree.Node;
import abstractSyntaxTree.Parameter.ParameterList; import abstractSyntaxTree.Parameter.ParameterList;
@ -11,7 +12,7 @@ import java.util.LinkedHashMap;
public interface IExpression extends Node { public interface IExpression extends Node {
// typeCheck method // typeCheck method
//TypeCheckResult typeCheck() throws Exception; //TypeCheckResult typeCheck() throws Exception;
TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception; TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException;
// visit method for code generation // visit method for code generation
void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception; void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception;

View File

@ -1,6 +1,7 @@
package abstractSyntaxTree.Expression; package abstractSyntaxTree.Expression;
import TypeCheck.AbstractType; import TypeCheck.AbstractType;
import TypeCheck.TypeCheckException;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import abstractSyntaxTree.Class.RefType; import abstractSyntaxTree.Class.RefType;
import abstractSyntaxTree.Parameter.ParameterList; import abstractSyntaxTree.Parameter.ParameterList;
@ -30,10 +31,11 @@ public class InstVarExpression extends AbstractType implements IExpression{
} }
@Override @Override
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception { public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
//todo ///////////////////
String varType = typeContext.get(classRef.name).get(fieldName); String varType = typeContext.get(classRef.name).get(fieldName);
if (varType == null) {
throw new TypeCheckException("Field " + fieldName + " was not found in class " + classRef.name + ".");
}
TypeCheckResult result = new TypeCheckResult(); TypeCheckResult result = new TypeCheckResult();
result.type = varType; result.type = varType;
return result; return result;

View File

@ -18,7 +18,7 @@ public class IntConstantExpression extends AbstractType implements IExpression{
} }
@Override @Override
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception { public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) {
TypeCheckResult result = new TypeCheckResult(); TypeCheckResult result = new TypeCheckResult();
result.type = "int"; result.type = "int";
setTypeCheckResult(result); setTypeCheckResult(result);

View File

@ -1,6 +1,7 @@
package abstractSyntaxTree.Expression; package abstractSyntaxTree.Expression;
import TypeCheck.AbstractType; import TypeCheck.AbstractType;
import TypeCheck.TypeCheckException;
import TypeCheck.TypeCheckHelper; import TypeCheck.TypeCheckHelper;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import org.objectweb.asm.*; import org.objectweb.asm.*;
@ -25,12 +26,12 @@ public class LocalVarIdentifier extends AbstractType implements IExpression{
} }
@Override @Override
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception { public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
TypeCheckResult result = new TypeCheckResult(); TypeCheckResult result = new TypeCheckResult();
if (localVars.containsKey(identifier)) { if (localVars.containsKey(identifier)) {
result.type = localVars.get(identifier); result.type = localVars.get(identifier);
} else { } else {
throw new Exception("TypeCheck Exception: Local var " + identifier + " does not exist."); throw new TypeCheckException("Local var " + identifier + " does not exist.");
} }
setTypeCheckResult(result); setTypeCheckResult(result);
return result; return result;

View File

@ -1,6 +1,7 @@
package abstractSyntaxTree.Expression; package abstractSyntaxTree.Expression;
import TypeCheck.AbstractType; import TypeCheck.AbstractType;
import TypeCheck.TypeCheckException;
import TypeCheck.TypeCheckHelper; import TypeCheck.TypeCheckHelper;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import abstractSyntaxTree.Datatype.IDatatype; import abstractSyntaxTree.Datatype.IDatatype;
@ -20,7 +21,7 @@ public class UnaryExpression extends AbstractType implements IExpression{
this.operand = operand; this.operand = operand;
} }
@Override @Override
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception { public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
TypeCheckResult result = new TypeCheckResult(); TypeCheckResult result = new TypeCheckResult();
TypeCheckResult operandTypeCheckResult = operand.typeCheck(); TypeCheckResult operandTypeCheckResult = operand.typeCheck();

View File

@ -1,5 +1,6 @@
package abstractSyntaxTree; package abstractSyntaxTree;
import TypeCheck.TypeCheckException;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import abstractSyntaxTree.Class.FieldDecl; import abstractSyntaxTree.Class.FieldDecl;
import abstractSyntaxTree.Class.MethodDecl; import abstractSyntaxTree.Class.MethodDecl;
@ -27,7 +28,7 @@ public class Program implements Node {
} }
public TypeCheckResult typeCheck() throws Exception{ public TypeCheckResult typeCheck() throws TypeCheckException {
this.typeContext = new HashMap<>(); this.typeContext = new HashMap<>();
this.methodContext = new HashMap<>(); this.methodContext = new HashMap<>();

View File

@ -1,5 +1,6 @@
package abstractSyntaxTree.Statement; package abstractSyntaxTree.Statement;
import TypeCheck.TypeCheckException;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import TypeCheck.AbstractType; import TypeCheck.AbstractType;
import abstractSyntaxTree.Class.FieldDecl; import abstractSyntaxTree.Class.FieldDecl;
@ -28,7 +29,7 @@ public class BlockStatement extends AbstractType implements IStatement {
@Override @Override
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext,
HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, String>> typeContext,
HashMap<String, String> localVars) throws Exception { HashMap<String, String> localVars) throws TypeCheckException {
TypeCheckResult result = new TypeCheckResult(); TypeCheckResult result = new TypeCheckResult();
this.localVars = localVars; this.localVars = localVars;
@ -54,10 +55,10 @@ public class BlockStatement extends AbstractType implements IStatement {
if (!firstType.equals(this.returnType) || !firstType.equals(this.returnType)) { if (!firstType.equals(this.returnType) || !firstType.equals(this.returnType)) {
if (!firstType.equals("void") && this.returnType != null) { if (!firstType.equals("void") && this.returnType != null) {
throw new Exception("TypeCheck Exception: if paths return wrong type"); throw new TypeCheckException("The if-Path returns the wrong type.");
} }
if (!secondType.equals("void") && this.returnType != null) { if (!secondType.equals("void") && this.returnType != null) {
throw new Exception("TypeCheck Exception: else paths return wrong type"); throw new TypeCheckException("The else-path returns the wrong type.");
} }
boolean firstIsVoid = firstType.equals("void"); boolean firstIsVoid = firstType.equals("void");
@ -78,11 +79,9 @@ public class BlockStatement extends AbstractType implements IStatement {
this.returnType = typeOfCurrentStatement.type; this.returnType = typeOfCurrentStatement.type;
if (!typeOfCurrentStatement.type.equals(this.returnType)) if (!typeOfCurrentStatement.type.equals(this.returnType))
throw new Exception("TypeCheck Exception: Block returns the wrong type."); throw new TypeCheckException("At least some statements of the block returns the wrong type or missing return statement.");
} }
result.type = this.returnType; result.type = this.returnType;
// todo check if the block returns the needed return type in every case
// todo ignore unreachable statements?
setTypeCheckResult(result); setTypeCheckResult(result);
return result; return result;
} }

View File

@ -13,7 +13,7 @@ import java.util.Objects;
public class EmptyStatement extends AbstractType implements IStatement{ public class EmptyStatement extends AbstractType implements IStatement{
@Override @Override
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception { public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) {
TypeCheckResult result = new TypeCheckResult(); TypeCheckResult result = new TypeCheckResult();
result.type = "void"; result.type = "void";
return result; return result;

View File

@ -1,5 +1,6 @@
package abstractSyntaxTree.Statement; package abstractSyntaxTree.Statement;
import TypeCheck.TypeCheckException;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import abstractSyntaxTree.Node; import abstractSyntaxTree.Node;
import abstractSyntaxTree.Parameter.ParameterList; import abstractSyntaxTree.Parameter.ParameterList;
@ -11,7 +12,7 @@ import java.util.List;
public interface IStatement extends Node { public interface IStatement extends Node {
TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception; TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException;
void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception; void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception;
TypeCheckResult getTypeCheckResult(); TypeCheckResult getTypeCheckResult();

View File

@ -1,5 +1,6 @@
package abstractSyntaxTree.Statement; package abstractSyntaxTree.Statement;
import TypeCheck.TypeCheckException;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import TypeCheck.AbstractType; import TypeCheck.AbstractType;
import abstractSyntaxTree.Expression.IExpression; import abstractSyntaxTree.Expression.IExpression;
@ -24,13 +25,13 @@ public class IfElseStatement extends AbstractType implements IStatement{
@Override @Override
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception { public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
TypeCheckResult result = new TypeCheckResult(); TypeCheckResult result = new TypeCheckResult();
TypeCheckResult conditionType = condition.typeCheck(methodContext, typeContext, localVars); TypeCheckResult conditionType = condition.typeCheck(methodContext, typeContext, localVars);
if (!conditionType.type.equals("boolean")) { if (!conditionType.type.equals("boolean")) {
throw new IllegalArgumentException("should be boolean"); throw new TypeCheckException("The condition of a if statement is " + conditionType.type + ", but should be boolean.");
} }
TypeCheckResult ifStatementType = ifStatement.typeCheck(methodContext, typeContext, localVars); TypeCheckResult ifStatementType = ifStatement.typeCheck(methodContext, typeContext, localVars);
@ -38,7 +39,7 @@ public class IfElseStatement extends AbstractType implements IStatement{
if (!ifStatementType.type.equals(elseStatementType.type)) { if (!ifStatementType.type.equals(elseStatementType.type)) {
if(ifStatementType.type != "void" && elseStatementType.type != "void") if(ifStatementType.type != "void" && elseStatementType.type != "void")
throw new IllegalArgumentException("TypeCeck Exception: if and else have different types"); throw new TypeCheckException("If- and else-path return different not-void types.");
} }
result.type = ifStatementType.type + "," + elseStatementType.type; result.type = ifStatementType.type + "," + elseStatementType.type;

View File

@ -1,5 +1,6 @@
package abstractSyntaxTree.Statement; package abstractSyntaxTree.Statement;
import TypeCheck.TypeCheckException;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import TypeCheck.AbstractType; import TypeCheck.AbstractType;
import abstractSyntaxTree.Expression.IExpression; import abstractSyntaxTree.Expression.IExpression;
@ -23,13 +24,13 @@ public class IfStatement extends AbstractType implements IStatement{
} }
@Override @Override
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception { public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
TypeCheckResult result = new TypeCheckResult(); TypeCheckResult result = new TypeCheckResult();
TypeCheckResult conditionType = condition.typeCheck(methodContext, typeContext, localVars); TypeCheckResult conditionType = condition.typeCheck(methodContext, typeContext, localVars);
if (!conditionType.equals("bool")) { if (!conditionType.type.equals("boolean")) {
throw new Exception("TypeCheck Exception: Condition of If-Statement should be bool."); throw new TypeCheckException("Condition of If-Statement should is " + conditionType.type + ", but should be boolean.");
} }
TypeCheckResult ifStatementType = ifStatement.typeCheck(methodContext, typeContext, localVars); TypeCheckResult ifStatementType = ifStatement.typeCheck(methodContext, typeContext, localVars);

View File

@ -1,6 +1,7 @@
package abstractSyntaxTree.Statement; package abstractSyntaxTree.Statement;
import TypeCheck.AbstractType; import TypeCheck.AbstractType;
import TypeCheck.TypeCheckException;
import TypeCheck.TypeCheckHelper; import TypeCheck.TypeCheckHelper;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import abstractSyntaxTree.Parameter.ParameterList; import abstractSyntaxTree.Parameter.ParameterList;
@ -17,7 +18,7 @@ public class LocalVarDecl extends AbstractType implements IStatement{
this.identifier = identifier; this.identifier = identifier;
} }
@Override @Override
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception { public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
TypeCheckHelper.typeExists(this.type, new ArrayList<>(methodContext.keySet())); TypeCheckHelper.typeExists(this.type, new ArrayList<>(methodContext.keySet()));
localVars.put(this.identifier, this.type); localVars.put(this.identifier, this.type);

View File

@ -1,5 +1,6 @@
package abstractSyntaxTree.Statement; package abstractSyntaxTree.Statement;
import TypeCheck.TypeCheckException;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import TypeCheck.AbstractType; import TypeCheck.AbstractType;
import abstractSyntaxTree.Expression.IExpression; import abstractSyntaxTree.Expression.IExpression;
@ -19,7 +20,7 @@ public class ReturnStatement extends AbstractType implements IStatement{
} }
@Override @Override
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception { public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
TypeCheckResult result = new TypeCheckResult(); TypeCheckResult result = new TypeCheckResult();
if (expression == null) { if (expression == null) {
@ -45,7 +46,7 @@ public class ReturnStatement extends AbstractType implements IStatement{
//TODO: Resolve how do we get the type of the expression //TODO: Resolve how do we get the type of the expression
String type = expression.getTypeCheckResult().type; String type = expression.getTypeCheckResult().type;
if (type.equals("int") || type.equals("bool") || type.equals("char")) { if (type.equals("int") || type.equals("boolean") || type.equals("char")) {
mv.visitInsn(Opcodes.IRETURN); mv.visitInsn(Opcodes.IRETURN);
} else { } else {
mv.visitInsn(Opcodes.ARETURN); mv.visitInsn(Opcodes.ARETURN);

View File

@ -1,5 +1,6 @@
package abstractSyntaxTree.Statement; package abstractSyntaxTree.Statement;
import TypeCheck.TypeCheckException;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import TypeCheck.AbstractType; import TypeCheck.AbstractType;
import abstractSyntaxTree.Expression.IExpression; import abstractSyntaxTree.Expression.IExpression;
@ -21,12 +22,12 @@ public class WhileStatement extends AbstractType implements IStatement {
} }
@Override @Override
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception { public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
TypeCheckResult result = new TypeCheckResult(); TypeCheckResult result = new TypeCheckResult();
// check condition // check condition
TypeCheckResult conditionType = condition.typeCheck(methodContext, typeContext, localVars); TypeCheckResult conditionType = condition.typeCheck(methodContext, typeContext, localVars);
if (!conditionType.equals("bool")) { if (!conditionType.type.equals("boolean")) {
throw new IllegalArgumentException("Expected boolean"); throw new IllegalArgumentException("Expected boolean");
} }

View File

@ -1,6 +1,7 @@
package abstractSyntaxTree.StatementExpression; package abstractSyntaxTree.StatementExpression;
import TypeCheck.AbstractType; import TypeCheck.AbstractType;
import TypeCheck.TypeCheckException;
import TypeCheck.TypeCheckHelper; import TypeCheck.TypeCheckHelper;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import abstractSyntaxTree.Expression.IExpression; import abstractSyntaxTree.Expression.IExpression;
@ -28,7 +29,7 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
} }
@Override @Override
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception { public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
TypeCheckHelper helper = new TypeCheckHelper(); TypeCheckHelper helper = new TypeCheckHelper();
TypeCheckResult result = new TypeCheckResult(); TypeCheckResult result = new TypeCheckResult();
@ -48,7 +49,7 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
if(Objects.equals(leftType.type, "boolean")) if(Objects.equals(leftType.type, "boolean"))
leftType.type = "bool"; leftType.type = "bool";
if (!Objects.equals(upperbound, leftType.type)) { if (!Objects.equals(upperbound, leftType.type)) {
throw new Exception("TypeCheck Exception: upper bound of assignment is not left type"); throw new TypeCheckException("The upper bound of assignment is not the left type.");
} }
result.type = "void"; result.type = "void";
setTypeCheckResult(result); setTypeCheckResult(result);

View File

@ -1,12 +1,14 @@
package abstractSyntaxTree.StatementExpression; package abstractSyntaxTree.StatementExpression;
import TypeCheck.AbstractType; import TypeCheck.AbstractType;
import TypeCheck.TypeCheckException;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import abstractSyntaxTree.Class.MethodDecl; import abstractSyntaxTree.Class.MethodDecl;
import abstractSyntaxTree.Class.RefType; import abstractSyntaxTree.Class.RefType;
import abstractSyntaxTree.Expression.IExpression; import abstractSyntaxTree.Expression.IExpression;
import abstractSyntaxTree.Parameter.ParameterList; import abstractSyntaxTree.Parameter.ParameterList;
import abstractSyntaxTree.Statement.IStatement; import abstractSyntaxTree.Statement.IStatement;
import jdk.jshell.spi.ExecutionControl;
import org.objectweb.asm.ClassWriter; import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
@ -28,7 +30,8 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
this.arguments = arguments; this.arguments = arguments;
} }
public TypeCheckResult typeCheck() throws Exception { @Override
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
TypeCheckResult result = new TypeCheckResult(); TypeCheckResult result = new TypeCheckResult();
RefType searchMethodHere; RefType searchMethodHere;
@ -41,18 +44,12 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
List<MethodDecl> methods = searchMethodHere.methodDecls; List<MethodDecl> methods = searchMethodHere.methodDecls;
if(!methods.contains(methodName)){ if(!methods.contains(methodName)){
throw new Exception("method not found"); throw new TypeCheckException("The method " + methodName + " is called, but does not exist.");
} }
return result; return result;
} }
@Override
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
return null;
}
//Errors occur due to the change in parameter in the RefType class //Errors occur due to the change in parameter in the RefType class
// I need the methodContext here to get the method descriptor // I need the methodContext here to get the method descriptor
@Override @Override

View File

@ -1,6 +1,7 @@
package abstractSyntaxTree.StatementExpression; package abstractSyntaxTree.StatementExpression;
import TypeCheck.AbstractType; import TypeCheck.AbstractType;
import TypeCheck.TypeCheckException;
import TypeCheck.TypeCheckHelper; import TypeCheck.TypeCheckHelper;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import abstractSyntaxTree.Expression.IExpression; import abstractSyntaxTree.Expression.IExpression;
@ -26,14 +27,16 @@ public class NewStatementExpression extends AbstractType implements IExpression,
} }
@Override @Override
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception { public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
//todo testen wenn in ast vorhanden
if(!TypeCheckHelper.typeExists(className, new ArrayList<>(typeContext.keySet()))){ if(!TypeCheckHelper.typeExists(className, new ArrayList<>(typeContext.keySet()))){
throw new Exception("TypeCheck Exception: An instance of " + className + " is created, but the type does not exist."); throw new TypeCheckException("An instance of " + className + " is created, but the type does not exist.");
} }
TypeCheckResult result = new TypeCheckResult(); TypeCheckResult result = new TypeCheckResult();
result.type = className; result.type = className;
setTypeCheckResult(result); setTypeCheckResult(result);
return result; return result;
} }
@Override @Override

View File

@ -1,7 +1,16 @@
package abstractSyntaxTree.StatementExpression; package abstractSyntaxTree.StatementExpression;
import TypeCheck.TypeCheckException;
import TypeCheck.TypeCheckResult;
import abstractSyntaxTree.Expression.IExpression;
import abstractSyntaxTree.Expression.InstVarExpression; import abstractSyntaxTree.Expression.InstVarExpression;
import abstractSyntaxTree.Node; import abstractSyntaxTree.Node;
import abstractSyntaxTree.Parameter.ParameterList;
import abstractSyntaxTree.Statement.IStatement;
import org.objectweb.asm.MethodVisitor;
import java.util.HashMap;
import java.util.LinkedHashMap;
public class Receiver implements Node { public class Receiver implements Node {
boolean thisExpression; boolean thisExpression;
@ -24,6 +33,7 @@ public class Receiver implements Node {
public Receiver(String identifier) { public Receiver(String identifier) {
this.identifier = identifier; this.identifier = identifier;
} }
} }