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>>, },
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}