Skip to main content

refrain_core/
ast.rs

1//! Refrain AST.
2//!
3//! A `Refrain` is a named time-pattern with three structural stages —
4//! `territorialize`, `deterritorialize`, `reterritorialize` — each containing
5//! a `Pattern` tree built from primitive `Op` nodes.
6
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
10pub struct Refrain {
11    pub name: String,
12    pub territorialize: Option<Pattern>,
13    pub deterritorialize: Option<Pattern>,
14    pub reterritorialize: Option<Pattern>,
15}
16
17#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
18pub enum Pattern {
19    Op(Op),
20    Seq(Vec<Pattern>),
21}
22
23#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
24pub enum Op {
25    Note { pitch: String, dur: String },
26    Loop { count: u32, body: Box<Pattern> },
27    Diff { x: String, t: String },
28    Quotient { rels: Vec<String> },
29    Sym(String),
30    Call { head: String, args: Vec<Pattern> },
31}
32
33impl Refrain {
34    pub fn new(name: impl Into<String>) -> Self {
35        Self {
36            name: name.into(),
37            territorialize: None,
38            deterritorialize: None,
39            reterritorialize: None,
40        }
41    }
42
43    pub fn stages(&self) -> impl Iterator<Item = (StageKind, &Pattern)> {
44        let t = self
45            .territorialize
46            .as_ref()
47            .map(|p| (StageKind::Territorialize, p));
48        let d = self
49            .deterritorialize
50            .as_ref()
51            .map(|p| (StageKind::Deterritorialize, p));
52        let r = self
53            .reterritorialize
54            .as_ref()
55            .map(|p| (StageKind::Reterritorialize, p));
56        t.into_iter().chain(d).chain(r)
57    }
58}
59
60#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
61pub enum StageKind {
62    Territorialize,
63    Deterritorialize,
64    Reterritorialize,
65}
66
67impl StageKind {
68    pub fn as_str(self) -> &'static str {
69        match self {
70            StageKind::Territorialize => "territorialize",
71            StageKind::Deterritorialize => "deterritorialize",
72            StageKind::Reterritorialize => "reterritorialize",
73        }
74    }
75}