package org.nlamah.QL.TypeChecker;
import org.nlamah.QBase.Constants.QBaseQuestionType;
import org.nlamah.QBase.TypeChecker.QBaseAbstractTypeChecker;
import org.nlamah.QL.Error.IdentifierTypeMismatchError;
import org.nlamah.QL.Interfaces.QLNodeVisitor;
import org.nlamah.QL.Model.Form.Abstract.QLNode;
import org.nlamah.QL.Model.Expression.Binary.AddExpression;
import org.nlamah.QL.Model.Expression.Binary.AndExpression;
import org.nlamah.QL.Model.Expression.Binary.DivideExpression;
import org.nlamah.QL.Model.Expression.Binary.EqualExpression;
import org.nlamah.QL.Model.Expression.Binary.GreaterThanEqualExpression;
import org.nlamah.QL.Model.Expression.Binary.GreaterThanExpression;
import org.nlamah.QL.Model.Expression.Binary.MultiplyExpression;
import org.nlamah.QL.Model.Expression.Binary.OrExpression;
import org.nlamah.QL.Model.Expression.Binary.SmallerThanEqualExpression;
import org.nlamah.QL.Model.Expression.Binary.SmallerThanExpression;
import org.nlamah.QL.Model.Expression.Binary.SubtractExpression;
import org.nlamah.QL.Model.Expression.Binary.UnEqualExpression;
import org.nlamah.QL.Model.Expression.Literal.BooleanLiteral;
import org.nlamah.QL.Model.Expression.Literal.IdentifierLiteral;
import org.nlamah.QL.Model.Expression.Literal.NumberLiteral;
import org.nlamah.QL.Model.Expression.Literal.TextLiteral;
import org.nlamah.QL.Model.Expression.Unary.MinusExpression;
import org.nlamah.QL.Model.Expression.Unary.NotExpression;
import org.nlamah.QL.Model.Expression.Unary.PlusExpression;
import org.nlamah.QL.Model.Form.ComputedQuestion;
import org.nlamah.QL.Model.Form.ConditionalBlock;
import org.nlamah.QL.Model.Form.ElseIfThenBlock;
import org.nlamah.QL.Model.Form.ElseThenBlock;
import org.nlamah.QL.Model.Form.Form;
import org.nlamah.QL.Model.Form.IfThenBlock;
import org.nlamah.QL.Model.Form.InputQuestion;
public class IdentifierTypeChecker extends QBaseAbstractTypeChecker implements QLNodeVisitor
{
private QBaseQuestionType expectedIdentifierType;
private IdentifierLiteral identifier;
public IdentifierTypeChecker(IdentifierLiteral identifier)
{
this.identifier = identifier;
identifier.accept(this);
}
@Override
public QLNode visit(AddExpression expression)
{
expectedIdentifierType = QBaseQuestionType.NUMBER;
return null;
}
@Override
public QLNode visit(AndExpression expression)
{
expectedIdentifierType = QBaseQuestionType.BOOLEAN;
return null;
}
@Override
public QLNode visit(DivideExpression expression)
{
expectedIdentifierType = QBaseQuestionType.NUMBER;
return null;
}
@Override
public QLNode visit(EqualExpression expression)
{
if (identifier.equals(expression.leftHandExpression()) && (expression.rightHandExpression() instanceof IdentifierLiteral))
{
expectedIdentifierType = ((IdentifierLiteral) expression.rightHandExpression()).type();
}
else if (identifier.equals(expression.rightHandExpression()) && (expression.leftHandExpression() instanceof IdentifierLiteral))
{
expectedIdentifierType = ((IdentifierLiteral) expression.leftHandExpression()).type();
}
else if (identifier.equals(expression.leftHandExpression()))
{
expectedIdentifierType = expression.rightHandExpression().type();
}
else if (identifier.equals(expression.rightHandExpression()))
{
expectedIdentifierType = expression.leftHandExpression().type();
}
return null;
}
@Override
public QLNode visit(GreaterThanExpression expression)
{
expectedIdentifierType = QBaseQuestionType.NUMBER;
return null;
}
@Override
public QLNode visit(GreaterThanEqualExpression expression)
{
expectedIdentifierType = QBaseQuestionType.NUMBER;
return null;
}
@Override
public QLNode visit(MultiplyExpression expression)
{
expectedIdentifierType = QBaseQuestionType.NUMBER;
return null;
}
@Override
public QLNode visit(OrExpression expression)
{
expectedIdentifierType = QBaseQuestionType.NUMBER;
return null;
}
@Override
public QLNode visit(SmallerThanEqualExpression expression)
{
expectedIdentifierType = QBaseQuestionType.NUMBER;
return null;
}
@Override
public QLNode visit(SmallerThanExpression expression)
{
expectedIdentifierType = QBaseQuestionType.NUMBER;
return null;
}
@Override
public QLNode visit(SubtractExpression expression)
{
expectedIdentifierType = QBaseQuestionType.NUMBER;
return null;
}
@Override
public QLNode visit(UnEqualExpression expression)
{
if (identifier.equals(expression.leftHandExpression()) && (expression.rightHandExpression() instanceof IdentifierLiteral))
{
expectedIdentifierType = ((IdentifierLiteral) expression.rightHandExpression()).type();
}
else if (identifier.equals(expression.rightHandExpression()) && (expression.leftHandExpression() instanceof IdentifierLiteral))
{
expectedIdentifierType = ((IdentifierLiteral) expression.leftHandExpression()).type();
}
else if (identifier.equals(expression.leftHandExpression()))
{
expectedIdentifierType = expression.rightHandExpression().type();
}
else if (identifier.equals(expression.rightHandExpression()))
{
expectedIdentifierType = expression.leftHandExpression().type();
}
return null;
}
@Override
public QLNode visit(MinusExpression expression)
{
expectedIdentifierType = QBaseQuestionType.NUMBER;
return null;
}
@Override
public QLNode visit(NotExpression expression)
{
expectedIdentifierType = QBaseQuestionType.BOOLEAN;
return null;
}
@Override
public QLNode visit(PlusExpression expression)
{
expectedIdentifierType = QBaseQuestionType.NUMBER;
return null;
}
@Override
public QLNode visit(BooleanLiteral booleanLiteral)
{
assert(false);
return null;
}
@Override
public QLNode visit(IdentifierLiteral identifierLiteral)
{
identifierLiteral.parentNode().accept(this);
if (identifierLiteral.type() != expectedIdentifierType)
{
errors.add(new IdentifierTypeMismatchError(identifier));
}
expectedIdentifierType = identifierLiteral.type();
return null;
}
@Override
public QLNode visit(NumberLiteral numberLiteral)
{
assert(false);
return null;
}
@Override
public QLNode visit(TextLiteral textLiteral)
{
assert(false);
return null;
}
@Override
public QLNode visit(ConditionalBlock conditionalBlock)
{
assert(false);
return null;
}
@Override
public QLNode visit(ElseIfThenBlock elseIfThenBlock)
{
expectedIdentifierType = QBaseQuestionType.BOOLEAN;
return null;
}
@Override
public QLNode visit(ElseThenBlock elseThenBlock)
{
assert(false);
return null;
}
@Override
public QLNode visit(Form form)
{
assert(false);
return null;
}
@Override
public QLNode visit(IfThenBlock ifThenBlock)
{
expectedIdentifierType = QBaseQuestionType.BOOLEAN;
return null;
}
@Override
public QLNode visit(InputQuestion inputQuestion)
{
assert(false);
return null;
}
@Override
public QLNode visit(ComputedQuestion computedQuestion)
{
expectedIdentifierType = computedQuestion.returnType();
return null;
}
}