added some Semantic Tests
Some checks are pending
Gitea Actions Demo / Explore-Gitea-Actions (push) Waiting to run

This commit is contained in:
Bruder John 2024-06-27 10:45:38 +02:00
parent 576146c4fc
commit 10eb17497e
17 changed files with 220 additions and 91 deletions

View File

@ -1,11 +1,14 @@
package ast.expressions.unaryexpressions;
import ast.ASTNode;
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<String> identifiers = new ArrayList<>();
@ -17,4 +20,9 @@ public class MemberAccessNode implements ASTNode {
identifiers.add(identifier);
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -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);
}
}

View File

@ -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,7 +22,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.EnumAccessModifierNode;
import ast.type.type.*;
import semantic.context.Context;
import semantic.exceptions.*;
@ -150,7 +153,7 @@ public class SemanticAnalyzer implements SemanticVisitor {
if (resultType == null) {
resultType = new BaseType(TypeEnum.VOID);
}
if(methodNode.getType() == null){
if (methodNode.getType() == null) {
methodNode.setType(new BaseType(TypeEnum.VOID));
}
if (!resultType.equals(methodNode.getType())) {
@ -185,7 +188,7 @@ public class SemanticAnalyzer implements SemanticVisitor {
if (toCheck.expression != null) {
var result = toCheck.expression.accept(this);
return new TypeCheckResult(true, result.getType());
} else if(toCheck.voidReturn){
} else if (toCheck.voidReturn) {
return new TypeCheckResult(false, new BaseType(TypeEnum.VOID));
}
return new TypeCheckResult(true, null);
@ -223,7 +226,7 @@ public class SemanticAnalyzer implements SemanticVisitor {
@Override
public TypeCheckResult analyze(AssignableNode toCheck) {
if ( currentFields.get(toCheck.identifier) != null){
if (currentFields.get(toCheck.identifier) != null) {
return new TypeCheckResult(true, currentFields.get(toCheck.identifier));
} else if (currentScope.getLocalVar(toCheck.identifier) != null) {
return new TypeCheckResult(true, currentScope.getLocalVar(toCheck.identifier));
@ -264,19 +267,16 @@ public class SemanticAnalyzer implements SemanticVisitor {
var rResult = rExpression.accept(this);
var variable = currentScope.getLocalVar(toCheck.assignable.identifier);
if(variable == null){
if (variable == null) {
variable = currentFields.get(toCheck.assignable.identifier);
}
if (!Objects.equals(variable, rExpression.getType())) {
if (!Objects.equals(variable, 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
@ -295,25 +295,43 @@ public class SemanticAnalyzer implements SemanticVisitor {
@Override
public TypeCheckResult analyze(MethodCallNode toCheck) {
var targetType = currentScope.getLocalVar(toCheck.target.identifier);
if(targetType == null){
targetType = currentFields.get(toCheck.target.identifier);
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) {
return new TypeCheckResult(true, getTypeFromMethod(toCheck, reference));
}
} else {
if(toCheck.target.thisTar){
return new TypeCheckResult(true, getTypeFromMethod(toCheck, new ReferenceType(currentClass.identifier)));
} else {
var result = toCheck.target.accept(this);
if (result.getType() instanceof ReferenceType reference) {
return new TypeCheckResult(true, getTypeFromMethod(toCheck, reference));
}
}
}
if(targetType instanceof ReferenceType reference){
var classContext = context.getClass(reference.getIdentifier());
return null;
}
if(classContext == null){
errors.add(new NotDefinedException(toCheck.target.identifier + "is not Defined"));
}else {
var methods = classContext.getMethods();
for (var method : methods) {
if(toCheck.identifier.equals(method.getIdentifier()) && method.getParameters().size() == toCheck.parameters.size()){
return new TypeCheckResult(true, method.getType());
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()) && method.getParameters().size() == toCheck.parameters.size()) {
if(method.accesModifier.accessType == EnumAccessModifierNode.PUBLIC){
return method.getType();
}else {
errors.add(new NotVisibleException("This Method is not Visible"));
}
}
}
} else {
}
return null;
}
@ -348,7 +366,7 @@ public class SemanticAnalyzer implements SemanticVisitor {
@Override
public TypeCheckResult analyze(NewDeclarationNode toCheck) {
if(context.containsClass(toCheck.identifier)) {
if (context.containsClass(toCheck.identifier)) {
return new TypeCheckResult(true, new ReferenceType(toCheck.identifier));
}
@ -404,6 +422,48 @@ public class SemanticAnalyzer implements SemanticVisitor {
errors.add(new NotDeclaredException("Var is not Declared"));
}
return new TypeCheckResult(valid, 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);
currentType = currentField.getType();
}
}
}
return new TypeCheckResult(true, currentType);
}
@Override
public TypeCheckResult analyze(TargetNode targetNode) {
if (targetNode.memberAccess != null) {
return targetNode.memberAccess.accept(this);
}
return null;
}
}

View File

@ -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,6 +12,7 @@ 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 typechecker.TypeCheckResult;
@ -38,8 +40,6 @@ public interface SemanticVisitor {
TypeCheckResult analyze(ElseNode toCheck);
//TypeCheckResult analyze(ForNode toCheck);
TypeCheckResult analyze(AssignNode toCheck);
TypeCheckResult analyze(DecrementNode toCheck);
@ -66,4 +66,8 @@ public interface SemanticVisitor {
TypeCheckResult analyze(UnaryNode toCheck);
TypeCheckResult analyze(MemberAccessNode toCheck);
TypeCheckResult analyze(TargetNode toCheck);
}

View File

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

View File

@ -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<String, Class<?>> 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()) {
@ -127,9 +153,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 +183,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.

View File

@ -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;
}
}

View File

@ -1,8 +0,0 @@
// @expected: TypeMismatchException
public class Example {
public static void testMethod(int x){
}
}

View File

@ -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;
}
}

View File

@ -1,41 +1,8 @@
public class Example {
public int a;
public Car c;
public void test(){
c = new Car();
int speed = c.getSpeed();
}
public static int testReturnMethod(int b, boolean bo){
a = b;
return a;
}
public void testOjektMethod(int testInt){
Test testClass = new Test();
int b = testClass.getFirstInt(testInt);
}
}
public class Test {
public int firstInt;
public int getFirstInt(int b){
return firstInt--;
}
}
public class Car{
private int speed;
public int getSpeed(){
public int getSpeed(boolean boo){
return speed;
}

View File

@ -0,0 +1,13 @@
public class Car{
private int speed;
public int getSpeed(){
return speed;
}
public int test(){
return this.getSpeed();
}
}