@devaloop/devalang 0.0.1-alpha.13 → 0.0.1-alpha.15

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 (110) hide show
  1. package/.devalang +2 -3
  2. package/Cargo.toml +58 -54
  3. package/README.md +59 -27
  4. package/docs/CHANGELOG.md +99 -2
  5. package/docs/CONTRIBUTING.md +1 -0
  6. package/docs/ROADMAP.md +3 -3
  7. package/docs/TODO.md +5 -4
  8. package/examples/automation.deva +44 -0
  9. package/examples/bank.deva +2 -4
  10. package/examples/function.deva +15 -0
  11. package/examples/index.deva +41 -11
  12. package/examples/plugin.deva +15 -0
  13. package/out-tsc/bin/devalang.exe +0 -0
  14. package/package.json +6 -6
  15. package/project-version.json +3 -3
  16. package/rust/cli/bank.rs +16 -16
  17. package/rust/cli/build.rs +69 -30
  18. package/rust/cli/check.rs +46 -6
  19. package/rust/cli/driver.rs +40 -28
  20. package/rust/cli/install.rs +22 -7
  21. package/rust/cli/login.rs +134 -0
  22. package/rust/cli/mod.rs +2 -1
  23. package/rust/cli/play.rs +44 -19
  24. package/rust/cli/update.rs +1 -1
  25. package/rust/common/api.rs +5 -0
  26. package/rust/common/cdn.rs +3 -9
  27. package/rust/common/mod.rs +3 -1
  28. package/rust/common/sso.rs +5 -0
  29. package/rust/config/driver.rs +19 -1
  30. package/rust/config/loader.rs +56 -10
  31. package/rust/core/audio/engine.rs +314 -63
  32. package/rust/core/audio/evaluator.rs +101 -0
  33. package/rust/core/audio/interpreter/arrow_call.rs +60 -15
  34. package/rust/core/audio/interpreter/automate.rs +18 -0
  35. package/rust/core/audio/interpreter/call.rs +4 -4
  36. package/rust/core/audio/interpreter/condition.rs +3 -3
  37. package/rust/core/audio/interpreter/driver.rs +68 -30
  38. package/rust/core/audio/interpreter/let_.rs +14 -7
  39. package/rust/core/audio/interpreter/loop_.rs +39 -6
  40. package/rust/core/audio/interpreter/mod.rs +2 -1
  41. package/rust/core/audio/interpreter/sleep.rs +2 -4
  42. package/rust/core/audio/interpreter/spawn.rs +4 -4
  43. package/rust/core/audio/loader/trigger.rs +2 -5
  44. package/rust/core/audio/mod.rs +2 -1
  45. package/rust/core/audio/renderer.rs +1 -1
  46. package/rust/core/audio/special/easing.rs +120 -0
  47. package/rust/core/audio/special/env.rs +41 -0
  48. package/rust/core/audio/special/math.rs +92 -0
  49. package/rust/core/audio/special/mod.rs +9 -0
  50. package/rust/core/audio/special/modulator.rs +120 -0
  51. package/rust/core/builder/mod.rs +11 -6
  52. package/rust/core/debugger/store.rs +1 -1
  53. package/rust/core/error/mod.rs +4 -1
  54. package/rust/core/lexer/handler/arrow.rs +60 -9
  55. package/rust/core/lexer/handler/at.rs +4 -4
  56. package/rust/core/lexer/handler/brace.rs +8 -8
  57. package/rust/core/lexer/handler/colon.rs +4 -4
  58. package/rust/core/lexer/handler/comment.rs +2 -2
  59. package/rust/core/lexer/handler/dot.rs +4 -4
  60. package/rust/core/lexer/handler/driver.rs +42 -13
  61. package/rust/core/lexer/handler/identifier.rs +5 -4
  62. package/rust/core/lexer/handler/indent.rs +16 -2
  63. package/rust/core/lexer/handler/newline.rs +1 -1
  64. package/rust/core/lexer/handler/number.rs +3 -3
  65. package/rust/core/lexer/handler/operator.rs +3 -1
  66. package/rust/core/lexer/handler/parenthesis.rs +8 -8
  67. package/rust/core/lexer/handler/slash.rs +5 -5
  68. package/rust/core/lexer/handler/string.rs +1 -1
  69. package/rust/core/lexer/mod.rs +1 -1
  70. package/rust/core/lexer/token.rs +4 -0
  71. package/rust/core/mod.rs +2 -1
  72. package/rust/core/parser/driver.rs +134 -11
  73. package/rust/core/parser/handler/arrow_call.rs +141 -65
  74. package/rust/core/parser/handler/at.rs +1 -1
  75. package/rust/core/parser/handler/bank.rs +35 -7
  76. package/rust/core/parser/handler/dot.rs +43 -22
  77. package/rust/core/parser/handler/identifier/automate.rs +194 -0
  78. package/rust/core/parser/handler/identifier/function.rs +2 -3
  79. package/rust/core/parser/handler/identifier/let_.rs +16 -0
  80. package/rust/core/parser/handler/identifier/mod.rs +14 -10
  81. package/rust/core/parser/handler/identifier/print.rs +29 -0
  82. package/rust/core/parser/handler/identifier/sleep.rs +1 -1
  83. package/rust/core/parser/handler/identifier/synth.rs +7 -9
  84. package/rust/core/parser/handler/loop_.rs +60 -43
  85. package/rust/core/parser/statement.rs +5 -0
  86. package/rust/core/plugin/loader.rs +48 -0
  87. package/rust/core/plugin/mod.rs +1 -0
  88. package/rust/core/preprocessor/loader.rs +7 -5
  89. package/rust/core/preprocessor/processor.rs +4 -4
  90. package/rust/core/preprocessor/resolver/bank.rs +1 -2
  91. package/rust/core/preprocessor/resolver/call.rs +19 -18
  92. package/rust/core/preprocessor/resolver/driver.rs +7 -5
  93. package/rust/core/preprocessor/resolver/function.rs +3 -13
  94. package/rust/core/preprocessor/resolver/loop_.rs +31 -1
  95. package/rust/core/preprocessor/resolver/spawn.rs +3 -22
  96. package/rust/core/preprocessor/resolver/tempo.rs +1 -1
  97. package/rust/core/preprocessor/resolver/trigger.rs +2 -3
  98. package/rust/core/preprocessor/resolver/value.rs +6 -12
  99. package/rust/core/shared/bank.rs +1 -1
  100. package/rust/core/utils/path.rs +1 -1
  101. package/rust/core/utils/validation.rs +0 -1
  102. package/rust/installer/addon.rs +80 -0
  103. package/rust/installer/bank.rs +25 -15
  104. package/rust/installer/mod.rs +4 -1
  105. package/rust/installer/plugin.rs +55 -0
  106. package/rust/main.rs +32 -10
  107. package/rust/utils/error.rs +51 -0
  108. package/rust/utils/logger.rs +20 -0
  109. package/rust/utils/mod.rs +1 -44
  110. package/rust/utils/spinner.rs +3 -5
package/rust/cli/play.rs CHANGED
@@ -1,13 +1,11 @@
1
1
  use crate::{
2
- core::{
2
+ config::driver::Config, core::{
3
3
  builder::Builder,
4
- debugger::{ lexer::write_lexer_log_file, preprocessor::write_preprocessor_log_file },
4
+ debugger::{ lexer::write_lexer_log_file, module::{write_module_function_log_file, write_module_variable_log_file}, preprocessor::write_preprocessor_log_file, store::{write_function_log_file, write_variables_log_file} },
5
5
  preprocessor::loader::ModuleLoader,
6
6
  store::global::GlobalStore,
7
7
  utils::path::{ find_entry_file, normalize_path },
8
- },
9
- config::driver::Config,
10
- utils::{ logger::{ LogLevel, Logger }, spinner::with_spinner, watcher::watch_directory },
8
+ }, utils::{ logger::{ LogLevel, Logger }, spinner::with_spinner, watcher::watch_directory }
11
9
  };
12
10
 
13
11
  use std::{ path::Path, sync::mpsc::channel, thread, time::Duration };
@@ -20,7 +18,8 @@ pub fn handle_play_command(
20
18
  entry: Option<String>,
21
19
  output: Option<String>,
22
20
  watch: bool,
23
- repeat: bool
21
+ repeat: bool,
22
+ debug: bool
24
23
  ) {
25
24
  use crate::core::audio::player::AudioPlayer;
26
25
 
@@ -76,7 +75,7 @@ pub fn handle_play_command(
76
75
  });
77
76
 
78
77
  // Main thread: build + play in a loop
79
- begin_play(&config, &entry_file, &output_path);
78
+ begin_play(&config, &entry_file, &output_path, debug);
80
79
  audio_player.play_file_once(&audio_file);
81
80
 
82
81
  logger.log_message(LogLevel::Watcher, "Watching for changes... Press Ctrl+C to exit.");
@@ -84,7 +83,7 @@ pub fn handle_play_command(
84
83
  while let Ok(_) = rx.recv() {
85
84
  logger.log_message(LogLevel::Watcher, "Change detected, rebuilding...");
86
85
 
87
- begin_play(&config, &entry_file, &output_path);
86
+ begin_play(&config, &entry_file, &output_path, debug);
88
87
 
89
88
  logger.log_message(LogLevel::Info, "🎵 Playback started (once mode)...");
90
89
 
@@ -92,7 +91,7 @@ pub fn handle_play_command(
92
91
  }
93
92
  } else if fetched_repeat {
94
93
  // Initial build to start from a clean slate
95
- begin_play(&config, &entry_file, &output_path);
94
+ begin_play(&config, &entry_file, &output_path, debug);
96
95
 
97
96
  logger.log_message(LogLevel::Info, "🎵 Playback started (repeat mode)...");
98
97
 
@@ -112,7 +111,7 @@ pub fn handle_play_command(
112
111
 
113
112
  // Rebuild in a separate thread
114
113
  std::thread::spawn(move || {
115
- begin_play(&config_clone, &entry_file, &output_path);
114
+ begin_play(&config_clone, &entry_file, &output_path, debug);
116
115
  });
117
116
 
118
117
  last_snapshot = current_snapshot;
@@ -126,7 +125,7 @@ pub fn handle_play_command(
126
125
  }
127
126
  } else {
128
127
  // Single execution
129
- begin_play(&config, &entry_file, &output_path);
128
+ begin_play(&config, &entry_file, &output_path, debug);
130
129
 
131
130
  logger.log_message(LogLevel::Info, "🎵 Playback started (once mode)...");
132
131
 
@@ -135,7 +134,7 @@ pub fn handle_play_command(
135
134
  }
136
135
  }
137
136
 
138
- fn begin_play(config: &Option<Config>, entry_file: &str, output: &str) {
137
+ fn begin_play(_config: &Option<Config>, entry_file: &str, output: &str, debug: bool) {
139
138
  let spinner = with_spinner("Building...", || {
140
139
  thread::sleep(Duration::from_millis(800));
141
140
  });
@@ -149,16 +148,41 @@ fn begin_play(config: &Option<Config>, entry_file: &str, output: &str) {
149
148
  let (modules_tokens, modules_statements) = loader.load_all_modules(&mut global_store);
150
149
 
151
150
  // SECTION Write logs
152
- write_lexer_log_file(&normalized_output_dir, "lexer_tokens.log", modules_tokens.clone());
153
- write_preprocessor_log_file(
154
- &normalized_output_dir,
155
- "resolved_statements.log",
156
- modules_statements.clone()
157
- );
151
+ if debug {
152
+ for (module_path, module) in global_store.modules.clone() {
153
+ write_module_variable_log_file(
154
+ &normalized_output_dir,
155
+ &module_path,
156
+ &module.variable_table
157
+ );
158
+ write_module_function_log_file(
159
+ &normalized_output_dir,
160
+ &module_path,
161
+ &module.function_table
162
+ );
163
+ }
164
+
165
+ write_lexer_log_file(&normalized_output_dir, "lexer_tokens.log", modules_tokens.clone());
166
+ write_preprocessor_log_file(
167
+ &normalized_output_dir,
168
+ "resolved_statements.log",
169
+ modules_statements.clone()
170
+ );
171
+ write_variables_log_file(
172
+ &normalized_output_dir,
173
+ "global_variables.log",
174
+ global_store.variables.clone()
175
+ );
176
+ write_function_log_file(
177
+ &normalized_output_dir,
178
+ "global_functions.log",
179
+ global_store.functions.clone()
180
+ );
181
+ }
158
182
 
159
183
  // SECTION Building AST and Audio
160
184
  let builder = Builder::new();
161
- builder.build_ast(&modules_statements, &output);
185
+ builder.build_ast(&modules_statements, &output, false);
162
186
  builder.build_audio(&modules_statements, &output, &mut global_store);
163
187
 
164
188
  // SECTION Logging
@@ -169,6 +193,7 @@ fn begin_play(config: &Option<Config>, entry_file: &str, output: &str) {
169
193
  normalized_output_dir
170
194
  );
171
195
 
196
+ spinner.finish_and_clear();
172
197
  logger.log_message(LogLevel::Success, &success_message);
173
198
  }
174
199
 
@@ -1,4 +1,4 @@
1
- pub async fn handle_update_command(only: Option<String>) -> Result<(), Box<dyn std::error::Error>> {
1
+ pub async fn handle_update_command(_only: Option<String>) -> Result<(), Box<dyn std::error::Error>> {
2
2
  println!("Updates are not yet implemented. This is a placeholder function.");
3
3
  Ok(())
4
4
  }
@@ -0,0 +1,5 @@
1
+ pub fn get_api_url() -> String {
2
+ let api_url = "https://api.devalang.com";
3
+ // let api_url = "http://127.0.0.1:8989";
4
+ api_url.to_string()
5
+ }
@@ -1,11 +1,5 @@
1
1
  pub fn get_cdn_url() -> String {
2
- let cdn_url = std::env
3
- ::var("CDN_URL")
4
- .unwrap_or_else(|_| "https://cdn.devalang.com".to_string());
5
-
6
- if !cdn_url.ends_with('/') {
7
- format!("{}/", cdn_url)
8
- } else {
9
- cdn_url
10
- }
2
+ let cdn_url = "https://cdn.devalang.com";
3
+ // let cdn_url = "http://127.0.0.1:8888";
4
+ cdn_url.to_string()
11
5
  }
@@ -1 +1,3 @@
1
- pub mod cdn;
1
+ pub mod cdn;
2
+ pub mod api;
3
+ pub mod sso;
@@ -0,0 +1,5 @@
1
+ pub fn get_sso_url() -> String {
2
+ let sso_url = "https://sso.devalang.com";
3
+ // let sso_url = "http://localhost:5174";
4
+ sso_url.to_string()
5
+ }
@@ -1,9 +1,12 @@
1
+ use std::collections::HashMap;
2
+
1
3
  use serde::{ Deserialize, Serialize };
2
4
 
3
5
  #[derive(Debug, Deserialize, Clone, Serialize)]
4
6
  pub struct Config {
5
7
  pub defaults: ConfigDefaults,
6
8
  pub banks: Option<Vec<BankEntry>>,
9
+ pub plugins: Option<Vec<PluginEntry>>,
7
10
  }
8
11
 
9
12
  #[derive(Debug, Deserialize, Clone, Serialize)]
@@ -14,11 +17,24 @@ pub struct ConfigDefaults {
14
17
  pub repeat: Option<bool>,
15
18
  }
16
19
 
20
+ #[derive(Debug, Deserialize, Clone, Serialize)]
21
+ pub struct BankMetadata {
22
+ pub bank: HashMap<String, String>,
23
+ pub triggers: Option<Vec<HashMap<String, String>>>,
24
+ }
25
+
17
26
  #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
18
27
  pub struct BankEntry {
19
28
  pub path: String,
20
29
  pub version: Option<String>,
21
- pub author: Option<String>,
30
+ }
31
+
32
+ #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
33
+ pub struct PluginEntry {
34
+ pub path: String,
35
+ pub version: String,
36
+ pub author: String,
37
+ pub access: String,
22
38
  }
23
39
 
24
40
  impl Config {
@@ -31,6 +47,7 @@ impl Config {
31
47
  repeat: None,
32
48
  },
33
49
  banks: Some(Vec::new()),
50
+ plugins: Some(Vec::new()),
34
51
  }
35
52
  }
36
53
 
@@ -48,6 +65,7 @@ impl Config {
48
65
  repeat,
49
66
  },
50
67
  banks: Some(Vec::new()),
68
+ plugins: Some(Vec::new()),
51
69
  }
52
70
  }
53
71
 
@@ -1,6 +1,5 @@
1
1
  use std::{ fs, path::Path };
2
- use std::collections::HashMap;
3
- use crate::config::driver::{ BankEntry, Config };
2
+ use crate::config::driver::{ BankEntry, BankMetadata, Config };
4
3
 
5
4
  pub fn load_config(path: Option<&Path>) -> Option<Config> {
6
5
  let config_path = path.unwrap_or_else(|| Path::new(".devalang"));
@@ -56,6 +55,59 @@ pub fn remove_bank_from_config(config: &mut Config, dependency: &str) {
56
55
  }
57
56
  }
58
57
 
58
+ pub fn add_plugin_to_config(config: &mut Config, real_path: &Path, dependency: &str) {
59
+ if config.plugins.is_none() {
60
+ config.plugins = Some(Vec::new());
61
+ }
62
+
63
+ let plugins = config.plugins.as_mut().unwrap();
64
+
65
+ let exists = plugins.iter().any(|p| p.path == dependency);
66
+ if exists {
67
+ println!("Plugin '{}' already in config", dependency);
68
+ return;
69
+ }
70
+
71
+ let metadata_path = Path::new(real_path).join("plugin.toml");
72
+
73
+ if !metadata_path.exists() {
74
+ eprintln!("❌ Plugin metadata file '{}' does not exist", metadata_path.display());
75
+ return;
76
+ }
77
+
78
+ let metadata_content = std::fs
79
+ ::read_to_string(&metadata_path)
80
+ .expect("Failed to read plugin metadata file");
81
+
82
+ let metadata: std::collections::HashMap<String, String> = toml
83
+ ::from_str(&metadata_content)
84
+ .expect("Failed to parse plugin metadata file");
85
+
86
+ let plugin_entry = crate::config::driver::PluginEntry {
87
+ path: dependency.to_string(),
88
+ version: metadata
89
+ .get("version")
90
+ .cloned()
91
+ .unwrap_or_else(|| "0.0.1".to_string()),
92
+ author: metadata
93
+ .get("author")
94
+ .cloned()
95
+ .unwrap_or_else(|| "unknown".to_string()),
96
+ access: metadata
97
+ .get("access")
98
+ .cloned()
99
+ .unwrap_or_else(|| "public".to_string()),
100
+ };
101
+
102
+ plugins.push(plugin_entry);
103
+
104
+ if let Err(e) = config.write(config) {
105
+ eprintln!("❌ Failed to write config: {}", e);
106
+ } else {
107
+ println!("✅ Plugin '{}' added to config", dependency);
108
+ }
109
+ }
110
+
59
111
  pub fn add_bank_to_config(config: &mut Config, real_path: &Path, dependency: &str) {
60
112
  if config.banks.is_none() {
61
113
  config.banks = Some(Vec::new());
@@ -80,24 +132,18 @@ pub fn add_bank_to_config(config: &mut Config, real_path: &Path, dependency: &st
80
132
  ::read_to_string(&metadata_path)
81
133
  .expect("Failed to read bank metadata file");
82
134
 
83
- let metadata: HashMap<String, String> = toml
135
+ let metadata: BankMetadata = toml
84
136
  ::from_str(&metadata_content)
85
137
  .expect("Failed to parse bank metadata file");
86
138
 
87
139
  let bank_to_insert = BankEntry {
88
140
  path: dependency.to_string(),
89
141
  version: Some(
90
- metadata
142
+ metadata.bank
91
143
  .get("version")
92
144
  .cloned()
93
145
  .unwrap_or_else(|| "0.0.1".to_string())
94
146
  ),
95
- author: Some(
96
- metadata
97
- .get("author")
98
- .cloned()
99
- .unwrap_or_else(|| "unknown".to_string())
100
- ),
101
147
  };
102
148
 
103
149
  banks.push(bank_to_insert);