package org.uva.student.calinwouter.qlqls.ql.typechecker; import org.uva.student.calinwouter.qlqls.generated.analysis.AnalysisAdapter; import org.uva.student.calinwouter.qlqls.generated.node.*; import org.uva.student.calinwouter.qlqls.ql.interfaces.ITypeDescriptor; import org.uva.student.calinwouter.qlqls.ql.model.StaticFields; import org.uva.student.calinwouter.qlqls.ql.model.QLTypeCheckResults; import org.uva.student.calinwouter.qlqls.ql.types.BooleanValue; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import static org.uva.student.calinwouter.qlqls.ql.helper.ASTHelper.*; public class PStatementTypeChecker extends AnalysisAdapter { private final StaticFields staticFields; private final PExpressionTypeChecker pExpressionTypeChecker; private final Map<String, List<String>> variableDependencies; private final QLTypeCheckResults QLTypeCheckResults; private void typeCheckExpressionIsBoolean(PExpression ifExpression) { ifExpression.apply(pExpressionTypeChecker); pExpressionTypeChecker.checkLastEntryIsOfType(BooleanValue.BOOL_VALUE_TYPE_DESCRIPTOR); } private void typeCheckIfExpression(AIfStatement node) { final PExpression ifExpression = node.getExpression(); typeCheckExpressionIsBoolean(ifExpression); } private void typeCheckIfExpression(AIfElseStatement node) { final PExpression ifExpression = node.getExpression(); typeCheckExpressionIsBoolean(ifExpression); } @Override public void caseAIfStatement(final AIfStatement node) { typeCheckIfExpression(node); typeCheckThenStatements(node); } private void typeCheckStatement(PStatement node) { node.apply(this); } @Override public void caseAIfElseStatement(AIfElseStatement node) { typeCheckIfExpression(node); typeCheckThenStatements(node); typeCheckElseStatements(node); } private void typeCheckThenStatements(AIfStatement node) { for (PStatement thenStatement : node.getThenStatementList()) { typeCheckStatement(thenStatement); } } private void typeCheckThenStatements(AIfElseStatement node) { for (PStatement thenStatement : node.getThenStatementList()) { typeCheckStatement(thenStatement); } } private void typeCheckElseStatements(AIfElseStatement node) { for (PStatement elseStatement : node.getElseStatementList()) { typeCheckStatement(elseStatement); } } private ITypeDescriptor getTypeOfField(AValueStatement node) { final String identifier = getIdentifier(node); return staticFields.getTypeOfField(identifier); } private void processExpressionOf(AValueStatement node) { final PExpression expression = node.getExpression(); expression.apply(pExpressionTypeChecker); } private void checkExpressionIsOfType(AValueStatement node, ITypeDescriptor typeDescriptor) { processExpressionOf(node); pExpressionTypeChecker.checkLastEntryIsOfType(typeDescriptor); } private void checkCyclicDependency(String identifier){ for(String dependency: variableDependencies.get(identifier)){ if(variableDependencies.get(dependency) != null && variableDependencies.get(dependency).contains(identifier)) { QLTypeCheckResults.addCyclicDependencyError(identifier, dependency); } } } @Override public void caseAValueStatement(AValueStatement node) { final ITypeDescriptor typeDescriptor = getTypeOfField(node); final String identifier = getIdentifier(node); variableDependencies.put(identifier, new LinkedList<String>()); pExpressionTypeChecker.setLastComputedValueIdentifier(identifier); checkExpressionIsOfType(node, typeDescriptor); checkCyclicDependency(identifier); pExpressionTypeChecker.setLastComputedValueIdentifier(null); } public PStatementTypeChecker(StaticFields staticFields, QLTypeCheckResults QLTypeCheckResults) { this.staticFields = staticFields; this.QLTypeCheckResults = QLTypeCheckResults; variableDependencies = new HashMap<String, List<String>>(); this.pExpressionTypeChecker = new PExpressionTypeChecker(staticFields, QLTypeCheckResults, variableDependencies); } }