diff --git a/src/main/java/ast/members/ConstructorNode.java b/src/main/java/ast/members/ConstructorNode.java index 4e19933..2ff9f94 100644 --- a/src/main/java/ast/members/ConstructorNode.java +++ b/src/main/java/ast/members/ConstructorNode.java @@ -10,10 +10,14 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; -public class ConstructorNode extends MethodNode { +public class ConstructorNode extends MethodNode implements Visitable { + public AccessModifierNode accessType; + public String identifier; + public List parameters = new ArrayList<>(); + public BlockNode block; public ConstructorNode(String accessType, String identifier, BlockNode block) { - this.accesModifier = new AccessModifierNode(accessType); + this.accessType = new AccessModifierNode(accessType); this.identifier = identifier; this.block = block; } diff --git a/src/main/java/ast/members/MethodNode.java b/src/main/java/ast/members/MethodNode.java index 3661fb2..46a654d 100644 --- a/src/main/java/ast/members/MethodNode.java +++ b/src/main/java/ast/members/MethodNode.java @@ -17,7 +17,7 @@ public class MethodNode implements MemberNode, Visitable { public AccessModifierNode accesModifier; private ITypeNode type; public Boolean voidType; - protected String identifier; + private String identifier; public List parameters = new ArrayList<>(); public BlockNode block; diff --git a/src/main/java/bytecode/MethodCodeGen.java b/src/main/java/bytecode/MethodCodeGen.java index 02cf267..ab6e8e1 100644 --- a/src/main/java/bytecode/MethodCodeGen.java +++ b/src/main/java/bytecode/MethodCodeGen.java @@ -53,7 +53,7 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor { @Override public void visit(ConstructorNode constructorNode) { methodVisitor = - classWriter.visitMethod(mapper.mapAccessTypeToOpcode(constructorNode.accesModifier), + classWriter.visitMethod(mapper.mapAccessTypeToOpcode(constructorNode.accessType), "", mapper.generateMethodDescriptor(new BaseType(TypeEnum.VOID), constructorNode.parameters), null, diff --git a/src/main/java/semantic/Scope.java b/src/main/java/semantic/Scope.java index cde47c0..b6b40c4 100644 --- a/src/main/java/semantic/Scope.java +++ b/src/main/java/semantic/Scope.java @@ -16,7 +16,7 @@ public class Scope { public void addLocalVar(String name, ITypeNode type) { if (this.contains(name)) { - SemanticAnalyzer.errors.add(new AlreadyDeclaredException("Duplicate local variable " + name)); + throw new AlreadyDeclaredException("Variable " + name + " already exists in this scope"); } localVars.peek().put(name, type); } diff --git a/src/main/java/semantic/SemanticAnalyzer.java b/src/main/java/semantic/SemanticAnalyzer.java index 110effd..6ebd124 100644 --- a/src/main/java/semantic/SemanticAnalyzer.java +++ b/src/main/java/semantic/SemanticAnalyzer.java @@ -112,49 +112,53 @@ public class SemanticAnalyzer implements SemanticVisitor { @Override public TypeCheckResult analyze(MethodNode methodNode) { + if (methodNode instanceof ConstructorNode) { + return new TypeCheckResult(true, new BaseType(TypeEnum.VOID)); + } else { - var valid = true; + var valid = true; - for (var otherMethod : currentClass.getMethods()) { - if (Objects.equals(otherMethod, methodNode)) - break; - if (otherMethod.isSame(methodNode)) { - errors.add(new AlreadyDeclaredException( - "Method " + methodNode.getIdentifier() + " is already defined in class " - + currentClass.identifier)); - valid = false; + for (var otherMethod : currentClass.getMethods()) { + if (Objects.equals(otherMethod, methodNode)) + break; + if (otherMethod.isSame(methodNode)) { + errors.add(new AlreadyDeclaredException( + "Method " + methodNode.getIdentifier() + " is already defined in class " + + currentClass.identifier)); + valid = false; + } } - } - currentScope.pushScope(); - for (var parameter : methodNode.getParameters()) { - var result = parameter.accept(this); + currentScope.pushScope(); + for (var parameter : methodNode.getParameters()) { + var result = parameter.accept(this); + valid = valid && result.isValid(); + try { + currentScope.addLocalVar(parameter.identifier, parameter.type); + } catch (AlreadyDeclaredException e) { + errors.add(new AlreadyDeclaredException(parameter.identifier)); + } + + } + + currentMethodReturnType = methodNode.getType(); + currentNullType = currentMethodReturnType; + + var result = methodNode.block.accept(this); valid = valid && result.isValid(); - try { - currentScope.addLocalVar(parameter.identifier, parameter.type); - } catch (AlreadyDeclaredException e) { - errors.add(new AlreadyDeclaredException(parameter.identifier)); + currentScope.popScope(); + ITypeNode resultType = result.getType(); + + if (resultType == null) { + resultType = new BaseType(TypeEnum.VOID); + } + if (methodNode.getType() == null) { + methodNode.setType(new BaseType(TypeEnum.VOID)); } + return new TypeCheckResult(valid, resultType); + } - - currentMethodReturnType = methodNode.getType(); - currentNullType = currentMethodReturnType; - - var result = methodNode.block.accept(this); - valid = valid && result.isValid(); - currentScope.popScope(); - ITypeNode resultType = result.getType(); - - if (resultType == null) { - resultType = new BaseType(TypeEnum.VOID); - } - if (methodNode.getType() == null) { - methodNode.setType(new BaseType(TypeEnum.VOID)); - } - - return new TypeCheckResult(valid, resultType); - } @Override @@ -220,7 +224,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(); @@ -246,9 +250,6 @@ public class SemanticAnalyzer implements SemanticVisitor { if (currentFields.get(toCheck.identifier) != null) { var type = currentFields.get(toCheck.identifier); toCheck.setTypeNode(type); - MemberAccessNode memberAccessNode = new MemberAccessNode(false); - memberAccessNode.identifiers.add(currentClass.identifier); - toCheck.memberAccess = memberAccessNode; return new TypeCheckResult(true, type); } else if (currentScope.getLocalVar(toCheck.identifier) != null) { var type = currentScope.getLocalVar(toCheck.identifier); @@ -408,7 +409,6 @@ public class SemanticAnalyzer implements SemanticVisitor { case PLUS, MINUS: if (calcRes.getType() instanceof BaseType calcType && dotRes.getType() instanceof BaseType dotType && calcType.getTypeEnum().equals(TypeEnum.INT) && dotType.getTypeEnum().equals(TypeEnum.INT)) { - calcNode.setType(new BaseType(TypeEnum.INT)); return new TypeCheckResult(true, new BaseType(TypeEnum.INT)); } break; @@ -416,12 +416,10 @@ public class SemanticAnalyzer implements SemanticVisitor { } } else { - calcNode.setType(calcRes.getType()); return new TypeCheckResult(calcRes.isValid(), calcRes.getType()); } } else if (calcNode.dotExpression != null) { var dotRes = calcNode.dotExpression.accept(this); - calcNode.setType(dotRes.getType()); return new TypeCheckResult(dotRes.isValid(), dotRes.getType()); } return new TypeCheckResult(false, null); @@ -464,7 +462,6 @@ public class SemanticAnalyzer implements SemanticVisitor { 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)) { - nonCalculationNode.setType(new BaseType(TypeEnum.BOOL)); return new TypeCheckResult(true, new BaseType(TypeEnum.BOOL)); } else { errors.add(new TypeMismatchException("Both types must be Integer")); @@ -473,7 +470,6 @@ public class SemanticAnalyzer implements SemanticVisitor { case OR, AND: if (expResult.getType() instanceof BaseType expResultType && expResultType.getTypeEnum().equals(TypeEnum.INT) && unaryResult.getType() instanceof BaseType unaryResultType && unaryResultType.getTypeEnum().equals(TypeEnum.INT)) { - nonCalculationNode.setType(new BaseType(TypeEnum.BOOL)); return new TypeCheckResult(true, new BaseType(TypeEnum.BOOL)); } else { errors.add(new TypeMismatchException("Both types must be Boolean")); @@ -482,7 +478,6 @@ public class SemanticAnalyzer implements SemanticVisitor { case EQUAL, NOT_EQUAL: if (expResult.getType() instanceof BaseType expResultType && unaryResult.getType() instanceof BaseType unaryResultType && Objects.equals(expResultType, unaryResultType)) { - nonCalculationNode.setType(new BaseType(TypeEnum.BOOL)); return new TypeCheckResult(true, new BaseType(TypeEnum.BOOL)); } else { errors.add(new TypeMismatchException("Both types must be the same")); @@ -498,13 +493,9 @@ public class SemanticAnalyzer implements SemanticVisitor { if (unary.identifier != null) { if (currentScope.contains(unary.identifier)) { - var type = currentScope.getLocalVar(unary.identifier); - unary.setType(type); - return new TypeCheckResult(valid, type); + return new TypeCheckResult(valid, currentScope.getLocalVar(unary.identifier)); } else if (currentFields.get(unary.identifier) != null) { - var type = currentFields.get(unary.identifier); - unary.setType(type); - return new TypeCheckResult(valid, type); + return new TypeCheckResult(valid, currentFields.get(unary.identifier)); } else if (unary.statement != null) { var result = unary.statement.accept(this); unary.setType(result.getType()); @@ -514,19 +505,15 @@ public class SemanticAnalyzer implements SemanticVisitor { } } else if (unary.statement != null) { var result = unary.statement.accept(this); - unary.setType(result.getType()); return new TypeCheckResult(result.isValid(), result.getType()); } else if (unary.value != null) { var result = unary.value.accept(this); - unary.setType(result.getType()); return new TypeCheckResult(result.isValid(), result.getType()); } else if (unary.memberAccess != null) { var result = unary.memberAccess.accept(this); - unary.setType(result.getType()); return new TypeCheckResult(result.isValid(), result.getType()); } else if (unary.expression != null) { var result = unary.expression.accept(this); - unary.setType(result.getType()); return new TypeCheckResult(result.isValid(), result.getType()); } @@ -538,10 +525,6 @@ public class SemanticAnalyzer implements SemanticVisitor { ITypeNode currentType = null; - if (memberAccessNode.thisExpr) { - currentType = new ReferenceType(currentClass.identifier); - } - for (String s : memberAccessNode.identifiers) { if (currentType == null) { if (currentScope.getLocalVar(s) != null) { @@ -559,7 +542,7 @@ public class SemanticAnalyzer implements SemanticVisitor { var currentTypeClass = context.getClass(reference.getIdentifier()); var currentField = currentTypeClass.getField(s); - if (currentField.getAccessModifier().accessType == EnumAccessModifierNode.PUBLIC || memberAccessNode.thisExpr) { + if (currentField.getAccessModifier().accessType == EnumAccessModifierNode.PUBLIC) { currentType = currentField.getType(); } else { errors.add(new NotVisibleException("This field is not visible")); diff --git a/src/main/java/semantic/context/FieldContext.java b/src/main/java/semantic/context/FieldContext.java index 3869bb1..aba5ba0 100644 --- a/src/main/java/semantic/context/FieldContext.java +++ b/src/main/java/semantic/context/FieldContext.java @@ -4,15 +4,13 @@ import ast.members.FieldNode; import ast.type.*; import ast.type.type.*; -import java.util.Objects; - public class FieldContext { private AccessModifierNode accessModifier; private ITypeNode type; public FieldContext(FieldNode field) { - accessModifier = Objects.requireNonNullElseGet(field.accessTypeNode, () -> new AccessModifierNode("private")); + accessModifier = field.accessTypeNode; type = field.type; } diff --git a/src/test/resources/input/typedAstExceptionsTests/DuplicatedConstructor.java b/src/test/resources/input/typedAstExceptionsTests/DuplicatedConstructor.java deleted file mode 100644 index 3d877a3..0000000 --- a/src/test/resources/input/typedAstExceptionsTests/DuplicatedConstructor.java +++ /dev/null @@ -1,12 +0,0 @@ -// @expected: AlreadyDeclaredException -public class AllFeaturesClassExample { - - public AllFeaturesClassExample(boolean b){ - - } - - public AllFeaturesClassExample(boolean b){ - - } - -} diff --git a/src/test/resources/input/typedAstExceptionsTests/FieldOrParameterTypeMismatch.java b/src/test/resources/input/typedAstExceptionsTests/FieldOrParameterTypeMismatch.java deleted file mode 100644 index 0a9c17c..0000000 --- a/src/test/resources/input/typedAstExceptionsTests/FieldOrParameterTypeMismatch.java +++ /dev/null @@ -1,10 +0,0 @@ -// @expected: TypeMismatchException -public class AllFeaturesClassExample { - int x; - - public boolean test(boolean x){ - return this.x; - } - -} - diff --git a/src/test/resources/input/typedAstFeaturesTests/ConstructorOverloading.java b/src/test/resources/input/typedAstFeaturesTests/ConstructorOverloading.java deleted file mode 100644 index 1e0bc49..0000000 --- a/src/test/resources/input/typedAstFeaturesTests/ConstructorOverloading.java +++ /dev/null @@ -1,11 +0,0 @@ -public class AllFeaturesClassExample { - - public AllFeaturesClassExample(boolean b){ - - } - - public AllFeaturesClassExample(boolean b, int a){ - - } - -} diff --git a/src/test/resources/input/typedAstFeaturesTests/CorrectTest.java b/src/test/resources/input/typedAstFeaturesTests/CorrectTest.java index 4d27ecd..5ef0b26 100644 --- a/src/test/resources/input/typedAstFeaturesTests/CorrectTest.java +++ b/src/test/resources/input/typedAstFeaturesTests/CorrectTest.java @@ -1,10 +1,38 @@ - public class AllFeaturesClassExample { - int x; + 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++) { + } + - public void test(){ - x = 1; } -} +// 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(); +// } +}