Skip to content

math_spec.expansion

Macro calls, expanded into the syntax tree before resolution reads it.

A named expression is resolution's: it resolves the entry once and puts that node where the name stood.

expand(node, ns, context) #

expand(
    node: ArithmeticNode, ns: Namespace, context: str
) -> ArithmeticNode
expand(
    node: ComparisonNode, ns: Namespace, context: str
) -> ComparisonNode

Expand every macro call under node; a comparison stays a comparison and arithmetic stays arithmetic.

PARAMETER DESCRIPTION
node

The parsed expression.

TYPE: ParsedNode

ns

Where the macros are declared.

TYPE: Namespace

context

What an error names.

TYPE: str

Source code in src/math_spec/expansion.py
def expand(node: ParsedNode, ns: Namespace, context: str) -> ParsedNode:
    """Expand every macro call under *node*; a comparison stays a comparison and arithmetic stays arithmetic.

    Args:
        node: The parsed expression.
        ns: Where the macros are declared.
        context: What an error names.
    """
    if isinstance(node, ComparisonNode):
        return ComparisonNode(node.op, _expand(node.left, ns, context, ()), _expand(node.right, ns, context, ()))
    return _expand(node, ns, context, ())

macro_signature(name, macro) #

Human-readable call signature, for error messages.

Source code in src/math_spec/expansion.py
def macro_signature(name: str, macro: MacroBlock) -> str:
    """Human-readable call signature, for error messages."""
    parts = [*macro.args, *(f'{k}=...' for k in macro.kwargs)]
    return f'{name}({", ".join(parts)})'

parse_and_expand(text, ns, context) #

Parse text and expand every macro call in it.

PARAMETER DESCRIPTION
text

The expression as the file wrote it.

TYPE: str

ns

Where the macros are declared.

TYPE: Namespace

context

What an error names.

TYPE: str

Source code in src/math_spec/expansion.py
def parse_and_expand(text: str, ns: Namespace, context: str) -> ParsedNode:
    """Parse *text* and expand every macro call in it.

    Args:
        text: The expression as the file wrote it.
        ns: Where the macros are declared.
        context: What an error names.
    """
    return expand(parse_expression(text), ns, context)

parse_template(name, macro, context) #

Parse a macro template, rejecting comparisons.

Source code in src/math_spec/expansion.py
def parse_template(name: str, macro: MacroBlock, context: str) -> ArithmeticNode:
    """Parse a macro template, rejecting comparisons."""
    body = parse_expression(macro.template)
    if isinstance(body, ComparisonNode):
        msg = f"{context}: macro '{name}' template must not contain a comparison operator. Got: {macro.template!r}"
        raise SchemaError(msg)
    return body