@devaloop/devalang 0.0.1-alpha.9 → 0.0.1-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (322) hide show
  1. package/.cargo/config.toml +2 -0
  2. package/.devalang +6 -1
  3. package/.github/workflows/ci.yml +103 -0
  4. package/Cargo.toml +81 -48
  5. package/README.md +137 -154
  6. package/docs/CHANGELOG.md +428 -1
  7. package/docs/CONTRIBUTING.md +101 -0
  8. package/docs/ROADMAP.md +14 -7
  9. package/docs/TODO.md +16 -15
  10. package/examples/automation.deva +42 -0
  11. package/examples/bank.deva +7 -0
  12. package/examples/bus.deva +10 -0
  13. package/examples/duration.deva +9 -0
  14. package/examples/effect.deva +2 -0
  15. package/examples/events.deva +12 -0
  16. package/examples/filter.deva +11 -0
  17. package/examples/function.deva +15 -0
  18. package/examples/index.deva +57 -12
  19. package/examples/lfo.deva +9 -0
  20. package/examples/loop.deva +5 -12
  21. package/examples/pattern.deva +8 -0
  22. package/examples/plugin.deva +16 -0
  23. package/examples/synth.deva +11 -1
  24. package/examples/synth_types.deva +17 -0
  25. package/examples/variables.deva +1 -1
  26. package/out-tsc/bin/index.d.ts +2 -0
  27. package/out-tsc/bin/index.js +51 -7
  28. package/out-tsc/core/functions/index.d.ts +42 -0
  29. package/out-tsc/core/functions/index.js +87 -0
  30. package/out-tsc/core/index.d.ts +6 -0
  31. package/out-tsc/core/index.js +22 -0
  32. package/out-tsc/core/types/index.d.ts +4 -0
  33. package/out-tsc/core/types/index.js +20 -0
  34. package/out-tsc/core/types/plugin.d.ts +18 -0
  35. package/out-tsc/core/types/plugin.js +2 -0
  36. package/out-tsc/core/types/result.d.ts +27 -0
  37. package/out-tsc/core/types/result.js +2 -0
  38. package/out-tsc/core/types/statement.d.ts +106 -0
  39. package/out-tsc/core/types/statement.js +2 -0
  40. package/out-tsc/core/types/value.d.ts +43 -0
  41. package/out-tsc/core/types/value.js +2 -0
  42. package/out-tsc/index.d.ts +7 -0
  43. package/out-tsc/index.js +42 -1
  44. package/out-tsc/pkg/devalang_core.d.ts +15 -0
  45. package/out-tsc/pkg/devalang_core.js +65 -0
  46. package/out-tsc/pkg/devalang_core_bg.wasm.d.ts +34 -0
  47. package/out-tsc/scripts/copy-wasm-dts.d.ts +1 -0
  48. package/out-tsc/scripts/copy-wasm-dts.js +73 -0
  49. package/out-tsc/scripts/postinstall.d.ts +1 -0
  50. package/out-tsc/scripts/postinstall.js +83 -0
  51. package/out-tsc/scripts/version/bump.d.ts +1 -0
  52. package/out-tsc/scripts/version/fetch.d.ts +1 -0
  53. package/out-tsc/scripts/version/index.d.ts +1 -0
  54. package/out-tsc/scripts/version/sync.d.ts +1 -0
  55. package/package.json +28 -7
  56. package/project-version.json +4 -4
  57. package/rust/cli/bank/api.rs +122 -0
  58. package/rust/cli/bank/commands.rs +306 -0
  59. package/rust/cli/bank/mod.rs +29 -0
  60. package/rust/cli/build/commands.rs +153 -0
  61. package/rust/cli/build/mod.rs +2 -0
  62. package/rust/cli/build/process.rs +165 -0
  63. package/rust/cli/check/mod.rs +208 -0
  64. package/rust/cli/discover/commands.rs +253 -0
  65. package/rust/cli/discover/config.rs +111 -0
  66. package/rust/cli/discover/fs.rs +19 -0
  67. package/rust/cli/discover/install.rs +103 -0
  68. package/rust/cli/discover/metadata.rs +48 -0
  69. package/rust/cli/discover/mod.rs +5 -0
  70. package/rust/cli/{init.rs → init/commands.rs} +32 -23
  71. package/rust/cli/init/mod.rs +1 -0
  72. package/rust/cli/install/addon.rs +118 -0
  73. package/rust/cli/install/bank.rs +72 -0
  74. package/rust/cli/install/commands.rs +35 -0
  75. package/rust/cli/install/mod.rs +4 -0
  76. package/rust/cli/install/plugin.rs +80 -0
  77. package/rust/cli/login/commands.rs +124 -0
  78. package/rust/cli/login/mod.rs +1 -0
  79. package/rust/cli/mod.rs +9 -202
  80. package/rust/cli/parser.rs +359 -0
  81. package/rust/cli/play/commands.rs +375 -0
  82. package/rust/cli/play/io.rs +17 -0
  83. package/rust/cli/play/mod.rs +5 -0
  84. package/rust/cli/play/process.rs +159 -0
  85. package/rust/cli/play/realtime.rs +91 -0
  86. package/rust/cli/play/utils.rs +23 -0
  87. package/rust/cli/telemetry/commands.rs +22 -0
  88. package/rust/cli/telemetry/event_creator.rs +80 -0
  89. package/rust/cli/telemetry/mod.rs +3 -0
  90. package/rust/cli/telemetry/send.rs +51 -0
  91. package/rust/cli/{template.rs → template/commands.rs} +17 -5
  92. package/rust/cli/template/mod.rs +1 -0
  93. package/rust/cli/update/commands.rs +6 -0
  94. package/rust/cli/update/mod.rs +1 -0
  95. package/rust/config/driver.rs +112 -0
  96. package/rust/config/mod.rs +3 -16
  97. package/rust/config/ops.rs +26 -0
  98. package/rust/config/settings.rs +101 -0
  99. package/rust/core/audio/engine/driver.rs +220 -0
  100. package/rust/core/audio/engine/export.rs +169 -0
  101. package/rust/core/audio/engine/helpers.rs +178 -0
  102. package/rust/core/audio/engine/mod.rs +56 -0
  103. package/rust/core/audio/engine/notes/dsp.rs +85 -0
  104. package/rust/core/audio/engine/notes/mod.rs +44 -0
  105. package/rust/core/audio/engine/notes/params.rs +294 -0
  106. package/rust/core/audio/engine/sample/insert.rs +199 -0
  107. package/rust/core/audio/engine/sample/mod.rs +40 -0
  108. package/rust/core/audio/engine/sample/padding.rs +170 -0
  109. package/rust/core/audio/evaluator/condition.rs +61 -0
  110. package/rust/core/audio/evaluator/mod.rs +9 -0
  111. package/rust/core/audio/evaluator/numeric.rs +152 -0
  112. package/rust/core/audio/evaluator/rhs.rs +16 -0
  113. package/rust/core/audio/evaluator/string_expr.rs +94 -0
  114. package/rust/core/audio/interpreter/driver.rs +574 -216
  115. package/rust/core/audio/interpreter/mod.rs +2 -12
  116. package/rust/core/audio/interpreter/statements/arrow_call/interprete.rs +175 -0
  117. package/rust/core/audio/interpreter/statements/arrow_call/methods/chord.rs +384 -0
  118. package/rust/core/audio/interpreter/statements/arrow_call/methods/mod.rs +2 -0
  119. package/rust/core/audio/interpreter/statements/arrow_call/methods/note.rs +316 -0
  120. package/rust/core/audio/interpreter/statements/arrow_call/mod.rs +3 -0
  121. package/rust/core/audio/interpreter/statements/arrow_call/types/arp.rs +192 -0
  122. package/rust/core/audio/interpreter/statements/arrow_call/types/mod.rs +24 -0
  123. package/rust/core/audio/interpreter/statements/arrow_call/types/pad.rs +116 -0
  124. package/rust/core/audio/interpreter/statements/arrow_call/types/pluck.rs +97 -0
  125. package/rust/core/audio/interpreter/statements/arrow_call/types/sub.rs +100 -0
  126. package/rust/core/audio/interpreter/statements/automate.rs +16 -0
  127. package/rust/core/audio/interpreter/statements/call.rs +295 -0
  128. package/rust/core/audio/interpreter/{condition.rs → statements/condition.rs} +72 -69
  129. package/rust/core/audio/interpreter/statements/function.rs +24 -0
  130. package/rust/core/audio/interpreter/statements/let_.rs +36 -0
  131. package/rust/core/audio/interpreter/statements/load.rs +17 -0
  132. package/rust/core/audio/interpreter/statements/loop_.rs +115 -0
  133. package/rust/core/audio/interpreter/statements/mod.rs +12 -0
  134. package/rust/core/audio/interpreter/statements/sleep.rs +28 -0
  135. package/rust/core/audio/interpreter/statements/spawn.rs +253 -0
  136. package/rust/core/audio/interpreter/statements/tempo.rs +40 -0
  137. package/rust/core/audio/interpreter/statements/trigger.rs +239 -0
  138. package/rust/core/audio/loader/mod.rs +1 -1
  139. package/rust/core/audio/loader/trigger.rs +98 -52
  140. package/rust/core/audio/mod.rs +2 -2
  141. package/rust/core/audio/player.rs +28 -12
  142. package/rust/core/audio/special/easing.rs +189 -0
  143. package/rust/core/audio/special/env.rs +45 -0
  144. package/rust/core/audio/special/math.rs +134 -0
  145. package/rust/core/audio/special/mod.rs +9 -0
  146. package/rust/core/audio/special/modulator.rs +143 -0
  147. package/rust/core/builder/mod.rs +129 -80
  148. package/rust/core/debugger/lexer.rs +4 -4
  149. package/rust/core/debugger/logs.rs +52 -0
  150. package/rust/core/debugger/mod.rs +11 -2
  151. package/rust/core/debugger/preprocessor.rs +4 -4
  152. package/rust/core/debugger/store.rs +38 -25
  153. package/rust/core/error/mod.rs +221 -12
  154. package/rust/core/lexer/driver.rs +59 -0
  155. package/rust/core/lexer/handler/arrow.rs +62 -11
  156. package/rust/core/lexer/handler/at.rs +5 -5
  157. package/rust/core/lexer/handler/brace.rs +11 -11
  158. package/rust/core/lexer/handler/colon.rs +5 -5
  159. package/rust/core/lexer/handler/comment.rs +3 -3
  160. package/rust/core/lexer/handler/dot.rs +6 -6
  161. package/rust/core/lexer/handler/driver.rs +143 -32
  162. package/rust/core/lexer/handler/identifier.rs +11 -5
  163. package/rust/core/lexer/handler/indent.rs +18 -4
  164. package/rust/core/lexer/handler/mod.rs +6 -5
  165. package/rust/core/lexer/handler/newline.rs +3 -3
  166. package/rust/core/lexer/handler/number.rs +5 -5
  167. package/rust/core/lexer/handler/operator.rs +5 -3
  168. package/rust/core/lexer/handler/parenthesis.rs +41 -0
  169. package/rust/core/lexer/handler/slash.rs +21 -0
  170. package/rust/core/lexer/handler/string.rs +3 -3
  171. package/rust/core/lexer/mod.rs +1 -49
  172. package/rust/core/lexer/token.rs +17 -12
  173. package/rust/core/mod.rs +9 -10
  174. package/rust/core/parser/driver/block.rs +111 -0
  175. package/rust/core/parser/driver/cursor.rs +82 -0
  176. package/rust/core/parser/driver/driver_impl.rs +139 -0
  177. package/rust/core/parser/driver/mod.rs +6 -0
  178. package/rust/core/parser/driver/parse_array.rs +120 -0
  179. package/rust/core/parser/driver/parse_map.rs +223 -0
  180. package/rust/core/parser/driver/parser.rs +160 -0
  181. package/rust/core/parser/handler/arrow_call.rs +277 -126
  182. package/rust/core/parser/handler/at.rs +142 -25
  183. package/rust/core/parser/handler/bank.rs +83 -20
  184. package/rust/core/parser/handler/condition.rs +14 -5
  185. package/rust/core/parser/handler/dot.rs +111 -75
  186. package/rust/core/parser/handler/identifier/automate.rs +254 -0
  187. package/rust/core/parser/handler/identifier/call.rs +74 -24
  188. package/rust/core/parser/handler/identifier/emit.rs +70 -0
  189. package/rust/core/parser/handler/identifier/function.rs +113 -0
  190. package/rust/core/parser/handler/identifier/group.rs +28 -14
  191. package/rust/core/parser/handler/identifier/let_.rs +61 -21
  192. package/rust/core/parser/handler/identifier/mod.rs +24 -20
  193. package/rust/core/parser/handler/identifier/on.rs +107 -0
  194. package/rust/core/parser/handler/identifier/print.rs +49 -0
  195. package/rust/core/parser/handler/identifier/sleep.rs +77 -14
  196. package/rust/core/parser/handler/identifier/spawn.rs +81 -31
  197. package/rust/core/parser/handler/identifier/synth.rs +102 -32
  198. package/rust/core/parser/handler/loop_.rs +144 -22
  199. package/rust/core/parser/handler/mod.rs +6 -5
  200. package/rust/core/parser/handler/pattern.rs +74 -0
  201. package/rust/core/parser/handler/tempo.rs +67 -9
  202. package/rust/core/parser/mod.rs +3 -4
  203. package/rust/core/parser/statement.rs +6 -92
  204. package/rust/core/plugin/loader.rs +137 -0
  205. package/rust/core/plugin/mod.rs +2 -0
  206. package/rust/core/plugin/runner/mod.rs +11 -0
  207. package/rust/core/plugin/runner/non_wasm.rs +297 -0
  208. package/rust/core/plugin/runner/wasm32.rs +43 -0
  209. package/rust/core/preprocessor/loader/inject.rs +278 -0
  210. package/rust/core/preprocessor/loader/loader_helpers.rs +110 -0
  211. package/rust/core/preprocessor/loader/mod.rs +235 -0
  212. package/rust/core/preprocessor/mod.rs +4 -4
  213. package/rust/core/preprocessor/module.rs +55 -50
  214. package/rust/core/preprocessor/processor/handlers.rs +107 -0
  215. package/rust/core/preprocessor/processor/mod.rs +1 -0
  216. package/rust/core/preprocessor/resolver/bank.rs +14 -12
  217. package/rust/core/preprocessor/resolver/call.rs +106 -105
  218. package/rust/core/preprocessor/resolver/condition.rs +13 -10
  219. package/rust/core/preprocessor/resolver/driver.rs +145 -48
  220. package/rust/core/preprocessor/resolver/function.rs +69 -0
  221. package/rust/core/preprocessor/resolver/group.rs +122 -61
  222. package/rust/core/preprocessor/resolver/let_.rs +13 -12
  223. package/rust/core/preprocessor/resolver/loop_.rs +240 -13
  224. package/rust/core/preprocessor/resolver/mod.rs +8 -6
  225. package/rust/core/preprocessor/resolver/pattern.rs +83 -0
  226. package/rust/core/preprocessor/resolver/spawn.rs +83 -42
  227. package/rust/core/preprocessor/resolver/synth.rs +15 -11
  228. package/rust/core/preprocessor/resolver/tempo.rs +13 -14
  229. package/rust/core/preprocessor/resolver/trigger.rs +32 -28
  230. package/rust/core/preprocessor/resolver/value.rs +111 -13
  231. package/rust/core/store/global.rs +57 -39
  232. package/rust/core/store/mod.rs +0 -3
  233. package/rust/lib.rs +323 -117
  234. package/rust/main.rs +388 -65
  235. package/rust/types/Cargo.toml +11 -0
  236. package/rust/types/src/addons.rs +55 -0
  237. package/rust/types/src/ast.rs +202 -0
  238. package/rust/types/src/config.rs +84 -0
  239. package/rust/types/src/lib.rs +15 -0
  240. package/rust/types/src/plugin.rs +20 -0
  241. package/rust/types/src/store.rs +139 -0
  242. package/rust/types/src/telemetry.rs +85 -0
  243. package/rust/utils/Cargo.toml +26 -0
  244. package/rust/utils/src/error.rs +186 -0
  245. package/rust/utils/src/file.rs +94 -0
  246. package/rust/utils/src/first_usage.rs +97 -0
  247. package/rust/utils/{mod.rs → src/lib.rs} +6 -3
  248. package/rust/utils/{logger.rs → src/logger.rs} +94 -17
  249. package/rust/utils/src/path.rs +129 -0
  250. package/rust/utils/src/signature.rs +41 -0
  251. package/rust/utils/{spinner.rs → src/spinner.rs} +7 -8
  252. package/rust/utils/src/version.rs +27 -0
  253. package/rust/utils/{watcher.rs → src/watcher.rs} +17 -4
  254. package/rust/web/api.rs +5 -0
  255. package/rust/web/cdn.rs +34 -0
  256. package/rust/web/mod.rs +3 -0
  257. package/rust/web/sso.rs +5 -0
  258. package/templates/minimal/README.md +143 -127
  259. package/templates/welcome/README.md +143 -127
  260. package/templates/welcome/src/index.deva +56 -8
  261. package/templates/welcome/src/variables.deva +2 -4
  262. package/tests/integration.rs +21 -0
  263. package/tests/rust/cli_check_build.rs +21 -0
  264. package/tests/rust/cli_help.rs +12 -0
  265. package/tests/rust/cli_template_list.rs +10 -0
  266. package/tests/rust/cli_version.rs +11 -0
  267. package/tests/typescript/index.spec.ts +136 -0
  268. package/tests/typescript/playhead.spec.ts +36 -0
  269. package/tests/typescript/render_e2e.spec.ts +77 -0
  270. package/tsconfig.json +12 -10
  271. package/typescript/bin/index.ts +19 -5
  272. package/typescript/core/functions/index.ts +94 -0
  273. package/typescript/core/index.ts +6 -0
  274. package/typescript/core/types/index.ts +4 -0
  275. package/typescript/core/types/plugin.ts +19 -0
  276. package/typescript/core/types/result.ts +29 -0
  277. package/typescript/core/types/statement.ts +47 -0
  278. package/typescript/core/types/value.ts +29 -0
  279. package/typescript/index.ts +8 -1
  280. package/typescript/pkg/devalang_core.d.ts +4 -0
  281. package/typescript/pkg/devalang_core.ts +65 -0
  282. package/typescript/scripts/copy-wasm-dts.ts +41 -0
  283. package/typescript/scripts/postinstall.ts +85 -0
  284. package/typescript/scripts/version/bump.ts +0 -1
  285. package/typescript/scripts/version/index.ts +0 -1
  286. package/docs/COMMANDS.md +0 -85
  287. package/docs/CONFIG.md +0 -30
  288. package/docs/SYNTAX.md +0 -210
  289. package/out-tsc/bin/devalang.exe +0 -0
  290. package/out-tsc/scripts/postbuild.js +0 -11
  291. package/rust/cli/build.rs +0 -137
  292. package/rust/cli/check.rs +0 -117
  293. package/rust/cli/play.rs +0 -193
  294. package/rust/config/loader.rs +0 -13
  295. package/rust/core/audio/engine.rs +0 -203
  296. package/rust/core/audio/evaluator.rs +0 -31
  297. package/rust/core/audio/interpreter/arrow_call.rs +0 -129
  298. package/rust/core/audio/interpreter/call.rs +0 -64
  299. package/rust/core/audio/interpreter/let_.rs +0 -19
  300. package/rust/core/audio/interpreter/load.rs +0 -18
  301. package/rust/core/audio/interpreter/loop_.rs +0 -67
  302. package/rust/core/audio/interpreter/sleep.rs +0 -36
  303. package/rust/core/audio/interpreter/spawn.rs +0 -66
  304. package/rust/core/audio/interpreter/tempo.rs +0 -16
  305. package/rust/core/audio/interpreter/trigger.rs +0 -69
  306. package/rust/core/audio/renderer.rs +0 -54
  307. package/rust/core/parser/driver.rs +0 -331
  308. package/rust/core/preprocessor/loader.rs +0 -193
  309. package/rust/core/preprocessor/processor.rs +0 -76
  310. package/rust/core/shared/duration.rs +0 -8
  311. package/rust/core/shared/mod.rs +0 -2
  312. package/rust/core/shared/value.rs +0 -18
  313. package/rust/core/store/export.rs +0 -28
  314. package/rust/core/store/import.rs +0 -28
  315. package/rust/core/store/variable.rs +0 -28
  316. package/rust/core/utils/mod.rs +0 -2
  317. package/rust/core/utils/path.rs +0 -31
  318. package/rust/core/utils/validation.rs +0 -37
  319. package/rust/utils/file.rs +0 -35
  320. package/rust/utils/signature.rs +0 -17
  321. package/rust/utils/version.rs +0 -15
  322. package/typescript/scripts/postbuild.ts +0 -8
@@ -1,67 +0,0 @@
1
- use crate::core::{
2
- audio::{ engine::AudioEngine, interpreter::driver::execute_audio_block },
3
- parser::statement::{ Statement, StatementKind },
4
- shared::{ duration::Duration, value::Value },
5
- store::variable::VariableTable,
6
- };
7
-
8
- pub fn interprete_loop_statement(
9
- stmt: &Statement,
10
- audio_engine: AudioEngine,
11
- variable_table: VariableTable,
12
- base_bpm: f32,
13
- base_duration: f32,
14
- max_end_time: f32,
15
- cursor_time: f32
16
- ) -> (AudioEngine, f32, f32) {
17
- if let Value::Map(loop_value) = &stmt.value {
18
- let loop_count = match loop_value.get("iterator") {
19
- Some(Value::Number(n)) => *n as usize,
20
- Some(Value::Identifier(ident)) => {
21
- if let Some(Value::Number(n)) = variable_table.get(ident) {
22
- *n as usize
23
- } else {
24
- eprintln!("❌ Loop iterator must be a number, found: {:?}", ident);
25
- return (audio_engine, max_end_time, cursor_time);
26
- }
27
- }
28
- _ => {
29
- eprintln!("❌ Loop iterator must be a number, found: {:?}", loop_value.get("iterator"));
30
- return (audio_engine, max_end_time, cursor_time);
31
- }
32
- };
33
-
34
- let loop_body = match loop_value.get("body") {
35
- Some(Value::Block(body)) => body.clone(),
36
- _ => {
37
- eprintln!("❌ Loop body must be a block, found: {:?}", loop_value.get("body"));
38
- return (audio_engine, max_end_time, cursor_time);
39
- }
40
- };
41
-
42
- let mut engine = audio_engine;
43
- let mut cur_time = cursor_time;
44
- let mut max_time = max_end_time;
45
-
46
- for _ in 0..loop_count {
47
- let (eng, _, end_time) = execute_audio_block(
48
- engine,
49
- variable_table.clone(),
50
- loop_body.clone(),
51
- base_bpm,
52
- base_duration,
53
- max_time,
54
- cur_time
55
- );
56
-
57
- engine = eng;
58
- cur_time = end_time;
59
- max_time = max_time.max(end_time);
60
- }
61
-
62
- (engine, max_time, cur_time)
63
- } else {
64
- eprintln!("❌ Loop statement value is not a map");
65
- (audio_engine, max_end_time, cursor_time)
66
- }
67
- }
@@ -1,36 +0,0 @@
1
- use crate::core::{
2
- audio::{ engine::AudioEngine, loader::trigger::load_trigger },
3
- parser::statement::{ Statement, StatementKind },
4
- shared::{ duration::Duration, value::Value },
5
- store::variable::VariableTable,
6
- };
7
-
8
- pub fn interprete_sleep_statement(
9
- stmt: &Statement,
10
- cursor_time: f32,
11
- max_end_time: f32,
12
- ) -> (f32, f32) {
13
- let duration_secs = match &stmt.value {
14
- Value::Number(ms) => *ms / 1000.0,
15
- Value::String(s) if s.ends_with("ms") => {
16
- s.trim_end_matches("ms").parse::<f32>().map(|ms| ms / 1000.0).unwrap_or_else(|_| {
17
- eprintln!("❌ Invalid sleep value (ms): {}", s);
18
- 0.0
19
- })
20
- }
21
- Value::String(s) if s.ends_with("s") => {
22
- s.trim_end_matches("s").parse::<f32>().unwrap_or_else(|_| {
23
- eprintln!("❌ Invalid sleep value (s): {}", s);
24
- 0.0
25
- })
26
- }
27
- other => {
28
- eprintln!("❌ Invalid sleep value: {:?}", other);
29
- 0.0
30
- }
31
- };
32
-
33
- let new_cursor = cursor_time + duration_secs;
34
- let new_max = max_end_time.max(new_cursor);
35
- (new_cursor, new_max)
36
- }
@@ -1,66 +0,0 @@
1
- use crate::core::{
2
- audio::{ engine::AudioEngine, interpreter::driver::execute_audio_block },
3
- parser::statement::Statement,
4
- shared::value::Value,
5
- store::variable::VariableTable,
6
- };
7
-
8
- pub fn interprete_spawn_statement(
9
- stmt: &Statement,
10
- audio_engine: AudioEngine,
11
- variable_table: &VariableTable,
12
- base_bpm: f32,
13
- base_duration: f32,
14
- cursor_time: f32,
15
- max_end_time: f32
16
- ) -> Option<(f32, f32, AudioEngine)> {
17
- match &stmt.value {
18
- Value::String(identifier) | Value::Identifier(identifier) => {
19
- handle_spawn_identifier(
20
- identifier,
21
- audio_engine,
22
- variable_table,
23
- base_bpm,
24
- base_duration,
25
- cursor_time,
26
- max_end_time
27
- )
28
- }
29
-
30
- _ => {
31
- eprintln!("❌ Invalid spawn statement: expected identifier, found {:?}", stmt.value);
32
- None
33
- }
34
- }
35
- }
36
-
37
- fn handle_spawn_identifier(
38
- identifier: &str,
39
- audio_engine: AudioEngine,
40
- variable_table: &VariableTable,
41
- base_bpm: f32,
42
- base_duration: f32,
43
- cursor_time: f32,
44
- max_end_time: f32
45
- ) -> Option<(f32, f32, AudioEngine)> {
46
- if let Some(Value::Map(map)) = variable_table.get(identifier) {
47
- if let Some(Value::Block(block)) = map.get("body") {
48
- let (eng, _, end_time) = execute_audio_block(
49
- audio_engine.clone(),
50
- variable_table.clone(),
51
- block.clone(),
52
- base_bpm,
53
- base_duration,
54
- max_end_time,
55
- cursor_time
56
- );
57
- return Some((max_end_time.max(end_time), end_time, eng));
58
- } else {
59
- eprintln!("❌ Spawn group '{}' has no 'body' block", identifier);
60
- }
61
- } else {
62
- eprintln!("❌ Spawn group '{}' not found or not a map", identifier);
63
- }
64
-
65
- None
66
- }
@@ -1,16 +0,0 @@
1
- use crate::core::{ parser::statement::{ Statement, StatementKind }, shared::value::Value };
2
-
3
- pub fn interprete_tempo_statement(stmt: &Statement) -> Option<(f32, f32)> {
4
- if let StatementKind::Tempo = &stmt.kind {
5
- if let Value::Number(bpm) = &stmt.value {
6
- let bpm = *bpm as f32;
7
- let duration = 60.0 / bpm;
8
-
9
- return Some((bpm, duration));
10
- } else {
11
- eprintln!("❌ Invalid tempo value: {:?}", stmt.value);
12
- }
13
- }
14
-
15
- None
16
- }
@@ -1,69 +0,0 @@
1
- use crate::core::{
2
- audio::{ engine::AudioEngine, loader::trigger::load_trigger },
3
- parser::statement::{ Statement, StatementKind },
4
- shared::{ duration::Duration, value::Value },
5
- store::variable::VariableTable,
6
- };
7
-
8
- pub fn interprete_trigger_statement(
9
- stmt: &Statement,
10
- audio_engine: &mut AudioEngine,
11
- variable_table: &VariableTable,
12
- base_duration: f32,
13
- cursor_time: f32,
14
- max_end_time: f32
15
- ) -> Option<(f32, f32, AudioEngine)> {
16
- if let StatementKind::Trigger { entity, duration } = &stmt.kind {
17
- if let Some(trigger_val) = variable_table.get(entity) {
18
- let duration_secs = match duration {
19
- Duration::Number(n) => *n,
20
-
21
- Duration::Identifier(id) => {
22
- if id == "auto" {
23
- 1.0
24
- } else {
25
- match variable_table.get(id) {
26
- Some(Value::Number(n)) => *n,
27
- Some(Value::Identifier(other)) if other == "auto" => 1.0,
28
- Some(other) => {
29
- eprintln!(
30
- "❌ Invalid duration reference '{}': expected number, got {:?}",
31
- id,
32
- other
33
- );
34
- return None;
35
- }
36
- None => {
37
- eprintln!("❌ Duration identifier '{}' not found", id);
38
- return None;
39
- }
40
- }
41
- }
42
- }
43
-
44
- Duration::Auto => 1.0,
45
- };
46
-
47
- let duration_final = duration_secs * base_duration;
48
-
49
- let (src, _) = load_trigger(
50
- trigger_val,
51
- duration,
52
- base_duration,
53
- variable_table.clone()
54
- );
55
-
56
- let mut updated_engine = audio_engine.clone();
57
- updated_engine.insert_sample(&src, cursor_time, duration_final, None);
58
-
59
- let new_cursor_time = cursor_time + duration_final;
60
- let new_max_end_time = new_cursor_time.max(max_end_time);
61
-
62
- return Some((new_cursor_time, new_max_end_time, updated_engine));
63
- } else {
64
- eprintln!("❌ Unknown trigger entity: {}", entity);
65
- }
66
- }
67
-
68
- None
69
- }
@@ -1,54 +0,0 @@
1
- use std::collections::HashMap;
2
-
3
- use crate::{
4
- core::{
5
- audio::{ engine::AudioEngine, interpreter::driver::run_audio_program },
6
- parser::statement::Statement,
7
- store::global::GlobalStore,
8
- },
9
- utils::logger::{ LogLevel, Logger },
10
- };
11
-
12
- pub fn render_audio_with_modules(
13
- modules: HashMap<String, Vec<Statement>>,
14
- output_dir: &str,
15
- global_store: &mut GlobalStore
16
- ) -> HashMap<String, AudioEngine> {
17
- let mut result = HashMap::new();
18
-
19
- for (module_name, statements) in modules {
20
- let mut global_max_end_time: f32 = 0.0;
21
- let mut initial_engine = AudioEngine::new(module_name.clone());
22
-
23
- // Apply global variables to the initial engine
24
- if let Some(module) = global_store.get_module(&module_name) {
25
- initial_engine.set_variables(module.variable_table.clone());
26
- }
27
-
28
- // interprete statements to fill the audio buffer
29
- let (mut updated_engine, _bpm, module_max_end_time) = run_audio_program(
30
- &statements,
31
- initial_engine,
32
- module_name.clone(),
33
- output_dir.to_string()
34
- );
35
-
36
- // Verify if the buffer is silent (all samples are zero)
37
- if updated_engine.buffer.iter().all(|&s| s == 0) {
38
- let logger = Logger::new();
39
- logger.log_message(
40
- LogLevel::Warning,
41
- &format!("Module '{}' ignored: silent buffer (no non-zero samples)", module_name)
42
- );
43
- continue;
44
- }
45
-
46
- // Determines the maximum end time for the module
47
- global_max_end_time = global_max_end_time.max(module_max_end_time);
48
- updated_engine.set_duration(global_max_end_time);
49
-
50
- result.insert(module_name, updated_engine);
51
- }
52
-
53
- result
54
- }
@@ -1,331 +0,0 @@
1
- use crate::core::{
2
- lexer::token::{ Token, TokenKind },
3
- parser::{
4
- handler::{
5
- arrow_call::parse_arrow_call,
6
- at::parse_at_token,
7
- bank::parse_bank_token,
8
- condition::parse_condition_token,
9
- dot::parse_dot_token,
10
- identifier::parse_identifier_token,
11
- loop_::parse_loop_token,
12
- tempo::parse_tempo_token,
13
- },
14
- statement::Statement,
15
- },
16
- shared::value::Value,
17
- store::global::GlobalStore,
18
- };
19
-
20
- #[derive(Debug, Clone, PartialEq)]
21
- pub struct Parser {
22
- pub resolve_modules: bool,
23
- pub tokens: Vec<Token>,
24
- pub token_index: usize,
25
- pub current_module: String,
26
- pub previous: Option<Token>,
27
- }
28
-
29
- impl Parser {
30
- pub fn new() -> Self {
31
- Parser {
32
- resolve_modules: false,
33
- tokens: Vec::new(),
34
- token_index: 0,
35
- current_module: String::new(),
36
- previous: None,
37
- }
38
- }
39
-
40
- pub fn set_current_module(&mut self, module_path: String) {
41
- self.current_module = module_path;
42
- }
43
-
44
- pub fn advance(&mut self) -> Option<&Token> {
45
- if self.is_eof() {
46
- return None;
47
- }
48
-
49
- self.previous = self.tokens.get(self.token_index).cloned();
50
- self.token_index += 1;
51
-
52
- self.tokens.get(self.token_index - 1)
53
- }
54
-
55
- pub fn peek_is(&self, expected: &str) -> bool {
56
- self.peek().map_or(false, |t| t.lexeme == expected)
57
- }
58
-
59
- pub fn peek_nth(&self, n: usize) -> Option<&Token> {
60
- if self.token_index + n < self.tokens.len() {
61
- self.tokens.get(self.token_index + n)
62
- } else {
63
- None
64
- }
65
- }
66
-
67
- pub fn advance_if(&mut self, kind: TokenKind) -> bool {
68
- if self.match_token(kind) { true } else { false }
69
- }
70
-
71
- pub fn match_token(&mut self, kind: TokenKind) -> bool {
72
- if let Some(tok) = self.peek() {
73
- if tok.kind == kind {
74
- self.advance();
75
- return true;
76
- }
77
- }
78
- false
79
- }
80
-
81
- pub fn previous_clone(&self) -> Option<Token> {
82
- self.previous.clone()
83
- }
84
-
85
- pub fn parse_block(
86
- &self,
87
- tokens: Vec<Token>,
88
- global_store: &mut GlobalStore
89
- ) -> Vec<Statement> {
90
- let mut inner_parser = Parser {
91
- resolve_modules: self.resolve_modules,
92
- tokens,
93
- token_index: 0,
94
- current_module: self.current_module.clone(),
95
- previous: None,
96
- };
97
-
98
- inner_parser.parse_tokens(inner_parser.tokens.clone(), global_store)
99
- }
100
-
101
- pub fn parse_tokens(
102
- &mut self,
103
- tokens: Vec<Token>,
104
- global_store: &mut GlobalStore
105
- ) -> Vec<Statement> {
106
- self.tokens = tokens;
107
- self.token_index = 0;
108
-
109
- let mut statements = Vec::new();
110
-
111
- while !self.is_eof() {
112
- let token = match self.peek() {
113
- Some(t) => t.clone(),
114
- None => {
115
- break;
116
- }
117
- };
118
-
119
- let statement = match &token.kind {
120
- TokenKind::At => parse_at_token(self, global_store),
121
- TokenKind::Identifier => {
122
- if let Some(next) = self.peek_nth(1).cloned() {
123
- if next.kind == TokenKind::Arrow {
124
- parse_arrow_call(self, global_store)
125
- } else {
126
- parse_identifier_token(self, global_store)
127
- }
128
- } else {
129
- parse_identifier_token(self, global_store)
130
- }
131
- }
132
- TokenKind::Dot => parse_dot_token(self, global_store),
133
- TokenKind::Tempo => parse_tempo_token(self, global_store),
134
- TokenKind::Bank => parse_bank_token(self, global_store),
135
- TokenKind::Loop => parse_loop_token(self, global_store),
136
- TokenKind::If => parse_condition_token(self, global_store),
137
-
138
- | TokenKind::Else // Ignore else, already handled in `parse_condition_token`
139
- | TokenKind::Comment
140
- | TokenKind::Equals
141
- | TokenKind::Colon
142
- | TokenKind::Number
143
- | TokenKind::String
144
- | TokenKind::LBrace
145
- | TokenKind::RBrace
146
- | TokenKind::Comma
147
- | TokenKind::Newline
148
- | TokenKind::Dedent
149
- | TokenKind::Indent => {
150
- self.advance();
151
- continue;
152
- }
153
-
154
- TokenKind::EOF => {
155
- break;
156
- }
157
-
158
- _ => {
159
- println!("Unhandled token: {:?}", token);
160
- self.advance();
161
- Statement::unknown()
162
- }
163
- };
164
-
165
- statements.push(statement);
166
- }
167
-
168
- statements
169
- }
170
-
171
- pub fn check_token(&self, kind: TokenKind) -> bool {
172
- self.peek().map_or(false, |t| t.kind == kind)
173
- }
174
-
175
- pub fn parse_map_value(&mut self) -> Option<Value> {
176
- if !self.match_token(TokenKind::LBrace) {
177
- return None;
178
- }
179
-
180
- let mut map = std::collections::HashMap::new();
181
-
182
- while !self.check_token(TokenKind::RBrace) && !self.is_eof() {
183
- let key = if let Some(token) = self.advance() {
184
- token.lexeme.clone()
185
- } else {
186
- break;
187
- };
188
-
189
- if !self.match_token(TokenKind::Colon) {
190
- println!("Expected ':' after map key '{}'", key);
191
- break;
192
- }
193
-
194
- let value = if let Some(token) = self.peek_clone() {
195
- match token.kind {
196
- TokenKind::String => {
197
- self.advance();
198
- Value::String(token.lexeme.clone())
199
- }
200
- TokenKind::Number => {
201
- self.advance();
202
- Value::Number(token.lexeme.parse().unwrap_or(0.0))
203
- }
204
- TokenKind::Identifier => {
205
- self.advance();
206
- Value::Identifier(token.lexeme.clone())
207
- }
208
- _ => {
209
- println!("Unexpected token in map value: {:?}", token);
210
- Value::Null
211
- }
212
- }
213
- } else {
214
- Value::Null
215
- };
216
-
217
- map.insert(key, value);
218
- }
219
-
220
- if !self.match_token(TokenKind::RBrace) {
221
- println!("Expected '}}' at end of map");
222
- }
223
-
224
- Some(Value::Map(map))
225
- }
226
-
227
- pub fn peek(&self) -> Option<&Token> {
228
- self.tokens.get(self.token_index)
229
- }
230
-
231
- pub fn peek_clone(&self) -> Option<Token> {
232
- self.tokens.get(self.token_index).cloned()
233
- }
234
-
235
- pub fn expect(&mut self, kind: TokenKind) -> Result<&Token, String> {
236
- let tok = self.advance().ok_or("Unexpected end of input")?;
237
- if tok.kind == kind {
238
- Ok(tok)
239
- } else {
240
- Err(format!("Expected {:?}, got {:?}", kind, tok.kind))
241
- }
242
- }
243
-
244
- pub fn collect_block_tokens(&mut self, base_indent: usize) -> Vec<Token> {
245
- let mut tokens = Vec::new();
246
-
247
- while let Some(tok) = self.peek() {
248
- if tok.indent <= base_indent && tok.kind != TokenKind::Newline {
249
- break;
250
- }
251
- tokens.push(self.advance().unwrap().clone());
252
- }
253
-
254
- tokens
255
- }
256
-
257
- pub fn collect_until<F>(&mut self, condition: F) -> Vec<Token> where F: Fn(&Token) -> bool {
258
- let mut collected = Vec::new();
259
- while let Some(token) = self.peek() {
260
- if token.kind == TokenKind::Newline || token.kind == TokenKind::Indent {
261
- self.advance(); // Skip newlines and indents
262
- continue;
263
- }
264
- if token.kind == TokenKind::EOF {
265
- break;
266
- }
267
- if condition(token) {
268
- break;
269
- }
270
- collected.push(self.advance().unwrap().clone());
271
- }
272
- collected
273
- }
274
-
275
- pub fn is_eof(&self) -> bool {
276
- self.token_index >= self.tokens.len()
277
- }
278
-
279
- pub fn parse_block_until_next_else(
280
- &mut self,
281
- base_indent: usize,
282
- global_store: &mut GlobalStore
283
- ) -> Vec<Statement> {
284
- let mut block_tokens = Vec::new();
285
-
286
- while let Some(tok) = self.peek() {
287
- // Stop if we encounter an 'else' at same indent level
288
- if tok.lexeme == "else" && tok.indent == base_indent {
289
- break;
290
- }
291
- block_tokens.push(self.advance().unwrap().clone());
292
- }
293
-
294
- self.parse_block(block_tokens, global_store)
295
- }
296
-
297
- pub fn parse_condition_until_colon(&mut self) -> Option<Value> {
298
- let tokens = self.collect_until(|t| t.kind == TokenKind::Colon);
299
- if tokens.is_empty() {
300
- return None;
301
- }
302
-
303
- let condition = tokens
304
- .iter()
305
- .map(|t| t.lexeme.clone())
306
- .collect::<Vec<_>>()
307
- .join(" ");
308
-
309
- Some(Value::String(condition))
310
- }
311
-
312
- pub fn parse_block_until_else_or_dedent(
313
- &mut self,
314
- base_indent: usize,
315
- global_store: &mut GlobalStore
316
- ) -> Vec<Statement> {
317
- let mut tokens = Vec::new();
318
-
319
- while let Some(tok) = self.peek() {
320
- if tok.lexeme == "else" && tok.indent == base_indent {
321
- break;
322
- }
323
- if tok.indent < base_indent && tok.kind != TokenKind::Newline {
324
- break;
325
- }
326
- tokens.push(self.advance().unwrap().clone());
327
- }
328
-
329
- self.parse_block(tokens, global_store)
330
- }
331
- }