diff --git a/include/anthem/Arithmetics.h b/include/anthem/Arithmetics.h new file mode 100644 index 0000000..e867e73 --- /dev/null +++ b/include/anthem/Arithmetics.h @@ -0,0 +1,154 @@ +#ifndef __ANTHEM__ARITHMETICS_H +#define __ANTHEM__ARITHMETICS_H + +#include + +namespace anthem +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Arithmetics +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct DefaultVariableDomainAccessor +{ + ast::Domain operator()(const ast::Variable &variable) + { + return variable.declaration->domain; + } +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +EvaluationResult isArithmetic(const ast::Term &term, Arguments &&...); + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +struct IsTermArithmeticVisitor +{ + template + static EvaluationResult visit(const ast::BinaryOperation &binaryOperation, Arguments &&... arguments) + { + const auto isLeftArithemtic = isArithmetic(binaryOperation.left, std::forward(arguments)...); + const auto isRightArithmetic = isArithmetic(binaryOperation.right, std::forward(arguments)...); + + if (isLeftArithemtic == EvaluationResult::Error || isRightArithmetic == EvaluationResult::Error) + return EvaluationResult::Error; + + if (isLeftArithemtic == EvaluationResult::False || isRightArithmetic == EvaluationResult::False) + return EvaluationResult::Error; + + if (isLeftArithemtic == EvaluationResult::Unknown || isRightArithmetic == EvaluationResult::Unknown) + return EvaluationResult::Unknown; + + return EvaluationResult::True; + } + + template + static EvaluationResult visit(const ast::Boolean &, Arguments &&...) + { + return EvaluationResult::False; + } + + template + static EvaluationResult visit(const ast::Function &function, Arguments &&...) + { + switch (function.declaration->domain) + { + case ast::Domain::General: + return EvaluationResult::False; + case ast::Domain::Integer: + return EvaluationResult::True; + case ast::Domain::Unknown: + return EvaluationResult::Unknown; + } + + return EvaluationResult::Unknown; + } + + template + static EvaluationResult visit(const ast::Integer &, Arguments &&...) + { + return EvaluationResult::True; + } + + template + static EvaluationResult visit(const ast::Interval &interval, Arguments &&... arguments) + { + const auto isFromArithmetic = isArithmetic(interval.from, std::forward(arguments)...); + const auto isToArithmetic = isArithmetic(interval.to, std::forward(arguments)...); + + if (isFromArithmetic == EvaluationResult::Error || isToArithmetic == EvaluationResult::Error) + return EvaluationResult::Error; + + if (isFromArithmetic == EvaluationResult::False || isToArithmetic == EvaluationResult::False) + return EvaluationResult::Error; + + if (isFromArithmetic == EvaluationResult::Unknown || isToArithmetic == EvaluationResult::Unknown) + return EvaluationResult::Unknown; + + return EvaluationResult::True; + } + + template + static EvaluationResult visit(const ast::SpecialInteger &, Arguments &&...) + { + return EvaluationResult::False; + } + + template + static EvaluationResult visit(const ast::String &, Arguments &&...) + { + return EvaluationResult::False; + } + + template + static EvaluationResult visit(const ast::UnaryOperation &unaryOperation, Arguments &&... arguments) + { + const auto isArgumentArithmetic = isArithmetic(unaryOperation.argument, std::forward(arguments)...); + + switch (unaryOperation.operator_) + { + case ast::UnaryOperation::Operator::Absolute: + return (isArgumentArithmetic == EvaluationResult::False ? EvaluationResult::Error : isArgumentArithmetic); + } + + return EvaluationResult::Unknown; + } + + template + static EvaluationResult visit(const ast::Variable &variable, Arguments &&... arguments) + { + const auto domain = VariableDomainAccessor()(variable, std::forward(arguments)...); + + switch (domain) + { + case ast::Domain::General: + return EvaluationResult::False; + case ast::Domain::Integer: + return EvaluationResult::True; + case ast::Domain::Unknown: + return EvaluationResult::Unknown; + } + + return EvaluationResult::Unknown; + } +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +EvaluationResult isArithmetic(const ast::Term &term, Arguments &&... arguments) +{ + return term.accept(IsTermArithmeticVisitor(), std::forward(arguments)...); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +} + +#endif diff --git a/src/anthem/IntegerVariableDetection.cpp b/src/anthem/IntegerVariableDetection.cpp index efc411c..af4aa4b 100644 --- a/src/anthem/IntegerVariableDetection.cpp +++ b/src/anthem/IntegerVariableDetection.cpp @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -44,107 +45,11 @@ void clearVariableDomainMap(VariableDomainMap &variableDomainMap) //////////////////////////////////////////////////////////////////////////////////////////////////// -EvaluationResult isArithmetic(const ast::Term &term, VariableDomainMap &variableDomainMap); - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -struct IsTermArithmeticVisitor +struct VariableDomainMapAccessor { - static EvaluationResult visit(const ast::BinaryOperation &binaryOperation, VariableDomainMap &variableDomainMap) + ast::Domain operator()(const ast::Variable &variable, VariableDomainMap &variableDomainMap) { - const auto isLeftArithemtic = isArithmetic(binaryOperation.left, variableDomainMap); - const auto isRightArithmetic = isArithmetic(binaryOperation.right, variableDomainMap); - - if (isLeftArithemtic == EvaluationResult::Error || isRightArithmetic == EvaluationResult::Error) - return EvaluationResult::Error; - - if (isLeftArithemtic == EvaluationResult::False || isRightArithmetic == EvaluationResult::False) - return EvaluationResult::Error; - - if (isLeftArithemtic == EvaluationResult::Unknown || isRightArithmetic == EvaluationResult::Unknown) - return EvaluationResult::Unknown; - - return EvaluationResult::True; - } - - static EvaluationResult visit(const ast::Boolean &, VariableDomainMap &) - { - return EvaluationResult::False; - } - - static EvaluationResult visit(const ast::Function &function, VariableDomainMap &) - { - switch (function.declaration->domain) - { - case ast::Domain::General: - return EvaluationResult::False; - case ast::Domain::Integer: - return EvaluationResult::True; - case ast::Domain::Unknown: - return EvaluationResult::Unknown; - } - - return EvaluationResult::Unknown; - } - - static EvaluationResult visit(const ast::Integer &, VariableDomainMap &) - { - return EvaluationResult::True; - } - - static EvaluationResult visit(const ast::Interval &interval, VariableDomainMap &variableDomainMap) - { - const auto isFromArithmetic = isArithmetic(interval.from, variableDomainMap); - const auto isToArithmetic = isArithmetic(interval.to, variableDomainMap); - - if (isFromArithmetic == EvaluationResult::Error || isToArithmetic == EvaluationResult::Error) - return EvaluationResult::Error; - - if (isFromArithmetic == EvaluationResult::False || isToArithmetic == EvaluationResult::False) - return EvaluationResult::Error; - - if (isFromArithmetic == EvaluationResult::Unknown || isToArithmetic == EvaluationResult::Unknown) - return EvaluationResult::Unknown; - - return EvaluationResult::True; - } - - static EvaluationResult visit(const ast::SpecialInteger &, VariableDomainMap &) - { - return EvaluationResult::False; - } - - static EvaluationResult visit(const ast::String &, VariableDomainMap &) - { - return EvaluationResult::False; - } - - static EvaluationResult visit(const ast::UnaryOperation &unaryOperation, VariableDomainMap &variableDomainMap) - { - const auto isArgumentArithmetic = isArithmetic(unaryOperation.argument, variableDomainMap); - - switch (unaryOperation.operator_) - { - case ast::UnaryOperation::Operator::Absolute: - return (isArgumentArithmetic == EvaluationResult::False ? EvaluationResult::Error : isArgumentArithmetic); - } - - return EvaluationResult::Unknown; - } - - static EvaluationResult visit(const ast::Variable &variable, VariableDomainMap &variableDomainMap) - { - switch (domain(variable, variableDomainMap)) - { - case ast::Domain::General: - return EvaluationResult::False; - case ast::Domain::Integer: - return EvaluationResult::True; - case ast::Domain::Unknown: - return EvaluationResult::Unknown; - } - - return EvaluationResult::Unknown; + return domain(variable, variableDomainMap); } }; @@ -152,7 +57,7 @@ struct IsTermArithmeticVisitor EvaluationResult isArithmetic(const ast::Term &term, VariableDomainMap &variableDomainMap) { - return term.accept(IsTermArithmeticVisitor(), variableDomainMap); + return isArithmetic(term, variableDomainMap); } ////////////////////////////////////////////////////////////////////////////////////////////////////