From b7affd75ae9b3024492e7b240bd55574c8b6ddd9 Mon Sep 17 00:00:00 2001 From: Bruder John Date: Wed, 3 Jul 2024 15:35:09 +0200 Subject: [PATCH] added chainedmethods --- src/main/java/semantic/SemanticAnalyzer.java | 60 ++++++++++++++++--- src/main/java/semantic/context/Context.java | 4 ++ .../ClassNotDeclared.java | 12 ++++ .../typedAstFeaturesTests/ChainedMethods.java | 29 +++++++++ .../typedAstFeaturesTests/CorrectTest.java | 50 ++++++---------- 5 files changed, 115 insertions(+), 40 deletions(-) create mode 100644 src/test/resources/input/typedAstExceptionsTests/ClassNotDeclared.java create mode 100644 src/test/resources/input/typedAstFeaturesTests/ChainedMethods.java diff --git a/src/main/java/semantic/SemanticAnalyzer.java b/src/main/java/semantic/SemanticAnalyzer.java index 6ebd124..bbe2aa1 100644 --- a/src/main/java/semantic/SemanticAnalyzer.java +++ b/src/main/java/semantic/SemanticAnalyzer.java @@ -21,6 +21,7 @@ import ast.statementexpressions.AssignableNode; import ast.statementexpressions.NewDeclarationNode; import ast.statementexpressions.crementexpressions.DecrementNode; import ast.statementexpressions.crementexpressions.IncrementNode; +import ast.statementexpressions.methodcallstatementnexpressions.ChainedMethodNode; import ast.statementexpressions.methodcallstatementnexpressions.MethodCallNode; import ast.statementexpressions.methodcallstatementnexpressions.TargetNode; import ast.statements.*; @@ -29,6 +30,7 @@ import ast.type.EnumAccessModifierNode; import ast.type.ValueNode; import ast.type.type.*; import com.sun.jdi.IntegerType; +import semantic.context.ClassContext; import semantic.context.Context; import semantic.exceptions.*; import typechecker.TypeCheckResult; @@ -163,6 +165,11 @@ public class SemanticAnalyzer implements SemanticVisitor { @Override public TypeCheckResult analyze(FieldNode toCheck) { + if (toCheck.type instanceof ReferenceType referenceType) { + if(!context.containsClass(referenceType.getIdentifier())){ + errors.add(new NotDeclaredException(referenceType.getIdentifier() + " not declared")); + } + } if (currentFields.get(toCheck.identifier) != null) { errors.add(new AlreadyDeclaredException("Already declared " + toCheck.identifier)); return new TypeCheckResult(false, null); @@ -170,6 +177,8 @@ public class SemanticAnalyzer implements SemanticVisitor { currentFields.put(toCheck.identifier, toCheck.type); } return new TypeCheckResult(true, null); + + } @Override @@ -224,7 +233,7 @@ public class SemanticAnalyzer implements SemanticVisitor { } for (IStatementNode statementNode : blockNode.statements) { var result = statementNode.accept(this); - if(!(statementNode instanceof IncrementNode) && !(statementNode instanceof DecrementNode)){ + if (!(statementNode instanceof IncrementNode) && !(statementNode instanceof DecrementNode)) { if (result.getType() != null) { if (blockReturnType == null) { blockReturnType = result.getType(); @@ -275,13 +284,6 @@ public class SemanticAnalyzer implements SemanticVisitor { currentNullType = oldNullType; var valid = true; - // This check currently handles things like : - /** - * private int i; - * void foo(int i){ - * i = i; - * } - */ if (assignable.equals(rExpression)) { errors.add(new TypeMismatchException("Cannot assign to self")); valid = false; @@ -324,6 +326,15 @@ public class SemanticAnalyzer implements SemanticVisitor { targetType = currentFields.get(toCheck.target.identifier); } if (targetType instanceof ReferenceType reference) { + if (!toCheck.chainedMethods.isEmpty()) { + for (ChainedMethodNode chainedMethod : toCheck.chainedMethods) { + var type = getTypeFromMethod(chainedMethod, reference); + if (type instanceof ReferenceType referenceType) + reference = referenceType; + else + errors.add(new TypeMismatchException("Ein Basetyp hat keine funktionen")); + } + } var type = getTypeFromMethod(toCheck, reference); if (type != null) { return new TypeCheckResult(true, type); @@ -620,4 +631,37 @@ public class SemanticAnalyzer implements SemanticVisitor { return null; } + private ITypeNode getTypeFromMethod(ChainedMethodNode toCheck, ReferenceType reference) { + var classContext = context.getClass(reference.getIdentifier()); + + var methods = classContext.getMethods(); + for (var method : methods) { + if (toCheck.identifier.equals(method.getIdentifier())) { + if (method.getParameters().size() == toCheck.expressions.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.expressions.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")); + } + + } + } + } + } + + return null; + } + } \ No newline at end of file diff --git a/src/main/java/semantic/context/Context.java b/src/main/java/semantic/context/Context.java index 39e279a..4b20c8f 100644 --- a/src/main/java/semantic/context/Context.java +++ b/src/main/java/semantic/context/Context.java @@ -21,6 +21,10 @@ public class Context { return classes.get(identifier); } + public HashMap getClasses() { + return classes; + } + public boolean containsClass(String identifier) { return classes.containsKey(identifier); } diff --git a/src/test/resources/input/typedAstExceptionsTests/ClassNotDeclared.java b/src/test/resources/input/typedAstExceptionsTests/ClassNotDeclared.java new file mode 100644 index 0000000..6e2b81e --- /dev/null +++ b/src/test/resources/input/typedAstExceptionsTests/ClassNotDeclared.java @@ -0,0 +1,12 @@ +// @expected: NotDeclaredException +public class Test { + + public House1 h; + + +} + +public class House { + + +} diff --git a/src/test/resources/input/typedAstFeaturesTests/ChainedMethods.java b/src/test/resources/input/typedAstFeaturesTests/ChainedMethods.java new file mode 100644 index 0000000..7156569 --- /dev/null +++ b/src/test/resources/input/typedAstFeaturesTests/ChainedMethods.java @@ -0,0 +1,29 @@ +public class Test { + + public House h; + + public int test(House h){ + return h.getW().getSize(); + } + + +} + +public class House { + + private Window w; + + public Window getW(){ + return w; + } + +} + +public class Window{ + + private int size; + + public int getSize() { + return size; + } +} \ No newline at end of file diff --git a/src/test/resources/input/typedAstFeaturesTests/CorrectTest.java b/src/test/resources/input/typedAstFeaturesTests/CorrectTest.java index 5ef0b26..09585f9 100644 --- a/src/test/resources/input/typedAstFeaturesTests/CorrectTest.java +++ b/src/test/resources/input/typedAstFeaturesTests/CorrectTest.java @@ -1,38 +1,24 @@ -public class AllFeaturesClassExample { - int a; - boolean b; - char c; +public class Test { - public void controlStructures(int adf, boolean bool) { - if (a > (10 + 8)) { + public Car c; + + public int test(boolean b, int x) { + if (b == true) { + return c.getSpeed(); } else { + return x; } - - - 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 Car { + + private int speed; + + public int getSpeed() { + return speed; + } + +} +