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