Added BaseType And refferenz Type
Some checks are pending
Gitea Actions Demo / Explore-Gitea-Actions (push) Waiting to run

This commit is contained in:
Bruder John 2024-06-21 16:42:27 +02:00
parent b9ada16dd1
commit cf41babcb7
32 changed files with 296 additions and 147 deletions

View File

@ -1,11 +1,11 @@
package ast.expression; package ast.expression;
import ast.ASTNode; import ast.ASTNode;
import ast.type.type.TypeNode; import ast.type.type.ITypeNode;
import visitor.Visitable; import visitor.Visitable;
public interface IExpressionNode extends ASTNode, Visitable { public interface IExpressionNode extends ASTNode, Visitable {
TypeNode getType(); ITypeNode getType();
} }

View File

@ -1,7 +1,7 @@
package ast.expression.binaryexpression; package ast.expression.binaryexpression;
import ast.expression.IExpressionNode; import ast.expression.IExpressionNode;
import ast.type.type.TypeNode; import ast.type.type.*;
import semantic.SemanticVisitor; import semantic.SemanticVisitor;
import typechecker.TypeCheckResult; import typechecker.TypeCheckResult;
@ -13,7 +13,7 @@ public class BinaryExpressionNode implements IExpressionNode {
} }
@Override @Override
public TypeNode getType() { public ITypeNode getType() {
return null; return null;
} }
} }

View File

@ -1,6 +1,6 @@
package ast.expression.binaryexpression; package ast.expression.binaryexpression;
import ast.type.type.TypeNode; import ast.type.type.*;
import semantic.SemanticVisitor; import semantic.SemanticVisitor;
import typechecker.TypeCheckResult; import typechecker.TypeCheckResult;
@ -25,7 +25,7 @@ public class CalculationExpressionNode extends BinaryExpressionNode {
} }
@Override @Override
public TypeNode getType() { public ITypeNode getType() {
return null; return null;
} }

View File

@ -1,6 +1,6 @@
package ast.expression.binaryexpression; package ast.expression.binaryexpression;
import ast.type.type.TypeNode; import ast.type.type.*;
import semantic.SemanticVisitor; import semantic.SemanticVisitor;
import typechecker.TypeCheckResult; import typechecker.TypeCheckResult;
@ -25,7 +25,7 @@ public class DotExpressionNode extends BinaryExpressionNode {
} }
@Override @Override
public TypeNode getType() { public ITypeNode getType() {
return null; return null;
} }

View File

@ -2,7 +2,7 @@ package ast.expression.binaryexpression;
import ast.expression.unaryexpression.MemberAccessNode; import ast.expression.unaryexpression.MemberAccessNode;
import ast.statement.statementexpression.methodcallstatementnexpression.MethodCallStatementExpressionNode; import ast.statement.statementexpression.methodcallstatementnexpression.MethodCallStatementExpressionNode;
import ast.type.type.TypeNode; import ast.type.type.*;
import ast.type.ValueNode; import ast.type.ValueNode;
import semantic.SemanticVisitor; import semantic.SemanticVisitor;
import typechecker.TypeCheckResult; import typechecker.TypeCheckResult;
@ -37,7 +37,7 @@ public class DotSubstractionExpressionNode extends BinaryExpressionNode {
} }
@Override @Override
public TypeNode getType() { public ITypeNode getType() {
return null; return null;
} }

View File

@ -2,7 +2,7 @@ package ast.expression.binaryexpression;
import ast.expression.IExpressionNode; import ast.expression.IExpressionNode;
import ast.expression.unaryexpression.UnaryExpressionNode; import ast.expression.unaryexpression.UnaryExpressionNode;
import ast.type.type.TypeNode; import ast.type.type.*;
import semantic.SemanticVisitor; import semantic.SemanticVisitor;
import typechecker.TypeCheckResult; import typechecker.TypeCheckResult;
@ -23,7 +23,7 @@ public class NonCalculationExpressionNode extends BinaryExpressionNode {
} }
@Override @Override
public TypeNode getType() { public ITypeNode getType() {
return null; return null;
} }

View File

@ -2,7 +2,7 @@ package ast.expression.unaryexpression;
import ast.expression.IExpressionNode; import ast.expression.IExpressionNode;
import ast.statement.IStatementNode; import ast.statement.IStatementNode;
import ast.type.type.TypeNode; import ast.type.type.*;
import ast.type.ValueNode; import ast.type.ValueNode;
import semantic.SemanticVisitor; import semantic.SemanticVisitor;
import typechecker.TypeCheckResult; import typechecker.TypeCheckResult;
@ -17,7 +17,7 @@ public class UnaryExpressionNode implements IExpressionNode {
public NotExpressionNode notExpression; public NotExpressionNode notExpression;
public IStatementNode statement; public IStatementNode statement;
public IExpressionNode expression; public IExpressionNode expression;
private TypeNode type; private ITypeNode type;
public UnaryExpressionNode(String value) { public UnaryExpressionNode(String value) {
if(Objects.equals(value, "this")) { if(Objects.equals(value, "this")) {
@ -53,11 +53,11 @@ public class UnaryExpressionNode implements IExpressionNode {
} }
@Override @Override
public TypeNode getType() { public ITypeNode getType() {
return type; return type;
} }
public void setType(TypeNode type) { public void setType(ITypeNode type) {
this.type = type; this.type = type;
} }

View File

@ -3,11 +3,14 @@ package ast.member;
import ast.block.BlockNode; import ast.block.BlockNode;
import ast.parameter.ParameterNode; import ast.parameter.ParameterNode;
import ast.type.AccessModifierNode; import ast.type.AccessModifierNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import visitor.Visitable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class ConstructorNode extends MethodNode { public class ConstructorNode extends MethodNode {
public AccessModifierNode accessType; public AccessModifierNode accessType;
public String identifier; public String identifier;
public List<ParameterNode> parameters = new ArrayList<>(); public List<ParameterNode> parameters = new ArrayList<>();

View File

@ -1,17 +1,17 @@
package ast.member; package ast.member;
import ast.type.AccessModifierNode; import ast.type.AccessModifierNode;
import ast.type.type.TypeNode; import ast.type.type.ITypeNode;
import semantic.SemanticVisitor; import semantic.SemanticVisitor;
import typechecker.TypeCheckResult; import typechecker.TypeCheckResult;
import visitor.Visitable; import visitor.Visitable;
public class FieldNode implements MemberNode, Visitable { public class FieldNode implements MemberNode, Visitable {
public AccessModifierNode accessTypeNode; public AccessModifierNode accessTypeNode;
public TypeNode type; public ITypeNode type;
public String identifier; public String identifier;
public FieldNode(AccessModifierNode accessTypeNode, TypeNode type, String name){ public FieldNode(AccessModifierNode accessTypeNode, ITypeNode type, String name){
this.accessTypeNode = accessTypeNode; this.accessTypeNode = accessTypeNode;
this.type = type; this.type = type;
this.identifier = name; this.identifier = name;

View File

@ -3,7 +3,7 @@ package ast.member;
import ast.block.BlockNode; import ast.block.BlockNode;
import ast.parameter.ParameterNode; import ast.parameter.ParameterNode;
import ast.type.AccessModifierNode; import ast.type.AccessModifierNode;
import ast.type.type.TypeNode; import ast.type.type.*;
import bytecode.visitor.MethodVisitor; import bytecode.visitor.MethodVisitor;
import semantic.SemanticVisitor; import semantic.SemanticVisitor;
import typechecker.TypeCheckResult; import typechecker.TypeCheckResult;
@ -15,7 +15,7 @@ import java.util.Objects;
public class MethodNode implements MemberNode, Visitable { public class MethodNode implements MemberNode, Visitable {
public AccessModifierNode accesModifier; public AccessModifierNode accesModifier;
public TypeNode type; private ITypeNode type;
public Boolean voidType; public Boolean voidType;
private String identifier; private String identifier;
public List<ParameterNode> parameters = new ArrayList<>(); public List<ParameterNode> parameters = new ArrayList<>();
@ -27,9 +27,9 @@ public class MethodNode implements MemberNode, Visitable {
this.block = block; this.block = block;
} }
public MethodNode(String accessModifier, String type, Boolean voidType, String identifier, BlockNode block){ public MethodNode(String accessModifier, ITypeNode type, Boolean voidType, String identifier, BlockNode block){
this.accesModifier = new AccessModifierNode(accessModifier); this.accesModifier = new AccessModifierNode(accessModifier);
this.type = new TypeNode(type); this.type = type;
this.voidType = voidType; this.voidType = voidType;
this.identifier = identifier; this.identifier = identifier;
this.block = block; this.block = block;
@ -71,6 +71,14 @@ public class MethodNode implements MemberNode, Visitable {
return identifier; return identifier;
} }
public ITypeNode getType() {
return type;
}
public void setType(ITypeNode type) {
this.type = type;
}
public void setIdentifier(String identifier) { public void setIdentifier(String identifier) {
this.identifier = identifier; this.identifier = identifier;
} }

View File

@ -1,16 +1,16 @@
package ast.parameter; package ast.parameter;
import ast.ASTNode; import ast.ASTNode;
import ast.type.type.TypeNode; import ast.type.type.*;
import semantic.SemanticVisitor; import semantic.SemanticVisitor;
import typechecker.TypeCheckResult; import typechecker.TypeCheckResult;
import visitor.Visitable; import visitor.Visitable;
public class ParameterNode implements ASTNode, Visitable { public class ParameterNode implements ASTNode, Visitable {
public TypeNode type; public ITypeNode type;
public String identifier; public String identifier;
public ParameterNode(TypeNode type, String identifier) { public ParameterNode(ITypeNode type, String identifier) {
this.type = type; this.type = type;
this.identifier = identifier; this.identifier = identifier;
} }

View File

@ -1,17 +1,17 @@
package ast.statement; package ast.statement;
import ast.expression.IExpressionNode; import ast.expression.IExpressionNode;
import ast.type.type.TypeNode; import ast.type.type.*;
import semantic.SemanticVisitor; import semantic.SemanticVisitor;
import typechecker.TypeCheckResult; import typechecker.TypeCheckResult;
public class LocalVariableDeclarationNode implements IStatementNode { public class LocalVariableDeclarationNode implements IStatementNode {
public TypeNode type; public ITypeNode type;
public String identifier; public String identifier;
public String assign; public String assign;
public IExpressionNode expression; public IExpressionNode expression;
public LocalVariableDeclarationNode(TypeNode type, String identifier, String assign, IExpressionNode expression) { public LocalVariableDeclarationNode(ITypeNode type, String identifier, String assign, IExpressionNode expression) {
this.type = type; this.type = type;
this.identifier = identifier; this.identifier = identifier;
this.assign = assign; this.assign = assign;

View File

@ -1,8 +1,6 @@
package ast.statement.statementexpression; package ast.statement.statementexpression;
import ast.ASTNode;
import ast.expression.IExpressionNode; import ast.expression.IExpressionNode;
import ast.type.type.TypeNode;
import semantic.SemanticVisitor; import semantic.SemanticVisitor;
import typechecker.TypeCheckResult; import typechecker.TypeCheckResult;

View File

@ -1,8 +1,6 @@
package ast.statement.statementexpression; package ast.statement.statementexpression;
import ast.ASTNode;
import ast.expression.unaryexpression.MemberAccessNode; import ast.expression.unaryexpression.MemberAccessNode;
import ast.type.type.TypeNode;
import semantic.SemanticVisitor; import semantic.SemanticVisitor;
import typechecker.TypeCheckResult; import typechecker.TypeCheckResult;

View File

@ -1,4 +1,30 @@
package ast.type.type; package ast.type.type;
public class BaseType { public class BaseType implements ITypeNode {
private TypeEnum typeEnum;
public BaseType(TypeEnum typeEnum) {
this.typeEnum = typeEnum;
}
public TypeEnum getTypeEnum() {
return typeEnum;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
BaseType other = (BaseType) obj;
if (typeEnum != other.typeEnum)
return false;
return true;
}
} }

View File

@ -0,0 +1,5 @@
package ast.type.type;
public interface ITypeNode {
}

View File

@ -1,4 +1,33 @@
package ast.type.type; package ast.type.type;
public class ReferenceType { public class ReferenceType implements ITypeNode{
private String identifier;
public ReferenceType(String identifier) {
this.identifier = identifier;
}
public String getIdentifier() {
return identifier;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ReferenceType other = (ReferenceType) obj;
if (identifier == null) {
if (other.identifier != null)
return false;
} else if (!identifier.equals(other.identifier))
return false;
return true;
}
} }

View File

@ -0,0 +1,9 @@
package ast.type.type;
public enum TypeEnum {
VOID,
INT,
CHAR,
BOOL;
}

View File

@ -1,33 +0,0 @@
package ast.type.type;
import ast.type.EnumTypeNode;
public class TypeNode {
public EnumTypeNode type;
public TypeNode(String type) {
setType(type);
}
private void setType(String type) {
switch(type) {
case "int":
this.type = EnumTypeNode.INT;
break;
case "boolean":
this.type = EnumTypeNode.BOOLEAN;
break;
case "char":
this.type = EnumTypeNode.CHAR;
break;
default:
this.type = EnumTypeNode.IDENTIFIER;
}
}
public boolean equals(TypeNode o) {
return !o.type.equals(this.type);
}
}

View File

@ -4,7 +4,7 @@ import ast.ClassNode;
import ast.member.FieldNode; import ast.member.FieldNode;
import ast.member.MemberNode; import ast.member.MemberNode;
import ast.member.MethodNode; import ast.member.MethodNode;
import ast.type.type.TypeNode; import ast.type.type.BaseType;
import bytecode.visitor.ClassVisitor; import bytecode.visitor.ClassVisitor;
import java.io.File; import java.io.File;
import org.objectweb.asm.ClassWriter; import org.objectweb.asm.ClassWriter;
@ -44,7 +44,7 @@ public class ClassCodeGen implements ClassVisitor {
@Override @Override
public void visit(FieldNode fieldNode) { public void visit(FieldNode fieldNode) {
if(fieldNode.type instanceof TypeNode baseTypeNode){ if(fieldNode.type instanceof BaseType baseTypeNode){
// classWriter.visitField(mapper.mapAccessTypeToOpcode(fieldNode.accessTypeNode), fieldNode.identifier, mapper.getTypeChar(baseTypeNode.enumType), null, null ); // classWriter.visitField(mapper.mapAccessTypeToOpcode(fieldNode.accessTypeNode), fieldNode.identifier, mapper.getTypeChar(baseTypeNode.enumType), null, null );
} }
classWriter.visitEnd(); classWriter.visitEnd();

View File

@ -29,7 +29,7 @@ import ast.statement.statementexpression.methodcallstatementnexpression.ChainedM
import ast.statement.statementexpression.methodcallstatementnexpression.MethodCallStatementExpressionNode; import ast.statement.statementexpression.methodcallstatementnexpression.MethodCallStatementExpressionNode;
import ast.statement.statementexpression.methodcallstatementnexpression.TargetNode; import ast.statement.statementexpression.methodcallstatementnexpression.TargetNode;
import ast.type.*; import ast.type.*;
import ast.type.type.TypeNode; import ast.type.type.*;
import org.antlr.v4.runtime.tree.TerminalNode; import org.antlr.v4.runtime.tree.TerminalNode;
import parser.generated.*; import parser.generated.*;
@ -68,7 +68,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
return new MethodNode((BlockNode) visit(ctx.block())); return new MethodNode((BlockNode) visit(ctx.block()));
} else { } else {
if(ctx.type() != null) { if(ctx.type() != null) {
MethodNode methodNode = new MethodNode(ctx.AccessModifier().getText(), ctx.type().getText(), false, ctx.Identifier().getText(), (BlockNode) visit(ctx.block())); MethodNode methodNode = new MethodNode(ctx.AccessModifier().getText(), createTypeNode(ctx.type().getText()), false, ctx.Identifier().getText(), (BlockNode) visit(ctx.block()));
for(SimpleJavaParser.ParameterContext parameter : ctx.parameterList().parameter()) { for(SimpleJavaParser.ParameterContext parameter : ctx.parameterList().parameter()) {
methodNode.addParameter((ParameterNode) visit(parameter)); methodNode.addParameter((ParameterNode) visit(parameter));
} }
@ -85,12 +85,12 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
@Override @Override
public ASTNode visitFieldDeclaration(SimpleJavaParser.FieldDeclarationContext ctx) { public ASTNode visitFieldDeclaration(SimpleJavaParser.FieldDeclarationContext ctx) {
return new FieldNode(new AccessModifierNode(ctx.AccessModifier().getText()), new TypeNode(ctx.type().getText()), ctx.Identifier().getText()); return new FieldNode(new AccessModifierNode(ctx.AccessModifier().getText()), createTypeNode(ctx.type().getText()), ctx.Identifier().getText());
} }
@Override @Override
public ASTNode visitParameter(SimpleJavaParser.ParameterContext ctx) { public ASTNode visitParameter(SimpleJavaParser.ParameterContext ctx) {
return new ParameterNode(new TypeNode(ctx.type().getText()), ctx.Identifier().getText()); return new ParameterNode(createTypeNode(ctx.type().getText()), ctx.Identifier().getText());
} }
@Override @Override
@ -120,7 +120,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
@Override @Override
public ASTNode visitLocalVariableDeclaration(SimpleJavaParser.LocalVariableDeclarationContext ctx) { public ASTNode visitLocalVariableDeclaration(SimpleJavaParser.LocalVariableDeclarationContext ctx) {
return new LocalVariableDeclarationNode(new TypeNode(ctx.type().getText()), ctx.Identifier().getText(), ctx.Assign().getText(), (IExpressionNode) visit(ctx.expression())); return new LocalVariableDeclarationNode(createTypeNode(ctx.type().getText()), ctx.Identifier().getText(), ctx.Assign().getText(), (IExpressionNode) visit(ctx.expression()));
} }
@Override @Override
@ -401,4 +401,15 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
} }
return null; return null;
} }
public ITypeNode createTypeNode(String identifier){
return switch (identifier) {
case "int" -> new BaseType(TypeEnum.INT);
case "boolean" -> new BaseType(TypeEnum.BOOL);
case "char" -> new BaseType(TypeEnum.CHAR);
case "void" -> new BaseType(TypeEnum.VOID);
default -> new ReferenceType(identifier);
};
}
} }

View File

@ -1,6 +1,6 @@
package semantic; package semantic;
import ast.type.type.TypeNode; import ast.type.type.*;
import semantic.exeptions.AlreadyDeclearedException; import semantic.exeptions.AlreadyDeclearedException;
import java.util.HashMap; import java.util.HashMap;
@ -8,21 +8,28 @@ import java.util.Stack;
public class Scope { public class Scope {
private Stack<HashMap<String, TypeNode>> localVars; private Stack<HashMap<String, ITypeNode>> localVars;
public Scope() { public Scope() {
localVars = new Stack<HashMap<String, TypeNode>>(); localVars = new Stack<HashMap<String, ITypeNode>>();
} }
public void addLocalVar(String name, TypeNode type) { public void addLocalVar(String name, ITypeNode type) {
if (this.contains(name)) { if (this.contains(name)) {
throw new AlreadyDeclearedException("Variable " + name + " already exists in this scope"); throw new AlreadyDeclearedException("Variable " + name + " already exists in this scope");
} }
localVars.peek().put(name, type); localVars.peek().put(name, type);
} }
public ITypeNode getLocalVar(String name) {
for (HashMap<String, ITypeNode> map : localVars) {
return map.get(name);
}
return null;
}
public boolean contains(String name) { public boolean contains(String name) {
for (HashMap<String, TypeNode> map : localVars) { for (HashMap<String, ITypeNode> map : localVars) {
if (map.containsKey(name)) { if (map.containsKey(name)) {
return true; return true;
} }
@ -31,7 +38,7 @@ public class Scope {
} }
public void pushScope() { public void pushScope() {
localVars.push(new HashMap<String, TypeNode>()); localVars.push(new HashMap<String, ITypeNode>());
} }
public void popScope() { public void popScope() {

View File

@ -23,26 +23,22 @@ import ast.statement.statementexpression.NewDeclarationStatementExpressionNode;
import ast.statement.statementexpression.crementExpression.DecrementExpressionNode; import ast.statement.statementexpression.crementExpression.DecrementExpressionNode;
import ast.statement.statementexpression.crementExpression.IncrementExpressionNode; import ast.statement.statementexpression.crementExpression.IncrementExpressionNode;
import ast.statement.statementexpression.methodcallstatementnexpression.MethodCallStatementExpressionNode; import ast.statement.statementexpression.methodcallstatementnexpression.MethodCallStatementExpressionNode;
import ast.type.type.BaseType; import ast.type.type.*;
import ast.type.type.ReferenceType;
import ast.type.type.TypeNode;
import semantic.context.Context; import semantic.context.Context;
import semantic.exeptions.AlreadyDeclearedException; import semantic.exeptions.*;
import semantic.exeptions.AlreadyDefinedException;
import semantic.exeptions.NotDeclearedException;
import semantic.exeptions.TypeMismatchException;
import typechecker.TypeCheckResult; import typechecker.TypeCheckResult;
public class SemanticAnalyzer implements SemanticVisitor { public class SemanticAnalyzer implements SemanticVisitor {
private static HashMap<String, TypeNode> currentFields = new HashMap<>(); private static HashMap<String, ITypeNode> currentFields = new HashMap<>();
public static ArrayList<Exception> errors = new ArrayList<>(); public static ArrayList<Exception> errors = new ArrayList<>();
private static Context context; private static Context context;
private static Scope currentScope; private static Scope currentScope;
private static ClassNode currentClass; private static ClassNode currentClass;
private static TypeNode currentNullType; private static ITypeNode currentNullType;
private ITypeNode currentMethodReturnType;
public static ASTNode generateTast(ASTNode node) { public static ASTNode generateTast(ASTNode node) {
SemanticAnalyzer semanticCheck = new SemanticAnalyzer(); SemanticAnalyzer semanticCheck = new SemanticAnalyzer();
@ -111,59 +107,59 @@ public class SemanticAnalyzer implements SemanticVisitor {
@Override @Override
public TypeCheckResult analyze(MethodNode methodNode) { public TypeCheckResult analyze(MethodNode methodNode) {
var valid = true; if (methodNode instanceof ConstructorNode) {
return new TypeCheckResult(true, new BaseType(TypeEnum.VOID));
} else {
for (var otherMethod : currentClass.getMethods()) { var valid = true;
if (Objects.equals(otherMethod, methodNode))
break;
if (otherMethod.isSame(methodNode)) {
errors.add(new AlreadyDeclearedException(
"Method " + methodNode.getIdentifier() + " is already defined in class "
+ currentClass.identifier));
valid = false;
}
}
currentScope.pushScope(); for (var otherMethod : currentClass.getMethods()) {
for (var parameter : methodNode.getParameters()) { if (Objects.equals(otherMethod, methodNode))
var result = parameter.accept(this); break;
valid = valid && result.isValid(); if (otherMethod.isSame(methodNode)) {
try { errors.add(new AlreadyDeclearedException(
currentScope.addLocalVar(parameter.identifier, parameter.type); "Method " + methodNode.getIdentifier() + " is already defined in class "
} catch (AlreadyDeclearedException e) { + currentClass.identifier));
errors.add(new AlreadyDeclearedException(parameter.identifier)); valid = false;
}
} }
} currentScope.pushScope();
// Check if this method is already declared for (var parameter : methodNode.getParameters()) {
var result = parameter.accept(this);
valid = valid && result.isValid();
try {
currentScope.addLocalVar(parameter.identifier, parameter.type);
} catch (AlreadyDeclearedException e) {
errors.add(new AlreadyDeclearedException(parameter.identifier));
}
// currentMethodReturnType = methodDecl.getType(); }
// currentNullType = currentMethodReturnType; // Solange nicht in einem Assign oder Methoden-Aufruf dieser Typ // Check if this method is already declared
TypeNode resultType = new TypeNode("void"); currentMethodReturnType = methodNode.getType();
currentNullType = currentMethodReturnType; // Solange nicht in einem Assign oder Methoden-Aufruf dieser Typ
ITypeNode resultType = new BaseType(TypeEnum.VOID);
if (methodNode.block != null) {
// gesetzt ist, ist dieser der Rückgabewert der Methode // gesetzt ist, ist dieser der Rückgabewert der Methode
var result = methodNode.block.accept(this); var result = methodNode.block.accept(this);
valid = valid && result.isValid(); valid = valid && result.isValid();
currentScope.popScope(); currentScope.popScope();
resultType = result.getType(); resultType = result.getType();
/*
if (resultType == null) { if (resultType == null) {
resultType = new BaseType(Primitives.VOID); resultType = new BaseType(TypeEnum.VOID);
} }
if (!resultType.equals(methodDecl.getType())) { if (!resultType.equals(methodNode.getType())) {
errors.add(new TypeMismatchException("Method-Declaration " + methodDecl.getIdentifier() + " with type " errors.add(new TypeMismatchException("Method-Declaration " + methodNode.getIdentifier() + " with type "
+ methodDecl.getType() + " has at least one Mismatching return Type:" + methodNode.getType() + " has at least one Mismatching return Type:"));
+ TypeHelper.generateLocationString(methodDecl.line, methodDecl.column, fileName)));
valid = false; valid = false;
} }
*/ return new TypeCheckResult(valid, resultType);
}
return new TypeCheckResult(valid, resultType); }
} }
@Override @Override
@ -184,7 +180,9 @@ public class SemanticAnalyzer implements SemanticVisitor {
@Override @Override
public TypeCheckResult analyze(ReturnStatementNode toCheck) { public TypeCheckResult analyze(ReturnStatementNode toCheck) {
return null;
var result = toCheck.expression.accept(this);
return new TypeCheckResult(true, result.getType());
} }
@Override @Override
@ -201,11 +199,18 @@ public class SemanticAnalyzer implements SemanticVisitor {
@Override @Override
public TypeCheckResult analyze(BlockNode blockNode) { public TypeCheckResult analyze(BlockNode blockNode) {
ITypeNode blockReturnType = null;
for (IStatementNode statementNode : blockNode.statements) { for (IStatementNode statementNode : blockNode.statements) {
statementNode.accept(this); var result = statementNode.accept(this);
if(result.getType() != null){
if(blockReturnType == null){
blockReturnType = result.getType();
} else {
errors.add(new MultipleReturnTypes("There are multiple Return types"));
}
}
} }
return new TypeCheckResult(true, null); return new TypeCheckResult(true, blockReturnType);
} }
@Override @Override
@ -260,7 +265,7 @@ public class SemanticAnalyzer implements SemanticVisitor {
// } // }
valid = valid && lResult.isValid() && rResult.isValid(); valid = valid && lResult.isValid() && rResult.isValid();
currentNullType = null; currentNullType = null;
return new TypeCheckResult(valid, null); // return type is null to get the return type sufficently return new TypeCheckResult(valid, new BaseType(TypeEnum.VOID)); // return type is null to get the return type sufficently
} }
@Override @Override
@ -322,7 +327,7 @@ public class SemanticAnalyzer implements SemanticVisitor {
@Override @Override
public TypeCheckResult analyze(CalculationExpressionNode calcNode) { public TypeCheckResult analyze(CalculationExpressionNode calcNode) {
if(calcNode.calculationExpression != null){ if (calcNode.calculationExpression != null) {
calcNode.calculationExpression.accept(this); calcNode.calculationExpression.accept(this);
} }
return null; return null;
@ -352,7 +357,7 @@ public class SemanticAnalyzer implements SemanticVisitor {
return new TypeCheckResult(false, null); return new TypeCheckResult(false, null);
} }
return new TypeCheckResult(valid, unary.getType()); return new TypeCheckResult(valid, currentScope.getLocalVar(unary.identifier));
} }
} }

View File

@ -2,19 +2,19 @@ package semantic.context;
import ast.member.FieldNode; import ast.member.FieldNode;
import ast.type.*; import ast.type.*;
import ast.type.type.TypeNode; import ast.type.type.*;
public class FieldContext { public class FieldContext {
private AccessModifierNode accessModifier; private AccessModifierNode accessModifier;
private TypeNode type; private ITypeNode type;
public FieldContext(FieldNode field) { public FieldContext(FieldNode field) {
accessModifier = field.accessTypeNode; accessModifier = field.accessTypeNode;
type = field.type; type = field.type;
} }
public TypeNode getType() { public ITypeNode getType() {
return type; return type;
} }

View File

@ -0,0 +1,9 @@
package semantic.exeptions;
public class MultipleReturnTypes extends RuntimeException {
public MultipleReturnTypes(String message) {
super(message);
}
}

View File

@ -1,14 +1,14 @@
package typechecker; package typechecker;
import ast.type.type.TypeNode; import ast.type.type.ITypeNode;
public class TypeCheckResult { public class TypeCheckResult {
private boolean valid; private boolean valid;
private TypeNode type; private ITypeNode type;
public TypeCheckResult(boolean valid, TypeNode type) { public TypeCheckResult(boolean valid, ITypeNode type) {
this.valid = valid; this.valid = valid;
this.type = type; this.type = type;
} }
@ -17,7 +17,7 @@ public class TypeCheckResult {
return valid; return valid;
} }
public TypeNode getType() { public ITypeNode getType() {
return type; return type;
} }
} }

View File

@ -12,6 +12,7 @@ import parser.astBuilder.ASTBuilder;
import parser.generated.SimpleJavaLexer; import parser.generated.SimpleJavaLexer;
import parser.generated.SimpleJavaParser; import parser.generated.SimpleJavaParser;
import semantic.exeptions.AlreadyDeclearedException; import semantic.exeptions.AlreadyDeclearedException;
import semantic.exeptions.MultipleReturnTypes;
import semantic.exeptions.NotDeclearedException; import semantic.exeptions.NotDeclearedException;
import semantic.exeptions.TypeMismatchException; import semantic.exeptions.TypeMismatchException;
@ -208,7 +209,31 @@ public class EndToTAST {
CharStream codeCharStream = null; CharStream codeCharStream = null;
try { try {
codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/TypeMismatchRefType.java")); codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/CorrectRetType.java"));
} catch (IOException e) {
throw new RuntimeException(e);
}
SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream);
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
ParseTree parseTree = parser.program();
ASTBuilder astBuilder = new ASTBuilder();
ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree);
ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree);
assertTrue(SemanticAnalyzer.errors.isEmpty());
}
@Test
public void retTypeMismatch(){
CharStream codeCharStream = null;
try {
codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/retTypeMismatch.java"));
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@ -228,4 +253,29 @@ public class EndToTAST {
} }
@Test
public void multipleRetType(){
CharStream codeCharStream = null;
try {
codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/MultipleRetTypes.java"));
} catch (IOException e) {
throw new RuntimeException(e);
}
SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream);
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
ParseTree parseTree = parser.program();
ASTBuilder astBuilder = new ASTBuilder();
ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree);
ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree);
assertFalse(SemanticAnalyzer.errors.isEmpty());
assertInstanceOf(MultipleReturnTypes.class, SemanticAnalyzer.errors.getFirst());
}
} }

View File

@ -6,7 +6,7 @@ import ast.member.FieldNode;
import ast.member.MethodNode; import ast.member.MethodNode;
import ast.parameter.ParameterNode; import ast.parameter.ParameterNode;
import ast.type.AccessModifierNode; import ast.type.AccessModifierNode;
import ast.type.type.TypeNode; import ast.type.type.*;
public class Mocker { public class Mocker {
@ -16,11 +16,11 @@ public class Mocker {
ClassNode c = new ClassNode(); ClassNode c = new ClassNode();
c.identifier = "testClass"; c.identifier = "testClass";
FieldNode f1 = new FieldNode(new AccessModifierNode("public"), new TypeNode("int"), "a"); FieldNode f1 = new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a");
c.members.add(f1); c.members.add(f1);
FieldNode f2 = new FieldNode(new AccessModifierNode("public"), new TypeNode("int"), "a"); FieldNode f2 = new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a");
c.members.add(f2); c.members.add(f2);
@ -36,7 +36,7 @@ public class Mocker {
MethodNode methodNode = new MethodNode(); MethodNode methodNode = new MethodNode();
//Parameter //Parameter
ParameterNode parameterNode = new ParameterNode(new TypeNode("int"), "a"); ParameterNode parameterNode = new ParameterNode(new BaseType(TypeEnum.INT), "a");
methodNode.addParameter(parameterNode); methodNode.addParameter(parameterNode);
@ -59,7 +59,7 @@ public class Mocker {
MethodNode methodNode = new MethodNode(); MethodNode methodNode = new MethodNode();
methodNode.block = new BlockNode(); methodNode.block = new BlockNode();
methodNode.type = new TypeNode("int"); methodNode.setType(new BaseType(TypeEnum.INT));
methodNode.setIdentifier("testMethod"); methodNode.setIdentifier("testMethod");
@ -67,7 +67,7 @@ public class Mocker {
MethodNode methodNode1 = new MethodNode(); MethodNode methodNode1 = new MethodNode();
methodNode1.block = new BlockNode(); methodNode1.block = new BlockNode();
methodNode1.type = new TypeNode("int"); methodNode1.setType(new BaseType(TypeEnum.INT));
methodNode1.setIdentifier("testMethod"); methodNode1.setIdentifier("testMethod");

View File

@ -0,0 +1,7 @@
public class Example {
public static int testMethod(int x){
return x;
}
}

View File

@ -2,7 +2,9 @@ public class Example {
public int a; public int a;
public static int testMethod(char x){ public static int testMethod(int b){
a = b;
} }

View File

@ -0,0 +1,8 @@
public class Example {
public static int testMethod(int x, char c){
return x;
return c;
}
}

View File

@ -0,0 +1,7 @@
public class Example {
public static int testMethod(char x){
return x;
}
}