Loading...
Searching...
No Matches
Conditional

Definition

Conditional support for the fpx preprocessor.

This module implements the complete conditional compilation machinery used by fpx. It provides functionality equivalent to the traditional C preprocessor directives while also introducing a few convenience extensions.

Supported directives include:

  • #if / #elif Evaluate arbitrary constant expressions using evaluate_expression().
  • #ifdef / #ifndef Test whether a macro has been defined.
  • #elifdef / #elifndef fpx extensions combining #elif semantics with macro existence tests.
  • #else Select the fallback branch when no previous branch in the same conditional group has been activated.
  • #endif Terminate the current conditional block.

Nested conditional blocks are supported up to MAX_COND_DEPTH levels.

The implementation follows the standard "first-match" semantics: once a branch of a conditional group evaluates to true, all remaining #elif, #elifdef, #elifndef, and #else directives belonging to the same group are ignored.

Internally, the module maintains a stack of conditional states (cond_stack) together with the current nesting depth (cond_depth). The helper function is_active() determines whether the current source line belongs to an active branch and therefore should be processed by the remainder of the preprocessor.

Design

Each active conditional nesting level stores two pieces of state:

  • active Indicates whether the current branch should emit code.
  • has_met Indicates whether a previous branch within the same #if/#elif/#else group has already been selected.

This design allows efficient evaluation of deeply nested conditionals while preserving correct first-match semantics.

Examples

  1. Include guard pattern:

    #ifndef MY_HEADER_H
    #define MY_HEADER_H
    ! Header contents
    #endif
  2. Feature selection using expression evaluation:

    #if DEBUG >= 2
    print *, 'Verbose debugging'
    #elif DEBUG == 1
    print *, 'Standard debugging'
    #else
    ! Silent mode
    #endif
  3. Platform-dependent compilation:

    #ifdef _OPENMP
    use omp_lib
    #else
    integer, parameter :: omp_get_thread_num = 0
    #endif
  4. Conditional compilation using macro existence:

    #if defined(USE_MPI) && (MPI_VERSION >= 3)
    use mpi_f08
    #endif
  5. Using the fpx extension #elifdef:

    #ifdef USE_CUDA
    call gpu_backend()
    #elifdef USE_OPENMP
    call omp_backend()
    #else
    call serial_backend()
    #endif
  6. Nested conditionals:

    #ifdef DEBUG
    #if DEBUG > 1
    print *, 'Extra diagnostics'
    #endif
    #endif

Data Types

type  cond_state
 State associated with a single conditional nesting level. More...

Variables

◆ cond_depth

integer, public cond_depth = 0

Current nesting depth of conditional directives (0 = outside any if).

Definition at line 176 of file conditional.f90.

◆ cond_stack

type(cond_state), dimension(max_cond_depth), public cond_stack

Global stack of conditional states (depth-limited).

Definition at line 172 of file conditional.f90.

Methods

◆ handle_elif()

subroutine, public handle_elif ( type(context), intent(in) ctx,
type(macro), dimension(:), intent(inout), allocatable macros,
character(*), intent(in) token )

Process elif - alternative branch after if/elif Only activates if no previous branch in the group was taken.

Parameters
[in]ctxContext source line containing the directive
[in,out]macrosCurrent macro table
[in]tokenUsually 'elif'

Definition at line 310 of file conditional.f90.

◆ handle_elifdef()

subroutine, public handle_elifdef ( type(context), intent(in) ctx,
type(macro), dimension(:), intent(in) macros,
character(*), intent(in) token )

Process elifdef - test if a macro is defined.

Parameters
[in]ctxContext source line containing the directive
[in]macrosCurrent macro table
[in]tokenUsually 'elifdef'

Definition at line 346 of file conditional.f90.

◆ handle_elifndef()

subroutine, public handle_elifndef ( type(context), intent(in) ctx,
type(macro), dimension(:), intent(in) macros,
character(*), intent(in) token )

Process elifndef - test if a macro is not defined.

Parameters
[in]ctxContext source line containing the directive
[in]macrosCurrent macro table
[in]tokenUsually 'elifndef'

Definition at line 382 of file conditional.f90.

◆ handle_else()

subroutine, public handle_else ( type(context), intent(in) ctx)

Process else - final fallback branch Activates only if no previous if/elif branch was true.

Parameters
[in]ctxContext (for error messages)

Definition at line 417 of file conditional.f90.

◆ handle_endif()

subroutine, public handle_endif ( type(context), intent(in) ctx)

Process endif - end of conditional block Pops the top state from the stack. Reports error on unmatched endif.

Parameters
[in]ctxContext (for error messages)

Definition at line 445 of file conditional.f90.

◆ handle_if()

subroutine, public handle_if ( type(context), intent(in) ctx,
type(macro), dimension(:), intent(inout), allocatable macros,
character(*), intent(in) token )

Process a if directive with constant expression evaluation Evaluates the expression after if using evaluate_expression() and pushes a new state onto the conditional stack.

Parameters
[in]ctxContext source line containing the directive
[in,out]macrosCurrent macro table
[in]tokenUsually 'if'

Definition at line 213 of file conditional.f90.

◆ handle_ifdef()

subroutine, public handle_ifdef ( type(context), intent(in) ctx,
type(macro), dimension(:), intent(in) macros,
character(*), intent(in) token )

Process ifdef - test if a macro is defined.

Parameters
[in]ctxContext source line containing the directive
[in]macrosCurrent macro table
[in]tokenUsually 'ifdef'

Definition at line 245 of file conditional.f90.

◆ handle_ifndef()

subroutine, public handle_ifndef ( type(context), intent(in) ctx,
type(macro), dimension(:), intent(in) macros,
character(*), intent(in) token )

Process ifndef - test if a macro is NOT defined.

Parameters
[in]ctxContext source line containing the directive
[in]macrosCurrent macro table
[in]tokenUsually 'ifndef'

Definition at line 277 of file conditional.f90.

◆ is_active()

logical function, public is_active

Determine whether the current source position is active.

Traverses all enclosing conditional levels and returns .true. only if every surrounding conditional branch is active.

This routine is used throughout the preprocessing pipeline to decide whether directives should be executed and whether ordinary source lines should be emitted.

Returns
.true. if the current line belongs to an active branch; .false. otherwise.

Definition at line 194 of file conditional.f90.