@devaloop/devalang 0.0.1-beta.2 → 0.0.1-beta.3

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 (159) hide show
  1. package/Cargo.toml +84 -81
  2. package/README.md +3 -2
  3. package/docs/CHANGELOG.md +41 -0
  4. package/docs/ROADMAP.md +3 -3
  5. package/examples/chain.deva +19 -0
  6. package/examples/plugin.deva +10 -10
  7. package/examples/routing.deva +23 -0
  8. package/out-tsc/bin/project-version.json +6 -0
  9. package/out-tsc/pkg/devalang_core_bg.wasm.d.ts +8 -8
  10. package/out-tsc/scripts/version/copy-to-binary.d.ts +1 -0
  11. package/out-tsc/scripts/version/copy-to-binary.js +79 -0
  12. package/package.json +23 -10
  13. package/project-version.json +3 -3
  14. package/rust/bindings/Cargo.toml +9 -0
  15. package/rust/bindings/src/lib.rs +86 -0
  16. package/rust/cli/addon/commands.rs +35 -0
  17. package/rust/cli/addon/download.rs +234 -0
  18. package/rust/cli/addon/install.rs +33 -0
  19. package/rust/cli/addon/list.rs +224 -0
  20. package/rust/cli/addon/metadata.rs +124 -0
  21. package/rust/cli/addon/mod.rs +8 -0
  22. package/rust/cli/addon/remove.rs +271 -0
  23. package/rust/cli/addon/update.rs +305 -0
  24. package/rust/cli/{install/addon.rs → addon/utils.rs} +109 -118
  25. package/rust/cli/build/commands.rs +153 -153
  26. package/rust/cli/build/process.rs +165 -165
  27. package/rust/cli/check/mod.rs +208 -208
  28. package/rust/cli/discover/commands.rs +275 -253
  29. package/rust/cli/discover/config.rs +109 -111
  30. package/rust/cli/discover/fs.rs +19 -19
  31. package/rust/cli/discover/install.rs +214 -103
  32. package/rust/cli/discover/metadata.rs +48 -48
  33. package/rust/cli/discover/mod.rs +5 -5
  34. package/rust/cli/me/commands.rs +52 -0
  35. package/rust/cli/me/mod.rs +1 -0
  36. package/rust/cli/mod.rs +12 -12
  37. package/rust/cli/parser.rs +30 -69
  38. package/rust/cli/play/commands.rs +375 -375
  39. package/rust/cli/play/process.rs +159 -159
  40. package/rust/core/audio/engine/driver.rs +19 -2
  41. package/rust/core/audio/engine/export.rs +169 -169
  42. package/rust/core/audio/engine/mod.rs +56 -56
  43. package/rust/core/audio/engine/notes/dsp.rs +88 -85
  44. package/rust/core/audio/engine/notes/mod.rs +53 -44
  45. package/rust/core/audio/engine/notes/params.rs +294 -294
  46. package/rust/core/audio/engine/sample/insert.rs +148 -47
  47. package/rust/core/audio/engine/sample/mod.rs +40 -40
  48. package/rust/core/audio/engine/sample/padding.rs +170 -170
  49. package/rust/core/audio/evaluator/condition.rs +61 -61
  50. package/rust/core/audio/evaluator/numeric.rs +152 -152
  51. package/rust/core/audio/evaluator/rhs.rs +16 -16
  52. package/rust/core/audio/evaluator/string_expr.rs +94 -94
  53. package/rust/core/audio/interpreter/driver.rs +574 -574
  54. package/rust/core/audio/interpreter/mod.rs +2 -2
  55. package/rust/core/audio/interpreter/statements/arrow_call/interprete.rs +9 -5
  56. package/rust/core/audio/interpreter/statements/arrow_call/methods/chord.rs +398 -384
  57. package/rust/core/audio/interpreter/statements/arrow_call/methods/effects.rs +323 -0
  58. package/rust/core/audio/interpreter/statements/arrow_call/methods/mod.rs +1 -0
  59. package/rust/core/audio/interpreter/statements/arrow_call/methods/note.rs +66 -11
  60. package/rust/core/audio/interpreter/statements/arrow_call/mod.rs +3 -3
  61. package/rust/core/audio/interpreter/statements/arrow_call/types/arp.rs +192 -192
  62. package/rust/core/audio/interpreter/statements/arrow_call/types/mod.rs +24 -24
  63. package/rust/core/audio/interpreter/statements/arrow_call/types/pad.rs +116 -116
  64. package/rust/core/audio/interpreter/statements/arrow_call/types/pluck.rs +97 -97
  65. package/rust/core/audio/interpreter/statements/arrow_call/types/sub.rs +100 -100
  66. package/rust/core/audio/interpreter/statements/automate.rs +16 -16
  67. package/rust/core/audio/interpreter/statements/call.rs +31 -1
  68. package/rust/core/audio/interpreter/statements/condition.rs +72 -72
  69. package/rust/core/audio/interpreter/statements/function.rs +24 -24
  70. package/rust/core/audio/interpreter/statements/let_.rs +36 -36
  71. package/rust/core/audio/interpreter/statements/load.rs +17 -17
  72. package/rust/core/audio/interpreter/statements/loop_.rs +115 -115
  73. package/rust/core/audio/interpreter/statements/spawn.rs +51 -2
  74. package/rust/core/audio/interpreter/statements/trigger.rs +242 -239
  75. package/rust/core/audio/loader/trigger.rs +98 -98
  76. package/rust/core/audio/player.rs +70 -70
  77. package/rust/core/audio/special/mod.rs +9 -9
  78. package/rust/core/builder/mod.rs +129 -129
  79. package/rust/core/debugger/lexer.rs +27 -27
  80. package/rust/core/debugger/logs.rs +52 -52
  81. package/rust/core/debugger/preprocessor.rs +27 -27
  82. package/rust/core/debugger/store.rs +38 -38
  83. package/rust/core/lexer/driver.rs +59 -59
  84. package/rust/core/lexer/handler/arrow.rs +82 -82
  85. package/rust/core/lexer/handler/at.rs +21 -21
  86. package/rust/core/lexer/handler/brace.rs +41 -41
  87. package/rust/core/lexer/handler/colon.rs +21 -21
  88. package/rust/core/lexer/handler/comment.rs +30 -30
  89. package/rust/core/lexer/handler/dot.rs +21 -21
  90. package/rust/core/lexer/handler/driver.rs +337 -337
  91. package/rust/core/lexer/handler/identifier.rs +47 -47
  92. package/rust/core/lexer/handler/indent.rs +66 -66
  93. package/rust/core/lexer/handler/mod.rs +15 -15
  94. package/rust/core/lexer/handler/newline.rs +23 -23
  95. package/rust/core/lexer/handler/number.rs +31 -31
  96. package/rust/core/lexer/handler/operator.rs +46 -46
  97. package/rust/core/lexer/handler/parenthesis.rs +41 -41
  98. package/rust/core/lexer/handler/slash.rs +21 -21
  99. package/rust/core/lexer/handler/string.rs +63 -63
  100. package/rust/core/lexer/mod.rs +3 -3
  101. package/rust/core/mod.rs +9 -9
  102. package/rust/core/parser/driver/block.rs +111 -111
  103. package/rust/core/parser/driver/cursor.rs +82 -82
  104. package/rust/core/parser/driver/driver_impl.rs +21 -1
  105. package/rust/core/parser/driver/mod.rs +6 -6
  106. package/rust/core/parser/driver/parse_array.rs +120 -120
  107. package/rust/core/parser/driver/parse_map.rs +247 -223
  108. package/rust/core/parser/driver/parser.rs +160 -160
  109. package/rust/core/parser/handler/arrow_call.rs +65 -14
  110. package/rust/core/parser/handler/identifier/synth.rs +171 -135
  111. package/rust/core/parser/handler/mod.rs +9 -9
  112. package/rust/core/parser/handler/pattern.rs +24 -1
  113. package/rust/core/plugin/loader.rs +137 -137
  114. package/rust/core/plugin/mod.rs +2 -2
  115. package/rust/core/plugin/runner/non_wasm.rs +481 -297
  116. package/rust/core/plugin/runner/wasm32.rs +1 -0
  117. package/rust/core/preprocessor/loader/inject.rs +313 -278
  118. package/rust/core/preprocessor/loader/loader_helpers.rs +110 -110
  119. package/rust/core/preprocessor/loader/mod.rs +235 -235
  120. package/rust/core/preprocessor/module.rs +55 -55
  121. package/rust/core/preprocessor/processor/handlers.rs +107 -107
  122. package/rust/core/preprocessor/resolver/bank.rs +49 -49
  123. package/rust/core/preprocessor/resolver/call.rs +124 -124
  124. package/rust/core/preprocessor/resolver/condition.rs +95 -95
  125. package/rust/core/preprocessor/resolver/driver.rs +324 -324
  126. package/rust/core/preprocessor/resolver/function.rs +69 -69
  127. package/rust/core/preprocessor/resolver/group.rs +122 -122
  128. package/rust/core/preprocessor/resolver/let_.rs +32 -32
  129. package/rust/core/preprocessor/resolver/loop_.rs +318 -318
  130. package/rust/core/preprocessor/resolver/mod.rs +16 -16
  131. package/rust/core/preprocessor/resolver/pattern.rs +95 -83
  132. package/rust/core/preprocessor/resolver/spawn.rs +99 -99
  133. package/rust/core/preprocessor/resolver/synth.rs +54 -54
  134. package/rust/core/preprocessor/resolver/tempo.rs +48 -48
  135. package/rust/core/preprocessor/resolver/trigger.rs +116 -116
  136. package/rust/core/preprocessor/resolver/value.rs +176 -176
  137. package/rust/core/store/global.rs +57 -57
  138. package/rust/lib.rs +323 -323
  139. package/rust/macros/Cargo.toml +14 -0
  140. package/rust/macros/src/lib.rs +52 -0
  141. package/rust/main.rs +311 -142
  142. package/rust/types/Cargo.toml +1 -1
  143. package/rust/types/src/addons.rs +3 -1
  144. package/rust/types/src/config.rs +1 -3
  145. package/rust/utils/Cargo.toml +5 -2
  146. package/rust/utils/src/file.rs +397 -14
  147. package/rust/utils/src/path.rs +31 -2
  148. package/rust/utils/src/version.rs +38 -7
  149. package/rust/web/auth.rs +5 -0
  150. package/rust/web/forge.rs +5 -0
  151. package/rust/web/mod.rs +5 -3
  152. package/typescript/scripts/version/copy-to-binary.ts +82 -0
  153. package/rust/cli/bank/api.rs +0 -122
  154. package/rust/cli/bank/commands.rs +0 -306
  155. package/rust/cli/bank/mod.rs +0 -29
  156. package/rust/cli/install/bank.rs +0 -72
  157. package/rust/cli/install/commands.rs +0 -35
  158. package/rust/cli/install/mod.rs +0 -4
  159. package/rust/cli/install/plugin.rs +0 -80
@@ -1,98 +1,98 @@
1
- use crate::core::parser::statement::StatementKind;
2
- use devalang_types::store::VariableTable;
3
- use devalang_types::{Duration, Value};
4
-
5
- pub fn load_trigger(
6
- trigger: &Value,
7
- duration: &Duration,
8
- _effects: &Option<Value>,
9
- base_duration: f32,
10
- variable_table: VariableTable,
11
- ) -> (String, f32) {
12
- let mut trigger_path = String::new();
13
- let mut duration_as_secs = 0.0;
14
-
15
- match trigger {
16
- Value::String(src) => {
17
- trigger_path = src.to_string();
18
- }
19
- Value::Identifier(src) => {
20
- trigger_path = src.to_string();
21
- }
22
-
23
- Value::Map(map) => {
24
- if let Some(Value::String(src)) = map.get("entity") {
25
- trigger_path = format!("devalang://bank/{}", src);
26
- } else if let Some(Value::Identifier(src)) = map.get("entity") {
27
- trigger_path = format!("devalang://bank/{}", src);
28
- } else {
29
- eprintln!(
30
- "❌ Trigger map must contain an 'entity' key with a string or identifier value."
31
- );
32
- }
33
- }
34
- Value::Sample(src) => {
35
- trigger_path = src.to_string();
36
- }
37
- Value::Statement(stmt) => {
38
- if let StatementKind::Trigger {
39
- entity,
40
- duration: _,
41
- effects: _,
42
- } = &stmt.kind
43
- {
44
- trigger_path = entity.clone();
45
- } else {
46
- eprintln!(
47
- "❌ Trigger statement must be of type 'Trigger', found: {:?}",
48
- stmt.kind
49
- );
50
- }
51
- }
52
- _ => {
53
- eprintln!(
54
- "❌ Invalid trigger type. Expected a string or identifier variable, found: {:?}",
55
- trigger
56
- );
57
- }
58
- }
59
-
60
- match duration {
61
- Duration::Identifier(duration_identifier) => {
62
- if duration_identifier == "auto" {
63
- duration_as_secs = base_duration;
64
- } else if let Some(Value::Number(num)) = variable_table.get(duration_identifier) {
65
- duration_as_secs = *num;
66
- } else if let Some(Value::String(num_str)) = variable_table.get(duration_identifier) {
67
- duration_as_secs = num_str.parse::<f32>().unwrap_or(base_duration);
68
- } else if let Some(Value::Identifier(num_str)) = variable_table.get(duration_identifier)
69
- {
70
- duration_as_secs = num_str.parse::<f32>().unwrap_or(base_duration);
71
- } else {
72
- eprintln!("❌ Invalid duration identifier: {}", duration_identifier);
73
- }
74
- }
75
-
76
- Duration::Number(num) => {
77
- duration_as_secs = *num;
78
- }
79
-
80
- Duration::Auto => {
81
- duration_as_secs = base_duration;
82
- }
83
-
84
- Duration::Beat(beat_str) => {
85
- let parts: Vec<&str> = beat_str.split('/').collect();
86
-
87
- if parts.len() == 2 {
88
- let numerator: f32 = parts[0].parse().unwrap_or(1.0);
89
- let denominator: f32 = parts[1].parse().unwrap_or(1.0);
90
- duration_as_secs = (numerator / denominator) * base_duration;
91
- } else {
92
- eprintln!("❌ Invalid beat duration format: {}", beat_str);
93
- }
94
- }
95
- }
96
-
97
- (trigger_path, duration_as_secs)
98
- }
1
+ use crate::core::parser::statement::StatementKind;
2
+ use devalang_types::store::VariableTable;
3
+ use devalang_types::{Duration, Value};
4
+
5
+ pub fn load_trigger(
6
+ trigger: &Value,
7
+ duration: &Duration,
8
+ _effects: &Option<Value>,
9
+ base_duration: f32,
10
+ variable_table: VariableTable,
11
+ ) -> (String, f32) {
12
+ let mut trigger_path = String::new();
13
+ let mut duration_as_secs = 0.0;
14
+
15
+ match trigger {
16
+ Value::String(src) => {
17
+ trigger_path = src.to_string();
18
+ }
19
+ Value::Identifier(src) => {
20
+ trigger_path = src.to_string();
21
+ }
22
+
23
+ Value::Map(map) => {
24
+ if let Some(Value::String(src)) = map.get("entity") {
25
+ trigger_path = format!("devalang://bank/{}", src);
26
+ } else if let Some(Value::Identifier(src)) = map.get("entity") {
27
+ trigger_path = format!("devalang://bank/{}", src);
28
+ } else {
29
+ eprintln!(
30
+ "❌ Trigger map must contain an 'entity' key with a string or identifier value."
31
+ );
32
+ }
33
+ }
34
+ Value::Sample(src) => {
35
+ trigger_path = src.to_string();
36
+ }
37
+ Value::Statement(stmt) => {
38
+ if let StatementKind::Trigger {
39
+ entity,
40
+ duration: _,
41
+ effects: _,
42
+ } = &stmt.kind
43
+ {
44
+ trigger_path = entity.clone();
45
+ } else {
46
+ eprintln!(
47
+ "❌ Trigger statement must be of type 'Trigger', found: {:?}",
48
+ stmt.kind
49
+ );
50
+ }
51
+ }
52
+ _ => {
53
+ eprintln!(
54
+ "❌ Invalid trigger type. Expected a string or identifier variable, found: {:?}",
55
+ trigger
56
+ );
57
+ }
58
+ }
59
+
60
+ match duration {
61
+ Duration::Identifier(duration_identifier) => {
62
+ if duration_identifier == "auto" {
63
+ duration_as_secs = base_duration;
64
+ } else if let Some(Value::Number(num)) = variable_table.get(duration_identifier) {
65
+ duration_as_secs = *num;
66
+ } else if let Some(Value::String(num_str)) = variable_table.get(duration_identifier) {
67
+ duration_as_secs = num_str.parse::<f32>().unwrap_or(base_duration);
68
+ } else if let Some(Value::Identifier(num_str)) = variable_table.get(duration_identifier)
69
+ {
70
+ duration_as_secs = num_str.parse::<f32>().unwrap_or(base_duration);
71
+ } else {
72
+ eprintln!("❌ Invalid duration identifier: {}", duration_identifier);
73
+ }
74
+ }
75
+
76
+ Duration::Number(num) => {
77
+ duration_as_secs = *num;
78
+ }
79
+
80
+ Duration::Auto => {
81
+ duration_as_secs = base_duration;
82
+ }
83
+
84
+ Duration::Beat(beat_str) => {
85
+ let parts: Vec<&str> = beat_str.split('/').collect();
86
+
87
+ if parts.len() == 2 {
88
+ let numerator: f32 = parts[0].parse().unwrap_or(1.0);
89
+ let denominator: f32 = parts[1].parse().unwrap_or(1.0);
90
+ duration_as_secs = (numerator / denominator) * base_duration;
91
+ } else {
92
+ eprintln!("❌ Invalid beat duration format: {}", beat_str);
93
+ }
94
+ }
95
+ }
96
+
97
+ (trigger_path, duration_as_secs)
98
+ }
@@ -1,70 +1,70 @@
1
- use rodio::{Decoder, OutputStream, OutputStreamHandle, Sink, Source};
2
- use std::{fs::File, io::BufReader};
3
-
4
- pub struct AudioPlayer {
5
- _stream: OutputStream,
6
- handle: OutputStreamHandle,
7
- sink: Sink,
8
- last_path: Option<String>,
9
- }
10
-
11
- impl Default for AudioPlayer {
12
- fn default() -> Self {
13
- Self::new()
14
- }
15
- }
16
-
17
- impl AudioPlayer {
18
- pub fn new() -> Self {
19
- let (stream, handle) = OutputStream::try_default().unwrap();
20
- let sink = Sink::try_new(&handle).unwrap();
21
-
22
- Self {
23
- _stream: stream,
24
- handle,
25
- sink,
26
- last_path: None,
27
- }
28
- }
29
-
30
- fn load_source(&self, path: &str) -> Option<impl Source<Item = f32> + Send + 'static> {
31
- if let Ok(file) = File::open(path) {
32
- let reader = BufReader::new(file);
33
- match Decoder::new(reader) {
34
- Ok(decoder) => Some(decoder.convert_samples()),
35
- Err(e) => {
36
- eprintln!("❌ Failed to decode audio file '{}': {}", path, e);
37
- None
38
- }
39
- }
40
- } else {
41
- eprintln!("❌ Could not open audio file: {}", path);
42
- None
43
- }
44
- }
45
-
46
- pub fn play_file_once(&mut self, path: &str) {
47
- self.sink.stop();
48
- self.sink = Sink::try_new(&self.handle).unwrap();
49
- self.sink.set_volume(1.0);
50
-
51
- if let Some(source) = self.load_source(path) {
52
- self.sink.append(source);
53
- self.last_path = Some(path.to_string());
54
- } else {
55
- eprintln!("⚠️ Skipping playback: failed to load '{}'", path);
56
- }
57
- }
58
-
59
- pub fn replay_last(&mut self) {
60
- if let Some(path) = self.last_path.clone() {
61
- self.play_file_once(&path);
62
- } else {
63
- eprintln!("⚠️ No previous audio to replay.");
64
- }
65
- }
66
-
67
- pub fn wait_until_end(&self) {
68
- self.sink.sleep_until_end();
69
- }
70
- }
1
+ use rodio::{Decoder, OutputStream, OutputStreamHandle, Sink, Source};
2
+ use std::{fs::File, io::BufReader};
3
+
4
+ pub struct AudioPlayer {
5
+ _stream: OutputStream,
6
+ handle: OutputStreamHandle,
7
+ sink: Sink,
8
+ last_path: Option<String>,
9
+ }
10
+
11
+ impl Default for AudioPlayer {
12
+ fn default() -> Self {
13
+ Self::new()
14
+ }
15
+ }
16
+
17
+ impl AudioPlayer {
18
+ pub fn new() -> Self {
19
+ let (stream, handle) = OutputStream::try_default().unwrap();
20
+ let sink = Sink::try_new(&handle).unwrap();
21
+
22
+ Self {
23
+ _stream: stream,
24
+ handle,
25
+ sink,
26
+ last_path: None,
27
+ }
28
+ }
29
+
30
+ fn load_source(&self, path: &str) -> Option<impl Source<Item = f32> + Send + 'static> {
31
+ if let Ok(file) = File::open(path) {
32
+ let reader = BufReader::new(file);
33
+ match Decoder::new(reader) {
34
+ Ok(decoder) => Some(decoder.convert_samples()),
35
+ Err(e) => {
36
+ eprintln!("❌ Failed to decode audio file '{}': {}", path, e);
37
+ None
38
+ }
39
+ }
40
+ } else {
41
+ eprintln!("❌ Could not open audio file: {}", path);
42
+ None
43
+ }
44
+ }
45
+
46
+ pub fn play_file_once(&mut self, path: &str) {
47
+ self.sink.stop();
48
+ self.sink = Sink::try_new(&self.handle).unwrap();
49
+ self.sink.set_volume(1.0);
50
+
51
+ if let Some(source) = self.load_source(path) {
52
+ self.sink.append(source);
53
+ self.last_path = Some(path.to_string());
54
+ } else {
55
+ eprintln!("⚠️ Skipping playback: failed to load '{}'", path);
56
+ }
57
+ }
58
+
59
+ pub fn replay_last(&mut self) {
60
+ if let Some(path) = self.last_path.clone() {
61
+ self.play_file_once(&path);
62
+ } else {
63
+ eprintln!("⚠️ No previous audio to replay.");
64
+ }
65
+ }
66
+
67
+ pub fn wait_until_end(&self) {
68
+ self.sink.sleep_until_end();
69
+ }
70
+ }
@@ -1,9 +1,9 @@
1
- pub mod easing;
2
- pub mod env;
3
- pub mod math;
4
- pub mod modulator;
5
-
6
- pub use easing::find_and_eval_first_easing_call;
7
- pub use env::resolve_env_atom;
8
- pub use math::find_and_eval_first_math_call;
9
- pub use modulator::find_and_eval_first_mod_call;
1
+ pub mod easing;
2
+ pub mod env;
3
+ pub mod math;
4
+ pub mod modulator;
5
+
6
+ pub use easing::find_and_eval_first_easing_call;
7
+ pub use env::resolve_env_atom;
8
+ pub use math::find_and_eval_first_math_call;
9
+ pub use modulator::find_and_eval_first_mod_call;
@@ -1,129 +1,129 @@
1
- use crate::core::audio::engine::render_audio_with_modules;
2
- use crate::core::parser::statement::Statement;
3
- use crate::core::store::global::GlobalStore;
4
- use devalang_utils::logger::Logger;
5
- use std::io::Write;
6
- use std::{collections::HashMap, fs::create_dir_all};
7
-
8
- pub struct Builder {}
9
-
10
- impl Default for Builder {
11
- fn default() -> Self {
12
- Self::new()
13
- }
14
- }
15
-
16
- impl Builder {
17
- pub fn new() -> Self {
18
- Builder {}
19
- }
20
-
21
- pub fn build_ast(
22
- &self,
23
- modules: &HashMap<String, Vec<Statement>>,
24
- out_dir: &str,
25
- compress: bool,
26
- ) {
27
- for (name, statements) in modules {
28
- let formatted_name = name.split("/").last().unwrap_or(name);
29
- let formatted_name = formatted_name.replace(".deva", "");
30
-
31
- create_dir_all(format!("{}/ast", out_dir)).expect("Failed to create AST directory");
32
-
33
- let file_path = format!("{}/ast/{}.json", out_dir, formatted_name);
34
- let mut file = std::fs::File::create(file_path).expect("Failed to create AST file");
35
- let content = if compress {
36
- serde_json::to_string(&statements).expect("Failed to serialize AST")
37
- } else {
38
- serde_json::to_string_pretty(&statements).expect("Failed to serialize AST")
39
- };
40
-
41
- file.write_all(content.as_bytes())
42
- .expect("Failed to write AST to file");
43
- }
44
- }
45
-
46
- pub fn build_audio(
47
- &self,
48
- modules: &HashMap<String, Vec<Statement>>,
49
- normalized_output_dir: &str,
50
- global_store: &mut GlobalStore,
51
- audio_format: Option<String>,
52
- sample_rate: Option<u32>,
53
- ) {
54
- let logger = Logger::new();
55
-
56
- let audio_engines =
57
- render_audio_with_modules(modules.clone(), normalized_output_dir, global_store);
58
-
59
- create_dir_all(format!("{}/audio", normalized_output_dir))
60
- .expect("Failed to create audio directory");
61
-
62
- for (module_name, mut audio_engine) in audio_engines {
63
- let formatted_module_name = module_name
64
- .split('/')
65
- .next_back()
66
- .unwrap_or(&module_name)
67
- .replace(".deva", "");
68
-
69
- let output_path = format!(
70
- "{}/audio/{}.wav",
71
- normalized_output_dir, formatted_module_name
72
- );
73
-
74
- match audio_engine.generate_wav_file(&output_path, audio_format.clone(), sample_rate) {
75
- Ok(_) => {}
76
- Err(msg) => {
77
- logger.log_error_with_stacktrace(
78
- &format!(
79
- "Unable to generate WAV file for module '{}': {}",
80
- formatted_module_name, msg
81
- ),
82
- &module_name,
83
- );
84
- }
85
- }
86
- }
87
- }
88
-
89
- pub fn build_midi(
90
- &self,
91
- modules: &HashMap<String, Vec<Statement>>,
92
- normalized_output_dir: &str,
93
- global_store: &mut GlobalStore,
94
- ) {
95
- let logger = Logger::new();
96
-
97
- let audio_engines =
98
- render_audio_with_modules(modules.clone(), normalized_output_dir, global_store);
99
-
100
- create_dir_all(format!("{}/midi", normalized_output_dir))
101
- .expect("Failed to create MIDI directory");
102
-
103
- for (module_name, mut audio_engine) in audio_engines {
104
- let formatted_module_name = module_name
105
- .split('/')
106
- .next_back()
107
- .unwrap_or(&module_name)
108
- .replace(".deva", "");
109
-
110
- let output_path = format!(
111
- "{}/midi/{}.mid",
112
- normalized_output_dir, formatted_module_name
113
- );
114
-
115
- match audio_engine.generate_midi_file(&output_path, None, None) {
116
- Ok(_) => {}
117
- Err(msg) => {
118
- logger.log_error_with_stacktrace(
119
- &format!(
120
- "Unable to generate MIDI file for module '{}': {}",
121
- formatted_module_name, msg
122
- ),
123
- &module_name,
124
- );
125
- }
126
- }
127
- }
128
- }
129
- }
1
+ use crate::core::audio::engine::render_audio_with_modules;
2
+ use crate::core::parser::statement::Statement;
3
+ use crate::core::store::global::GlobalStore;
4
+ use devalang_utils::logger::Logger;
5
+ use std::io::Write;
6
+ use std::{collections::HashMap, fs::create_dir_all};
7
+
8
+ pub struct Builder {}
9
+
10
+ impl Default for Builder {
11
+ fn default() -> Self {
12
+ Self::new()
13
+ }
14
+ }
15
+
16
+ impl Builder {
17
+ pub fn new() -> Self {
18
+ Builder {}
19
+ }
20
+
21
+ pub fn build_ast(
22
+ &self,
23
+ modules: &HashMap<String, Vec<Statement>>,
24
+ out_dir: &str,
25
+ compress: bool,
26
+ ) {
27
+ for (name, statements) in modules {
28
+ let formatted_name = name.split("/").last().unwrap_or(name);
29
+ let formatted_name = formatted_name.replace(".deva", "");
30
+
31
+ create_dir_all(format!("{}/ast", out_dir)).expect("Failed to create AST directory");
32
+
33
+ let file_path = format!("{}/ast/{}.json", out_dir, formatted_name);
34
+ let mut file = std::fs::File::create(file_path).expect("Failed to create AST file");
35
+ let content = if compress {
36
+ serde_json::to_string(&statements).expect("Failed to serialize AST")
37
+ } else {
38
+ serde_json::to_string_pretty(&statements).expect("Failed to serialize AST")
39
+ };
40
+
41
+ file.write_all(content.as_bytes())
42
+ .expect("Failed to write AST to file");
43
+ }
44
+ }
45
+
46
+ pub fn build_audio(
47
+ &self,
48
+ modules: &HashMap<String, Vec<Statement>>,
49
+ normalized_output_dir: &str,
50
+ global_store: &mut GlobalStore,
51
+ audio_format: Option<String>,
52
+ sample_rate: Option<u32>,
53
+ ) {
54
+ let logger = Logger::new();
55
+
56
+ let audio_engines =
57
+ render_audio_with_modules(modules.clone(), normalized_output_dir, global_store);
58
+
59
+ create_dir_all(format!("{}/audio", normalized_output_dir))
60
+ .expect("Failed to create audio directory");
61
+
62
+ for (module_name, mut audio_engine) in audio_engines {
63
+ let formatted_module_name = module_name
64
+ .split('/')
65
+ .next_back()
66
+ .unwrap_or(&module_name)
67
+ .replace(".deva", "");
68
+
69
+ let output_path = format!(
70
+ "{}/audio/{}.wav",
71
+ normalized_output_dir, formatted_module_name
72
+ );
73
+
74
+ match audio_engine.generate_wav_file(&output_path, audio_format.clone(), sample_rate) {
75
+ Ok(_) => {}
76
+ Err(msg) => {
77
+ logger.log_error_with_stacktrace(
78
+ &format!(
79
+ "Unable to generate WAV file for module '{}': {}",
80
+ formatted_module_name, msg
81
+ ),
82
+ &module_name,
83
+ );
84
+ }
85
+ }
86
+ }
87
+ }
88
+
89
+ pub fn build_midi(
90
+ &self,
91
+ modules: &HashMap<String, Vec<Statement>>,
92
+ normalized_output_dir: &str,
93
+ global_store: &mut GlobalStore,
94
+ ) {
95
+ let logger = Logger::new();
96
+
97
+ let audio_engines =
98
+ render_audio_with_modules(modules.clone(), normalized_output_dir, global_store);
99
+
100
+ create_dir_all(format!("{}/midi", normalized_output_dir))
101
+ .expect("Failed to create MIDI directory");
102
+
103
+ for (module_name, mut audio_engine) in audio_engines {
104
+ let formatted_module_name = module_name
105
+ .split('/')
106
+ .next_back()
107
+ .unwrap_or(&module_name)
108
+ .replace(".deva", "");
109
+
110
+ let output_path = format!(
111
+ "{}/midi/{}.mid",
112
+ normalized_output_dir, formatted_module_name
113
+ );
114
+
115
+ match audio_engine.generate_midi_file(&output_path, None, None) {
116
+ Ok(_) => {}
117
+ Err(msg) => {
118
+ logger.log_error_with_stacktrace(
119
+ &format!(
120
+ "Unable to generate MIDI file for module '{}': {}",
121
+ formatted_module_name, msg
122
+ ),
123
+ &module_name,
124
+ );
125
+ }
126
+ }
127
+ }
128
+ }
129
+ }
@@ -1,27 +1,27 @@
1
- use crate::core::{debugger::Debugger, lexer::token::Token};
2
- use std::{collections::HashMap, fs::create_dir_all};
3
-
4
- pub fn write_lexer_log_file(
5
- output_dir: &str,
6
- file_name: &str,
7
- modules: HashMap<String, Vec<Token>>,
8
- ) {
9
- let debugger = Debugger::new();
10
- let mut content = String::new();
11
-
12
- let log_directory = format!("{}/logs", output_dir);
13
-
14
- create_dir_all(&log_directory).expect("Failed to create log directory");
15
-
16
- for (path, tokens) in modules {
17
- content.push_str(&format!("--- Resolved Tokens for {} ---\n", path));
18
-
19
- for token in tokens {
20
- content.push_str(&format!("{:?}\n", token));
21
- }
22
-
23
- content.push('\n');
24
- }
25
-
26
- debugger.write_log_file(&log_directory, file_name, &content);
27
- }
1
+ use crate::core::{debugger::Debugger, lexer::token::Token};
2
+ use std::{collections::HashMap, fs::create_dir_all};
3
+
4
+ pub fn write_lexer_log_file(
5
+ output_dir: &str,
6
+ file_name: &str,
7
+ modules: HashMap<String, Vec<Token>>,
8
+ ) {
9
+ let debugger = Debugger::new();
10
+ let mut content = String::new();
11
+
12
+ let log_directory = format!("{}/logs", output_dir);
13
+
14
+ create_dir_all(&log_directory).expect("Failed to create log directory");
15
+
16
+ for (path, tokens) in modules {
17
+ content.push_str(&format!("--- Resolved Tokens for {} ---\n", path));
18
+
19
+ for token in tokens {
20
+ content.push_str(&format!("{:?}\n", token));
21
+ }
22
+
23
+ content.push('\n');
24
+ }
25
+
26
+ debugger.write_log_file(&log_directory, file_name, &content);
27
+ }