#pragma once

#include "dvm.h"
#include "../DirectiveProcessing/directive_parser.h"
#include "CFGraph/CFGraph.h"
#include "CFGraph/RD_subst.h"

// Regime defines the regime of private removing
enum class Regime { DEFLT = 1, REGULAR_INDEXES };

// PrivateToRemove represents private variable of loop, that can be removed
// by substitution of its definition statements (DEF) into usage statements (USE).
// fixedDimensions is used for comparison of DEF and USE statements
struct PrivateToRemove {
    LoopGraph* loop;
    SgSymbol* varSymbol;
    Regime regime;
    std::vector<std::pair<SgAssignStmt*, SgStatement*>> defUseStmtsPairs;
    std::vector<bool> fixedDimensions;
};

// removePrivates removes all privates from vector privatesToRemoveGloval
// and add info messages
void removePrivates(std::string filename, std::vector<Messages>& messages,
                    const std::map<std::string, CommonBlock*>& commonBlocks,
                    const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo,
                    int& countOfTransform);

// removePrivatesAnalysis checks all private variables in loopGraphs specified by usersDirectives
// if they can be removed, and adds those that can to vector privatesToRemoveGloval.
// if private var cannot be removed, the error message is returned with vector messages
void removePrivatesAnalysis(std::string filename, 
                            std::vector<LoopGraph*>& loopGraphs,
                            std::vector<Messages>& messages,
                            const std::map<std::pair<std::string, int>, std::set<SgStatement*>>& usersDirectives,
                            const std::map<std::string, CommonBlock*>& commonBlocks, 
                            const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo);
