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    Call { name: String, args: Vec<Value> },
26    Block(Vec<Statement>),
27    Sample(String),
28    Beat(String),
29    Statement(Box<Statement>),
30    StatementKind(Box<StatementKind>),
31    Midi(String),
32    Range { start: Box<Value>, end: Box<Value> },
33    Unknown,
34    Null,
35}
36
37impl Default for Value {
38    fn default() -> Self {
39        Value::Null
40    }
41}
42
43impl Value {
44    pub fn get(&self, key: &str) -> Option<&Value> {
45        if let Value::Map(map) = self {
46            map.get(key)
47        } else {
48            None
49        }
50    }
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
54#[serde(tag = "kind")]
55pub enum StatementKind {
56    Tempo {
57        value: f32,
58        body: Option<Vec<Statement>>,
59    },
60    Print,
61    Pattern {
62        name: String,
63        target: Option<String>,
64    },
65    Trigger {
66        entity: String,
67        duration: DurationValue,
68        effects: Option<Value>,
69    },
70    Sleep,
71    Call {
72        name: String,
73        args: Vec<Value>,
74    },
75    Load {
76        source: String,
77        alias: String,
78    },
79    Use {
80        name: String,
81        alias: Option<String>,
82    },
83    UsePlugin {
84        author: String,
85        name: String,
86        alias: String,
87    },
88    Automate {
89        target: String,
90    },
91    ArrowCall {
92        target: String,
93        method: String,
94        args: Vec<Value>,
95    },
96    Function {
97        name: String,
98        parameters: Vec<String>,
99        body: Vec<Statement>,
100    },
101    Assign {
102        target: String,
103        property: String,
104    },
105    Synth,
106    Bank {
107        name: String,
108        alias: Option<String>,
109    },
110    Let {
111        name: String,
112        value: Option<Value>,
113    },
114    Var {
115        name: String,
116        value: Option<Value>,
117    },
118    Const {
119        name: String,
120        value: Option<Value>,
121    },
122    Group {
123        name: String,
124        body: Vec<Statement>,
125    },
126    Spawn {
127        name: String,
128        args: Vec<Value>,
129    },
130    Loop {
131        count: Value,
132        body: Vec<Statement>,
133    },
134    For {
135        variable: String,
136        iterable: Value,
137        body: Vec<Statement>,
138    },
139    Routing {
140        body: Vec<Statement>,
141    },
142    RoutingNode {
143        name: String,
144        alias: Option<String>,
145    },
146    RoutingFx {
147        target: String,
148        effects: Value,
149    },
150    RoutingRoute {
151        source: String,
152        destination: String,
153        effects: Option<Value>,
154    },
155    RoutingDuck {
156        source: String,
157        destination: String,
158        effect: Value,
159    },
160    RoutingSidechain {
161        source: String,
162        destination: String,
163        effect: Value,
164    },
165    Bind {
166        source: String,
167        target: String,
168    },
169    FxPipeline {
170        effects: Vec<Value>,
171        subject: String,
172    },
173    Node {
174        name: String,
175    },
176    Sidechain {
177        source: String,
178        effect: Value,
179        target: Option<String>,
180    },
181    Include(String),
182    Export {
183        names: Vec<String>,
184        source: String,
185    },
186    Import {
187        names: Vec<String>,
188        source: String,
189    },
190    On {
191        event: String,
192        args: Option<Vec<Value>>,
193        body: Vec<Statement>,
194    },
195    Emit {
196        event: String,
197        payload: Option<Value>,
198    },
199    If {
200        condition: Value,
201        body: Vec<Statement>,
202        else_body: Option<Vec<Statement>>, // Can contain statements or another If for else if
203    },
204    Return {
205        value: Option<Box<Value>>,
206    },
207    Break,
208    Comment,
209    Indent,
210    Dedent,
211    NewLine,
212    Unknown,
213    Error {
214        message: String,
215    },
216}
217
218impl Default for StatementKind {
219    fn default() -> Self {
220        StatementKind::Unknown
221    }
222}
223
224#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
225pub struct Statement {
226    pub kind: StatementKind,
227    #[serde(default)]
228    pub value: Value,
229    pub indent: usize,
230    pub line: usize,
231    pub column: usize,
232}
233
234impl Statement {
235    pub fn new(
236        kind: StatementKind,
237        value: Value,
238        indent: usize,
239        line: usize,
240        column: usize,
241    ) -> Self {
242        Self {
243            kind,
244            value,
245            indent,
246            line,
247            column,
248        }
249    }
250
251    pub fn tempo(value: f32, line: usize, column: usize) -> Self {
252        Self::new(
253            StatementKind::Tempo { value, body: None },
254            Value::Null,
255            0,
256            line,
257            column,
258        )
259    }
260
261    pub fn print(message: impl Into<String>, line: usize, column: usize) -> Self {
262        Self::new(
263            StatementKind::Print,
264            Value::String(message.into()),
265            0,
266            line,
267            column,
268        )
269    }
270
271    pub fn trigger(
272        entity: impl Into<String>,
273        duration: DurationValue,
274        effects: Option<Value>,
275        line: usize,
276        column: usize,
277    ) -> Self {
278        Self::new(
279            StatementKind::Trigger {
280                entity: entity.into(),
281                duration,
282                effects,
283            },
284            Value::Null,
285            0,
286            line,
287            column,
288        )
289    }
290
291    pub fn unknown() -> Self {
292        Self::default()
293    }
294
295    pub fn unknown_with_pos(indent: usize, line: usize, column: usize) -> Self {
296        Self::new(StatementKind::Unknown, Value::Null, indent, line, column)
297    }
298
299    pub fn error_with_pos(indent: usize, line: usize, column: usize, message: String) -> Self {
300        Self::new(
301            StatementKind::Error { message },
302            Value::Null,
303            indent,
304            line,
305            column,
306        )
307    }
308}