mirror of
https://github.com/JonathanFleischmann/CompilerULTIMATE.git
synced 2024-12-28 03:08:02 +00:00
Implemented TypeCheck
This commit is contained in:
parent
deeea62737
commit
5fa439ec90
@ -1,4 +1,11 @@
|
||||
package de.maishai.ast;
|
||||
|
||||
import de.maishai.typedast.Type;
|
||||
import de.maishai.ast.records.Class;
|
||||
import java.util.Map;
|
||||
|
||||
public interface Node {
|
||||
|
||||
public Type typeCheck(Map<String, Type> localVars, Map<String, Class> classes);
|
||||
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
package de.maishai.ast;
|
||||
public interface Statement extends Node {
|
||||
|
||||
}
|
||||
|
@ -1,7 +0,0 @@
|
||||
package de.maishai.ast;
|
||||
|
||||
public enum Type {
|
||||
INT,
|
||||
BOOL,
|
||||
CHAR
|
||||
}
|
@ -3,6 +3,20 @@ package de.maishai.ast.records;
|
||||
|
||||
import de.maishai.ast.Expression;
|
||||
import de.maishai.ast.Statement;
|
||||
import de.maishai.typedast.Type;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public record Assignment(Id loc, Expression value) implements Statement, Expression {
|
||||
@Override
|
||||
public Type typeCheck(Map<String, Type> localVars, Map<String, Class> classes) {
|
||||
|
||||
if (localVars.get(loc.name()) == null) {
|
||||
throw new RuntimeException("Variable " + loc.name() + " not declared");
|
||||
}
|
||||
if (!localVars.get(loc.name()).equals(value.typeCheck(localVars, classes))) {
|
||||
throw new RuntimeException("Type mismatch in assignment to " + loc.name());
|
||||
}
|
||||
return loc.typeCheck(localVars, classes);
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,17 @@ package de.maishai.ast.records;
|
||||
|
||||
import de.maishai.ast.Expression;
|
||||
import de.maishai.ast.Operator;
|
||||
import de.maishai.typedast.Type;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public record Binary(Expression left, Operator op, Expression right) implements Expression {
|
||||
@Override
|
||||
public Type typeCheck(Map<String, Type> localVars, Map<String, Class> classes) {
|
||||
// x = y + z -> y, z : int
|
||||
if(left.typeCheck(localVars, classes) != Type.INT && right.typeCheck(localVars, classes) != Type.INT) {
|
||||
throw new RuntimeException("Binary operation on non-integers");
|
||||
}
|
||||
return Type.INT;
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,23 @@ package de.maishai.ast.records;
|
||||
|
||||
import de.maishai.ast.Node;
|
||||
import de.maishai.ast.Statement;
|
||||
import de.maishai.typedast.Type;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public record Block(List<Variable> vars, List<Statement> stmts) implements Node {
|
||||
@Override
|
||||
public Type typeCheck(Map<String, Type> localVars, Map<String, Class> classes) {
|
||||
// Add the variables to the local variables
|
||||
for (Variable var : vars) {
|
||||
localVars.put(var.name(), var.type());
|
||||
}
|
||||
// Type check the statements
|
||||
for (Statement stmt : stmts) {
|
||||
stmt.typeCheck(localVars, classes);
|
||||
}
|
||||
// Return the type of the last statement
|
||||
return stmts.get(stmts.size() - 1).typeCheck(localVars, classes);
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,13 @@ package de.maishai.ast.records;
|
||||
|
||||
|
||||
import de.maishai.ast.Expression;
|
||||
import de.maishai.typedast.Type;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public record BoolConstant(Boolean value) implements Expression {
|
||||
@Override
|
||||
public Type typeCheck(Map<String, Type> localVars, Map<String, Class> classes) {
|
||||
return Type.BOOL;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,13 @@ package de.maishai.ast.records;
|
||||
|
||||
|
||||
import de.maishai.ast.Statement;
|
||||
import de.maishai.typedast.Type;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public record Break() implements Statement {
|
||||
@Override
|
||||
public Type typeCheck(Map<String, Type> localVars, Map<String, Class> classes) {
|
||||
return Type.VOID;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,13 @@ package de.maishai.ast.records;
|
||||
|
||||
|
||||
import de.maishai.ast.Expression;
|
||||
import de.maishai.typedast.Type;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public record CharConstant(char value) implements Expression {
|
||||
@Override
|
||||
public Type typeCheck(Map<String, Type> localVars, Map<String, Class> classes) {
|
||||
return Type.CHAR;
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,25 @@
|
||||
package de.maishai.ast.records;
|
||||
|
||||
import de.maishai.ast.Node;
|
||||
import de.maishai.typedast.Type;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public record Class(Id id ,List<Variable> variables, List<Method> methods) implements Node {
|
||||
@Override
|
||||
public Type typeCheck(Map<String, Type> localVars, Map<String, Class> classes) {
|
||||
if(classes.containsKey(id.name())) {
|
||||
throw new RuntimeException("Class " + id.name() + " already declared");
|
||||
}
|
||||
classes.put(id.name(), this);
|
||||
for(Variable variable : variables) {
|
||||
variable.typeCheck(localVars, classes);
|
||||
}
|
||||
for(Method method : methods) {
|
||||
method.typeCheck(localVars, classes);
|
||||
}
|
||||
|
||||
return Type.VOID;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,13 @@ package de.maishai.ast.records;
|
||||
|
||||
|
||||
import de.maishai.ast.Statement;
|
||||
import de.maishai.typedast.Type;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public record Continue() implements Statement {
|
||||
@Override
|
||||
public Type typeCheck(Map<String, Type> localVars, Map<String, Class> classes) {
|
||||
return Type.VOID;
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,21 @@ package de.maishai.ast.records;
|
||||
|
||||
import de.maishai.ast.Expression;
|
||||
import de.maishai.ast.Statement;
|
||||
import de.maishai.typedast.Type;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public record For(Expression assign, Expression cond, Expression inc, Block block) implements Statement {
|
||||
@Override
|
||||
public Type typeCheck(Map<String, Type> localVars, Map<String, Class> classes) {
|
||||
// like int i = 0
|
||||
assign.typeCheck(localVars, classes);
|
||||
// like i < 10 -> bool
|
||||
if (cond.typeCheck(localVars, classes) != Type.BOOL) {
|
||||
throw new RuntimeException("Condition must be of type bool");
|
||||
}
|
||||
// like i++
|
||||
inc.typeCheck(localVars, classes);
|
||||
return block.typeCheck(localVars, classes);
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,16 @@ package de.maishai.ast.records;
|
||||
|
||||
|
||||
import de.maishai.ast.Expression;
|
||||
import de.maishai.typedast.Type;
|
||||
|
||||
public record Id(String name) implements Expression {
|
||||
}
|
||||
import java.util.Map;
|
||||
|
||||
public record Id(String name) implements Expression {
|
||||
@Override
|
||||
public Type typeCheck(Map<String, Type> localVars, Map<String, Class> classes) {
|
||||
if(!localVars.containsKey(name)) {
|
||||
throw new RuntimeException("Variable " + name + " not declared");
|
||||
}
|
||||
return localVars.get(name);
|
||||
}
|
||||
}
|
||||
|
@ -2,5 +2,21 @@ package de.maishai.ast.records;
|
||||
|
||||
import de.maishai.ast.Expression;
|
||||
import de.maishai.ast.Statement;
|
||||
import de.maishai.typedast.Type;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public record IfElse(Expression cond, Block ifBlock, Block elseBlock) implements Statement {
|
||||
|
||||
@Override
|
||||
public Type typeCheck(Map<String, Type> localVars, Map<String, Class> classes) {
|
||||
|
||||
// Con must be type bool and both blocks must have the same type
|
||||
if(cond.typeCheck(localVars, classes).equals(Type.BOOL)
|
||||
&& ifBlock.typeCheck(localVars, classes).equals(elseBlock.typeCheck(localVars, classes))) {
|
||||
return ifBlock.typeCheck(localVars, classes);
|
||||
}
|
||||
|
||||
throw new RuntimeException("IfElse statement type check failed");
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,13 @@ package de.maishai.ast.records;
|
||||
|
||||
|
||||
import de.maishai.ast.Expression;
|
||||
import de.maishai.typedast.Type;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public record IntConstant(Integer value) implements Expression {
|
||||
@Override
|
||||
public Type typeCheck(Map<String, Type> localVars, Map<String, Class> classes) {
|
||||
return Type.INT;
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,15 @@ package de.maishai.ast.records;
|
||||
|
||||
import de.maishai.ast.Node;
|
||||
import de.maishai.ast.ReturnType;
|
||||
import de.maishai.typedast.Type;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public record MainMethod(ReturnType type, Id id, List<Parameter> params, Block block) implements Node {
|
||||
|
||||
@Override
|
||||
public Type typeCheck(Map<String, Type> localVars, Map<String, Class> classes) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,32 @@
|
||||
package de.maishai.ast.records;
|
||||
|
||||
|
||||
|
||||
import de.maishai.ast.Node;
|
||||
import de.maishai.ast.ReturnType;
|
||||
import de.maishai.typedast.Type;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public record Method(ReturnType type, Id id, List<Parameter> params, Block block) implements Node {
|
||||
public record Method(Type type, Id id, List<Parameter> params, Block block) implements Node {
|
||||
|
||||
@Override
|
||||
public Type typeCheck(Map<String, Type> localVars, Map<String, Class> classes) {
|
||||
if (localVars.containsKey(id.name())) {
|
||||
throw new RuntimeException("Variable " + id.name() + " already declared");
|
||||
}
|
||||
localVars.put(id.name(), type);
|
||||
|
||||
for (Parameter parameter : params) {
|
||||
parameter.typeCheck(localVars, classes);
|
||||
}
|
||||
|
||||
Type returnType = block.typeCheck(localVars, classes);
|
||||
if (!returnType.equals(type)) {
|
||||
throw new RuntimeException("Return type mismatch");
|
||||
}
|
||||
|
||||
return returnType;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,49 @@ package de.maishai.ast.records;
|
||||
|
||||
import de.maishai.ast.Expression;
|
||||
import de.maishai.ast.Statement;
|
||||
import de.maishai.typedast.Type;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public record MethodCall(Optional<String> receiver, String name, List<Expression> args) implements Expression, Statement {
|
||||
|
||||
@Override
|
||||
public Type typeCheck(Map<String, Type> localVars, Map<String, Class> classes) {
|
||||
Type returnType = null;
|
||||
|
||||
if(receiver.isPresent()) {
|
||||
// check if receiver is a local variable
|
||||
if(!localVars.containsKey(receiver.get())){
|
||||
throw new RuntimeException("Variable " + receiver.get() + " not found");
|
||||
}
|
||||
}
|
||||
|
||||
// check if method exists in class
|
||||
if(localVars.get(name) == null) {
|
||||
throw new RuntimeException("Variable " + name + " not found");
|
||||
}
|
||||
|
||||
Type type = localVars.get(name);
|
||||
Class class1 = classes.get(type.name());
|
||||
if(class1 == null) {
|
||||
throw new RuntimeException("Class " + type + " not found");
|
||||
}
|
||||
for(Method method : class1.methods()){
|
||||
if(method.id().name().equals(name)){
|
||||
for(int i = 0; i < method.params().size(); i++){
|
||||
if(!method.params().get(i).type().equals(args.get(i).typeCheck(localVars, classes))){
|
||||
throw new RuntimeException("Type mismatch in method call " + name);
|
||||
}
|
||||
}
|
||||
returnType = method.type();
|
||||
break;
|
||||
}else{
|
||||
throw new RuntimeException("Method " + name + " not found in class " + type);
|
||||
}
|
||||
}
|
||||
return returnType;
|
||||
}
|
||||
|
||||
public record MethodCall(String name, List<Expression> args) implements Expression, Statement {
|
||||
}
|
||||
|
@ -1,12 +1,18 @@
|
||||
package de.maishai.ast.records;
|
||||
|
||||
|
||||
|
||||
import de.maishai.ast.Expression;
|
||||
|
||||
import de.maishai.ast.Statement;
|
||||
import de.maishai.ast.Type;
|
||||
import de.maishai.typedast.Type;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public record New(Type type, List<Expression> args) implements Expression, Statement {
|
||||
|
||||
@Override
|
||||
public Type typeCheck(Map<String, Type> localVars, Map<String, Class> classes) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,18 @@ package de.maishai.ast.records;
|
||||
|
||||
|
||||
import de.maishai.ast.Node;
|
||||
import de.maishai.ast.Type;
|
||||
import de.maishai.typedast.Type;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public record Parameter(String name, Type type) implements Node {
|
||||
|
||||
@Override
|
||||
public Type typeCheck(Map<String, Type> localVars, Map<String, Class> classes) {
|
||||
if (localVars.containsKey(name)) {
|
||||
throw new RuntimeException("Variable " + name + " already declared");
|
||||
}
|
||||
localVars.put(name, type);
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,14 @@ package de.maishai.ast.records;
|
||||
|
||||
|
||||
import de.maishai.ast.Node;
|
||||
import de.maishai.typedast.Type;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public record Program(List<Class> variables) implements Node {
|
||||
@Override
|
||||
public Type typeCheck(Map<String, Type> localVars, Map<String, Class> classes) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,15 @@ package de.maishai.ast.records;
|
||||
|
||||
import de.maishai.ast.Expression;
|
||||
import de.maishai.ast.Statement;
|
||||
import de.maishai.typedast.Type;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public record Return(Expression ret) implements Statement {
|
||||
|
||||
@Override
|
||||
public Type typeCheck(Map<String, Type> localVars, Map<String, Class> classes) {
|
||||
return ret.typeCheck(localVars, classes);
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,14 @@ package de.maishai.ast.records;
|
||||
|
||||
|
||||
import de.maishai.ast.Statement;
|
||||
import de.maishai.typedast.Type;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
// Why does ReturnVoid not have statements
|
||||
public record ReturnVoid() implements Statement {
|
||||
@Override
|
||||
public Type typeCheck(Map<String, Type> localVars, Map<String, Class> classes) {
|
||||
return Type.VOID;
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,18 @@ package de.maishai.ast.records;
|
||||
|
||||
|
||||
import de.maishai.ast.Node;
|
||||
import de.maishai.ast.Type;
|
||||
import de.maishai.typedast.Type;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public record Variable(String name, Type type) implements Node {
|
||||
|
||||
@Override
|
||||
public Type typeCheck(Map<String, Type> localVars, Map<String, Class> classes) {
|
||||
if (localVars.containsKey(name)) {
|
||||
throw new RuntimeException("Variable " + name + " already declared");
|
||||
}
|
||||
localVars.put(name, type);
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,19 @@ package de.maishai.ast.records;
|
||||
|
||||
import de.maishai.ast.Expression;
|
||||
import de.maishai.ast.Statement;
|
||||
import de.maishai.typedast.Type;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public record While(Expression cond, Block block) implements Statement {
|
||||
|
||||
|
||||
@Override
|
||||
public Type typeCheck(Map<String, Type> localVars, Map<String, Class> classes) {
|
||||
Type condType = cond.typeCheck(localVars, classes);
|
||||
if (condType != Type.BOOL) {
|
||||
throw new RuntimeException("Condition must be of type bool");
|
||||
}
|
||||
return block.typeCheck(localVars, classes);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user