Turning stage declarations into one deterministic order (STG-1…STG-5).
Registration order is never an input. Neither is dict or set iteration order.
That is not fastidiousness: a stage program that depends on either produces a
different pipeline on a different Python run, and "it worked on my machine"
becomes an ordering bug nobody can reproduce.
order_stages
order_stages(descriptors: Sequence[StageDescriptor]) -> tuple[tuple[CompiledStage, ...], tuple[DiagnosticRecord, ...]]
Return the total stage order and the record of how it was decided.
Source code in src/symfonic/kernel/ordering.py
| def order_stages(
descriptors: Sequence[StageDescriptor],
) -> tuple[tuple[CompiledStage, ...], tuple[DiagnosticRecord, ...]]:
"""Return the total stage order and the record of how it was decided."""
by_id = _index(descriptors)
ordered: list[CompiledStage] = []
records: list[DiagnosticRecord] = []
for phase in PHASE_LADDER:
in_phase = sorted(
(d for d in descriptors if d.phase is phase),
key=lambda d: (d.priority, d.stage_id),
)
if not in_phase:
continue
edges = _edges(in_phase, by_id, dropped=records)
sequence = _topological(in_phase, edges)
for position, descriptor in enumerate(sequence):
previous = sequence[position - 1] if position else None
tie_break = _tie_break(previous, descriptor, edges)
ordered.append(
CompiledStage(
stage_id=descriptor.stage_id,
phase=descriptor.phase,
capability=descriptor.capability,
priority=descriptor.priority,
effects=descriptor.effects,
emits=descriptor.emits,
kind=descriptor.kind,
config=descriptor.frozen_config(),
tie_break=tie_break,
)
)
records.append(
DiagnosticRecord(
category="stage",
subject=descriptor.stage_id,
detail=(
f"phase={phase.value} position={position} "
f"capability={descriptor.capability} tie-break={tie_break}"
),
)
)
return tuple(ordered), tuple(records)
|