Example #1
0
    def _loop_range(
            itervar: str, inedges: List[gr.Edge],
            condition: sp.Expr) -> Optional[Tuple[sp.Expr, sp.Expr, sp.Expr]]:
        """
        Finds loop range from state machine.
        :param itersym: String representing the iteration variable.
        :param inedges: Incoming edges into guard state (length must be 2).
        :param condition: Condition as sympy expression.
        :return: A three-tuple of (start, end, stride) expressions, or None if
                 proper for-loop was not detected. ``end`` is inclusive.
        """
        # Find starting expression and stride
        itersym = symbolic.symbol(itervar)
        if (itersym in symbolic.pystr_to_symbolic(
                inedges[0].data.assignments[itervar]).free_symbols
                and itersym not in symbolic.pystr_to_symbolic(
                    inedges[1].data.assignments[itervar]).free_symbols):
            stride = (symbolic.pystr_to_symbolic(
                inedges[0].data.assignments[itervar]) - itersym)
            start = symbolic.pystr_to_symbolic(
                inedges[1].data.assignments[itervar])
        elif (itersym in symbolic.pystr_to_symbolic(
                inedges[1].data.assignments[itervar]).free_symbols
              and itersym not in symbolic.pystr_to_symbolic(
                  inedges[0].data.assignments[itervar]).free_symbols):
            stride = (symbolic.pystr_to_symbolic(
                inedges[1].data.assignments[itervar]) - itersym)
            start = symbolic.pystr_to_symbolic(
                inedges[0].data.assignments[itervar])
        else:
            return None

        # Find condition by matching expressions
        end: Optional[sp.Expr] = None
        a = sp.Wild('a')
        match = condition.match(itersym < a)
        if match:
            end = match[a] - 1
        if end is None:
            match = condition.match(itersym <= a)
            if match:
                end = match[a]
        if end is None:
            match = condition.match(itersym > a)
            if match:
                end = match[a] + 1
        if end is None:
            match = condition.match(itersym >= a)
            if match:
                end = match[a]

        if end is None:  # No match found
            return None

        return start, end, stride