@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
@@ -0,0 +1,55 @@
1
+ use std::path::{ Path, PathBuf };
2
+ use crate::{
3
+ common::cdn::get_cdn_url,
4
+ config::loader::{ add_plugin_to_config, load_config },
5
+ installer::utils::{ download_file, extract_archive },
6
+ };
7
+
8
+ pub async fn install_plugin(name: &str, target_dir: &Path) -> Result<(), String> {
9
+ let cdn_url = get_cdn_url();
10
+ let url = format!("{}/plugin/{}/download", cdn_url, name);
11
+
12
+ let plugin_dir = target_dir.join("plugin");
13
+ let archive_path = PathBuf::from(format!("./.deva/tmp/{}.devaplugin", name));
14
+ let extract_path = plugin_dir.join(name);
15
+
16
+ if extract_path.exists() {
17
+ println!(
18
+ "Plugin '{}' already exists at '{}'. Skipping install.",
19
+ name,
20
+ extract_path.display()
21
+ );
22
+ return Ok(());
23
+ }
24
+
25
+ download_file(&url, &archive_path).await.map_err(|e| format!("Failed to download: {}", e))?;
26
+
27
+ extract_archive(&archive_path, &extract_path).await.map_err(|e|
28
+ format!("Failed to extract: {}", e)
29
+ )?;
30
+
31
+ // Add the plugin to the config
32
+ let root_dir = target_dir
33
+ .parent()
34
+ .ok_or_else(|| "Failed to determine root directory".to_string())?;
35
+
36
+ let config_path = root_dir.join(".devalang");
37
+ if !config_path.exists() {
38
+ return Err(
39
+ format!(
40
+ "Config file not found at '{}'. Please run 'devalang init' before adding an addon",
41
+ config_path.display()
42
+ )
43
+ );
44
+ }
45
+
46
+ let mut config = load_config(Some(&config_path)).ok_or_else(||
47
+ format!("Failed to load config from '{}'", config_path.display())
48
+ )?;
49
+
50
+ let dependency_path = &format!("devalang://plugin/{}", name);
51
+
52
+ add_plugin_to_config(&mut config, &extract_path, dependency_path);
53
+
54
+ Ok(())
55
+ }
package/rust/main.rs CHANGED
@@ -15,18 +15,21 @@ use crate::{
15
15
  handle_bank_available_command,
16
16
  handle_bank_info_command,
17
17
  handle_bank_list_command,
18
- handle_remove_bank_command, handle_update_bank_command,
18
+ handle_remove_bank_command,
19
+ handle_update_bank_command,
19
20
  },
20
21
  build::handle_build_command,
21
22
  check::handle_check_command,
22
23
  driver::{ BankCommand, Cli, Commands, InstallCommand, TemplateCommand },
23
24
  init::handle_init_command,
24
- install::handle_install_bank_command,
25
+ install::handle_install_command,
26
+ login::handle_login_command,
25
27
  play::handle_play_command,
26
28
  template::{ handle_template_info_command, handle_template_list_command },
27
29
  update::handle_update_command,
28
30
  },
29
31
  config::{ driver::Config, loader::load_config },
32
+ installer::addon::AddonType,
30
33
  };
31
34
 
32
35
  #[tokio::main]
@@ -55,25 +58,35 @@ async fn main() -> io::Result<()> {
55
58
  }
56
59
  }
57
60
 
58
- Commands::Check { entry, output, watch, compilation_mode, debug } => {
59
- handle_check_command(config, entry, output, watch);
61
+ Commands::Check { entry, output, watch, debug } => {
62
+ handle_check_command(config, entry, output, watch, debug);
60
63
  }
61
64
 
62
- Commands::Build { entry, output, watch, compilation_mode, debug, compress } => {
63
- handle_build_command(config, entry, output, watch);
65
+ Commands::Build { entry, output, watch, debug, compress } => {
66
+ handle_build_command(config, entry, output, watch, debug, compress);
64
67
  }
65
68
 
66
- Commands::Play { entry, output, watch, repeat } => {
67
- handle_play_command(config, entry, output, watch, repeat);
69
+ Commands::Play { entry, output, watch, repeat, debug } => {
70
+ handle_play_command(config, entry, output, watch, repeat, debug);
68
71
  }
69
72
 
70
73
  Commands::Install { command } =>
71
74
  match command {
72
75
  InstallCommand::Bank { name } => {
73
- if let Err(err) = handle_install_bank_command(name).await {
76
+ if let Err(err) = handle_install_command(name, AddonType::Bank).await {
74
77
  eprintln!("❌ Failed to install bank: {}", err);
75
78
  }
76
79
  }
80
+ InstallCommand::Plugin { name } => {
81
+ if let Err(err) = handle_install_command(name, AddonType::Plugin).await {
82
+ eprintln!("❌ Failed to install plugin: {}", err);
83
+ }
84
+ }
85
+ InstallCommand::Preset { name } => {
86
+ if let Err(err) = handle_install_command(name, AddonType::Preset).await {
87
+ eprintln!("❌ Failed to install preset: {}", err);
88
+ }
89
+ }
77
90
  }
78
91
 
79
92
  Commands::Bank { command } =>
@@ -115,7 +128,16 @@ async fn main() -> io::Result<()> {
115
128
  }
116
129
  }
117
130
 
118
- _ => {}
131
+ Commands::Login { .. } => {
132
+ if let Err(err) = handle_login_command().await {
133
+ eprintln!("❌ Login failed: {}", err);
134
+ }
135
+ }
136
+
137
+ Commands::Logout { .. } => {
138
+ eprintln!("❌ Logout command is not implemented yet.");
139
+ }
140
+
119
141
  }
120
142
 
121
143
  Ok(())
@@ -0,0 +1,51 @@
1
+ use crate::core::{
2
+ error::ErrorResult,
3
+ parser::statement::{Statement, StatementKind},
4
+ shared::value::Value,
5
+ };
6
+
7
+ /// Recursively collects errors from a list of statements.
8
+ ///
9
+ /// This function traverses the provided statements and aggregates any
10
+ /// `Unknown` or explicit `Error` statements into a flat vector.
11
+ /// It also descends into loop bodies to ensure nested errors are
12
+ /// surfaced.
13
+ pub fn collect_errors_recursively(statements: &[Statement]) -> Vec<ErrorResult> {
14
+ let mut errors: Vec<ErrorResult> = Vec::new();
15
+
16
+ for stmt in statements {
17
+ match &stmt.kind {
18
+ StatementKind::Unknown => {
19
+ errors.push(ErrorResult {
20
+ message: format!("Unknown statement at line {}:{}", stmt.line, stmt.column),
21
+ line: stmt.line,
22
+ column: stmt.column,
23
+ });
24
+ }
25
+ StatementKind::Error { message } => {
26
+ errors.push(ErrorResult {
27
+ message: message.clone(),
28
+ line: stmt.line,
29
+ column: stmt.column,
30
+ });
31
+ }
32
+ StatementKind::Loop => {
33
+ if let Some(body_statements) = extract_loop_body_statements(&stmt.value) {
34
+ errors.extend(collect_errors_recursively(body_statements));
35
+ }
36
+ }
37
+ _ => {}
38
+ }
39
+ }
40
+
41
+ errors
42
+ }
43
+
44
+ fn extract_loop_body_statements(value: &Value) -> Option<&[Statement]> {
45
+ if let Value::Map(map) = value {
46
+ if let Some(Value::Block(statements)) = map.get("body") {
47
+ return Some(statements);
48
+ }
49
+ }
50
+ None
51
+ }
@@ -7,6 +7,7 @@ pub enum LogLevel {
7
7
  Success,
8
8
  Error,
9
9
  Info,
10
+ Print,
10
11
  Warning,
11
12
  Watcher,
12
13
  Debug,
@@ -33,6 +34,22 @@ impl Logger {
33
34
  // no-op for WASM
34
35
  }
35
36
 
37
+ // --- log_message_with_trace ---
38
+
39
+ #[cfg(feature = "cli")]
40
+ pub fn log_message_with_trace(&self, level: LogLevel, message: &str, trace: Vec<&str>) {
41
+ let formatted_status = self.format_status(level);
42
+ println!("🦊 {} {} {}", self.language_signature(), formatted_status, message);
43
+ for t in trace {
44
+ println!(" ↳ {}", t);
45
+ }
46
+ }
47
+
48
+ #[cfg(not(feature = "cli"))]
49
+ pub fn log_message_with_trace(&self, _level: LogLevel, _message: &str, _trace: Vec<&str>) {
50
+ // no-op for WASM
51
+ }
52
+
36
53
  // --- log_error_with_stacktrace ---
37
54
 
38
55
  #[cfg(feature = "cli")]
@@ -86,6 +103,7 @@ impl Logger {
86
103
  LogLevel::Warning => Color::Rgb { r: 255, g: 152, b: 0 },
87
104
  LogLevel::Watcher => Color::Rgb { r: 156, g: 39, b: 176 },
88
105
  LogLevel::Debug => Color::Rgb { r: 103, g: 58, b: 183 },
106
+ LogLevel::Print => Color::Rgb { r: 255, g: 255, b: 255 },
89
107
  };
90
108
 
91
109
  let status = match level {
@@ -95,6 +113,7 @@ impl Logger {
95
113
  LogLevel::Warning => "WARNING",
96
114
  LogLevel::Watcher => "WATCHER",
97
115
  LogLevel::Debug => "DEBUG",
116
+ LogLevel::Print => "PRINT",
98
117
  };
99
118
 
100
119
  s.push('[');
@@ -117,6 +136,7 @@ impl Logger {
117
136
  LogLevel::Warning => "[WARNING]",
118
137
  LogLevel::Watcher => "[WATCHER]",
119
138
  LogLevel::Debug => "[DEBUG]",
139
+ LogLevel::Print => "[PRINT]",
120
140
  }
121
141
  .to_string()
122
142
  }
package/rust/utils/mod.rs CHANGED
@@ -4,47 +4,4 @@ pub mod spinner;
4
4
  pub mod watcher;
5
5
  pub mod file;
6
6
  pub mod logger;
7
-
8
- use crate::core::parser::statement::{Statement, StatementKind};
9
- use crate::core::error::ErrorResult;
10
- use crate::core::shared::value::Value;
11
-
12
- pub fn collect_errors_recursively(statements: &[Statement]) -> Vec<ErrorResult> {
13
- let mut errors: Vec<ErrorResult> = Vec::new();
14
-
15
- for stmt in statements {
16
- match &stmt.kind {
17
- StatementKind::Unknown => {
18
- errors.push(ErrorResult {
19
- message: format!("Unknown statement at line {}:{}", stmt.line, stmt.column),
20
- line: stmt.line,
21
- column: stmt.column,
22
- });
23
- }
24
- StatementKind::Error { message } => {
25
- errors.push(ErrorResult {
26
- message: message.clone(),
27
- line: stmt.line,
28
- column: stmt.column,
29
- });
30
- }
31
- StatementKind::Loop => {
32
- if let Some(body_statements) = extract_loop_body_statements(&stmt.value) {
33
- errors.extend(collect_errors_recursively(body_statements));
34
- }
35
- }
36
- _ => {}
37
- }
38
- }
39
-
40
- errors
41
- }
42
-
43
- pub fn extract_loop_body_statements(value: &Value) -> Option<&[Statement]> {
44
- if let Value::Map(map) = value {
45
- if let Some(Value::Block(statements)) = map.get("body") {
46
- return Some(statements);
47
- }
48
- }
49
- None
50
- }
7
+ pub mod error;
@@ -3,7 +3,7 @@ use indicatif::{ ProgressBar, ProgressStyle };
3
3
  use std::{ time::Duration };
4
4
 
5
5
  #[cfg(feature = "cli")]
6
- pub fn with_spinner<T, F>(start_msg: &str, f: F) -> T where F: FnOnce() -> T {
6
+ pub fn with_spinner<T, F>(start_msg: &str, f: F) -> ProgressBar where F: FnOnce() -> T {
7
7
  let spinner = ProgressBar::new_spinner();
8
8
  spinner.set_style(
9
9
  ProgressStyle::with_template("{spinner:.green} {msg}")
@@ -13,9 +13,7 @@ pub fn with_spinner<T, F>(start_msg: &str, f: F) -> T where F: FnOnce() -> T {
13
13
  spinner.set_message(start_msg.to_string());
14
14
  spinner.enable_steady_tick(Duration::from_millis(80));
15
15
 
16
- let result = f();
16
+ let _ = f();
17
17
 
18
- spinner.finish_and_clear();
19
-
20
- result
18
+ spinner
21
19
  }