Skip to main content

ScenarioNode

Enum ScenarioNode 

Source
pub enum ScenarioNode {
    Phase(String),
    Comprehension {
        comprehension: Comprehension,
        children: Vec<ScenarioNode>,
        continue_if: Option<ContinueIfSpec>,
        anchor: Option<String>,
    },
    DoWhile {
        condition: String,
        counter: Option<String>,
        children: Vec<ScenarioNode>,
    },
    DoUntil {
        condition: String,
        counter: Option<String>,
        children: Vec<ScenarioNode>,
    },
    IncludedScenario {
        name: String,
        children: Vec<ScenarioNode>,
    },
    Bindings {
        source: String,
        children: Vec<ScenarioNode>,
    },
}
Expand description

A node in a scenario execution tree.

Scenarios are trees of phases and control flow constructs. Nesting is supported to arbitrary depth. All nodes are evaluated dynamically at runtime — no pre-flattening.

cycle is immutable — loop constructs declare their own counter variables for iteration indices.

All iteration shapes (for_each single-clause, for_combinations, for_each_union) collapse into one Comprehension variant carrying the canonical polydat::iteration::comprehension::Comprehension AST — the operator-tree form of the algebra layer. The structural variant (Cartesian / Union / Clause / Zip) is the discriminator; Filter and Order wrap the body when the workload declares where / order. See SRD-18b §“Iteration as a First-Class Concept” and polydat/docs/design/comprehension_cutover_contact_surfaces.md.

Variants§

§

Phase(String)

A single phase to execute.

§

Comprehension

Iteration node — single-clause for_each, multi-clause for_combinations, or for_each_union all map here. The Comprehension AST captures the iteration shape; the runtime executes the cross-product of clauses for the Cartesian mode and the concatenation of sub-spaces’ products for Union mode.

YAML forms (all normalize to this variant):

# Single clause
- for_each: "k in 10,100"

# Multi-clause cross product
- for_each: "profile in profiles, k in {k_values}"

# Multi-clause cross product (map form)
- for_combinations:
    profile: "matching_profiles('{dataset}', '{prefix}')"
    k: "{k_values}"

# Union of sub-spaces
- for_each:
  - "k in 10, limit in 10,20,30"
  - "k in 100, limit in 100,200,300"

Fields

§comprehension: Comprehension
§children: Vec<ScenarioNode>
§continue_if: Option<ContinueIfSpec>

SRD-101 — optional continue_if pre-entry gate bounding this sweep: evaluated per iteration before the body; a false predicate halts the sweep at its each scope, gracefully.

§anchor: Option<String>

SRD-109 — table-row anchor: anchor: <view> declares one report-table row per iteration of this sweep, in the view of that name. Views sharing a name must share coordinate label sets. Key metrics designated on phases beneath this node attach to its rows.

§

DoWhile

Execute children while condition is true (test after).

Fields

§condition: String
§counter: Option<String>
§children: Vec<ScenarioNode>
§

DoUntil

Execute children until condition becomes true (test after).

Fields

§condition: String
§counter: Option<String>
§children: Vec<ScenarioNode>
§

IncludedScenario

Logical inclusion of another scenario by name.

Wherever this node appears (top-level of a scenario, inside a phases: list under a for_each / for_combinations / for_each_union, etc.), it expands to the children of the named scenario at execution time. The wrapper is preserved (not flattened) so the scope tree retains the include hierarchy and the renderer can show the operator which scenario each group of phases came from.

Resolution happens once after parsing (see crate::parse::resolve_scenario_includes); cycles (A includes B includes A) are rejected with a clear error naming the cycle path.

YAML form:

scenarios:
  smoke:
    - schema
    - rampup
  bench:
    - scenario: smoke
    - for_each: "k in 10,100"
      phases:
        - scenario: smoke
        - search

Fields

§name: String
§children: Vec<ScenarioNode>
§

Bindings

Scenario-tree-level Polydat bindings block — the canonical way to introduce a scope-local layer of bound names anywhere in the scenario tree.

source is Polydat matter text exactly as a phase-level bindings: block would contain. Anything the Polydat grammar accepts is valid: const NAME := <literal>, derived bindings (scaled := mul(workload_limit, 2)), shared cells, init bindings, etc. Workload-param {name} and string-interpolation references resolve through the scope chain at kernel build time — no separate preprocessing pass.

Bindings is also the canonical lowered form of set:. The parser recognizes set: { name: value, ... } as syntactic sugar and emits a Bindings node whose source is final <name> := <polydat-literal>\n (one line per pair, declaration order preserved). So

- set: { mode: verbose }
  phases:
    - announce

is semantically identical to

- bindings: |
    const mode := "verbose"
  phases:
    - announce

Both produce one Bindings node. Authors keep the short set: form for the common override case; the long form unlocks the full Polydat grammar (derived bindings, expressions referencing other in-scope names, etc.) without any new variant.

Lexical-shadow semantics are uniform with phase-level bindings:: a const NAME := <value> shadows any upstream binding for NAME over this node’s children subtree. The shadow is enforced via the local-final transit-suppression rule in materialize_wiring_from_outer — the same mechanism every other scope uses.

Composition example (two siblings, each defining its own value for the same name; the included subtree is physically cloned per include site so encapsulation is per-instance):

scenarios:
  fanout:
    - set: { mode: verbose }
      phases:
        - scenario: load_test
    - set: { mode: quiet }
      phases:
        - scenario: load_test

Fields

§source: String
§children: Vec<ScenarioNode>

Trait Implementations§

Source§

impl Clone for ScenarioNode

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ScenarioNode

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for ScenarioNode

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl HasPolydatMatter for ScenarioNode

Source§

fn polydat_matter(&self) -> PolydatMatter

Classify this node’s contribution to Polydat content.
Source§

impl Serialize for ScenarioNode

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.