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    Print,
58    Pattern {
59        name: String,
60        target: Option<String>,
61    },
62    Trigger {
63        entity: String,
64        duration: DurationValue,
65        effects: Option<Value>,
66    },
67    Sleep,
68    Call {
69        name: String,
70        args: Vec<Value>,
71    },
72    Load {
73        source: String,
74        alias: String,
75    },
76    Use {
77        name: String,
78        alias: Option<String>,
79    },
80    UsePlugin {
81        author: String,
82        name: String,
83        alias: String,
84    },
85    Automate {
86        target: String,
87    },
88    ArrowCall {
89        target: String,
90        method: String,
91        args: Vec<Value>,
92    },
93    Function {
94        name: String,
95        parameters: Vec<String>,
96        body: Vec<Statement>,
97    },
98    Assign {
99        target: String,
100        property: String,
101    },
102    Synth,
103    Bank {
104        name: String,
105        alias: Option<String>,
106    },
107    Let {
108        name: String,
109        value: Option<Value>,
110    },
111    Var {
112        name: String,
113        value: Option<Value>,
114    },
115    Const {
116        name: String,
117        value: Option<Value>,
118    },
119    Group {
120        name: String,
121        body: Vec<Statement>,
122    },
123    Spawn {
124        name: String,
125        args: Vec<Value>,
126    },
127    Loop {
128        count: Value,
129        body: Vec<Statement>,
130    },
131    For {
132        variable: String,
133        iterable: Value,
134        body: Vec<Statement>,
135    },
136    Routing,
137    Bind {
138        source: String,
139        target: String,
140    },
141    FxPipeline {
142        effects: Vec<Value>,
143        subject: String,
144    },
145    Node {
146        name: String,
147    },
148    Sidechain {
149        source: String,
150        effect: Value,
151        target: Option<String>,
152    },
153    Include(String),
154    Export {
155        names: Vec<String>,
156        source: String,
157    },
158    Import {
159        names: Vec<String>,
160        source: String,
161    },
162    On {
163        event: String,
164        args: Option<Vec<Value>>,
165        body: Vec<Statement>,
166    },
167    Emit {
168        event: String,
169        payload: Option<Value>,
170    },
171    If {
172        condition: Value,
173        body: Vec<Statement>,
174        else_body: Option<Vec<Statement>>, // Can contain statements or another If for else if
175    },
176    Return {
177        value: Option<Box<Value>>,
178    },
179    Break,
180    Comment,
181    Indent,
182    Dedent,
183    NewLine,
184    Unknown,
185    Error {
186        message: String,
187    },
188}
189
190impl Default for StatementKind {
191    fn default() -> Self {
192        StatementKind::Unknown
193    }
194}
195
196#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
197pub struct Statement {
198    pub kind: StatementKind,
199    #[serde(default)]
200    pub value: Value,
201    pub indent: usize,
202    pub line: usize,
203    pub column: usize,
204}
205
206impl Statement {
207    pub fn new(
208        kind: StatementKind,
209        value: Value,
210        indent: usize,
211        line: usize,
212        column: usize,
213    ) -> Self {
214        Self {
215            kind,
216            value,
217            indent,
218            line,
219            column,
220        }
221    }
222
223    pub fn tempo(value: f32, line: usize, column: usize) -> Self {
224        Self::new(StatementKind::Tempo, Value::Number(value), 0, line, column)
225    }
226
227    pub fn print(message: impl Into<String>, line: usize, column: usize) -> Self {
228        Self::new(
229            StatementKind::Print,
230            Value::String(message.into()),
231            0,
232            line,
233            column,
234        )
235    }
236
237    pub fn trigger(
238        entity: impl Into<String>,
239        duration: DurationValue,
240        effects: Option<Value>,
241        line: usize,
242        column: usize,
243    ) -> Self {
244        Self::new(
245            StatementKind::Trigger {
246                entity: entity.into(),
247                duration,
248                effects,
249            },
250            Value::Null,
251            0,
252            line,
253            column,
254        )
255    }
256
257    pub fn unknown() -> Self {
258        Self::default()
259    }
260
261    pub fn unknown_with_pos(indent: usize, line: usize, column: usize) -> Self {
262        Self::new(StatementKind::Unknown, Value::Null, indent, line, column)
263    }
264
265    pub fn error_with_pos(indent: usize, line: usize, column: usize, message: String) -> Self {
266        Self::new(
267            StatementKind::Error { message },
268            Value::Null,
269            indent,
270            line,
271            column,
272        )
273    }
274}