diff --git a/src/main/java/ast/expressions/IExpressionNode.java b/src/main/java/ast/expressions/IExpressionNode.java index d1d380b..1a7a59e 100644 --- a/src/main/java/ast/expressions/IExpressionNode.java +++ b/src/main/java/ast/expressions/IExpressionNode.java @@ -8,4 +8,6 @@ public interface IExpressionNode extends ASTNode, Visitable { ITypeNode getType(); + void setType(ITypeNode type); + } diff --git a/src/main/java/ast/expressions/binaryexpressions/BinaryNode.java b/src/main/java/ast/expressions/binaryexpressions/BinaryNode.java index 9bfe8c2..f02aa2f 100644 --- a/src/main/java/ast/expressions/binaryexpressions/BinaryNode.java +++ b/src/main/java/ast/expressions/binaryexpressions/BinaryNode.java @@ -7,6 +7,8 @@ import typechecker.TypeCheckResult; public class BinaryNode implements IExpressionNode { + private ITypeNode typeNode; + @Override public TypeCheckResult accept(SemanticVisitor visitor) { return visitor.analyze(this); @@ -14,6 +16,11 @@ public class BinaryNode implements IExpressionNode { @Override public ITypeNode getType() { - return null; + return typeNode; + } + + @Override + public void setType(ITypeNode type) { + this.typeNode = type; } } diff --git a/src/main/java/ast/expressions/binaryexpressions/CalculationNode.java b/src/main/java/ast/expressions/binaryexpressions/CalculationNode.java index 4dec81a..f97d957 100644 --- a/src/main/java/ast/expressions/binaryexpressions/CalculationNode.java +++ b/src/main/java/ast/expressions/binaryexpressions/CalculationNode.java @@ -8,6 +8,7 @@ public class CalculationNode extends BinaryNode { public CalculationNode calculationExpression; public EnumLineOperator operator; public DotNode dotExpression; + private ITypeNode typeNode; public CalculationNode(CalculationNode calculationExpression, String operator, DotNode dotExpression) { this.calculationExpression = calculationExpression; @@ -32,9 +33,4 @@ public class CalculationNode extends BinaryNode { return visitor.analyze(this); } - @Override - public ITypeNode getType() { - return null; - } - } diff --git a/src/main/java/ast/expressions/binaryexpressions/DotNode.java b/src/main/java/ast/expressions/binaryexpressions/DotNode.java index 4cad9ec..0b31b01 100644 --- a/src/main/java/ast/expressions/binaryexpressions/DotNode.java +++ b/src/main/java/ast/expressions/binaryexpressions/DotNode.java @@ -34,9 +34,4 @@ public class DotNode extends BinaryNode { return visitor.analyze(this); } - @Override - public ITypeNode getType() { - return null; - } - } diff --git a/src/main/java/ast/expressions/binaryexpressions/DotSubstractionNode.java b/src/main/java/ast/expressions/binaryexpressions/DotSubstractionNode.java index 9537e15..812c58c 100644 --- a/src/main/java/ast/expressions/binaryexpressions/DotSubstractionNode.java +++ b/src/main/java/ast/expressions/binaryexpressions/DotSubstractionNode.java @@ -36,9 +36,4 @@ public class DotSubstractionNode extends BinaryNode { return visitor.analyze(this); } - @Override - public ITypeNode getType() { - return null; - } - } diff --git a/src/main/java/ast/expressions/binaryexpressions/NonCalculationNode.java b/src/main/java/ast/expressions/binaryexpressions/NonCalculationNode.java index d07a5f6..df0489b 100644 --- a/src/main/java/ast/expressions/binaryexpressions/NonCalculationNode.java +++ b/src/main/java/ast/expressions/binaryexpressions/NonCalculationNode.java @@ -42,9 +42,4 @@ public class NonCalculationNode extends BinaryNode { return visitor.analyze(this); } - @Override - public ITypeNode getType() { - return null; - } - } diff --git a/src/main/java/ast/expressions/unaryexpressions/MemberAccessNode.java b/src/main/java/ast/expressions/unaryexpressions/MemberAccessNode.java index aa85286..3ce6471 100644 --- a/src/main/java/ast/expressions/unaryexpressions/MemberAccessNode.java +++ b/src/main/java/ast/expressions/unaryexpressions/MemberAccessNode.java @@ -1,13 +1,18 @@ package ast.expressions.unaryexpressions; import ast.ASTNode; +import ast.type.type.ITypeNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; +import visitor.Visitable; import java.util.ArrayList; import java.util.List; -public class MemberAccessNode implements ASTNode { +public class MemberAccessNode implements ASTNode, Visitable { public Boolean thisExpr; public List identifiers = new ArrayList<>(); + private ITypeNode typeNode; public MemberAccessNode(Boolean thisExpr) { this.thisExpr = thisExpr; @@ -17,4 +22,17 @@ public class MemberAccessNode implements ASTNode { identifiers.add(identifier); } + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + + public ITypeNode getTypeNode() { + return typeNode; + } + + public void setTypeNode(ITypeNode typeNode) { + this.typeNode = typeNode; + } + } diff --git a/src/main/java/ast/members/ConstructorNode.java b/src/main/java/ast/members/ConstructorNode.java index d6a40c2..2d5400d 100644 --- a/src/main/java/ast/members/ConstructorNode.java +++ b/src/main/java/ast/members/ConstructorNode.java @@ -6,6 +6,7 @@ import ast.type.AccessModifierNode; import java.util.ArrayList; import java.util.List; +import java.util.Objects; public class ConstructorNode extends MethodNode { public AccessModifierNode accessType; @@ -23,4 +24,18 @@ public class ConstructorNode extends MethodNode { parameters.add(parameterNode); } + @Override + public boolean isSame(MethodNode methodNode) { + if (!(Objects.equals(this.identifier, methodNode.getIdentifier())) + || getParameters().size() != methodNode.getParameters().size()) { + return false; + } + + for (int i = 0; i < this.getParameters().size(); i++) { + if (!this.getParameters().get(i).type.equals(methodNode.getParameters().get(i).type)) { + return false; + } + } + return true; + } } diff --git a/src/main/java/ast/members/MainMethodNode.java b/src/main/java/ast/members/MainMethodNode.java index 3ae01a2..4680a26 100644 --- a/src/main/java/ast/members/MainMethodNode.java +++ b/src/main/java/ast/members/MainMethodNode.java @@ -3,7 +3,6 @@ package ast.members; import ast.statements.BlockNode; public class MainMethodNode extends MethodNode { - public BlockNode block; public MainMethodNode(BlockNode block) { this.block = block; diff --git a/src/main/java/ast/members/MethodNode.java b/src/main/java/ast/members/MethodNode.java index 5e10d48..1345508 100644 --- a/src/main/java/ast/members/MethodNode.java +++ b/src/main/java/ast/members/MethodNode.java @@ -46,7 +46,7 @@ public class MethodNode implements MemberNode, Visitable { } for (int i = 0; i < this.getParameters().size(); i++) { - if (this.getParameters().get(i).type.equals(methodNode.getParameters().get(i).type)) { + if (!this.getParameters().get(i).type.equals(methodNode.getParameters().get(i).type)) { return false; } } diff --git a/src/main/java/ast/statementexpressions/AssignableNode.java b/src/main/java/ast/statementexpressions/AssignableNode.java index d3a1677..83568d8 100644 --- a/src/main/java/ast/statementexpressions/AssignableNode.java +++ b/src/main/java/ast/statementexpressions/AssignableNode.java @@ -1,11 +1,13 @@ package ast.statementexpressions; import ast.expressions.unaryexpressions.MemberAccessNode; +import ast.type.type.ITypeNode; import semantic.SemanticVisitor; import typechecker.TypeCheckResult; public class AssignableNode implements IStatementExpressionNode { public String identifier; + private ITypeNode typeNode; public MemberAccessNode memberAccess; @@ -22,4 +24,12 @@ public class AssignableNode implements IStatementExpressionNode { return visitor.analyze(this); } + public ITypeNode getTypeNode() { + return typeNode; + } + + public void setTypeNode(ITypeNode typeNode) { + this.typeNode = typeNode; + } + } diff --git a/src/main/java/ast/statementexpressions/methodcallstatementnexpressions/TargetNode.java b/src/main/java/ast/statementexpressions/methodcallstatementnexpressions/TargetNode.java index 01e2344..01a1d78 100644 --- a/src/main/java/ast/statementexpressions/methodcallstatementnexpressions/TargetNode.java +++ b/src/main/java/ast/statementexpressions/methodcallstatementnexpressions/TargetNode.java @@ -3,8 +3,11 @@ package ast.statementexpressions.methodcallstatementnexpressions; import ast.ASTNode; import ast.expressions.unaryexpressions.MemberAccessNode; import ast.statementexpressions.NewDeclarationNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; +import visitor.Visitable; -public class TargetNode implements ASTNode { +public class TargetNode implements ASTNode, Visitable { public Boolean thisTar; public MemberAccessNode memberAccess; public NewDeclarationNode newDeclaration; @@ -25,4 +28,11 @@ public class TargetNode implements ASTNode { public TargetNode(String identifier) { this.identifier = identifier; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + + } \ No newline at end of file diff --git a/src/main/java/ast/statements/ElseNode.java b/src/main/java/ast/statements/ElseNode.java index 78b62f1..7099895 100644 --- a/src/main/java/ast/statements/ElseNode.java +++ b/src/main/java/ast/statements/ElseNode.java @@ -5,7 +5,7 @@ import semantic.SemanticVisitor; import typechecker.TypeCheckResult; public class ElseNode implements IStatementNode { - BlockNode block; + public BlockNode block; public ElseNode(BlockNode block) { this.block = block; @@ -14,6 +14,6 @@ public class ElseNode implements IStatementNode { @Override public TypeCheckResult accept(SemanticVisitor visitor) { - return null; + return visitor.analyze(this); } } diff --git a/src/main/java/ast/statements/IfElseNode.java b/src/main/java/ast/statements/IfElseNode.java index 34d40f3..55d4191 100644 --- a/src/main/java/ast/statements/IfElseNode.java +++ b/src/main/java/ast/statements/IfElseNode.java @@ -8,9 +8,9 @@ import java.util.ArrayList; import java.util.List; public class IfElseNode implements IStatementNode { - IfNode ifStatement; - List elseIfStatements = new ArrayList<>(); - ElseNode elseStatement; + public IfNode ifStatement; + public List elseIfStatements = new ArrayList<>(); + public ElseNode elseStatement; public IfElseNode(IfNode ifStatement, ElseNode elseNode) { this.ifStatement = ifStatement; @@ -23,6 +23,6 @@ public class IfElseNode implements IStatementNode { @Override public TypeCheckResult accept(SemanticVisitor visitor) { - return null; + return visitor.analyze(this); } } diff --git a/src/main/java/ast/statements/IfNode.java b/src/main/java/ast/statements/IfNode.java index 2f30788..46e15c0 100644 --- a/src/main/java/ast/statements/IfNode.java +++ b/src/main/java/ast/statements/IfNode.java @@ -6,8 +6,8 @@ import semantic.SemanticVisitor; import typechecker.TypeCheckResult; public class IfNode implements IStatementNode { - IExpressionNode expression; - BlockNode block; + public IExpressionNode expression; + public BlockNode block; public IfNode(IExpressionNode expression, BlockNode block) { this.expression = expression; @@ -16,6 +16,6 @@ public class IfNode implements IStatementNode { @Override public TypeCheckResult accept(SemanticVisitor visitor) { - return null; + return visitor.analyze(this); } } diff --git a/src/main/java/ast/statements/WhileNode.java b/src/main/java/ast/statements/WhileNode.java index 01c1160..ee93167 100644 --- a/src/main/java/ast/statements/WhileNode.java +++ b/src/main/java/ast/statements/WhileNode.java @@ -6,8 +6,8 @@ import semantic.SemanticVisitor; import typechecker.TypeCheckResult; public class WhileNode implements IStatementNode { - IExpressionNode expression; - BlockNode block; + public IExpressionNode expression; + public BlockNode block; public WhileNode(IExpressionNode expression, BlockNode block) { this.expression = expression; @@ -21,6 +21,6 @@ public class WhileNode implements IStatementNode { @Override public TypeCheckResult accept(SemanticVisitor visitor) { - return null; + return visitor.analyze(this); } } diff --git a/src/main/java/ast/type/ValueNode.java b/src/main/java/ast/type/ValueNode.java index b51f799..ec35af0 100644 --- a/src/main/java/ast/type/ValueNode.java +++ b/src/main/java/ast/type/ValueNode.java @@ -1,8 +1,11 @@ package ast.type; import ast.ASTNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; +import visitor.Visitable; -public class ValueNode implements ASTNode { +public class ValueNode implements ASTNode, Visitable { public EnumValueNode valueType; public String value; @@ -10,4 +13,10 @@ public class ValueNode implements ASTNode { this.valueType = valueType; this.value = value; } + + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } } diff --git a/src/main/java/semantic/SemanticAnalyzer.java b/src/main/java/semantic/SemanticAnalyzer.java index d00b2e3..6ebd124 100644 --- a/src/main/java/semantic/SemanticAnalyzer.java +++ b/src/main/java/semantic/SemanticAnalyzer.java @@ -9,6 +9,7 @@ import java.util.Objects; import ast.*; import ast.expressions.IExpressionNode; import ast.expressions.binaryexpressions.*; +import ast.expressions.unaryexpressions.MemberAccessNode; import ast.expressions.unaryexpressions.UnaryNode; import ast.members.ConstructorNode; import ast.members.FieldNode; @@ -21,8 +22,13 @@ import ast.statementexpressions.NewDeclarationNode; import ast.statementexpressions.crementexpressions.DecrementNode; import ast.statementexpressions.crementexpressions.IncrementNode; import ast.statementexpressions.methodcallstatementnexpressions.MethodCallNode; +import ast.statementexpressions.methodcallstatementnexpressions.TargetNode; import ast.statements.*; +import ast.type.AccessModifierNode; +import ast.type.EnumAccessModifierNode; +import ast.type.ValueNode; import ast.type.type.*; +import com.sun.jdi.IntegerType; import semantic.context.Context; import semantic.exceptions.*; import typechecker.TypeCheckResult; @@ -134,26 +140,20 @@ public class SemanticAnalyzer implements SemanticVisitor { } } - // Check if this method is already declared currentMethodReturnType = methodNode.getType(); - currentNullType = currentMethodReturnType; // Solange nicht in einem Assign oder Methoden-Aufruf dieser Typ + currentNullType = currentMethodReturnType; - ITypeNode resultType = new BaseType(TypeEnum.VOID); - - // gesetzt ist, ist dieser der Rückgabewert der Methode var result = methodNode.block.accept(this); valid = valid && result.isValid(); currentScope.popScope(); - resultType = result.getType(); + ITypeNode resultType = result.getType(); if (resultType == null) { resultType = new BaseType(TypeEnum.VOID); } - if (!resultType.equals(methodNode.getType())) { - errors.add(new TypeMismatchException("Method-Declaration " + methodNode.getIdentifier() + " with type " - + methodNode.getType() + " has at least one Mismatching return Type:")); - valid = false; + if (methodNode.getType() == null) { + methodNode.setType(new BaseType(TypeEnum.VOID)); } return new TypeCheckResult(valid, resultType); @@ -174,43 +174,65 @@ public class SemanticAnalyzer implements SemanticVisitor { @Override public TypeCheckResult analyze(IfNode toCheck) { + toCheck.block.accept(this); + + var resultExpression = toCheck.expression.accept(this); + if (resultExpression.isValid()) { + if (!resultExpression.getType().equals(new BaseType(TypeEnum.BOOL))) { + errors.add(new TypeMismatchException("Expression must be Boolean")); + return new TypeCheckResult(false, new BaseType(TypeEnum.VOID)); + } + } + return new TypeCheckResult(true, null); } @Override public TypeCheckResult analyze(ReturnNode toCheck) { - - if(toCheck.expression != null){ + if (toCheck.expression != null) { var result = toCheck.expression.accept(this); + if (result.isValid()) { + if (!result.getType().equals(currentMethodReturnType)) { + errors.add(new TypeMismatchException("Mismatched return Type from method")); + } + } return new TypeCheckResult(true, result.getType()); - } else { - return new TypeCheckResult(false, null); + } else if (toCheck.voidReturn) { + return new TypeCheckResult(true, new BaseType(TypeEnum.VOID)); } + return new TypeCheckResult(true, null); } @Override public TypeCheckResult analyze(WhileNode toCheck) { - return null; + var expResult = toCheck.expression.accept(this); + var blockRes = toCheck.block.accept(this); + return new TypeCheckResult(expResult.isValid() && blockRes.isValid(), blockRes.getType()); } @Override public TypeCheckResult analyze(ParameterNode toCheck) { - - - return new TypeCheckResult(true, null); + return new TypeCheckResult(true, toCheck.type); } @Override public TypeCheckResult analyze(BlockNode blockNode) { ITypeNode blockReturnType = null; + if (blockNode.statements.isEmpty()) { + return new TypeCheckResult(true, null); + } for (IStatementNode statementNode : blockNode.statements) { 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")); + if(!(statementNode instanceof IncrementNode) && !(statementNode instanceof DecrementNode)){ + if (result.getType() != null) { + if (blockReturnType == null) { + blockReturnType = result.getType(); + } else { + if (!blockReturnType.equals(result.getType())) { + errors.add(new MultipleReturnTypes("There are multiple Return types")); + } + } } } } @@ -219,20 +241,31 @@ public class SemanticAnalyzer implements SemanticVisitor { @Override public TypeCheckResult analyze(AssignableNode toCheck) { - return new TypeCheckResult(true, currentFields.get(toCheck.identifier)); + + if (toCheck.memberAccess != null) { + var result = toCheck.memberAccess.accept(this); + toCheck.setTypeNode(result.getType()); + return result; + } else { + if (currentFields.get(toCheck.identifier) != null) { + var type = currentFields.get(toCheck.identifier); + toCheck.setTypeNode(type); + return new TypeCheckResult(true, type); + } else if (currentScope.getLocalVar(toCheck.identifier) != null) { + var type = currentScope.getLocalVar(toCheck.identifier); + return new TypeCheckResult(true, type); + } + } + + return new TypeCheckResult(true, null); } @Override public TypeCheckResult analyze(ElseNode toCheck) { - return null; + return toCheck.block.accept(this); } - /*@Override - public TypeCheckResult analyze(ForNode toCheck) { - return null; - }*/ - @Override public TypeCheckResult analyze(AssignNode toCheck) { AssignableNode assignable = toCheck.assignable; @@ -258,33 +291,61 @@ public class SemanticAnalyzer implements SemanticVisitor { currentNullType = lResult.getType(); var rResult = rExpression.accept(this); - if (!Objects.equals(currentScope.getLocalVar(toCheck.assignable.identifier), rExpression.getType())) { + if (!Objects.equals(lResult.getType(), rResult.getType())) { errors.add(new TypeMismatchException( "Mismatch types in Assign-Statement: cannot convert from \"" + lResult.getType() + "\" to \"" + rResult.getType() + "\"")); valid = false; } -// else { -// toCheck.setType(assignable.getType()); -// } valid = valid && lResult.isValid() && rResult.isValid(); currentNullType = null; return new TypeCheckResult(valid, null); // return type is null to get the return type sufficently } @Override - public TypeCheckResult analyze(DecrementNode toCheck) { - return null; + public TypeCheckResult analyze(DecrementNode decrementNode) { + return decrementNode.assignableExpression.accept(this); } @Override public TypeCheckResult analyze(IfElseNode toCheck) { - return new TypeCheckResult(true, null); + var resultIf = toCheck.ifStatement.accept(this); + var resultElse = toCheck.elseStatement.accept(this); + + return new TypeCheckResult(resultIf.isValid() && resultElse.isValid(), new BaseType(TypeEnum.VOID)); } @Override public TypeCheckResult analyze(MethodCallNode toCheck) { - return null; + + if (toCheck.target.identifier != null) { + var targetType = currentScope.getLocalVar(toCheck.target.identifier); + if (targetType == null) { + targetType = currentFields.get(toCheck.target.identifier); + } + if (targetType instanceof ReferenceType reference) { + var type = getTypeFromMethod(toCheck, reference); + if (type != null) { + return new TypeCheckResult(true, type); + } else { + return new TypeCheckResult(false, null); + } + + } + } else { + if (toCheck.target.thisTar) { + var type = getTypeFromMethod(toCheck, new ReferenceType(currentClass.identifier)); + if (type != null) { + return new TypeCheckResult(true, type); + } + } else { + var result = toCheck.target.accept(this); + if (result.getType() instanceof ReferenceType reference) { + return new TypeCheckResult(true, getTypeFromMethod(toCheck, reference)); + } + } + } + return new TypeCheckResult(false, null); } @Override @@ -295,6 +356,9 @@ public class SemanticAnalyzer implements SemanticVisitor { TypeCheckResult result = localVarDecl.expression.accept(this); var resultType = localVarDecl.expression.getType(); + if (result.getType() != null) { + resultType = result.getType(); + } valid = result.isValid() && valid; if (!Objects.equals(resultType, localVarDecl.type)) { @@ -316,12 +380,17 @@ public class SemanticAnalyzer implements SemanticVisitor { @Override public TypeCheckResult analyze(NewDeclarationNode toCheck) { + + if (context.containsClass(toCheck.identifier)) { + return new TypeCheckResult(true, new ReferenceType(toCheck.identifier)); + } + return null; } @Override public TypeCheckResult analyze(IncrementNode toCheck) { - return null; + return toCheck.assignableExpression.accept(this); } @Override @@ -332,38 +401,223 @@ public class SemanticAnalyzer implements SemanticVisitor { @Override public TypeCheckResult analyze(CalculationNode calcNode) { if (calcNode.calculationExpression != null) { - calcNode.calculationExpression.accept(this); + var calcRes = calcNode.calculationExpression.accept(this); + if (calcNode.dotExpression != null) { + var dotRes = calcNode.dotExpression.accept(this); + + switch (calcNode.operator) { + case PLUS, MINUS: + if (calcRes.getType() instanceof BaseType calcType && dotRes.getType() instanceof BaseType dotType && + calcType.getTypeEnum().equals(TypeEnum.INT) && dotType.getTypeEnum().equals(TypeEnum.INT)) { + return new TypeCheckResult(true, new BaseType(TypeEnum.INT)); + } + break; + default: + } + + } else { + return new TypeCheckResult(calcRes.isValid(), calcRes.getType()); + } + } else if (calcNode.dotExpression != null) { + var dotRes = calcNode.dotExpression.accept(this); + return new TypeCheckResult(dotRes.isValid(), dotRes.getType()); + } + return new TypeCheckResult(false, null); + } + + @Override + public TypeCheckResult analyze(DotNode toCheck) { + if (toCheck.dotSubstractionExpression != null) { + return toCheck.dotSubstractionExpression.accept(this); + } + return new TypeCheckResult(false, null); + } + + @Override + public TypeCheckResult analyze(DotSubstractionNode toCheck) { + if (toCheck.value != null) { + return toCheck.value.accept(this); + } else if (toCheck.memberAccess != null) { + return toCheck.memberAccess.accept(this); + } else if (toCheck.methodCall != null) { + return toCheck.methodCall.accept(this); + } else if (toCheck.identifier != null) { + if (currentScope.contains(toCheck.identifier)) { + return new TypeCheckResult(true, currentScope.getLocalVar(toCheck.identifier)); + } else if (currentFields.get(toCheck.identifier) != null) { + return new TypeCheckResult(true, currentFields.get(toCheck.identifier)); + } + } else if (toCheck.calculationExpression != null) { + return toCheck.calculationExpression.accept(this); } return null; } @Override - public TypeCheckResult analyze(DotNode toCheck) { - return null; - } + public TypeCheckResult analyze(NonCalculationNode nonCalculationNode) { + var expResult = nonCalculationNode.expression.accept(this); + var unaryResult = nonCalculationNode.unaryExpression.accept(this); - @Override - public TypeCheckResult analyze(DotSubstractionNode toCheck) { - return null; - } + switch (nonCalculationNode.operator) { + case LESS, LESS_EQUAL, GREATER, GREATER_EQUAL: + if (expResult.getType() instanceof BaseType expResultType && expResultType.getTypeEnum().equals(TypeEnum.INT) && + unaryResult.getType() instanceof BaseType unaryResultType && unaryResultType.getTypeEnum().equals(TypeEnum.INT)) { + return new TypeCheckResult(true, new BaseType(TypeEnum.BOOL)); + } else { + errors.add(new TypeMismatchException("Both types must be Integer")); + } + break; + case OR, AND: + if (expResult.getType() instanceof BaseType expResultType && expResultType.getTypeEnum().equals(TypeEnum.INT) && + unaryResult.getType() instanceof BaseType unaryResultType && unaryResultType.getTypeEnum().equals(TypeEnum.INT)) { + return new TypeCheckResult(true, new BaseType(TypeEnum.BOOL)); + } else { + errors.add(new TypeMismatchException("Both types must be Boolean")); + } + break; + case EQUAL, NOT_EQUAL: + if (expResult.getType() instanceof BaseType expResultType && unaryResult.getType() instanceof BaseType unaryResultType + && Objects.equals(expResultType, unaryResultType)) { + return new TypeCheckResult(true, new BaseType(TypeEnum.BOOL)); + } else { + errors.add(new TypeMismatchException("Both types must be the same")); + } - @Override - public TypeCheckResult analyze(NonCalculationNode toCheck) { - return null; + } + return new TypeCheckResult(false, null); } @Override public TypeCheckResult analyze(UnaryNode unary) { var valid = true; - if (currentScope.contains(unary.identifier)) { - return new TypeCheckResult(valid, currentScope.getLocalVar(unary.identifier)); - } else if(currentFields.get(unary.identifier) != null) { - return new TypeCheckResult(valid, currentFields.get(unary.identifier)); - } else { - errors.add(new NotDeclaredException("Var is not Declared")); + if (unary.identifier != null) { + if (currentScope.contains(unary.identifier)) { + return new TypeCheckResult(valid, currentScope.getLocalVar(unary.identifier)); + } else if (currentFields.get(unary.identifier) != null) { + return new TypeCheckResult(valid, currentFields.get(unary.identifier)); + } else if (unary.statement != null) { + var result = unary.statement.accept(this); + unary.setType(result.getType()); + return result; + } else { + errors.add(new NotDeclaredException("Var is not Declared")); + } + } else if (unary.statement != null) { + var result = unary.statement.accept(this); + return new TypeCheckResult(result.isValid(), result.getType()); + } else if (unary.value != null) { + var result = unary.value.accept(this); + return new TypeCheckResult(result.isValid(), result.getType()); + } else if (unary.memberAccess != null) { + var result = unary.memberAccess.accept(this); + return new TypeCheckResult(result.isValid(), result.getType()); + } else if (unary.expression != null) { + var result = unary.expression.accept(this); + return new TypeCheckResult(result.isValid(), result.getType()); } - return new TypeCheckResult(valid, null); + + return new TypeCheckResult(false, null); + } + + @Override + public TypeCheckResult analyze(MemberAccessNode memberAccessNode) { + + ITypeNode currentType = null; + + for (String s : memberAccessNode.identifiers) { + if (currentType == null) { + if (currentScope.getLocalVar(s) != null) { + currentType = currentScope.getLocalVar(s); + + } else if (currentFields.get(s) != null) { + currentType = currentFields.get(s); + } else { + errors.add(new NotDeclaredException(s + "Not Declared")); + return new TypeCheckResult(false, null); + } + + } else { + if (currentType instanceof ReferenceType reference) { + var currentTypeClass = context.getClass(reference.getIdentifier()); + + var currentField = currentTypeClass.getField(s); + if (currentField.getAccessModifier().accessType == EnumAccessModifierNode.PUBLIC) { + currentType = currentField.getType(); + } else { + errors.add(new NotVisibleException("This field is not visible")); + return new TypeCheckResult(false, null); + } + } + } + + } + + return new TypeCheckResult(true, currentType); + } + + @Override + public TypeCheckResult analyze(TargetNode targetNode) { + + if (targetNode.memberAccess != null) { + return targetNode.memberAccess.accept(this); + } + return null; + } + + @Override + public TypeCheckResult analyze(ValueNode valueNode) { + + switch (valueNode.valueType) { + case INT_VALUE -> { + return new TypeCheckResult(true, new BaseType(TypeEnum.INT)); + } + case CHAR_VALUE -> { + return new TypeCheckResult(true, new BaseType(TypeEnum.CHAR)); + } + case BOOLEAN_VALUE -> { + return new TypeCheckResult(true, new BaseType(TypeEnum.BOOL)); + } + default -> { + return new TypeCheckResult(false, null); + } + } + } + + private ITypeNode getTypeFromMethod(MethodCallNode toCheck, ReferenceType reference) { + var classContext = context.getClass(reference.getIdentifier()); + + if (classContext == null) { + errors.add(new NotDeclaredException(toCheck.target.identifier + "is not Defined")); + } else { + var methods = classContext.getMethods(); + for (var method : methods) { + if (toCheck.identifier.equals(method.getIdentifier())) { + if (method.getParameters().size() == toCheck.parameters.size() && !(method instanceof ConstructorNode)) { + boolean same = true; + for (int i = 0; i < method.getParameters().size(); i++) { + var result1 = method.getParameters().get(i).accept(this); + var result2 = toCheck.parameters.get(i).accept(this); + if (!Objects.equals(result1.getType(), result2.getType())) { + same = false; + } + } + if (same) { + if (method.accesModifier.accessType == EnumAccessModifierNode.PUBLIC) { + if (method.getType() == null) { + return new BaseType(TypeEnum.VOID); + } + return method.getType(); + } else { + errors.add(new NotVisibleException("This Method is not Visible")); + } + } + } + } + } + errors.add(new WrongOverloading("No Method found with this parameters")); + } + return null; } } \ No newline at end of file diff --git a/src/main/java/semantic/SemanticVisitor.java b/src/main/java/semantic/SemanticVisitor.java index 974d1de..0c979ca 100644 --- a/src/main/java/semantic/SemanticVisitor.java +++ b/src/main/java/semantic/SemanticVisitor.java @@ -2,6 +2,7 @@ package semantic; import ast.*; import ast.expressions.binaryexpressions.*; +import ast.expressions.unaryexpressions.MemberAccessNode; import ast.expressions.unaryexpressions.UnaryNode; import ast.members.*; import ast.parameters.ParameterNode; @@ -11,7 +12,9 @@ import ast.statementexpressions.NewDeclarationNode; import ast.statementexpressions.crementexpressions.DecrementNode; import ast.statementexpressions.crementexpressions.IncrementNode; import ast.statementexpressions.methodcallstatementnexpressions.MethodCallNode; +import ast.statementexpressions.methodcallstatementnexpressions.TargetNode; import ast.statements.*; +import ast.type.ValueNode; import typechecker.TypeCheckResult; public interface SemanticVisitor { @@ -38,8 +41,6 @@ public interface SemanticVisitor { TypeCheckResult analyze(ElseNode toCheck); - //TypeCheckResult analyze(ForNode toCheck); - TypeCheckResult analyze(AssignNode toCheck); TypeCheckResult analyze(DecrementNode toCheck); @@ -66,4 +67,10 @@ public interface SemanticVisitor { TypeCheckResult analyze(UnaryNode toCheck); + TypeCheckResult analyze(MemberAccessNode toCheck); + + TypeCheckResult analyze(TargetNode toCheck); + + TypeCheckResult analyze(ValueNode toCheck); + } \ No newline at end of file diff --git a/src/main/java/semantic/context/ClassContext.java b/src/main/java/semantic/context/ClassContext.java index 1a79fc4..b9e39a4 100644 --- a/src/main/java/semantic/context/ClassContext.java +++ b/src/main/java/semantic/context/ClassContext.java @@ -2,11 +2,15 @@ package semantic.context; import ast.ClassNode; import ast.members.FieldNode; +import ast.members.MethodNode; + +import java.util.ArrayList; import java.util.HashMap; public class ClassContext { private HashMap fields; + private ArrayList methods = new ArrayList<>(); public ClassContext(ClassNode classNode) { @@ -15,6 +19,8 @@ public class ClassContext { classNode.members.forEach(member -> { if(member instanceof FieldNode fieldNode) { fields.put(fieldNode.identifier, new FieldContext(fieldNode)); + }else if(member instanceof MethodNode methodNode) { + methods.add(methodNode); } }); @@ -24,4 +30,8 @@ public class ClassContext { return fields.get(name); } + public ArrayList getMethods() { + return methods; + } + } diff --git a/src/main/java/semantic/context/Context.java b/src/main/java/semantic/context/Context.java index d6431ef..39e279a 100644 --- a/src/main/java/semantic/context/Context.java +++ b/src/main/java/semantic/context/Context.java @@ -21,4 +21,8 @@ public class Context { return classes.get(identifier); } + public boolean containsClass(String identifier) { + return classes.containsKey(identifier); + } + } diff --git a/src/main/java/semantic/context/FieldContext.java b/src/main/java/semantic/context/FieldContext.java index 8443520..aba5ba0 100644 --- a/src/main/java/semantic/context/FieldContext.java +++ b/src/main/java/semantic/context/FieldContext.java @@ -18,4 +18,8 @@ public class FieldContext { return type; } + public AccessModifierNode getAccessModifier() { + return accessModifier; + } + } diff --git a/src/main/java/semantic/exceptions/NotVisibleException.java b/src/main/java/semantic/exceptions/NotVisibleException.java new file mode 100644 index 0000000..efd7444 --- /dev/null +++ b/src/main/java/semantic/exceptions/NotVisibleException.java @@ -0,0 +1,9 @@ +package semantic.exceptions; + +public class NotVisibleException extends RuntimeException { + + public NotVisibleException(String message) { + super(message); + } + +} diff --git a/src/main/java/semantic/exceptions/WrongOverloading.java b/src/main/java/semantic/exceptions/WrongOverloading.java new file mode 100644 index 0000000..5cb42a8 --- /dev/null +++ b/src/main/java/semantic/exceptions/WrongOverloading.java @@ -0,0 +1,9 @@ +package semantic.exceptions; + +public class WrongOverloading extends RuntimeException { + + public WrongOverloading(String message) { + super(message); + } + +} diff --git a/src/test/java/semantic/EndToTypedAstTest.java b/src/test/java/semantic/EndToTypedAstTest.java index 9bf5485..637ebc1 100644 --- a/src/test/java/semantic/EndToTypedAstTest.java +++ b/src/test/java/semantic/EndToTypedAstTest.java @@ -26,11 +26,37 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import org.junit.jupiter.api.Test; + import static org.junit.jupiter.api.Assertions.*; public class EndToTypedAstTest { private static final Map> exceptionMap = new HashMap<>(); + @Test + public void testOnlyOneFile() { + SemanticAnalyzer.clearAnalyzer(); + + CharStream codeCharStream = null; + try { + codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/input/typedAstFeaturesTests/CorrectTest.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(); // parse the input + + /* ------------------------- AST builder -> AST ------------------------- */ + ASTBuilder astBuilder = new ASTBuilder(); + ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); + + var result = SemanticAnalyzer.generateTast(abstractSyntaxTree); + + assertTrue(SemanticAnalyzer.errors.isEmpty()); + } + @Test public void exceptionsTest() { String directoryPath = "src/test/resources/input/typedAstExceptionsTests"; @@ -88,7 +114,7 @@ public class EndToTypedAstTest { } @Test - public void featureTest(){ + public void featureTest() { String directoryPath = "src/test/resources/input/typedAstFeaturesTests"; File folder = new File(directoryPath); if (folder.isDirectory()) { @@ -115,6 +141,9 @@ public class EndToTypedAstTest { ASTNode typedAst = SemanticAnalyzer.generateTast(abstractSyntaxTree); System.out.println("Testing the file: " + file.getName()); + for(Exception runtimeException : SemanticAnalyzer.errors){ + runtimeException.printStackTrace(); + } assertTrue(SemanticAnalyzer.errors.isEmpty()); assertNotNull(typedAst); } @@ -127,9 +156,8 @@ public class EndToTypedAstTest { } - - // ------------------ Helpers ------------------ + /** * This method is used to extract the expected exception from a given file. * It reads the file line by line and uses a regular expression to match the expected exception annotation. @@ -158,25 +186,25 @@ public class EndToTypedAstTest { } /** - * This method is used to retrieve the Class object associated with a given exception name. - * It first prints the original exception name, then appends the package name to the exception name and prints it. - * It then retrieves the Class object from the exceptionMap using the fully qualified exception name. - * If the Class object is not found in the exceptionMap, it throws a RuntimeException. - * - * @param exceptionName The name of the exception for which the Class object is to be retrieved. - * @return The Class object associated with the given exception name. - * @throws RuntimeException If the Class object for the given exception name is not found in the exceptionMap. - */ -private Class getExceptionClass(String exceptionName) { - System.out.println(exceptionName); - exceptionName = "semantic.exceptions." + exceptionName; - System.out.println(exceptionName); - Class exceptionClass = exceptionMap.get(exceptionName); - if (exceptionClass == null) { - throw new RuntimeException("Exception class not found: " + exceptionName); + * This method is used to retrieve the Class object associated with a given exception name. + * It first prints the original exception name, then appends the package name to the exception name and prints it. + * It then retrieves the Class object from the exceptionMap using the fully qualified exception name. + * If the Class object is not found in the exceptionMap, it throws a RuntimeException. + * + * @param exceptionName The name of the exception for which the Class object is to be retrieved. + * @return The Class object associated with the given exception name. + * @throws RuntimeException If the Class object for the given exception name is not found in the exceptionMap. + */ + private Class getExceptionClass(String exceptionName) { + System.out.println(exceptionName); + exceptionName = "semantic.exceptions." + exceptionName; + System.out.println(exceptionName); + Class exceptionClass = exceptionMap.get(exceptionName); + if (exceptionClass == null) { + throw new RuntimeException("Exception class not found: " + exceptionName); + } + return exceptionClass; } - return exceptionClass; -} /** * This method is used to load custom exceptions from a specified package. diff --git a/src/test/java/semantic/Mocker.java b/src/test/java/semantic/Mocker.java deleted file mode 100644 index 683b385..0000000 --- a/src/test/java/semantic/Mocker.java +++ /dev/null @@ -1,102 +0,0 @@ -package semantic; - -import ast.*; -import ast.members.FieldNode; -import ast.members.MethodNode; -import ast.parameters.ParameterNode; -import ast.type.AccessModifierNode; -import ast.type.type.*; - -public class Mocker { - - public static ASTNode mockTwoSameFields(){ - ProgramNode p = new ProgramNode(); - - ClassNode c = new ClassNode(); - c.identifier = "testClass"; - - FieldNode f1 = new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a"); - - c.members.add(f1); - - FieldNode f2 = new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a"); - - c.members.add(f2); - - p.classes.add(c); - return p; - } - - public static ASTNode mockSimpleMethod(){ - ProgramNode p = new ProgramNode(); - - ClassNode c = new ClassNode(); - - MethodNode methodNode = new MethodNode(); - - //Parameter - ParameterNode parameterNode = new ParameterNode(new BaseType(TypeEnum.INT), "a"); - - methodNode.addParameter(parameterNode); - - //Statements - - //Block - methodNode.block = new ast.statements.BlockNode(); - - c.members.add(methodNode); - - p.classes.add(c); - - return p; - } - - public static ASTNode mockTwoSameMethods(){ - ProgramNode p = new ProgramNode(); - - ClassNode c = new ClassNode(); - - MethodNode methodNode = new MethodNode(); - methodNode.block = new ast.statements.BlockNode(); - methodNode.setType(new BaseType(TypeEnum.INT)); - - methodNode.setIdentifier("testMethod"); - - c.members.add(methodNode); - - MethodNode methodNode1 = new MethodNode(); - methodNode1.block = new ast.statements.BlockNode(); - methodNode1.setType(new BaseType(TypeEnum.INT)); - - methodNode1.setIdentifier("testMethod"); - - c.members.add(methodNode1); - - p.classes.add(c); - - return p; - } - - public static ASTNode mockTwoDifferentMethods(){ - ProgramNode p = new ProgramNode(); - - ClassNode c = new ClassNode(); - - MethodNode methodNode = new MethodNode(); - methodNode.block = new ast.statements.BlockNode(); - methodNode.setIdentifier("testMethod"); - - c.members.add(methodNode); - - MethodNode methodNode1 = new MethodNode(); - methodNode1.block = new ast.statements.BlockNode(); - methodNode1.setIdentifier("testMethod1"); - - c.members.add(methodNode1); - - p.classes.add(c); - - return p; - } - -} diff --git a/src/test/java/semantic/SemanticTest.java b/src/test/java/semantic/SemanticTest.java index a4039ac..58d0210 100644 --- a/src/test/java/semantic/SemanticTest.java +++ b/src/test/java/semantic/SemanticTest.java @@ -3,6 +3,18 @@ package semantic; public class SemanticTest { + public void test(){ + + } + + public void test(int a, boolean b){ + + } + + public void test(boolean b, int a){ + + } + // @Test // public void alreadyDeclaredLocalFieldVar() { // ProgramNode programNode = new ProgramNode(); diff --git a/src/test/resources/input/featureTests/BooleanOperations.class b/src/test/resources/input/featureTests/BooleanOperations.class new file mode 100644 index 0000000..cd8092a Binary files /dev/null and b/src/test/resources/input/featureTests/BooleanOperations.class differ diff --git a/src/test/resources/input/featureTests/CharManipulation.class b/src/test/resources/input/featureTests/CharManipulation.class new file mode 100644 index 0000000..e47890d Binary files /dev/null and b/src/test/resources/input/featureTests/CharManipulation.class differ diff --git a/src/test/resources/input/featureTests/ConditionalStatements.class b/src/test/resources/input/featureTests/ConditionalStatements.class new file mode 100644 index 0000000..7fa39b3 Binary files /dev/null and b/src/test/resources/input/featureTests/ConditionalStatements.class differ diff --git a/src/test/resources/input/featureTests/EmptyClassExample.class b/src/test/resources/input/featureTests/EmptyClassExample.class new file mode 100644 index 0000000..a6a129d Binary files /dev/null and b/src/test/resources/input/featureTests/EmptyClassExample.class differ diff --git a/src/test/resources/input/featureTests/LoopExamples.class b/src/test/resources/input/featureTests/LoopExamples.class new file mode 100644 index 0000000..2a398c6 Binary files /dev/null and b/src/test/resources/input/featureTests/LoopExamples.class differ diff --git a/src/test/resources/input/featureTests/MethodOverloading.class b/src/test/resources/input/featureTests/MethodOverloading.class new file mode 100644 index 0000000..2357744 Binary files /dev/null and b/src/test/resources/input/featureTests/MethodOverloading.class differ diff --git a/src/test/resources/input/typedAstExceptionsTests/BothTypesMustBeSame1.java b/src/test/resources/input/typedAstExceptionsTests/BothTypesMustBeSame1.java new file mode 100644 index 0000000..5a88a45 --- /dev/null +++ b/src/test/resources/input/typedAstExceptionsTests/BothTypesMustBeSame1.java @@ -0,0 +1,9 @@ +// @expected: TypeMismatchException +public class AllFeaturesClassExample { + + public void controlStructures(int a, boolean bool) { + while (a > bool) { + a--; + } + } +} diff --git a/src/test/resources/input/typedAstExceptionsTests/CompareBoolInt.java b/src/test/resources/input/typedAstExceptionsTests/CompareBoolInt.java new file mode 100644 index 0000000..1eb080a --- /dev/null +++ b/src/test/resources/input/typedAstExceptionsTests/CompareBoolInt.java @@ -0,0 +1,13 @@ +// @expected: TypeMismatchException +public class Test{ + + public void test(boolean b){ + if(b == 2){ + + } else { + + } + + } + +} diff --git a/src/test/resources/input/typedAstExceptionsTests/FieldIsNotVisible.java b/src/test/resources/input/typedAstExceptionsTests/FieldIsNotVisible.java new file mode 100644 index 0000000..ce099d3 --- /dev/null +++ b/src/test/resources/input/typedAstExceptionsTests/FieldIsNotVisible.java @@ -0,0 +1,20 @@ +// @expected: NotVisibleException +public class Test{ + + public Car c; + + public int test(){ + return c.speed; + } + +} + +public class Car{ + + private int speed; + + public int getSpeed(){ + return speed; + } + +} \ No newline at end of file diff --git a/src/test/resources/input/typedAstExceptionsTests/IfExpressionInt.java b/src/test/resources/input/typedAstExceptionsTests/IfExpressionInt.java new file mode 100644 index 0000000..2fbbbfc --- /dev/null +++ b/src/test/resources/input/typedAstExceptionsTests/IfExpressionInt.java @@ -0,0 +1,14 @@ +// @expected: TypeMismatchException +public class Test{ + + public void test(int x){ + + if(x){ + + } else { + + } + + } + +} \ No newline at end of file diff --git a/src/test/resources/input/typedAstExceptionsTests/MethodNotVisible.java b/src/test/resources/input/typedAstExceptionsTests/MethodNotVisible.java new file mode 100644 index 0000000..2631c3e --- /dev/null +++ b/src/test/resources/input/typedAstExceptionsTests/MethodNotVisible.java @@ -0,0 +1,21 @@ +// @expected: NotVisibleException +public class Test { + + public int firstInt; + public Car ca; + + public int speed(){ + return ca.getSpeed(); + } + +} + +public class Car{ + + private int speed; + + private int getSpeed(){ + return speed; + } + +} \ No newline at end of file diff --git a/src/test/resources/input/typedAstExceptionsTests/MissingOverloadingParameter.java b/src/test/resources/input/typedAstExceptionsTests/MissingOverloadingParameter.java new file mode 100644 index 0000000..17eac69 --- /dev/null +++ b/src/test/resources/input/typedAstExceptionsTests/MissingOverloadingParameter.java @@ -0,0 +1,19 @@ +// @expected: WrongOverloading +public class Test{ + + public void test(int x){ + + if(this.get()){ + + } else { + + } + + } + public boolean b; + + public boolean get(int c){ + return b; + } + +} \ No newline at end of file diff --git a/src/test/resources/input/typedAstExceptionsTests/MultipleReturnTypes.java b/src/test/resources/input/typedAstExceptionsTests/MultipleReturnTypes.java index f368e60..b59f6b9 100644 --- a/src/test/resources/input/typedAstExceptionsTests/MultipleReturnTypes.java +++ b/src/test/resources/input/typedAstExceptionsTests/MultipleReturnTypes.java @@ -1,4 +1,4 @@ -// @expected: MultipleReturnTypes +// @expected: TypeMismatchException public class Example { public static int testMethod(int x, char c){ diff --git a/src/test/resources/input/typedAstExceptionsTests/SelectWrongMethodCauseParameter.java b/src/test/resources/input/typedAstExceptionsTests/SelectWrongMethodCauseParameter.java new file mode 100644 index 0000000..f65e757 --- /dev/null +++ b/src/test/resources/input/typedAstExceptionsTests/SelectWrongMethodCauseParameter.java @@ -0,0 +1,22 @@ +// @expected: TypeMismatchException +public class Test{ + + public int i; + public boolean b; + + public int test(){ + + return this.test(i); + + } + + public void test(int a){ + + } + + public int test(boolean bool){ + int ret = 1; + return ret; + } + +} \ No newline at end of file diff --git a/src/test/resources/input/typedAstExceptionsTests/WrongIfClause.java b/src/test/resources/input/typedAstExceptionsTests/WrongIfClause.java deleted file mode 100644 index e1b7c27..0000000 --- a/src/test/resources/input/typedAstExceptionsTests/WrongIfClause.java +++ /dev/null @@ -1,8 +0,0 @@ -// @expected: TypeMismatchException -public class Example { - - public static void testMethod(int x){ - - } - -} diff --git a/src/test/resources/input/typedAstFeaturesTests/CallMethodFromObjekt.java b/src/test/resources/input/typedAstFeaturesTests/CallMethodFromObjekt.java new file mode 100644 index 0000000..61b94f2 --- /dev/null +++ b/src/test/resources/input/typedAstFeaturesTests/CallMethodFromObjekt.java @@ -0,0 +1,20 @@ +public class Test { + + public int firstInt; + public Car ca; + + public int speed(){ + return ca.getSpeed(); + } + +} + +public class Car{ + + private int speed; + + public int getSpeed(){ + return speed; + } + +} \ No newline at end of file diff --git a/src/test/resources/input/typedAstFeaturesTests/CorrectMemberAccess.java b/src/test/resources/input/typedAstFeaturesTests/CorrectMemberAccess.java new file mode 100644 index 0000000..b9f3dbb --- /dev/null +++ b/src/test/resources/input/typedAstFeaturesTests/CorrectMemberAccess.java @@ -0,0 +1,19 @@ +public class Test{ + + public Car c; + + public int test(){ + return c.getSpeed(); + } + +} + +public class Car{ + + private int speed; + + public int getSpeed(){ + return speed; + } + +} \ No newline at end of file diff --git a/src/test/resources/input/typedAstFeaturesTests/CorrectMethodParameter.java b/src/test/resources/input/typedAstFeaturesTests/CorrectMethodParameter.java new file mode 100644 index 0000000..ecfad3e --- /dev/null +++ b/src/test/resources/input/typedAstFeaturesTests/CorrectMethodParameter.java @@ -0,0 +1,18 @@ +public class Test{ + + public void test(int x){ + + if(this.get(x)){ + + } else { + + } + + } + public boolean b; + + public boolean get(int c){ + return b; + } + +} \ No newline at end of file diff --git a/src/test/resources/input/typedAstFeaturesTests/CorrectNonCalcTest.java b/src/test/resources/input/typedAstFeaturesTests/CorrectNonCalcTest.java new file mode 100644 index 0000000..d78e926 --- /dev/null +++ b/src/test/resources/input/typedAstFeaturesTests/CorrectNonCalcTest.java @@ -0,0 +1,12 @@ +public class Test{ + + public void test(boolean b){ + if(b == true){ + + } else { + + } + + } + +} diff --git a/src/test/resources/input/typedAstFeaturesTests/CorrectTest.java b/src/test/resources/input/typedAstFeaturesTests/CorrectTest.java index 054a49b..5ef0b26 100644 --- a/src/test/resources/input/typedAstFeaturesTests/CorrectTest.java +++ b/src/test/resources/input/typedAstFeaturesTests/CorrectTest.java @@ -1,18 +1,38 @@ -public class Example { - - public int a; - - public static int testMethod(int b, boolean bo){ - a = b; - if(bo){ +public class AllFeaturesClassExample { + int a; + boolean b; + char c; + public void controlStructures(int adf, boolean bool) { + if (a > (10 + 8)) { + } else { } - return a; + + + while (a > adf) { + a--; + } + + for (int i = 0; i < 5; i++) { + } + } - public static void testMethod(int b){ +// void logicalOperations() { + // Logische UND-Operation +// if (b && a > 5) { +// System.out.println("a ist größer als 5 und b ist wahr"); +// } - } + // Logische ODER-Operation +// if (b || a < 5) { +// System.out.println("b ist wahr oder a ist kleiner als 5"); +// } +// } -} \ No newline at end of file +// public static void main(String[] args) { +// AllFeaturesClassExample obj = new AllFeaturesClassExample(12, true, 'a'); +// obj.controlStructures(); +// } +} diff --git a/src/test/resources/input/typedAstFeaturesTests/FullTest.java b/src/test/resources/input/typedAstFeaturesTests/FullTest.java new file mode 100644 index 0000000..5c3a97b --- /dev/null +++ b/src/test/resources/input/typedAstFeaturesTests/FullTest.java @@ -0,0 +1,64 @@ + +public class AllFeaturesClassExample { + int a; + boolean b; + char c; + + public void controlStructures(int adf, boolean bool) { + if (a > (10 + 8)) { + } else { + } + + + while (a > adf) { + a--; + } + + for (int i = 0; i < 5; i++) { + } + + + } + +// void logicalOperations() { +// // Logische UND-Operation +// if (b && a > 5) { +//// System.out.println("a ist größer als 5 und b ist wahr"); +// } +// +// // Logische ODER-Operation +// if (b || a < 5) { +//// System.out.println("b ist wahr oder a ist kleiner als 5"); +// } +// } + +// public static void main(String[] args) { +// AllFeaturesClassExample obj = new AllFeaturesClassExample(12, true, 'a'); +// obj.controlStructures(); +// } +} + +public class Test { + + public Car c; + + public int test(boolean b, int x) { + if (b == true) { + return c.getSpeed(); + } else { + return x; + } + } + +} + +public class Car { + + private int speed; + + public int getSpeed() { + return speed; + } + +} + diff --git a/src/test/resources/input/typedAstFeaturesTests/IfExpressionBoolean.java b/src/test/resources/input/typedAstFeaturesTests/IfExpressionBoolean.java new file mode 100644 index 0000000..526a2f2 --- /dev/null +++ b/src/test/resources/input/typedAstFeaturesTests/IfExpressionBoolean.java @@ -0,0 +1,13 @@ +public class Car{ + + public void test(boolean boo){ + + if(boo){ + + } else { + + } + + } + +} \ No newline at end of file diff --git a/src/test/resources/input/typedAstFeaturesTests/IfReturn.java b/src/test/resources/input/typedAstFeaturesTests/IfReturn.java new file mode 100644 index 0000000..00cd263 --- /dev/null +++ b/src/test/resources/input/typedAstFeaturesTests/IfReturn.java @@ -0,0 +1,13 @@ +public class Car{ + + public int getSpeed(boolean bool, int a, int b){ + + if(bool){ + return a; + } else { + return b; + } + + } + +} \ No newline at end of file diff --git a/src/test/resources/input/typedAstFeaturesTests/SelectRightOverloadedMethod.java b/src/test/resources/input/typedAstFeaturesTests/SelectRightOverloadedMethod.java new file mode 100644 index 0000000..bcb6b9c --- /dev/null +++ b/src/test/resources/input/typedAstFeaturesTests/SelectRightOverloadedMethod.java @@ -0,0 +1,21 @@ +public class Test{ + + public int i; + public boolean b; + + public int test(){ + + return this.test(b); + + } + + public void test(int a){ + + } + + public int test(boolean bool){ + int ret = 1; + return ret; + } + +} \ No newline at end of file diff --git a/src/test/resources/input/typedAstFeaturesTests/ThisDotMethod.java b/src/test/resources/input/typedAstFeaturesTests/ThisDotMethod.java new file mode 100644 index 0000000..36bcade --- /dev/null +++ b/src/test/resources/input/typedAstFeaturesTests/ThisDotMethod.java @@ -0,0 +1,13 @@ +public class Car{ + + private int speed; + + public int getSpeed(){ + return speed; + } + + public int test(){ + return this.getSpeed(); + } + +} \ No newline at end of file diff --git a/src/test/resources/input/typedAstFeaturesTests/VoidReturnTypeIF.java b/src/test/resources/input/typedAstFeaturesTests/VoidReturnTypeIF.java new file mode 100644 index 0000000..bc31a27 --- /dev/null +++ b/src/test/resources/input/typedAstFeaturesTests/VoidReturnTypeIF.java @@ -0,0 +1,13 @@ +public class Car{ + + private int speed; + + public void getSpeed(boolean boo){ + if(boo){ + + } else { + + } + } + +} \ No newline at end of file