/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 * 
 * File:   dfa.h
 * Author: pgess  <v.melnychenko@xreate.org>
 *
 * Created on June 27, 2016, 1:50 PM
 */

#ifndef DFA_H
#define DFA_H

#include "transcendlayer.h"
#include <unordered_set>

namespace xreate { namespace latereasoning {
    typedef std::pair<std::string, SymbolPacked> LateParameter;
}}

namespace xreate {namespace dfa {
   
enum DFACallInstanceType {
    STRONG, WEAK
};
 
class DFACallInstance {
public:
    std::string fnName;
    std::vector<std::pair<SymbolPacked, SymbolNode>> args;
    SymbolNode retActual;
    DFACallInstanceType type;

    void print(std::ostringstream& output) const;
};

/** \brief Represents DFA Analysis report produced by DFAPass */
class DFAGraph : public IAnalysisReport {
public:
    // DFAGraph(TranscendLayer* engine): __transcend(engine){}
    virtual void print(std::ostringstream& output) const override;
    void addCallInstance(DFACallInstance && instance);
    void addDependency(const SymbolNode& node, const SymbolNode& subnodeBlock);
    void printInplaceAnnotation(const SymbolNode& node, const Expression& expression);
    void printLateAnnotation(const SymbolNode& node, const Expression& expression, 
                            const std::list<latereasoning::LateParameter>& symbols,
                            const std::list<std::string>& domains);
    void printAlias(const SymbolNode& symbFormal, const SymbolNode& symbActual);
    void printWeakAlias(const SymbolNode& symbFormal, const SymbolNode& symbActual);
    void printFunctionRet(ManagedFnPtr function, const SymbolNode& symbolRet);
    void printDependencies(std::ostringstream& output) const;
    void printSymbols(TranscendLayer* transcend);
    void printOperator(Operator, std::list<SymbolNode>&& operands, int dataOpListSize = 0);

private:
    mutable std::ostringstream __output;
    std::list<DFACallInstance> __callInstances;
    std::unordered_multimap<SymbolNode, SymbolNode> __dependencies;
    std::unordered_set<SymbolNode> __usedSymbols;
    std::unordered_set<SymbolNode> __roots;

    void printDependency(std::ostringstream& output, const SymbolNode& nodeCurrent, const SymbolNode& nodeDependent) const;
};
}} // end of namespace xreate::dfa

#endif /* DFA_H */
