polydat_core/kernel/subcontext/name.rs
1// Copyright 2024-2026 Jonathan Shook
2// SPDX-License-Identifier: Apache-2.0
3
4//! [`ChildName`] — structured identifier for a spawned child.
5//!
6//! Each parent records the
7//! names it has spawned children under so duplicate spawn under
8//! the same name is caught at the API boundary. Names are
9//! `PathBuf`-shaped (hierarchical, comparable, debug-printable);
10//! the runtime constructs them from workload scope-tree node
11//! labels (phase / op-template / iteration coordinate). See
12//! subcontext_construction.md §4.1.
13
14use std::fmt;
15
16/// Hierarchical identifier for a spawned sub-context.
17///
18/// Internally a slash-separated string of segments. Constructors
19/// match common workload-tree shapes:
20///
21/// - [`ChildName::phase`] — `phase/<name>`
22/// - [`ChildName::op`] — `op/<name>`
23/// - [`ChildName::iteration`] — `iter/<coord>`
24/// - [`ChildName::compose`] — append a segment under a parent name
25///
26/// Two names compare equal when their segment vectors are equal.
27#[derive(Debug, Clone, PartialEq, Eq, Hash)]
28pub struct ChildName {
29 segments: Vec<String>,
30}
31
32impl ChildName {
33 /// Create from raw segments. Used by tests / advanced callers
34 /// that have a pre-built path; production code prefers the
35 /// shape-specific constructors below.
36 pub fn from_segments<I, S>(segments: I) -> Self
37 where
38 I: IntoIterator<Item = S>,
39 S: Into<String>,
40 {
41 Self {
42 segments: segments.into_iter().map(Into::into).collect(),
43 }
44 }
45
46 /// `phase/<name>` — for a workload phase scope.
47 pub fn phase(name: impl Into<String>) -> Self {
48 Self {
49 segments: vec!["phase".into(), name.into()],
50 }
51 }
52
53 /// `op/<name>` — for an op-template scope under a phase.
54 pub fn op(name: impl Into<String>) -> Self {
55 Self {
56 segments: vec!["op".into(), name.into()],
57 }
58 }
59
60 /// `iter/<coord>` — for one iteration of a comprehension scope.
61 /// `coord` is the coordinate-tuple debug rendering used by the
62 /// scope-tree pre-walk.
63 pub fn iteration(coord: impl Into<String>) -> Self {
64 Self {
65 segments: vec!["iter".into(), coord.into()],
66 }
67 }
68
69 /// Compose: append `segment` to `parent_name`'s path.
70 pub fn compose(parent_name: &ChildName, segment: impl Into<String>) -> Self {
71 let mut segments = parent_name.segments.clone();
72 segments.push(segment.into());
73 Self { segments }
74 }
75
76 /// Borrow the segment list.
77 pub fn segments(&self) -> &[String] {
78 &self.segments
79 }
80
81 /// Render as a slash-joined path for diagnostics.
82 pub fn display(&self) -> String {
83 self.segments.join("/")
84 }
85}
86
87impl fmt::Display for ChildName {
88 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89 f.write_str(&self.display())
90 }
91}