mirror of
https://github.com/JonathanFleischmann/CompilerULTIMATE.git
synced 2024-12-28 17:48:03 +00:00
Implemented TypeCheck
This commit is contained in:
parent
deeea62737
commit
5fa439ec90
@ -1,4 +1,11 @@
|
|||||||
package de.maishai.ast;
|
package de.maishai.ast;
|
||||||
|
|
||||||
|
import de.maishai.typedast.Type;
|
||||||
|
import de.maishai.ast.records.Class;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public interface Node {
|
public interface Node {
|
||||||
|
|
||||||
|
public Type typeCheck(Map<String, Type> localVars, Map<String, Class> classes);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
package de.maishai.ast;
|
package de.maishai.ast;
|
||||||
public interface Statement extends Node {
|
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.Expression;
|
||||||
import de.maishai.ast.Statement;
|
import de.maishai.ast.Statement;
|
||||||
|
import de.maishai.typedast.Type;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public record Assignment(Id loc, Expression value) implements Statement, Expression {
|
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.Expression;
|
||||||
import de.maishai.ast.Operator;
|
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 {
|
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.Node;
|
||||||
import de.maishai.ast.Statement;
|
import de.maishai.ast.Statement;
|
||||||
|
import de.maishai.typedast.Type;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public record Block(List<Variable> vars, List<Statement> stmts) implements Node {
|
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.ast.Expression;
|
||||||
|
import de.maishai.typedast.Type;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public record BoolConstant(Boolean value) implements Expression {
|
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.ast.Statement;
|
||||||
|
import de.maishai.typedast.Type;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public record Break() implements Statement {
|
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.ast.Expression;
|
||||||
|
import de.maishai.typedast.Type;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public record CharConstant(char value) implements Expression {
|
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;
|
package de.maishai.ast.records;
|
||||||
|
|
||||||
import de.maishai.ast.Node;
|
import de.maishai.ast.Node;
|
||||||
|
import de.maishai.typedast.Type;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public record Class(Id id ,List<Variable> variables, List<Method> methods) implements Node {
|
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.ast.Statement;
|
||||||
|
import de.maishai.typedast.Type;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public record Continue() implements Statement {
|
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.Expression;
|
||||||
import de.maishai.ast.Statement;
|
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 {
|
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.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.Expression;
|
||||||
import de.maishai.ast.Statement;
|
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 {
|
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.ast.Expression;
|
||||||
|
import de.maishai.typedast.Type;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public record IntConstant(Integer value) implements Expression {
|
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.Node;
|
||||||
import de.maishai.ast.ReturnType;
|
import de.maishai.ast.ReturnType;
|
||||||
|
import de.maishai.typedast.Type;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public record MainMethod(ReturnType type, Id id, List<Parameter> params, Block block) implements Node {
|
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;
|
package de.maishai.ast.records;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import de.maishai.ast.Node;
|
import de.maishai.ast.Node;
|
||||||
import de.maishai.ast.ReturnType;
|
import de.maishai.ast.ReturnType;
|
||||||
|
import de.maishai.typedast.Type;
|
||||||
|
|
||||||
import java.util.List;
|
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.Expression;
|
||||||
import de.maishai.ast.Statement;
|
import de.maishai.ast.Statement;
|
||||||
|
import de.maishai.typedast.Type;
|
||||||
|
|
||||||
import java.util.List;
|
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;
|
package de.maishai.ast.records;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import de.maishai.ast.Expression;
|
import de.maishai.ast.Expression;
|
||||||
|
|
||||||
import de.maishai.ast.Statement;
|
import de.maishai.ast.Statement;
|
||||||
import de.maishai.ast.Type;
|
import de.maishai.typedast.Type;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public record New(Type type, List<Expression> args) implements Expression, Statement {
|
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.Node;
|
||||||
import de.maishai.ast.Type;
|
import de.maishai.typedast.Type;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public record Parameter(String name, Type type) implements Node {
|
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.ast.Node;
|
||||||
|
import de.maishai.typedast.Type;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public record Program(List<Class> variables) implements Node {
|
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.Expression;
|
||||||
import de.maishai.ast.Statement;
|
import de.maishai.ast.Statement;
|
||||||
|
import de.maishai.typedast.Type;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
public record Return(Expression ret) implements Statement {
|
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.ast.Statement;
|
||||||
|
import de.maishai.typedast.Type;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
// Why does ReturnVoid not have statements
|
||||||
public record ReturnVoid() implements Statement {
|
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.Node;
|
||||||
import de.maishai.ast.Type;
|
import de.maishai.typedast.Type;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public record Variable(String name, Type type) implements Node {
|
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.Expression;
|
||||||
import de.maishai.ast.Statement;
|
import de.maishai.ast.Statement;
|
||||||
|
import de.maishai.typedast.Type;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public record While(Expression cond, Block block) implements Statement {
|
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