/* 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:   temporalseqgraph.h
 * Author: pgess
 *
 * Created on February 4, 2019, 4:51 PM
 */

/**
 * \file temporalseqgraph.h
 * \brief Execution Order Graph representation
 */

#ifndef TEMPORALSEQGRAPH_H
#define TEMPORALSEQGRAPH_H

#include "transcendlayer.h"

namespace xreate{ namespace cfa{

enum TemporalOperator {SCOPE, EMPTY, AND, OR};

struct TemporalNode{
  ScopePacked scope;
  TemporalOperator mark;
  
  friend std::ostream& operator << (std::ostream& output, const TemporalNode& node);
  bool operator==(const TemporalNode& other) const 
    { return other.scope == scope && other.mark == mark; }
};

struct TemporalGuard{
  enum{IN, OUT} mark;
  unsigned int id;
};

typedef std::pair<TemporalNode, TemporalNode> Socket;

}} namespace std {

  bool operator<(const xreate::cfa::TemporalNode& x, const xreate::cfa::TemporalNode& y);
  
} namespace xreate {namespace cfa {

/**
 * \brief Execution order graph representation. Produced by CFATemporalSeqPass
 */
class TemporalSeqGraph: public IAnalysisReport{
  typedef boost::bimap<
  boost::bimaps::multiset_of<TemporalNode>,
  boost::bimaps::multiset_of<TemporalNode>> Graph;
  
public: 
  TemporalSeqGraph(TranscendLayer* transcend);
  
  void addSubScopes(const CodeScope*, const std::list<CodeScope*>&);
  void addBranchScopes(const CodeScope*, const std::list<CodeScope*>&);
  Socket addSocket(const CodeScope*, TemporalOperator mark);
  TemporalNode insertBefore(TemporalNode node, TemporalOperator mark);
  TemporalNode insertAfter(TemporalNode node, TemporalOperator mark);
  void connect(TemporalNode, TemporalNode);
  void connectGuarded(const Socket& from, const Socket& to);
  Socket getFnSocket(ManagedFnPtr calleeFn);
  Socket getUncertainFnSocket(const std::string& calleeName, const std::list<ManagedFnPtr>& candidates);
  
  bool isOrdered(const ScopePacked& scopeAfter, const ScopePacked& scopeBefore) const;
  bool isOrdered(const TemporalNode& nodeAfter, const TemporalNode& nodeBefore, std::set<TemporalNode>&) const;
  void print(std::ostringstream &output) const override;
  
private:
  Graph graph;
  std::multimap<TemporalNode, std::pair<TemporalNode, TemporalGuard>> graphGuarded;
  ScopePacked __idNextVacant = 0;
  unsigned int __guardNextVacant = 0;
  TranscendLayer* __transcend;
  std::map<ManagedFnPtr, Socket> __cacheFnSockets;
  std::map<std::string, Socket> __cacheUncertainFnSockets;
};
}
} //end of namespace xreate::cfa

#endif /* TEMPORALSEQGRAPH_H */

