Exemplo n.º 1
0
def _(rep: FixedStitchRepeat, unroll: bool = False) -> Node:
    # Cases where the only node a fixed stitch repeat contains is another fixed
    # stitch repeat should be flattened by multiplying the repeat times
    # together.
    if (rep.times.value != 1 and len(rep.stitches) == 1
            and isinstance(rep.stitches[0], FixedStitchRepeat)):
        first = rep.stitches[0]
        assert isinstance(first, FixedStitchRepeat)
        # noinspection PyTypeChecker
        return ast_map(
            replace(rep,
                    stitches=first.stitches,
                    times=NaturalLit.of(first.times.value * rep.times.value),
                    consumes=first.consumes * rep.times.value,
                    produces=first.produces * rep.times.value),
            partial(_flatten, unroll=unroll))
    else:
        stitches = []
        # noinspection PyTypeChecker
        for stitch in map(partial(_flatten, unroll=unroll), rep.stitches):
            if (isinstance(stitch, FixedStitchRepeat)
                    and stitch.times.value == 1):
                # Un-nest fixed stitch repeats that only repeat once.
                stitches.extend(stitch.stitches)
            else:
                stitches.append(stitch)
        return replace(rep, stitches=stitches)
Exemplo n.º 2
0
def reflect(node: Node) -> Node:
    """
    Reflects the AST horizontally.

    :param node: the AST to reflect
    :return: the reflected AST
    """
    return ast_map(node, reflect)
Exemplo n.º 3
0
def enclose(node: Node, env: Mapping[str, Node]) -> Node:
    """
    Encloses patterns in environment, in order to achieve lexical scoping.

    :param node: the AST node to enclose
    :param env: the environment that the pattern should form a closure with
    :return: an AST with environments baked into the patterns
    """
    # noinspection PyTypeChecker
    return ast_map(node, partial(enclose, env=env))
Exemplo n.º 4
0
def substitute(node: Node, env: Mapping[str, Node]) -> Node:
    """
    Substitutes all variables and calls in the AST with their equivalent
    expressions.

    :param node: the AST to transform
    :param env: the environment
    :return:
        the transformed expression with all variables and calls substituted out
    """
    # noinspection PyTypeChecker
    return ast_map(node, partial(substitute, env=env))
Exemplo n.º 5
0
def _alternate_sides(node: Node, side: Side = Side.Right) -> Node:
    """
    Ensures that every row alternates between right and wrong side, starting
    from the given side.

    :param node: the AST to alternate the sides of
    :param side: the side of the first row
    :return: (1) the AST with every row alternating sides, and
    (2) the side that the next row should be on
    """
    # noinspection PyTypeChecker
    return ast_map(node, partial(_alternate_sides, side=side))
Exemplo n.º 6
0
def _flatten(node: Node, unroll: bool = False) -> Node:
    """
    Flattens blocks, nested patterns, and nested fixed stitch repeats.

    :param node: the AST to transform
    :param unroll:
        whether to unroll row repeat expressions into a sequence of repeated
        rows
    :return: the flattened AST
    """
    # noinspection PyTypeChecker
    return ast_map(node, partial(_flatten, unroll=unroll))
Exemplo n.º 7
0
def infer_counts(node: Node, available: Optional[int] = None) -> Node:
    """
    Tries to count the number of stitches that each node consumes and produces.
    If not enough information is available for a particular node, its stitch
    counts are not updated.

    :param node: the AST to count stitches in
    :param available:
        the number of stitches remaining in the current row, if known
    :return:
        an AST with as many stitch counts (consumes and produces) as possible
        filled in
    """
    # noinspection PyTypeChecker
    return ast_map(node, partial(infer_counts, available=available))
Exemplo n.º 8
0
def _roll_repeated_rows(node: Node) -> Node:
    """
    Tries to find repeated sequences of rows to roll up into a row repeat.

    It uses a naive algorithm that can give weird output in cases where
    multiple overlapping sequences could be rolled up, but should work OK in
    most cases.

    **Note:** This ignores sides when comparing rows for equality (so RS: K and
    WS: K are considered equal), which mimics the way odd-numbered row repeats
    are knitted, but this means that :ref:`alternate_sides` must be run before
    this function.

    :param node: the AST to search for repeated rows
    :return: the AST with repeated rows rolled up
    """
    return ast_map(node, _roll_repeated_rows)
Exemplo n.º 9
0
 def all_to_rs(node: Node) -> Node:
     return ast_map(node, all_to_rs)
Exemplo n.º 10
0
def _combine_stitches(node: Node) -> Node:
    return ast_map(node, _combine_stitches)
Exemplo n.º 11
0
def _increase_expanding_repeats(node: Node, n: int) -> Node:
    # noinspection PyTypeChecker
    return ast_map(node, partial(_increase_expanding_repeats, n=n))
Exemplo n.º 12
0
def _repeat_across(node: Node, times: int) -> Node:
    # noinspection PyTypeChecker
    return ast_map(node, partial(_repeat_across, times=times))