devalang_wasm/language/syntax/ast/nodes/
mod.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
5#[serde(tag = "type", content = "value")]
6pub enum DurationValue {
7    Number(f32),
8    Identifier(String),
9    Beat(String),
10    Beats(f32),
11    Milliseconds(f32),
12    Auto,
13}
14
15#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
16#[serde(tag = "type", content = "value")]
17pub enum Value {
18    Boolean(bool),
19    Number(f32),
20    Duration(DurationValue),
21    Identifier(String),
22    String(String),
23    Array(Vec<Value>),
24    Map(HashMap<String, Value>),
25    Block(Vec<Statement>),
26    Sample(String),
27    Beat(String),
28    Statement(Box<Statement>),
29    StatementKind(Box<StatementKind>),
30    Midi(String),
31    Range { start: Box<Value>, end: Box<Value> },
32    Unknown,
33    Null,
34}
35
36impl Default for Value {
37    fn default() -> Self {
38        Value::Null
39    }
40}
41
42impl Value {
43    pub fn get(&self, key: &str) -> Option<&Value> {
44        if let Value::Map(map) = self {
45            map.get(key)
46        } else {
47            None
48        }
49    }
50}
51
52#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
53#[serde(tag = "kind")]
54pub enum StatementKind {
55    Tempo,
56    Print,
57    Pattern {
58        name: String,
59        target: Option<String>,
60    },
61    Trigger {
62        entity: String,
63        duration: DurationValue,
64        effects: Option<Value>,
65    },
66    Sleep,
67    Call {
68        name: String,
69        args: Vec<Value>,
70    },
71    Load {
72        source: String,
73        alias: String,
74    },
75    Use {
76        name: String,
77        alias: Option<String>,
78    },
79    Automate {
80        target: String,
81    },
82    ArrowCall {
83        target: String,
84        method: String,
85        args: Vec<Value>,
86    },
87    Function {
88        name: String,
89        parameters: Vec<String>,
90        body: Vec<Statement>,
91    },
92    Assign {
93        target: String,
94        property: String,
95    },
96    Synth,
97    Bank {
98        name: String,
99        alias: Option<String>,
100    },
101    Let {
102        name: String,
103        value: Option<Value>,
104    },
105    Var {
106        name: String,
107        value: Option<Value>,
108    },
109    Const {
110        name: String,
111        value: Option<Value>,
112    },
113    Group {
114        name: String,
115        body: Vec<Statement>,
116    },
117    Spawn {
118        name: String,
119        args: Vec<Value>,
120    },
121    Loop {
122        count: Value,
123        body: Vec<Statement>,
124    },
125    For {
126        variable: String,
127        iterable: Value,
128        body: Vec<Statement>,
129    },
130    Routing,
131    Bind {
132        source: String,
133        target: String,
134    },
135    FxPipeline {
136        effects: Vec<Value>,
137        subject: String,
138    },
139    Node {
140        name: String,
141    },
142    Sidechain {
143        source: String,
144        effect: Value,
145        target: Option<String>,
146    },
147    Include(String),
148    Export {
149        names: Vec<String>,
150        source: String,
151    },
152    Import {
153        names: Vec<String>,
154        source: String,
155    },
156    On {
157        event: String,
158        args: Option<Vec<Value>>,
159        body: Vec<Statement>,
160    },
161    Emit {
162        event: String,
163        payload: Option<Value>,
164    },
165    If {
166        condition: Value,
167        body: Vec<Statement>,
168        else_body: Option<Vec<Statement>>, // Can contain statements or another If for else if
169    },
170    Comment,
171    Indent,
172    Dedent,
173    NewLine,
174    Unknown,
175    Error {
176        message: String,
177    },
178}
179
180impl Default for StatementKind {
181    fn default() -> Self {
182        StatementKind::Unknown
183    }
184}
185
186#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
187pub struct Statement {
188    pub kind: StatementKind,
189    #[serde(default)]
190    pub value: Value,
191    pub indent: usize,
192    pub line: usize,
193    pub column: usize,
194}
195
196impl Statement {
197    pub fn new(
198        kind: StatementKind,
199        value: Value,
200        indent: usize,
201        line: usize,
202        column: usize,
203    ) -> Self {
204        Self {
205            kind,
206            value,
207            indent,
208            line,
209            column,
210        }
211    }
212
213    pub fn tempo(value: f32, line: usize, column: usize) -> Self {
214        Self::new(StatementKind::Tempo, Value::Number(value), 0, line, column)
215    }
216
217    pub fn print(message: impl Into<String>, line: usize, column: usize) -> Self {
218        Self::new(
219            StatementKind::Print,
220            Value::String(message.into()),
221            0,
222            line,
223            column,
224        )
225    }
226
227    pub fn trigger(
228        entity: impl Into<String>,
229        duration: DurationValue,
230        effects: Option<Value>,
231        line: usize,
232        column: usize,
233    ) -> Self {
234        Self::new(
235            StatementKind::Trigger {
236                entity: entity.into(),
237                duration,
238                effects,
239            },
240            Value::Null,
241            0,
242            line,
243            column,
244        )
245    }
246
247    pub fn unknown() -> Self {
248        Self::default()
249    }
250
251    pub fn unknown_with_pos(indent: usize, line: usize, column: usize) -> Self {
252        Self::new(StatementKind::Unknown, Value::Null, indent, line, column)
253    }
254
255    pub fn error_with_pos(indent: usize, line: usize, column: usize, message: String) -> Self {
256        Self::new(
257            StatementKind::Error { message },
258            Value::Null,
259            indent,
260            line,
261            column,
262        )
263    }
264}