@devaloop/devalang 0.0.1-alpha.14 → 0.0.1-alpha.16

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 (177) hide show
  1. package/.devalang +10 -8
  2. package/.github/workflows/ci.yml +92 -0
  3. package/Cargo.toml +60 -58
  4. package/README.md +32 -15
  5. package/docs/CHANGELOG.md +93 -1
  6. package/docs/CONTRIBUTING.md +101 -1
  7. package/docs/ROADMAP.md +2 -2
  8. package/docs/TODO.md +1 -1
  9. package/examples/automation.deva +42 -0
  10. package/examples/bank.deva +4 -4
  11. package/examples/events.deva +12 -0
  12. package/examples/function.deva +4 -4
  13. package/examples/index.deva +39 -25
  14. package/examples/loop.deva +5 -11
  15. package/examples/pattern.deva +8 -0
  16. package/examples/plugin.deva +16 -0
  17. package/examples/variables.deva +1 -1
  18. package/out-tsc/bin/index.js +51 -7
  19. package/out-tsc/index.js +3 -1
  20. package/out-tsc/scripts/postbuild.js +9 -10
  21. package/out-tsc/scripts/postinstall.js +49 -0
  22. package/package.json +12 -4
  23. package/project-version.json +3 -3
  24. package/rust/cli/bank.rs +462 -456
  25. package/rust/cli/build.rs +252 -199
  26. package/rust/cli/check.rs +221 -180
  27. package/rust/cli/driver.rs +297 -292
  28. package/rust/cli/generator.rs +1 -0
  29. package/rust/cli/init.rs +87 -79
  30. package/rust/cli/install.rs +35 -32
  31. package/rust/cli/login.rs +127 -134
  32. package/rust/cli/mod.rs +13 -11
  33. package/rust/cli/play.rs +1123 -218
  34. package/rust/cli/telemetry.rs +19 -0
  35. package/rust/cli/template.rs +69 -57
  36. package/rust/cli/update.rs +6 -4
  37. package/rust/common/api.rs +5 -8
  38. package/rust/common/cdn.rs +3 -6
  39. package/rust/common/mod.rs +3 -3
  40. package/rust/common/sso.rs +3 -6
  41. package/rust/config/driver.rs +118 -94
  42. package/rust/config/loader.rs +165 -156
  43. package/rust/config/mod.rs +4 -2
  44. package/rust/config/settings.rs +91 -0
  45. package/rust/config/stats.rs +257 -0
  46. package/rust/core/audio/engine.rs +696 -518
  47. package/rust/core/audio/evaluator.rs +263 -31
  48. package/rust/core/audio/interpreter/arrow_call.rs +198 -161
  49. package/rust/core/audio/interpreter/automate.rs +18 -0
  50. package/rust/core/audio/interpreter/call.rs +98 -95
  51. package/rust/core/audio/interpreter/condition.rs +70 -71
  52. package/rust/core/audio/interpreter/driver.rs +487 -198
  53. package/rust/core/audio/interpreter/function.rs +26 -21
  54. package/rust/core/audio/interpreter/let_.rs +38 -19
  55. package/rust/core/audio/interpreter/load.rs +18 -18
  56. package/rust/core/audio/interpreter/loop_.rs +113 -73
  57. package/rust/core/audio/interpreter/mod.rs +14 -13
  58. package/rust/core/audio/interpreter/sleep.rs +27 -30
  59. package/rust/core/audio/interpreter/spawn.rs +105 -102
  60. package/rust/core/audio/interpreter/tempo.rs +19 -16
  61. package/rust/core/audio/interpreter/trigger.rs +239 -210
  62. package/rust/core/audio/loader/mod.rs +1 -1
  63. package/rust/core/audio/loader/trigger.rs +100 -97
  64. package/rust/core/audio/mod.rs +7 -6
  65. package/rust/core/audio/player.rs +64 -64
  66. package/rust/core/audio/renderer.rs +56 -53
  67. package/rust/core/audio/special/easing.rs +189 -0
  68. package/rust/core/audio/special/env.rs +43 -0
  69. package/rust/core/audio/special/math.rs +102 -0
  70. package/rust/core/audio/special/mod.rs +9 -0
  71. package/rust/core/audio/special/modulator.rs +143 -0
  72. package/rust/core/builder/mod.rs +80 -85
  73. package/rust/core/debugger/lexer.rs +27 -27
  74. package/rust/core/debugger/mod.rs +24 -23
  75. package/rust/core/debugger/module.rs +55 -47
  76. package/rust/core/debugger/preprocessor.rs +27 -27
  77. package/rust/core/debugger/store.rs +40 -39
  78. package/rust/core/error/mod.rs +80 -66
  79. package/rust/core/lexer/handler/arrow.rs +82 -31
  80. package/rust/core/lexer/handler/at.rs +21 -21
  81. package/rust/core/lexer/handler/brace.rs +41 -41
  82. package/rust/core/lexer/handler/colon.rs +21 -21
  83. package/rust/core/lexer/handler/comment.rs +30 -30
  84. package/rust/core/lexer/handler/dot.rs +21 -21
  85. package/rust/core/lexer/handler/driver.rs +337 -263
  86. package/rust/core/lexer/handler/identifier.rs +46 -42
  87. package/rust/core/lexer/handler/indent.rs +66 -66
  88. package/rust/core/lexer/handler/mod.rs +16 -16
  89. package/rust/core/lexer/handler/newline.rs +23 -23
  90. package/rust/core/lexer/handler/number.rs +31 -31
  91. package/rust/core/lexer/handler/operator.rs +46 -44
  92. package/rust/core/lexer/handler/parenthesis.rs +41 -41
  93. package/rust/core/lexer/handler/slash.rs +21 -21
  94. package/rust/core/lexer/handler/string.rs +63 -63
  95. package/rust/core/lexer/mod.rs +54 -51
  96. package/rust/core/lexer/token.rs +97 -91
  97. package/rust/core/mod.rs +11 -11
  98. package/rust/core/parser/driver.rs +513 -408
  99. package/rust/core/parser/handler/arrow_call.rs +233 -211
  100. package/rust/core/parser/handler/at.rs +245 -162
  101. package/rust/core/parser/handler/bank.rs +94 -69
  102. package/rust/core/parser/handler/condition.rs +80 -74
  103. package/rust/core/parser/handler/dot.rs +143 -135
  104. package/rust/core/parser/handler/identifier/automate.rs +257 -0
  105. package/rust/core/parser/handler/identifier/call.rs +91 -88
  106. package/rust/core/parser/handler/identifier/emit.rs +66 -0
  107. package/rust/core/parser/handler/identifier/function.rs +100 -92
  108. package/rust/core/parser/handler/identifier/group.rs +85 -75
  109. package/rust/core/parser/handler/identifier/let_.rs +158 -127
  110. package/rust/core/parser/handler/identifier/mod.rs +54 -52
  111. package/rust/core/parser/handler/identifier/on.rs +98 -0
  112. package/rust/core/parser/handler/identifier/print.rs +52 -0
  113. package/rust/core/parser/handler/identifier/sleep.rs +36 -33
  114. package/rust/core/parser/handler/identifier/spawn.rs +91 -88
  115. package/rust/core/parser/handler/identifier/synth.rs +65 -65
  116. package/rust/core/parser/handler/loop_.rs +170 -72
  117. package/rust/core/parser/handler/mod.rs +8 -8
  118. package/rust/core/parser/handler/tempo.rs +53 -47
  119. package/rust/core/parser/mod.rs +4 -4
  120. package/rust/core/parser/statement.rs +142 -108
  121. package/rust/core/plugin/loader.rs +123 -48
  122. package/rust/core/plugin/mod.rs +2 -1
  123. package/rust/core/plugin/runner.rs +296 -0
  124. package/rust/core/preprocessor/loader.rs +515 -326
  125. package/rust/core/preprocessor/mod.rs +4 -4
  126. package/rust/core/preprocessor/module.rs +60 -58
  127. package/rust/core/preprocessor/processor.rs +99 -101
  128. package/rust/core/preprocessor/resolver/bank.rs +51 -49
  129. package/rust/core/preprocessor/resolver/call.rs +100 -100
  130. package/rust/core/preprocessor/resolver/condition.rs +97 -97
  131. package/rust/core/preprocessor/resolver/driver.rs +310 -278
  132. package/rust/core/preprocessor/resolver/function.rs +69 -78
  133. package/rust/core/preprocessor/resolver/group.rs +96 -91
  134. package/rust/core/preprocessor/resolver/let_.rs +32 -28
  135. package/rust/core/preprocessor/resolver/loop_.rs +320 -91
  136. package/rust/core/preprocessor/resolver/mod.rs +15 -15
  137. package/rust/core/preprocessor/resolver/spawn.rs +76 -92
  138. package/rust/core/preprocessor/resolver/synth.rs +56 -50
  139. package/rust/core/preprocessor/resolver/tempo.rs +50 -49
  140. package/rust/core/preprocessor/resolver/trigger.rs +113 -116
  141. package/rust/core/preprocessor/resolver/value.rs +81 -87
  142. package/rust/core/shared/bank.rs +1 -1
  143. package/rust/core/shared/duration.rs +9 -9
  144. package/rust/core/shared/mod.rs +3 -3
  145. package/rust/core/shared/value.rs +35 -32
  146. package/rust/core/store/function.rs +34 -34
  147. package/rust/core/store/global.rs +55 -38
  148. package/rust/core/store/mod.rs +5 -5
  149. package/rust/core/store/variable.rs +37 -34
  150. package/rust/core/utils/mod.rs +2 -2
  151. package/rust/core/utils/path.rs +37 -31
  152. package/rust/core/utils/validation.rs +35 -37
  153. package/rust/installer/addon.rs +84 -80
  154. package/rust/installer/bank.rs +62 -65
  155. package/rust/installer/mod.rs +5 -5
  156. package/rust/installer/plugin.rs +54 -55
  157. package/rust/installer/utils.rs +56 -56
  158. package/rust/lib.rs +156 -164
  159. package/rust/main.rs +250 -145
  160. package/rust/utils/error.rs +200 -0
  161. package/rust/utils/file.rs +38 -35
  162. package/rust/utils/first_usage.rs +76 -0
  163. package/rust/utils/logger.rs +195 -139
  164. package/rust/utils/mod.rs +9 -50
  165. package/rust/utils/signature.rs +19 -17
  166. package/rust/utils/spinner.rs +22 -19
  167. package/rust/utils/telemetry.rs +292 -0
  168. package/rust/utils/watcher.rs +34 -33
  169. package/templates/minimal/README.md +97 -121
  170. package/templates/welcome/README.md +97 -121
  171. package/typescript/bin/index.ts +19 -5
  172. package/typescript/index.ts +3 -1
  173. package/typescript/scripts/postbuild.ts +10 -6
  174. package/typescript/scripts/postinstall.ts +56 -0
  175. package/typescript/scripts/version/bump.ts +0 -1
  176. package/typescript/scripts/version/index.ts +0 -1
  177. package/out-tsc/bin/devalang.exe +0 -0
@@ -0,0 +1,18 @@
1
+ use crate::core::{
2
+ parser::statement::{Statement, StatementKind},
3
+ store::variable::VariableTable,
4
+ };
5
+
6
+ // Store automation configuration into the variable table under a namespaced key
7
+ // Key: "<target>__automation" => Value::Map({ target, params })
8
+ pub fn interprete_automate_statement(
9
+ stmt: &Statement,
10
+ variable_table: &mut VariableTable,
11
+ ) -> Option<VariableTable> {
12
+ if let StatementKind::Automate { target } = &stmt.kind {
13
+ let key = format!("{}__automation", target);
14
+ variable_table.set(key, stmt.value.clone());
15
+ return Some(variable_table.clone());
16
+ }
17
+ None
18
+ }
@@ -1,95 +1,98 @@
1
- use crate::core::{
2
- audio::{engine::AudioEngine, interpreter::driver::execute_audio_block},
3
- parser::statement::{Statement, StatementKind},
4
- shared::value::Value,
5
- store::{function::FunctionTable, global::GlobalStore, variable::VariableTable},
6
- };
7
-
8
- pub fn interprete_call_statement(
9
- stmt: &Statement,
10
- audio_engine: &mut AudioEngine,
11
- variable_table: &VariableTable,
12
- functions: &FunctionTable,
13
- global_store: &GlobalStore,
14
- base_bpm: f32,
15
- base_duration: f32,
16
- max_end_time: f32,
17
- cursor_time: f32,
18
- ) -> (f32, f32) {
19
- match &stmt.kind {
20
- StatementKind::Call { name, args } => {
21
- // Classic function call case
22
- if let Some(func) = functions.functions.get(name) {
23
- if func.parameters.len() != args.len() {
24
- eprintln!(
25
- "❌ Function '{}' expects {} args, got {}",
26
- name,
27
- func.parameters.len(),
28
- args.len()
29
- );
30
- return (max_end_time, cursor_time);
31
- }
32
-
33
- let mut local_vars = VariableTable::with_parent(variable_table.clone());
34
- for (param, arg) in func.parameters.iter().zip(args) {
35
- local_vars.set(param.clone(), arg.clone());
36
- }
37
-
38
- return execute_audio_block(
39
- audio_engine,
40
- global_store,
41
- local_vars,
42
- functions.clone(),
43
- func.body.clone(),
44
- base_bpm,
45
- base_duration,
46
- max_end_time,
47
- cursor_time,
48
- );
49
- }
50
-
51
- // Group case
52
- if let Some(group_stmt) = find_group(name, variable_table, global_store) {
53
- if let Value::Map(map) = &group_stmt.value {
54
- if let Some(Value::Block(body)) = map.get("body") {
55
- return execute_audio_block(
56
- audio_engine,
57
- global_store,
58
- variable_table.clone(),
59
- functions.clone(),
60
- body.clone(),
61
- base_bpm,
62
- base_duration,
63
- max_end_time,
64
- cursor_time,
65
- );
66
- }
67
- }
68
- }
69
-
70
- eprintln!("❌ Function or group '{}' not found", name);
71
- }
72
-
73
- _ => eprintln!("❌ interprete_call_statement expected Call, got {:?}", stmt.kind),
74
- }
75
-
76
- (max_end_time, cursor_time)
77
- }
78
-
79
- fn find_group<'a>(
80
- name: &str,
81
- variable_table: &'a VariableTable,
82
- global_store: &'a GlobalStore,
83
- ) -> Option<&'a Statement> {
84
- if let Some(Value::Statement(stmt_box)) = variable_table.get(name) {
85
- if let StatementKind::Group = stmt_box.kind {
86
- return Some(stmt_box);
87
- }
88
- }
89
- if let Some(Value::Statement(stmt_box)) = global_store.variables.variables.get(name) {
90
- if let StatementKind::Group = stmt_box.kind {
91
- return Some(stmt_box);
92
- }
93
- }
94
- None
95
- }
1
+ use crate::core::{
2
+ audio::{engine::AudioEngine, interpreter::driver::execute_audio_block},
3
+ parser::statement::{Statement, StatementKind},
4
+ shared::value::Value,
5
+ store::{function::FunctionTable, global::GlobalStore, variable::VariableTable},
6
+ };
7
+
8
+ pub fn interprete_call_statement(
9
+ stmt: &Statement,
10
+ audio_engine: &mut AudioEngine,
11
+ variable_table: &VariableTable,
12
+ functions: &FunctionTable,
13
+ global_store: &GlobalStore,
14
+ base_bpm: f32,
15
+ base_duration: f32,
16
+ max_end_time: f32,
17
+ cursor_time: f32,
18
+ ) -> (f32, f32) {
19
+ match &stmt.kind {
20
+ StatementKind::Call { name, args } => {
21
+ // Classic function call case
22
+ if let Some(func) = functions.functions.get(name) {
23
+ if func.parameters.len() != args.len() {
24
+ eprintln!(
25
+ "❌ Function '{}' expects {} args, got {}",
26
+ name,
27
+ func.parameters.len(),
28
+ args.len()
29
+ );
30
+ return (max_end_time, cursor_time);
31
+ }
32
+
33
+ let mut local_vars = VariableTable::with_parent(variable_table.clone());
34
+ for (param, arg) in func.parameters.iter().zip(args) {
35
+ local_vars.set(param.clone(), arg.clone());
36
+ }
37
+
38
+ return execute_audio_block(
39
+ audio_engine,
40
+ global_store,
41
+ local_vars,
42
+ functions.clone(),
43
+ &func.body,
44
+ base_bpm,
45
+ base_duration,
46
+ max_end_time,
47
+ cursor_time,
48
+ );
49
+ }
50
+
51
+ // Group case
52
+ if let Some(group_stmt) = find_group(name, variable_table, global_store) {
53
+ if let Value::Map(map) = &group_stmt.value {
54
+ if let Some(Value::Block(body)) = map.get("body") {
55
+ return execute_audio_block(
56
+ audio_engine,
57
+ global_store,
58
+ variable_table.clone(),
59
+ functions.clone(),
60
+ &body,
61
+ base_bpm,
62
+ base_duration,
63
+ max_end_time,
64
+ cursor_time,
65
+ );
66
+ }
67
+ }
68
+ }
69
+
70
+ eprintln!("❌ Function or group '{}' not found", name);
71
+ }
72
+
73
+ _ => eprintln!(
74
+ "❌ interprete_call_statement expected Call, got {:?}",
75
+ stmt.kind
76
+ ),
77
+ }
78
+
79
+ (max_end_time, cursor_time)
80
+ }
81
+
82
+ fn find_group<'a>(
83
+ name: &str,
84
+ variable_table: &'a VariableTable,
85
+ global_store: &'a GlobalStore,
86
+ ) -> Option<&'a Statement> {
87
+ if let Some(Value::Statement(stmt_box)) = variable_table.get(name) {
88
+ if let StatementKind::Group = stmt_box.kind {
89
+ return Some(stmt_box);
90
+ }
91
+ }
92
+ if let Some(Value::Statement(stmt_box)) = global_store.variables.variables.get(name) {
93
+ if let StatementKind::Group = stmt_box.kind {
94
+ return Some(stmt_box);
95
+ }
96
+ }
97
+ None
98
+ }
@@ -1,71 +1,70 @@
1
- use crate::core::{
2
- audio::{
3
- engine::AudioEngine,
4
- evaluator::evaluate_condition_string,
5
- interpreter::driver::execute_audio_block,
6
- },
7
- parser::statement::Statement,
8
- shared::value::Value,
9
- store::{ function::FunctionTable, global::GlobalStore, variable::VariableTable },
10
- };
11
-
12
- pub fn interprete_condition_statement(
13
- stmt: &Statement,
14
- audio_engine: &mut AudioEngine,
15
- global_store: &GlobalStore,
16
- variable_table: &VariableTable,
17
- functions_table: &FunctionTable,
18
- base_bpm: f32,
19
- base_duration: f32,
20
- max_end_time: f32,
21
- cursor_time: f32
22
- ) -> (f32, f32) {
23
- let mut cur_time = cursor_time;
24
- let mut max_time = max_end_time;
25
-
26
- let mut current = stmt.value.clone();
27
-
28
- loop {
29
- let Value::Map(map) = current else {
30
- break;
31
- };
32
-
33
- let should_execute = match map.get("condition") {
34
- Some(Value::Boolean(b)) => *b,
35
- Some(Value::String(expr)) => evaluate_condition_string(expr, &variable_table.clone()),
36
- Some(_) => false,
37
- None => true,
38
- };
39
-
40
- if should_execute {
41
- if let Some(Value::Block(block)) = map.get("body") {
42
- let (new_max, cursor_time) = execute_audio_block(
43
- audio_engine,
44
- global_store,
45
- variable_table.clone(),
46
- functions_table.clone(),
47
- block.clone(),
48
- base_bpm,
49
- base_duration,
50
- max_time,
51
- cur_time
52
- );
53
- return (new_max, cursor_time);
54
- } else {
55
- break;
56
- }
57
- }
58
-
59
- // Advance to the next condition
60
- match map.get("next") {
61
- Some(Value::Map(next_map)) => {
62
- current = Value::Map(next_map.clone());
63
- }
64
- _ => {
65
- break;
66
- }
67
- }
68
- }
69
-
70
- (max_end_time, cursor_time)
71
- }
1
+ use crate::core::{
2
+ audio::{
3
+ engine::AudioEngine, evaluator::evaluate_condition_string,
4
+ interpreter::driver::execute_audio_block,
5
+ },
6
+ parser::statement::Statement,
7
+ shared::value::Value,
8
+ store::{function::FunctionTable, global::GlobalStore, variable::VariableTable},
9
+ };
10
+
11
+ pub fn interprete_condition_statement(
12
+ stmt: &Statement,
13
+ audio_engine: &mut AudioEngine,
14
+ global_store: &GlobalStore,
15
+ variable_table: &VariableTable,
16
+ functions_table: &FunctionTable,
17
+ base_bpm: f32,
18
+ base_duration: f32,
19
+ max_end_time: f32,
20
+ cursor_time: f32,
21
+ ) -> (f32, f32) {
22
+ let cur_time = cursor_time;
23
+ let max_time = max_end_time;
24
+
25
+ let mut current = stmt.value.clone();
26
+
27
+ loop {
28
+ let Value::Map(map) = current else {
29
+ break;
30
+ };
31
+
32
+ let should_execute = match map.get("condition") {
33
+ Some(Value::Boolean(b)) => *b,
34
+ Some(Value::String(expr)) => evaluate_condition_string(expr, &variable_table.clone()),
35
+ Some(_) => false,
36
+ None => true,
37
+ };
38
+
39
+ if should_execute {
40
+ if let Some(Value::Block(block)) = map.get("body") {
41
+ let (new_max, cursor_time) = execute_audio_block(
42
+ audio_engine,
43
+ global_store,
44
+ variable_table.clone(),
45
+ functions_table.clone(),
46
+ &block,
47
+ base_bpm,
48
+ base_duration,
49
+ max_time,
50
+ cur_time,
51
+ );
52
+ return (new_max, cursor_time);
53
+ } else {
54
+ break;
55
+ }
56
+ }
57
+
58
+ // Advance to the next condition
59
+ match map.get("next") {
60
+ Some(Value::Map(next_map)) => {
61
+ current = Value::Map(next_map.clone());
62
+ }
63
+ _ => {
64
+ break;
65
+ }
66
+ }
67
+ }
68
+
69
+ (max_end_time, cursor_time)
70
+ }