<commit_before>﻿from collections import defaultdict
from .block import CompositBlock
from .ir import *
from .env import env
from . import utils
from logging import getLogger
logger = getLogger(__name__)


class DFNode(object):
    def __init__(self, typ, tag):
        self.typ = typ  # 'Stm', 'Loop', 'Block'
        self.tag = tag
        self.priority = -1  # 0 is highest priority
        self.begin = -1
        self.end = -1
        if typ == 'Stm':
            self.stm_index = tag.block.stms.index(tag)
        else:
            self.stm_index = 0
        self.instance_num = 0
        self.uses = []
        self.defs = []

    def __str__(self):
        if self.typ == 'Stm':
            s = 'Node {} {} {}:{} {} {}'.format(
                hex(self.__hash__())[-4:],
                self.priority,
                self.begin,
                self.end,
                self.tag,
                self.tag.block.name
            )
        elif self.typ == 'Loop':
            s = 'Node {} {} {}:{} Loop {}'.format(
                hex(self.__hash__())[-4:],
                self.priority,
                self.begin,
                self.end,
                self.tag.name
            )
        elif self.typ == 'Block':
            s = 'Node {} {} {}:{} Block'.format(
                hex(self.__hash__())[-4:],
                self.priority,
                self.begin,
                self.end
            )
        else:
            assert False
        return s

    def __repr__(self):
        return str(self)

    def __lt__(self, other):
        if self.priority == other.priority:
            return self.begin < other.begin
        return self.priority < other.priority

    def latency(self):
        return self.end - self.begin


class DataFlowGraph(object):
    def __init__(self, name, main_block, blocks):
        self.name = name
        self.main_block = main_block
        self.blocks = blocks
        self.nodes = []
        self.edges = {}
        self.succ_edges = defaultdict(set)
        self.pred_edges = defaultdict(set)
        self.src_nodes = set()
        self.parent = None
        self.children = []
        self.synth_params = main_block.synth_params

    def __str__(self):
        s = 'DFG all nodes ==============\n'
        sources = self.find_src()
        for n in sorted(self.traverse_nodes(self.succs, sources, [])):
            s += '  ' + str(n)
            s += '\n'
        s += 'DFG all edges ==============\n'
        for (n1, n2), (typ, back) in self.edges.items():
            back_edge = "(back) " if back else ''
            if typ == 'DefUse':
                prefix1 = 'def '
                prefix2 = '  -> use '
            elif typ == 'UseDef':
                prefix1 = 'use '
                prefix2 = '  -> def '
            elif typ == 'Seq':
                prefix1 = 'pred '
                prefix2 = '  -> succ '
            else:
                prefix1 = 'sync '
                prefix2 = '<- -> '
            s += '{}{} {}\n'.format(back_edge, prefix1, n1)
            s += '{}{} {}\n'.format(back_edge, prefix2, n2)
        return s

    def set_child(self, child):
        self.children.append(child)
        child.parent = self

    def add_stm_node(self, stm):
        n = self.find_node(stm)
        if not n:
            n = DFNode('Stm', stm)
            self.nodes.append(n)
        return n

    def remove_node(self, n):
        self.nodes.remove(n)

    def add_defuse_edge(self, n1, n2):
        self.add_edge('DefUse', n1, n2)

    def add_usedef_edge(self, n1, n2):
        self.add_edge('UseDef', n1, n2)

    def add_seq_edge(self, n1, n2):
        assert n1 and n2 and n1.tag and n2.tag
        assert n1 is not n2
        if (n1, n2) not in self.edges:
            self.edges[(n1, n2)] = ('Seq', False)
            edge = (n1, n2, 'Seq', False)
            self.succ_edges[n1].add(edge)
            self.pred_edges[n2].add(edge)

    def add_edge(self, typ, n1, n2):
        assert n1 and n2 and n1.tag and n2.tag
        assert n1 is not n2
        back = self._is_back_edge(n1, n2)
        if (n1, n2) not in self.edges:
            self.edges[(n1, n2)] = (typ, back)
            edge = (n1, n2, typ, back)
            self.succ_edges[n1].add(edge)
            self.pred_edges[n2].add(edge)
        else:
            _typ, _back = self.edges[(n1, n2)]
            assert back is _back
            if typ == _typ or _typ == 'DefUse':
                return
            if typ == 'DefUse':
                self.edges[(n1, n2)] = (typ, back)

    def remove_edge(self, n1, n2):
        typ, back = self.edges[n1, n2]
        del self.edges[(n1, n2)]
        edge = (n1, n2, typ, back)<commit_msg>Fix dataflow<commit_after>﻿from collections import defaultdict
from .block import CompositBlock
from .ir import *
from .env import env
from . import utils
from logging import getLogger
logger = getLogger(__name__)


class DFNode(object):
    def __init__(self, typ, tag):
        self.typ = typ  # 'Stm', 'Loop', 'Block'
        self.tag = tag
        self.priority = -1  # 0 is highest priority
        self.begin = -1
        self.end = -1
        if typ == 'Stm':
            self.stm_index = tag.block.stms.index(tag)
        else:
            self.stm_index = 0
        self.instance_num = 0
        self.uses = []
        self.defs = []

    def __str__(self):
        if self.typ == 'Stm':
            s = 'Node {} {} {}:{} {} {}'.format(
                hex(self.__hash__())[-4:],
                self.priority,
                self.begin,
                self.end,
                self.tag,
                self.tag.block.name
            )
        elif self.typ == 'Loop':
            s = 'Node {} {} {}:{} Loop {}'.format(
                hex(self.__hash__())[-4:],
                self.priority,
                self.begin,
                self.end,
                self.tag.name
            )
        elif self.typ == 'Block':
            s = 'Node {} {} {}:{} Block'.format(
                hex(self.__hash__())[-4:],
                self.priority,
                self.begin,
                self.end
            )
        else:
            assert False
        return s

    def __repr__(self):
        return str(self)

    def __lt__(self, other):
        if self.priority == other.priority:
            return self.begin < other.begin
        return self.priority < other.priority

    def latency(self):
        return self.end - self.begin


class DataFlowGraph(object):
    def __init__(self, name, main_block, blocks):
        self.name = name
        self.main_block = main_block
        self.blocks = blocks
        self.nodes = []
        self.edges = {}
        self.succ_edges = defaultdict(set)
        self.pred_edges = defaultdict(set)
        self.src_nodes = set()
        self.parent = None
        self.children = []
        self.synth_params = main_block.synth_params

    def __str__(self):
        s = 'DFG all nodes ==============\n'
        sources = self.find_src()
        for n in sorted(self.traverse_nodes(self.succs, sources, [])):
            s += '  ' + str(n)
            s += '\n'
        s += 'DFG all edges ==============\n'
        for (n1, n2), (typ, back) in self.edges.items():
            back_edge = "(back) " if back else ''
            if typ == 'DefUse':
                prefix1 = 'def '
                prefix2 = '  -> use '
            elif typ == 'UseDef':
                prefix1 = 'use '
                prefix2 = '  -> def '
            elif typ == 'Seq':
                prefix1 = 'pred '
                prefix2 = '  -> succ '
            else:
                prefix1 = 'sync '
                prefix2 = '<- -> '
            s += '{}{} {}\n'.format(back_edge, prefix1, n1)
            s += '{}{} {}\n'.format(back_edge, prefix2, n2)
        return s

    def set_child(self, child):
        self.children.append(child)
        child.parent = self

    def add_stm_node(self, stm):
        n = self.find_node(stm)
        if not n:
            n = DFNode('Stm', stm)
            self.nodes.append(n)
        return n

    def remove_node(self, n):
        self.nodes.remove(n)

    def add_defuse_edge(self, n1, n2):
        self.add_edge('DefUse', n1, n2)

    def add_usedef_edge(self, n1, n2):
        self.add_edge('UseDef', n1, n2)

    def add_seq_edge(self, n1, n2):
        assert n1 and n2 and n1.tag and n2.tag
        assert n1 is not n2
        if (n1, n2) not in self.edges:
            self._add_edge(n1, n2, 'Seq', False)
        else:
            _typ, _ = self.edges[(n1, n2)]
            if _typ != 'DefUse':
                # overwrite if existing edge type is 'UseDef'
                self._add_edge(n1, n2, 'Seq', False)

    def add_edge(self, typ, n1, n2):
        assert n1 and n2 and n1.tag and n2.tag
        assert n1 is not n2
        back = self._is_back_edge(n1, n2)
        if (n1, n2) not in self.edges:
            self._add_edge(n1, n2, typ, back)
        else:
            _typ, _back = self.edges[(n1, n2)]
            assert back is _back
            if typ == _typ or _typ == 'DefUse':
                return
            if typ == 'DefUse':
                self._add_edge(n1, n2, typ, back)

    def _add_edge(self, n1, n2, typ, back):
        self.edges[(n1, n2)] = (typ, back)
        edge = (n1, n2, typ, back)
        self.succ_edges[n1].add(edge)
        self.pred_edges[n2].add(edge)

    def remove_edge(self, n1, n2):
        typ, back = self.edges[n1, n2]
        del self.edges[(n1, n2)]
        edge = (n1, n2, typ, back)
{'fraction_non_alphanumeric': 0.13498478009866693, 'fraction_numerical': 0.01658444421118925, 'mean_word_length': 1.4569365652398143, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6487376', 'n_tokens_mistral': 3116, 'n_tokens_neox': 3011, 'n_words': 753}