diff --git a/cmake/Assertion.cmake b/cmake/Assertion.cmake index dfff286..797ac48 100644 --- a/cmake/Assertion.cmake +++ b/cmake/Assertion.cmake @@ -144,63 +144,143 @@ endmacro() # Asserts whether the given condition is true. # -# This function performs an assertion on the given condition. It will output a -# fatal error message if the assertion fails. +# Arguments: +# - ARG0: The first argument. +macro(_assert_internal_assert_1 ARG0) + if("${ARG0}" STREQUAL NOT) + # Do nothing on an empty condition. + else() + if(NOT "${ARG0}") + message(FATAL_ERROR "expected '${ARG0}' to resolve to true") + endif() + endif() +endmacro() + +# Asserts whether the given condition is false. # -# Refer to the documentation of the 'if' function for supported conditions to -# perform the assertion. -function(assert) - list(LENGTH ARGN ARGUMENTS_LENGTH) - if(ARGUMENTS_LENGTH GREATER 0) - set(ARGUMENTS ${ARGN}) +# Arguments: +# - ARG0: The first argument. +macro(_assert_internal_assert_1_not ARG0) + if("${ARG0}") + message(FATAL_ERROR "expected '${ARG0}' to resolve to false") + endif() +endmacro() - # Determines whether the given arguments start with 'NOT'. - list(GET ARGUMENTS 0 ARGUMENTS_0) - if(ARGUMENTS_0 STREQUAL NOT) - list(REMOVE_AT ARGUMENTS 0) - set(HAS_NOT TRUE) - set(WITH_NOT _not) +# Asserts whether the given unary condition is true. +# +# Arguments: +# - ARG0: The first argument. +# - ARG1: The second argument. +macro(_assert_internal_assert_2 ARG0 ARG1) + if("${ARG0}" STREQUAL NOT) + _assert_internal_assert_1_not("${ARG1}") + else() + string(TOLOWER "${ARG0}" OPERATOR) + if(COMMAND "_assert_internal_assert_2_${OPERATOR}") + cmake_language( + CALL "_assert_internal_assert_2_${OPERATOR}" "${ARG1}" + ) else() - set(HAS_NOT FALSE) - set(WITH_NOT "") + message(FATAL_ERROR "unsupported condition: ${ARG0} ${ARG1}") endif() + endif() +endmacro() - list(LENGTH ARGUMENTS ARGUMENTS_LENGTH) - if(ARGUMENTS_LENGTH EQUAL 0) - # Do nothing on an empty condition. - elseif(ARGUMENTS_LENGTH EQUAL 1) - list(GET ARGUMENTS 0 VALUE) - if(HAS_NOT AND "${VALUE}") - message(FATAL_ERROR "expected '${VALUE}' to resolve to false") - elseif(NOT HAS_NOT AND NOT "${VALUE}") - message(FATAL_ERROR "expected '${VALUE}' to resolve to true") - endif() - elseif(ARGUMENTS_LENGTH EQUAL 2) - list(GET ARGUMENTS 0 OPERATOR) - string(TOLOWER "${OPERATOR}" OPERATOR) - if(COMMAND "_assert_internal_assert_2${WITH_NOT}_${OPERATOR}") - list(GET ARGUMENTS 1 VALUE) - cmake_language(CALL "_assert_internal_assert_2${WITH_NOT}_${OPERATOR}" "${VALUE}") - else() - string(REPLACE ";" " " ARGUMENTS "${ARGUMENTS}") - message(FATAL_ERROR "unsupported condition: ${ARGUMENTS}") - endif() - elseif(ARGUMENTS_LENGTH EQUAL 3) - list(GET ARGUMENTS 1 OPERATOR) - string(TOLOWER "${OPERATOR}" OPERATOR) - if(COMMAND "_assert_internal_assert_3${WITH_NOT}_${OPERATOR}") - list(GET ARGUMENTS 0 LEFT_VALUE) - list(GET ARGUMENTS 2 RIGHT_VALUE) - cmake_language(CALL "_assert_internal_assert_3${WITH_NOT}_${OPERATOR}" "${LEFT_VALUE}" "${RIGHT_VALUE}") - else() - string(REPLACE ";" " " ARGUMENTS "${ARGUMENTS}") - message(FATAL_ERROR "unsupported condition: ${ARGUMENTS}") - endif() - elseif(ARGUMENTS_LENGTH GREATER 1) - string(REPLACE ";" " " ARGUMENTS "${ARGUMENTS}") - message(FATAL_ERROR "unsupported condition: ${ARGUMENTS}") +# Asserts whether the given unary condition is false. +# +# Arguments: +# - ARG0: The first argument. +# - ARG1: The second argument. +macro(_assert_internal_assert_2_not ARG0 ARG1) + string(TOLOWER "${ARG0}" OPERATOR) + if(COMMAND "_assert_internal_assert_2_not_${OPERATOR}") + cmake_language( + CALL "_assert_internal_assert_2_not_${OPERATOR}" "${ARG1}" + ) + else() + message(FATAL_ERROR "unsupported condition: ${ARG0} ${ARG1}") + endif() +endmacro() + +# Asserts whether the given binary condition is true. +# +# Arguments: +# - ARG0: The first argument. +# - ARG1: The second argument. +# - ARG2: The third argument. +macro(_assert_internal_assert_3 ARG0 ARG1 ARG2) + if("${ARG0}" STREQUAL NOT) + _assert_internal_assert_2_not("${ARG1}" "${ARG2}") + else() + string(TOLOWER "${ARG1}" OPERATOR) + if(COMMAND "_assert_internal_assert_3_${OPERATOR}") + cmake_language( + CALL "_assert_internal_assert_3_${OPERATOR}" "${ARG0}" "${ARG2}" + ) + else() + message(FATAL_ERROR "unsupported condition: ${ARG0} ${ARG1} ${ARG2}") endif() endif() +endmacro() + +# Asserts whether the given binary condition is false. +# +# Arguments: +# - ARG0: The first argument. +# - ARG1: The second argument. +# - ARG2: The third argument. +macro(_assert_internal_assert_3_not ARG0 ARG1 ARG2) + string(TOLOWER "${ARG1}" OPERATOR) + if(COMMAND "_assert_internal_assert_3_not_${OPERATOR}") + cmake_language( + CALL "_assert_internal_assert_3_not_${OPERATOR}" "${ARG0}" "${ARG2}" + ) + else() + message(FATAL_ERROR "unsupported condition: ${ARG0} ${ARG1} ${ARG2}") + endif() +endmacro() + +# Asserts whether the given condition is true. +# +# Arguments: +# - ARG0: The first argument. +# - ARG1: The second argument. +# - ARG2: The third argument. +# - ARG3: The fourth argument. +macro(_assert_internal_assert_4 ARG0 ARG1 ARG2 ARG3) + if("${ARG0}" STREQUAL NOT) + _assert_internal_assert_3_not("${ARG1}" "${ARG2}" "${ARG3}") + else() + message(FATAL_ERROR "unsupported condition: ${ARG0} ${ARG1} ${ARG2} ${ARG3}") + endif() +endmacro() + +# Asserts the given condition. +# +# This function performs an assertion on the given condition. It will output a +# fatal error message if the assertion fails. +# +# Refer to the documentation of the 'if' function for supported conditions to +# perform the assertion. +function(assert) + if(ARGC EQUAL 0) + # Do nothing on an empty condition. + elseif(ARGC EQUAL 1) + _assert_internal_assert_1("${ARGV0}") + elseif(ARGC EQUAL 2) + _assert_internal_assert_2("${ARGV0}" "${ARGV1}") + elseif(ARGC EQUAL 3) + _assert_internal_assert_3("${ARGV0}" "${ARGV1}" "${ARGV2}") + elseif(ARGC EQUAL 4) + _assert_internal_assert_4("${ARGV0}" "${ARGV1}" "${ARGV2}" "${ARGV3}") + else() + set(ARGS "${ARGV0} ${ARGV1} ${ARGV2} ${ARGV3}") + math(EXPR STOP "${ARGC} - 1") + foreach(I RANGE 4 STOP) + set(ARGS "${ARGS} ${ARGV${I}}") + endforeach() + message(FATAL_ERROR "unsupported condition: ${ARGS}") + endif() endfunction() # Begins a scope for mocking the 'message' function.