Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/ipc/ipdl/ipdl/cxx/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 6 kB image not shown  

Quellcode-Bibliothek code.py   Sprache: Python

 
# 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/.

# This module contains functionality for adding formatted, opaque "code" blocks
# into the IPDL ast. These code objects follow IPDL C++ ast patterns, and
# perform lowering in much the same way.

# In general it is recommended to use these for blocks of code which would
# otherwise be specified by building a hardcoded IPDL-C++ AST, as users of this
# API are often easier to read than users of the AST APIs in these cases.

import re
import math
import textwrap

from ipdl.cxx.ast import Node, Whitespace, GroupNode, VerbatimNode


# -----------------------------------------------------------------------------
# Public API.


def StmtCode(tmpl, **kwargs):
    """Perform template substitution to build opaque C++ AST nodes. See the
    module documentation for more information on the templating syntax.

    StmtCode nodes should be used where Stmt* nodes are used. They are placed
    on their own line and indented."""
    return _code(tmpl, False, kwargs)


def ExprCode(tmpl, **kwargs):
    """Perform template substitution to build opaque C++ AST nodes. See the
    module documentation for more information on the templating syntax.

    ExprCode nodes should be used where Expr* nodes are used. They are placed
    inline, and no trailing newline is added."""
    return _code(tmpl, True, kwargs)


def StmtVerbatim(text):
    """Build an opaque C++ AST node which emits input text verbatim.

    StmtVerbatim nodes should be used where Stmt* nodes are used. They are placed
    on their own line and indented."""
    return _verbatim(text, False)


def ExprVerbatim(text):
    """Build an opaque C++ AST node which emits input text verbatim.

    ExprVerbatim nodes should be used where Expr* nodes are used. They are
    placed inline, and no trailing newline is added."""
    return _verbatim(text, True)


# -----------------------------------------------------------------------------
# Implementation


def _code(tmpl, inline, context):
    # Remove common indentation, and strip the preceding newline from
    # '''-quoting, because we usually don't want it.
    if tmpl.startswith("\n"):
        tmpl = tmpl[1:]
    tmpl = textwrap.dedent(tmpl)

    # Process each line in turn, building up a list of nodes.
    nodes = []
    for idx, line in enumerate(tmpl.splitlines()):
        # Place newline tokens between lines in the input.
        if idx > 0:
            nodes.append(Whitespace.NL)

        # Don't indent the first line if `inline` is set.
        skip_indent = inline and idx == 0
        nodes.append(_line(line.rstrip(), skip_indent, idx + 1, context))

    # If we're inline, don't add the final trailing newline.
    if not inline:
        nodes.append(Whitespace.NL)
    return GroupNode(nodes)


def _verbatim(text, inline):
    # For simplicitly, _verbatim is implemented using the same logic as _code,
    # but with '$' characters escaped. This ensures we only need to worry about
    # a single, albeit complex, codepath.
    return _code(text.replace("$""$$"), inline, {})


# Pattern used to identify substitutions.
_substPat = re.compile(
    r"""
    \$(?:
        (?P<escaped>\$)                  | # '$$' is an escaped '$'
        (?P<list>[*,])?{(?P<expr>[^}]+)} | # ${expr}, $*{expr}, or $,{expr}
        (?P<invalid>)                      # For error reporting
    )
    """,
    re.IGNORECASE | re.VERBOSE,
)


def _line(raw, skip_indent, lineno, context):
    assert "\n" not in raw

    # Determine the level of indentation used for this line
    line = raw.lstrip()
    offset = int(math.ceil((len(raw) - len(line)) / 4))

    # If line starts with a directive, don't indent it.
    if line.startswith("#"):
        skip_indent = True

    column = 0
    children = []
    for match in _substPat.finditer(line):
        if match.group("invalid"is not None:
            raise ValueError("Invalid substitution on line %d" % lineno)

        # Any text from before the current entry should be written, and column
        # advanced.
        if match.start() > column:
            before = line[column : match.start()]
            children.append(VerbatimNode(before))
        column = match.end()

        # If we have an escaped group, emit a '$' node.
        if match.group("escaped"is not None:
            children.append(VerbatimNode("$"))
            continue

        # At this point we should have an expression.
        list_chr = match.group("list")
        expr = match.group("expr")
        assert expr is not None

        # Evaluate our expression in the context to get the values.
        try:
            values = eval(expr, context, {})
        except Exception as e:
            msg = "%s in substitution on line %d" % (repr(e), lineno)
            raise ValueError(msg) from e

        # If we aren't dealing with lists, wrap the result into a
        # single-element list.
        if list_chr is None:
            values = [values]

        # Check if this substitution is inline, or the entire line.
        inline = match.span() != (0, len(line))

        for idx, value in enumerate(values):
            # When using `,` as a list mode in a non-inline environment, put
            # each expression on its own line.
            multiline_list = list_chr == "," and not inline

            # If we're using ',' as list mode, put a comma between each node.
            if idx > 0 and list_chr == ",":
                children.append(VerbatimNode(",\n" if multiline_list else ", "))

            # Expr entries such as those used in multiline lists do not indent,
            # so add a node to handle indenting on each line.
            if multiline_list:
                children.append(VerbatimNode("", indent=True))

            # If our value isn't a node, turn it into one. Verbatim should be
            # inline unless indent isn't being skipped, and the match isn't
            # inline.
            if not isinstance(value, Node):
                value = _verbatim(str(value), skip_indent or inline)
            children.append(value)

        # If we were the entire line, indentation is handled by the added child
        # nodes. Do this after the above loop such that created verbatims have
        # the correct inline-ness.
        if not inline:
            skip_indent = True

    # Add any remaining text in the line.
    if len(line) > column:
        children.append(VerbatimNode(line[column:]))

    # If we have no children, just emit the empty string. This will become a
    # blank line.
    if len(children) == 0:
        return VerbatimNode("")

    # Add the initial indent if we aren't skipping it.
    if not skip_indent:
        children.insert(0, VerbatimNode("", indent=True))

    # Wrap ourselves into a group node with the correct indent offset
    return GroupNode(children, offset=offset)

Messung V0.5
C=73 H=89 G=81

¤ Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.0.12Bemerkung:  (vorverarbeitet)  ¤

*Bot Zugriff






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.