#pragma once

extern int staticShadowAnalysis;
extern int staticPrivateAnalysis;
extern int keepDvmDirectives;
extern int keepSpfDirs;
extern int consoleMode;
extern int automaticDeprecateArrays;
extern int maxShadowWidth;
extern int langOfMessages;
extern bool removeNestedIntervals;
extern int sharedMemoryParallelization;
extern int parallizeFreeLoops;
extern int ignoreIO;
extern int parseForInlining;
extern bool ignoreArrayDistributeState;
extern bool fullDepGraph;

extern "C" int out_free_form;
extern "C" int out_upper_case;
extern "C" int out_line_unlimit;

enum passes {
    UNROLL_LOOPS, //ordinal == 0
    CONVERT_TO_ENDDO,
    CORRECT_CODE_STYLE,
    CORRECT_FORMAT_PLACE,
    CREATE_NESTED_LOOPS,
    REVERSE_CREATED_NESTED_LOOPS,
    UNPARSE_FILE,

    LOOP_ANALYZER_DATA_DIST_S0,
    LOOP_ANALYZER_DATA_DIST_S1,
    LOOP_ANALYZER_DATA_DIST_S2,
    LOOP_ANALYZER_COMP_DIST,
    LOOP_ANALYZER_ALIGNS,
    LOOP_ANALYZER_NODIST,
    CREATE_TEMPLATE_LINKS,
    CREATE_DISTR_DIRS,
    CREATE_PARALLEL_DIRS,
    INSERT_PARALLEL_DIRS,
    INSERT_PARALLEL_DIRS_NODIST,
    INSERT_SHADOW_DIRS,
    EXTRACT_SHADOW_DIRS,
    CREATE_REMOTES,
    REMOVE_AND_CALC_SHADOW,
    TRANSFORM_SHADOW_IF_FULL,

    CALL_GRAPH,
    CALL_GRAPH2,
    CALL_GRAPH_IR,
    LOOP_GRAPH,

    CODE_CHECKER_PASSES,
    VERIFY_ENDDO,
    VERIFY_INCLUDES,
    VERIFY_EQUIVALENCE,
    VERIFY_COMMON,
    VERIFY_FUNC_DECL,
    VERIFY_OPERATORS,
    VERIFY_FORMAT,
    PREPROC_SPF,
    EXTRACT_PARALLEL_DIRS,
    CORRECT_VAR_DECL,
    PREPROC_ALLOCATES,
    CHECK_FUNC_TO_INCLUDE,
    CHECK_ARGS_DECL,

    FIND_FUNC_TO_INCLUDE,
    ONLY_ARRAY_GRAPH,

    PRIVATE_ANALYSIS_SPF,
    PRIVATE_CALL_GRAPH_STAGE1,
    PRIVATE_CALL_GRAPH_STAGE2,
    PRIVATE_CALL_GRAPH_STAGE3,
    ARRAY_ACCESS_ANALYSIS_FOR_CORNER,

    FILL_PAR_REGIONS_LINES,
    FILL_PAR_REGIONS,
    PRINT_PAR_REGIONS_ERRORS,
    RESOLVE_PAR_REGIONS,
    EXPAND_EXTRACT_PAR_REGION,
    LOOP_DATA_DEPENDENCIES,
    INSERT_INCLUDES,
    REMOVE_DVM_DIRS,
    REMOVE_DVM_DIRS_TO_COMMENTS,
    REMOVE_SPF_DIRS,
    REMOVE_DVM_INTERVALS,
    VERIFY_DVM_DIRS,

    MERGE_REGIONS,

    REMOVE_DIST_ARRAYS_FROM_IO,

    SUBST_EXPR,
    SUBST_EXPR_RD,
    REVERT_SUBST_EXPR,
    REVERT_SUBST_EXPR_RD,
    SUBST_EXPR_AND_UNPARSE,
    SUBST_EXPR_RD_AND_UNPARSE,

    GET_ALL_ARRAY_DECL,
    FILE_LINE_INFO,
    BUILD_INCLUDE_DEPENDENCIES,

    MACRO_EXPANSION,
    SWAP_ARRAY_DIMENSION,

    CONVERT_ASSIGN_TO_LOOP,
    CONVERT_LOOP_TO_ASSIGN,
    RESTORE_LOOP_FROM_ASSIGN,
    RESTORE_LOOP_FROM_ASSIGN_BACK,

    FILL_COMMON_BLOCKS,
    PREDICT_SCHEME,
    CALCULATE_STATS_SCHEME,
    GET_STATS_FOR_PREDICTOR,

    DEF_USE_STAGE1,
    DEF_USE_STAGE2,
    REVERT_SPF_DIRS,
    CLEAR_SPF_DIRS,

    CREATE_INTER_TREE,
    INSERT_INTER_TREE,

    MOVE_OPERATORS,

    SHADOW_GROUPING,
    INLINE_PROCEDURES,
    FILL_PARALLEL_REG_IR,
    ADD_TEMPL_TO_USE_ONLY,
    GCOV_PARSER,
    PRIVATE_ARRAYS_EXPANSION,
    PRIVATE_ARRAYS_SHRINKING,
    PRIVATE_ARRAYS_SHRINKING_ANALYSIS,
    LOOPS_SPLITTER,
    LOOPS_COMBINER,
    CHECK_PAR_REG_DIR,
    INSERT_REGIONS,
    CREATE_PARALLEL_REGIONS,
    PRIVATE_REMOVING_ANALYSIS,
    PRIVATE_REMOVING,

    DUPLICATE_FUNCTIONS,
    REMOVE_COPIES,
    RESTORE_COPIES,
    SWAP_LOOPS,
    RESTORE_SWAP_LOOPS,

    PARSE_FILES,
    PPPA_ANALYZER,
    SET_TO_ALL_DECL_INIT_ZERO,
    DUMP_DECLS_WITH_INIT,
    
    CREATE_CHECKPOINTS,
    CONVERT_SAVE_TO_MODULE,
    PROCESS_IO,
    CONVERT_STRUCTURES_TO_SIMPLE,

    PURE_INTENT_INSERT,
    PURE_COMMON_TO_PARAMS,
    PURE_SAVE_TO_PARAMS,
    PURE_MODULE_TO_PARAMS,

    REMOVE_UNUSED_FUNCTIONS,
    GROUP_ACTUAL_AND_REMOTE,
    GROUP_ACTUAL_AND_REMOTE_RESTORE,

    RENAME_SYMBOLS,
    FIND_PARAMETERS,
    BUILD_IR,
    LIVE_ANALYSIS_IR,
    PRIVATE_ANALYSIS_IR,
    REMOVE_DEAD_CODE,
    REMOVE_DEAD_CODE_AND_UNPARSE,

    FIX_COMMON_BLOCKS,
    PARSE_OMP_DIRS,
    REMOVE_OMP_DIRS,
    REMOVE_OMP_DIRS_TRANSFORM,
    REMOVE_COMMENTS,
    GET_MIN_MAX_BLOCK_DIST,
    CONVERT_TO_C,
    INSERT_NO_DISTR_FLAGS_FROM_GUI,

    SET_IMPLICIT_NONE,
    RENAME_INLCUDES,

    FIND_PRIVATE_ARRAYS_ANALYSIS,
    FIND_PRIVATE_ARRAYS,

    TRANSFORM_ASSUMED_SIZE_PARAMETERS,
    ARRAY_PROPAGATION,
    ARRAY_PROPAGATION_RESTORE,

    TEST_PASS,
    EMPTY_PASS
};

enum algorithms {
    CREATE_DISTIBUTION,
    CREATE_ALIGNS,
    EMPTY_ALGO
};

enum options {
    STATIC_SHADOW_ANALYSIS,
    STATIC_PRIVATE_ANALYSIS,
    FREE_FORM,
    KEEP_DVM_DIRECTIVES,
    KEEP_SPF_DIRECTIVES,
    PARALLIZE_FREE_LOOPS, // deprecated
    MAX_SHADOW_WIDTH,
    OUTPUT_UPPER,
    TRANSLATE_MESSAGES,
    KEEP_LOOPS_CLOSE_NESTING,
    KEEP_GCOV,
    ANALYSIS_OPTIONS,
    DEBUG_PRINT_ON,
    SHARED_MEMORY,
    IGNORE_IO_SAPFOR,
    KEEP_SPF_DIRECTIVES_AMONG_TRANSFORMATIONS,
    PARSE_FOR_INLINE,
    EMPTY_OPTION
};

extern const char* passNames[EMPTY_PASS + 1];
extern const char* optionNames[EMPTY_OPTION + 1];

extern bool passNamesWasInit;
static void setPassValues()
{
    if (passNamesWasInit)
        return;

    passNamesWasInit = true;
    passNames[UNROLL_LOOPS] = "UNROLL_LOOPS";
    passNames[CONVERT_TO_ENDDO] = "CONVERT_TO_ENDDO";
    passNames[CORRECT_CODE_STYLE] = "CORRECT_CODE_STYLE";
    passNames[LOOP_ANALYZER_DATA_DIST_S0] = "LOOP_ANALYZER_DATA_DIST_S0";
    passNames[LOOP_ANALYZER_DATA_DIST_S1] = "LOOP_ANALYZER_DATA_DIST_S1";
    passNames[LOOP_ANALYZER_DATA_DIST_S2] = "LOOP_ANALYZER_DATA_DIST_S2";
    passNames[LOOP_ANALYZER_COMP_DIST] = "LOOP_ANALYZER_COMP_DIST";
    passNames[LOOP_ANALYZER_ALIGNS] = "LOOP_ANALYZER_ALIGNS";
    passNames[LOOP_ANALYZER_NODIST] = "LOOP_ANALYZER_NODIST";
    passNames[CALL_GRAPH] = "CALL_GRAPH";
    passNames[LOOP_GRAPH] = "LOOP_GRAPH";
    passNames[VERIFY_ENDDO] = "VERIFY_ENDDO";
    passNames[VERIFY_INCLUDES] = "VERIFY_INCLUDES";
    passNames[VERIFY_EQUIVALENCE] = "VERIFY_EQUIVALENCE";
    passNames[VERIFY_COMMON] = "VERIFY_COMMON";
    passNames[VERIFY_OPERATORS] = "VERIFY_OPERATORS";
    passNames[FIND_FUNC_TO_INCLUDE] = "FIND_FUNC_TO_INCLUDE";
    passNames[CREATE_DISTR_DIRS] = "CREATE_DISTR_DIRS";
    passNames[CREATE_PARALLEL_DIRS] = "CREATE_PARALLEL_DIRS";
    passNames[INSERT_PARALLEL_DIRS] = "INSERT_PARALLEL_DIRS";
    passNames[INSERT_PARALLEL_DIRS_NODIST] = "INSERT_PARALLEL_DIRS_NODIST";
    passNames[ONLY_ARRAY_GRAPH] = "ONLY_ARRAY_GRAPH";
    passNames[PREPROC_SPF] = "PREPROC_SPF";
    passNames[EXTRACT_PARALLEL_DIRS] = "EXTRACT_PARALLEL_DIRS";
    passNames[CORRECT_VAR_DECL] = "CORRECT_VAR_DECL";
    passNames[PREPROC_ALLOCATES] = "PREPROC_ALLOCATES";
    passNames[CREATE_REMOTES] = "CREATE_REMOTES";
    passNames[PRIVATE_ANALYSIS_SPF] = "PRIVATE_ANALYSIS_SPF";
    passNames[PRIVATE_CALL_GRAPH_STAGE1] = "PRIVATE_CALL_GRAPH_STAGE1";
    passNames[PRIVATE_CALL_GRAPH_STAGE2] = "PRIVATE_CALL_GRAPH_STAGE2";
    passNames[PRIVATE_CALL_GRAPH_STAGE3] = "PRIVATE_CALL_GRAPH_STAGE3";
    passNames[FILL_PAR_REGIONS_LINES] = "FILL_PAR_REGIONS_LINES";
    passNames[FILL_PAR_REGIONS] = "FILL_PAR_REGIONS";
    passNames[RESOLVE_PAR_REGIONS] = "RESOLVE_PAR_REGIONS";
    passNames[EXPAND_EXTRACT_PAR_REGION] = "EXPAND_EXTRACT_PAR_REGION";
    passNames[LOOP_DATA_DEPENDENCIES] = "LOOP_DATA_DEPENDENCIES";
    passNames[INSERT_INCLUDES] = "INSERT_INCLUDES";
    passNames[REMOVE_DVM_DIRS] = "REMOVE_DVM_DIRS";
    passNames[VERIFY_DVM_DIRS] = "VERIFY_DVM_DIRS";
    passNames[REMOVE_DVM_DIRS_TO_COMMENTS] = "REMOVE_DVM_DIRS_TO_COMMENTS";
    passNames[REMOVE_SPF_DIRS] = "REMOVE_SPF_DIRS";
    passNames[MERGE_REGIONS] = "MERGE_REGIONS";
    passNames[REMOVE_DIST_ARRAYS_FROM_IO] = "REMOVE_DIST_ARRAYS_FROM_IO";
    passNames[SUBST_EXPR] = "SUBST_EXPR";
    passNames[SUBST_EXPR_RD] = "SUBST_EXPR_RD";
    passNames[CALL_GRAPH2] = "CALL_GRAPH2";
    passNames[REVERT_SUBST_EXPR] = "REVERT_SUBST_EXPR";
    passNames[REVERT_SUBST_EXPR_RD] = "REVERT_SUBST_EXPR_RD";
    passNames[CREATE_NESTED_LOOPS] = "CREATE_NESTED_LOOPS";
    passNames[UNPARSE_FILE] = "UNPARSE_FILE";
    passNames[CREATE_TEMPLATE_LINKS] = "CREATE_TEMPLATE_LINKS";
    passNames[CODE_CHECKER_PASSES] = "CODE_CHECKER_PASSES";
    passNames[CHECK_FUNC_TO_INCLUDE] = "CHECK_FUNC_TO_INCLUDE";
    passNames[CHECK_ARGS_DECL] = "CHECK_ARGS_DECL";
    passNames[GET_ALL_ARRAY_DECL] = "GET_ALL_ARRAY_DECL";
    passNames[INSERT_SHADOW_DIRS] = "INSERT_SHADOW_DIRS";
    passNames[EXTRACT_SHADOW_DIRS] = "EXTRACT_SHADOW_DIRS";
    passNames[FILE_LINE_INFO] = "FILE_LINE_INFO";
    passNames[SUBST_EXPR_AND_UNPARSE] = "SUBST_EXPR_AND_UNPARSE";
    passNames[SUBST_EXPR_RD_AND_UNPARSE] = "SUBST_EXPR_RD_AND_UNPARSE";
    passNames[BUILD_INCLUDE_DEPENDENCIES] = "BUILD_INCLUDE_DEPENDENCIES";
    passNames[EMPTY_PASS] = "EMPTY_PASS";
    passNames[REMOVE_AND_CALC_SHADOW] = "REMOVE_AND_CALC_SHADOW";
    passNames[TRANSFORM_SHADOW_IF_FULL] = "TRANSFORM_SHADOW_IF_FULL";
    passNames[MACRO_EXPANSION] = "MACRO_EXPANSION";
    passNames[SWAP_ARRAY_DIMENSION] = "SWAP_ARRAY_DIMENSION";
    passNames[REVERSE_CREATED_NESTED_LOOPS] = "REVERSE_CREATED_NESTED_LOOPS";
    passNames[CONVERT_ASSIGN_TO_LOOP] = "CONVERT_ASSIGN_TO_LOOP";
    passNames[CONVERT_LOOP_TO_ASSIGN] = "CONVERT_LOOP_TO_ASSIGN";
    passNames[ARRAY_ACCESS_ANALYSIS_FOR_CORNER] = "ARRAY_ACCESS_ANALYSIS_FOR_CORNER";
    passNames[FILL_COMMON_BLOCKS] = "FILL_COMMON_BLOCKS";
    passNames[PREDICT_SCHEME] = "PREDICT_SCHEME";
    passNames[GET_STATS_FOR_PREDICTOR] = "GET_STATS_FOR_PREDICTOR";
    passNames[DEF_USE_STAGE1] = "DEF_USE_STAGE1";
    passNames[DEF_USE_STAGE2] = "DEF_USE_STAGE2";    
    passNames[REVERT_SPF_DIRS] = "REVERT_SPF_DIRS";
    passNames[CLEAR_SPF_DIRS] = "CLEAR_SPF_DIRS";
    passNames[INSERT_REGIONS] = "INSERT_REGIONS";
    passNames[RESTORE_LOOP_FROM_ASSIGN] = "RESTORE_LOOP_FROM_ASSIGN";
    passNames[RESTORE_LOOP_FROM_ASSIGN_BACK] = "RESTORE_LOOP_FROM_ASSIGN_BACK";
    passNames[INLINE_PROCEDURES] = "INLINE_PROCEDURES";
    passNames[SHADOW_GROUPING] = "SHADOW_GROUPING";
    passNames[PRINT_PAR_REGIONS_ERRORS] = "PRINT_PAR_REGIONS_ERRORS";
    passNames[FILL_PARALLEL_REG_IR] = "FILL_PARALLEL_REG_IR";
    passNames[ADD_TEMPL_TO_USE_ONLY] = "ADD_TEMPL_TO_USE_ONLY";
    passNames[GCOV_PARSER] = "GCOV_PARSER";
    passNames[PRIVATE_ARRAYS_EXPANSION] = "PRIVATE_ARRAYS_EXPANSION";
    passNames[LOOPS_SPLITTER] = "LOOPS_SPLITTER";
    passNames[LOOPS_COMBINER] = "LOOPS_COMBINER";
    passNames[CHECK_PAR_REG_DIR] = "CHECK_PAR_REG_DIR";
    passNames[CREATE_INTER_TREE] = "CREATE_INTER_TREE";
    passNames[INSERT_INTER_TREE] = "INSERT_INTER_TREE";
    passNames[MOVE_OPERATORS] = "MOVE_OPERATORS";
    passNames[CREATE_PARALLEL_REGIONS] = "CREATE_PARALLEL_REGIONS";
    passNames[PRIVATE_REMOVING_ANALYSIS] = "PRIVATE_REMOVING_ANALYSIS";
    passNames[PRIVATE_REMOVING] = "PRIVATE_REMOVING";
    passNames[CALCULATE_STATS_SCHEME] = "CALCULATE_STATS_SCHEME";
    passNames[REMOVE_DVM_INTERVALS] = "REMOVE_DVM_INTERVALS";
    passNames[VERIFY_FUNC_DECL] = "VERIFY_FUNC_DECL";
    passNames[DUPLICATE_FUNCTIONS] = "DUPLICATE_FUNCTIONS";
    passNames[REMOVE_COPIES] = "REMOVE_COPIES";
    passNames[RESTORE_COPIES] = "RESTORE_COPIES";
    passNames[SWAP_LOOPS] = "SWAP_LOOPS";
    passNames[RESTORE_SWAP_LOOPS] = "RESTORE_SWAP_LOOPS";
    passNames[PRIVATE_ARRAYS_SHRINKING] = "PRIVATE_ARRAYS_SHRINKING";
    passNames[PRIVATE_ARRAYS_SHRINKING_ANALYSIS] = "PRIVATE_ARRAYS_SHRINKING_ANALYSIS";
    passNames[PARSE_FILES] = "PARSE_FILES";
    passNames[PPPA_ANALYZER] = "PPPA_ANALYZER";
    passNames[SET_TO_ALL_DECL_INIT_ZERO] = "SET_TO_ALL_DECL_INIT_ZERO";
    passNames[DUMP_DECLS_WITH_INIT] = "DUMP_DECLS_WITH_INIT";    
    passNames[CREATE_CHECKPOINTS] = "CREATE_CHEKPOINTS";
    passNames[CONVERT_SAVE_TO_MODULE] = "CONVERT_SAVE_TO_MODULE";
    passNames[PROCESS_IO] = "PROCESS_IO";
    passNames[CONVERT_STRUCTURES_TO_SIMPLE] = "CONVERT_STRUCTURES_TO_SIMPLE";

    passNames[PURE_INTENT_INSERT] = "PURE_INTENT_INSERT";
    passNames[PURE_COMMON_TO_PARAMS] = "PURE_COMMON_TO_PARAMS";
    passNames[PURE_SAVE_TO_PARAMS] = "PURE_SAVE_TO_PARAMS";
    passNames[PURE_MODULE_TO_PARAMS] = "PURE_MODULE_TO_PARAMS";

    passNames[REMOVE_UNUSED_FUNCTIONS] = "REMOVE_UNUSED_FUNCTIONS";
    passNames[GROUP_ACTUAL_AND_REMOTE] = "GROUP_ACTUAL_AND_REMOTE";
    passNames[GROUP_ACTUAL_AND_REMOTE_RESTORE] = "GROUP_ACTUAL_AND_REMOTE_RESTORE";
    passNames[VERIFY_FORMAT] = "VERIFY_FORMAT";
    passNames[CORRECT_FORMAT_PLACE] = "CORRECT_FORMAT_PLACE";

    passNames[RENAME_SYMBOLS] = "RENAME_SYMBOLS";
    passNames[FIND_PARAMETERS] = "FIND_PARAMETERS";
    passNames[BUILD_IR] = "BUILD_IR";
    passNames[CALL_GRAPH_IR] = "CALL_GRAPH_IR";
    passNames[LIVE_ANALYSIS_IR] = "LIVE_ANALYSIS_IR";
    passNames[PRIVATE_ANALYSIS_IR] = "PRIVATE_ANALYSIS_IR";
    passNames[REMOVE_DEAD_CODE] = "REMOVE_DEAD_CODE";
    passNames[REMOVE_DEAD_CODE_AND_UNPARSE] = "REMOVE_DEAD_CODE_AND_UNPARSE";

    passNames[FIX_COMMON_BLOCKS] = "FIX_COMMON_BLOCKS";
    passNames[PARSE_OMP_DIRS] = "PARSE_OMP_DIRS";
    passNames[REMOVE_OMP_DIRS] = "REMOVE_OMP_DIRS";
    passNames[REMOVE_OMP_DIRS_TRANSFORM] = "REMOVE_OMP_DIRS_TRANSFORM";
    passNames[REMOVE_COMMENTS] = "REMOVE_COMMENTS";
    passNames[GET_MIN_MAX_BLOCK_DIST] = "GET_MIN_MAX_BLOCK_DIST";
    passNames[CONVERT_TO_C] = "CONVERT_TO_C";
    passNames[SET_IMPLICIT_NONE] = "SET_IMPLICIT_NONE";
    passNames[RENAME_INLCUDES] = "RENAME_INLCUDES";
    passNames[INSERT_NO_DISTR_FLAGS_FROM_GUI] = "INSERT_NO_DISTR_FLAGS_FROM_GUI";
    passNames[FIND_PRIVATE_ARRAYS_ANALYSIS] = "FIND_PRIVATE_ARRAYS_ANALYSIS";
    passNames[FIND_PRIVATE_ARRAYS] = "FIND_PRIVATE_ARRAYS";

    passNames[TRANSFORM_ASSUMED_SIZE_PARAMETERS] = "TRANSFORM_ASSUMED_SIZE_PARAMETERS";
    passNames[ARRAY_PROPAGATION] = "ARRAY_PROPAGATION";
    passNames[ARRAY_PROPAGATION_RESTORE] = "ARRAY_PROPAGATION_RESTORE";
    passNames[TEST_PASS] = "TEST_PASS";
}

static int getPassCode(const std::string& passName)
{
    for (int z = 0; z < EMPTY_PASS + 1; ++z)
        if (passNames[z] == passName)
            return z;
    return -1;
}
void runPass(const int curr_regime, const char *proj_name = "dvm.proj", const char *folderName = NULL, bool root_call = false);
