// Data Flow Graph determination pass

#ifndef DFGPASS_H
#define DFGPASS_H

#include "abstractpass.h"
#include "analysis/dfagraph.h"

namespace xreate {

class ClaspLayer;

class DFAPass : public AbstractPass<xreate::analysis::SymbolNode> {
public:
    xreate::analysis::SymbolNode process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl="") override;
    xreate::analysis::SymbolNode process(const Expression& expression, PassContext context, const std::string& varDecl="") override;

    DFAPass(PassManager* manager);

    void init();
    void run();
    void finish();
    
private:
    struct 
    {
      xreate::analysis::DFAGraph* graph;
    } __context;
    
    struct ExpressionCache{
        std::vector<xreate::analysis::SymbolNode> operands;
        std::vector<xreate::analysis::SymbolNode> blocks;
        xreate::analysis::SymbolNode result;
    };

    std::map<Operator, Expression> __signatures;		//DFA data for particular operators
    ClaspLayer* clasp;
    
    void processCompoundOp(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& varDecl="");
    void processElementaryOp(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& varDecl="");
    
    void applyDependencies(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl);
    void applyInPlaceAnnotations(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl);
    void applySignatureAnnotations(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl);
    void applyStaticAnnotations(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl);
};
};

#endif
