@devaloop/devalang 0.0.1-alpha.16-hotfix.1 → 0.0.1-alpha.17

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 (235) hide show
  1. package/.cargo/config.toml +2 -0
  2. package/.devalang +6 -10
  3. package/.github/workflows/ci.yml +19 -8
  4. package/Cargo.toml +18 -2
  5. package/README.md +80 -33
  6. package/docs/CHANGELOG.md +56 -0
  7. package/docs/ROADMAP.md +6 -3
  8. package/examples/index.deva +52 -35
  9. package/out-tsc/bin/index.d.ts +2 -0
  10. package/out-tsc/core/functions/index.d.ts +37 -0
  11. package/out-tsc/core/functions/index.js +76 -0
  12. package/out-tsc/core/index.d.ts +6 -0
  13. package/out-tsc/core/index.js +22 -0
  14. package/out-tsc/core/types/index.d.ts +4 -0
  15. package/out-tsc/core/types/index.js +20 -0
  16. package/out-tsc/core/types/plugin.d.ts +18 -0
  17. package/out-tsc/core/types/plugin.js +2 -0
  18. package/out-tsc/core/types/result.d.ts +27 -0
  19. package/out-tsc/core/types/result.js +2 -0
  20. package/out-tsc/core/types/statement.d.ts +106 -0
  21. package/out-tsc/core/types/statement.js +2 -0
  22. package/out-tsc/core/types/value.d.ts +43 -0
  23. package/out-tsc/core/types/value.js +2 -0
  24. package/out-tsc/index.d.ts +7 -0
  25. package/out-tsc/index.js +41 -2
  26. package/out-tsc/pkg/devalang_core.d.ts +7 -0
  27. package/out-tsc/pkg/devalang_core_bg.wasm.d.ts +33 -0
  28. package/out-tsc/scripts/copy-wasm-dts.d.ts +1 -0
  29. package/out-tsc/scripts/copy-wasm-dts.js +73 -0
  30. package/out-tsc/scripts/postinstall.d.ts +1 -0
  31. package/out-tsc/scripts/postinstall.js +33 -23
  32. package/out-tsc/scripts/version/bump.d.ts +1 -0
  33. package/out-tsc/scripts/version/fetch.d.ts +1 -0
  34. package/out-tsc/scripts/version/index.d.ts +1 -0
  35. package/out-tsc/scripts/version/sync.d.ts +1 -0
  36. package/package.json +16 -4
  37. package/project-version.json +3 -3
  38. package/rust/cli/bank/api.rs +122 -0
  39. package/rust/cli/bank/commands.rs +275 -0
  40. package/rust/cli/bank/mod.rs +29 -0
  41. package/rust/cli/build/commands.rs +97 -0
  42. package/rust/cli/build/mod.rs +2 -0
  43. package/rust/cli/build/process.rs +146 -0
  44. package/rust/cli/{check.rs → check/mod.rs} +18 -31
  45. package/rust/cli/discover/commands.rs +253 -0
  46. package/rust/cli/discover/config.rs +111 -0
  47. package/rust/cli/discover/fs.rs +19 -0
  48. package/rust/cli/discover/install.rs +103 -0
  49. package/rust/cli/discover/metadata.rs +48 -0
  50. package/rust/cli/discover/mod.rs +5 -0
  51. package/rust/cli/{init.rs → init/commands.rs} +88 -87
  52. package/rust/cli/init/mod.rs +1 -0
  53. package/rust/{installer → cli/install}/addon.rs +5 -9
  54. package/rust/cli/install/bank.rs +53 -0
  55. package/rust/cli/{install.rs → install/commands.rs} +9 -9
  56. package/rust/{installer → cli/install}/mod.rs +2 -3
  57. package/rust/cli/install/plugin.rs +61 -0
  58. package/rust/cli/{login.rs → login/commands.rs} +8 -11
  59. package/rust/cli/login/mod.rs +1 -0
  60. package/rust/cli/mod.rs +2 -3
  61. package/rust/cli/{driver.rs → parser.rs} +19 -2
  62. package/rust/cli/play/commands.rs +324 -0
  63. package/rust/cli/play/io.rs +17 -0
  64. package/rust/cli/play/mod.rs +5 -0
  65. package/rust/cli/play/process.rs +150 -0
  66. package/rust/cli/play/realtime.rs +91 -0
  67. package/rust/cli/play/utils.rs +23 -0
  68. package/rust/cli/telemetry/commands.rs +22 -0
  69. package/rust/cli/telemetry/event_creator.rs +80 -0
  70. package/rust/cli/telemetry/mod.rs +3 -0
  71. package/rust/cli/telemetry/send.rs +51 -0
  72. package/rust/cli/{template.rs → template/commands.rs} +1 -1
  73. package/rust/cli/template/mod.rs +1 -0
  74. package/rust/cli/{update.rs → update/commands.rs} +6 -6
  75. package/rust/cli/update/mod.rs +1 -0
  76. package/rust/config/driver.rs +57 -72
  77. package/rust/config/mod.rs +1 -2
  78. package/rust/config/ops.rs +26 -0
  79. package/rust/config/settings.rs +60 -50
  80. package/rust/core/audio/engine/helpers.rs +146 -0
  81. package/rust/core/audio/engine/mod.rs +7 -0
  82. package/rust/core/audio/engine/sample.rs +298 -0
  83. package/rust/core/audio/engine/synth.rs +310 -0
  84. package/rust/core/audio/evaluator.rs +15 -12
  85. package/rust/core/audio/interpreter/arrow_call.rs +99 -24
  86. package/rust/core/audio/interpreter/call.rs +81 -60
  87. package/rust/core/audio/interpreter/condition.rs +3 -2
  88. package/rust/core/audio/interpreter/driver.rs +206 -151
  89. package/rust/core/audio/interpreter/let_.rs +1 -1
  90. package/rust/core/audio/interpreter/load.rs +2 -1
  91. package/rust/core/audio/interpreter/loop_.rs +7 -6
  92. package/rust/core/audio/interpreter/sleep.rs +2 -1
  93. package/rust/core/audio/interpreter/spawn.rs +45 -57
  94. package/rust/core/audio/interpreter/tempo.rs +31 -10
  95. package/rust/core/audio/interpreter/trigger.rs +2 -2
  96. package/rust/core/audio/loader/trigger.rs +4 -7
  97. package/rust/core/audio/player.rs +6 -0
  98. package/rust/core/audio/renderer.rs +5 -7
  99. package/rust/core/audio/special/env.rs +3 -1
  100. package/rust/core/audio/special/math.rs +4 -4
  101. package/rust/core/audio/special/modulator.rs +2 -2
  102. package/rust/core/builder/mod.rs +9 -3
  103. package/rust/core/debugger/lexer.rs +1 -1
  104. package/rust/core/debugger/mod.rs +6 -0
  105. package/rust/core/debugger/module.rs +4 -4
  106. package/rust/core/debugger/preprocessor.rs +1 -1
  107. package/rust/core/debugger/store.rs +2 -2
  108. package/rust/core/error/mod.rs +189 -0
  109. package/rust/core/lexer/handler/arrow.rs +1 -1
  110. package/rust/core/lexer/handler/at.rs +1 -1
  111. package/rust/core/lexer/handler/brace.rs +2 -2
  112. package/rust/core/lexer/handler/colon.rs +1 -1
  113. package/rust/core/lexer/handler/comment.rs +1 -1
  114. package/rust/core/lexer/handler/dot.rs +1 -1
  115. package/rust/core/lexer/handler/driver.rs +1 -1
  116. package/rust/core/lexer/handler/identifier.rs +1 -1
  117. package/rust/core/lexer/handler/mod.rs +1 -2
  118. package/rust/core/lexer/handler/number.rs +1 -1
  119. package/rust/core/lexer/handler/operator.rs +1 -1
  120. package/rust/core/lexer/handler/parenthesis.rs +2 -2
  121. package/rust/core/lexer/handler/slash.rs +1 -1
  122. package/rust/core/lexer/handler/string.rs +1 -1
  123. package/rust/core/lexer/mod.rs +22 -12
  124. package/rust/core/lexer/token.rs +90 -97
  125. package/rust/core/mod.rs +0 -1
  126. package/rust/core/parser/driver.rs +66 -13
  127. package/rust/core/parser/handler/arrow_call.rs +28 -8
  128. package/rust/core/parser/handler/at.rs +55 -21
  129. package/rust/core/parser/handler/bank.rs +14 -4
  130. package/rust/core/parser/handler/condition.rs +6 -3
  131. package/rust/core/parser/handler/dot.rs +2 -1
  132. package/rust/core/parser/handler/identifier/automate.rs +13 -16
  133. package/rust/core/parser/handler/identifier/call.rs +4 -4
  134. package/rust/core/parser/handler/identifier/emit.rs +9 -5
  135. package/rust/core/parser/handler/identifier/function.rs +20 -7
  136. package/rust/core/parser/handler/identifier/group.rs +11 -7
  137. package/rust/core/parser/handler/identifier/let_.rs +24 -9
  138. package/rust/core/parser/handler/identifier/mod.rs +6 -5
  139. package/rust/core/parser/handler/identifier/on.rs +16 -7
  140. package/rust/core/parser/handler/identifier/print.rs +6 -9
  141. package/rust/core/parser/handler/identifier/sleep.rs +12 -5
  142. package/rust/core/parser/handler/identifier/spawn.rs +4 -4
  143. package/rust/core/parser/handler/identifier/synth.rs +79 -9
  144. package/rust/core/parser/handler/loop_.rs +39 -14
  145. package/rust/core/parser/handler/tempo.rs +9 -5
  146. package/rust/core/parser/mod.rs +0 -1
  147. package/rust/core/parser/statement.rs +6 -137
  148. package/rust/core/plugin/loader.rs +41 -27
  149. package/rust/core/plugin/runner.rs +68 -17
  150. package/rust/core/preprocessor/loader.rs +155 -33
  151. package/rust/core/preprocessor/processor.rs +2 -2
  152. package/rust/core/preprocessor/resolver/bank.rs +6 -8
  153. package/rust/core/preprocessor/resolver/call.rs +20 -24
  154. package/rust/core/preprocessor/resolver/condition.rs +6 -8
  155. package/rust/core/preprocessor/resolver/driver.rs +14 -16
  156. package/rust/core/preprocessor/resolver/function.rs +6 -6
  157. package/rust/core/preprocessor/resolver/group.rs +6 -8
  158. package/rust/core/preprocessor/resolver/loop_.rs +8 -10
  159. package/rust/core/preprocessor/resolver/spawn.rs +19 -23
  160. package/rust/core/preprocessor/resolver/synth.rs +6 -8
  161. package/rust/core/preprocessor/resolver/tempo.rs +6 -8
  162. package/rust/core/preprocessor/resolver/trigger.rs +22 -19
  163. package/rust/core/preprocessor/resolver/value.rs +99 -4
  164. package/rust/core/store/export.rs +28 -28
  165. package/rust/core/store/function.rs +6 -0
  166. package/rust/core/store/global.rs +7 -1
  167. package/rust/core/store/import.rs +28 -28
  168. package/rust/core/store/variable.rs +1 -1
  169. package/rust/core/utils/mod.rs +0 -1
  170. package/rust/lib.rs +102 -9
  171. package/rust/main.rs +156 -45
  172. package/rust/types/Cargo.toml +8 -0
  173. package/rust/types/src/addons.rs +55 -0
  174. package/rust/types/src/ast.rs +198 -0
  175. package/rust/types/src/config.rs +74 -0
  176. package/rust/types/src/lib.rs +12 -0
  177. package/rust/types/src/telemetry.rs +85 -0
  178. package/rust/utils/Cargo.toml +23 -0
  179. package/rust/utils/{error.rs → src/error.rs} +186 -200
  180. package/rust/utils/src/file.rs +94 -0
  181. package/rust/utils/src/first_usage.rs +97 -0
  182. package/rust/utils/{mod.rs → src/lib.rs} +1 -1
  183. package/rust/utils/{logger.rs → src/logger.rs} +17 -12
  184. package/rust/utils/src/path.rs +88 -0
  185. package/rust/utils/src/signature.rs +41 -0
  186. package/rust/utils/{spinner.rs → src/spinner.rs} +3 -5
  187. package/rust/utils/src/version.rs +27 -0
  188. package/rust/utils/{watcher.rs → src/watcher.rs} +13 -1
  189. package/rust/web/api.rs +5 -0
  190. package/rust/web/cdn.rs +34 -0
  191. package/templates/minimal/README.md +98 -54
  192. package/templates/welcome/README.md +98 -54
  193. package/templates/welcome/src/index.deva +56 -8
  194. package/templates/welcome/src/variables.deva +2 -4
  195. package/tests/rust/TODO.md +0 -0
  196. package/tests/typescript/index.spec.ts +136 -0
  197. package/tests/typescript/playhead.spec.ts +36 -0
  198. package/tests/typescript/render_e2e.spec.ts +77 -0
  199. package/tsconfig.json +1 -1
  200. package/typescript/core/functions/index.ts +83 -0
  201. package/typescript/core/index.ts +6 -0
  202. package/typescript/core/types/index.ts +4 -0
  203. package/typescript/core/types/plugin.ts +19 -0
  204. package/typescript/core/types/result.ts +29 -0
  205. package/typescript/core/types/statement.ts +47 -0
  206. package/typescript/core/types/value.ts +29 -0
  207. package/typescript/index.ts +7 -2
  208. package/typescript/pkg/devalang_core.d.ts +4 -0
  209. package/typescript/scripts/copy-wasm-dts.ts +41 -0
  210. package/typescript/scripts/postinstall.ts +45 -32
  211. package/rust/cli/bank.rs +0 -462
  212. package/rust/cli/build.rs +0 -252
  213. package/rust/cli/generator.rs +0 -1
  214. package/rust/cli/play.rs +0 -1123
  215. package/rust/cli/telemetry.rs +0 -19
  216. package/rust/common/api.rs +0 -5
  217. package/rust/common/cdn.rs +0 -5
  218. package/rust/config/loader.rs +0 -165
  219. package/rust/config/stats.rs +0 -257
  220. package/rust/core/audio/engine.rs +0 -696
  221. package/rust/core/shared/bank.rs +0 -21
  222. package/rust/core/shared/duration.rs +0 -9
  223. package/rust/core/shared/mod.rs +0 -3
  224. package/rust/core/shared/value.rs +0 -35
  225. package/rust/core/utils/validation.rs +0 -35
  226. package/rust/installer/bank.rs +0 -62
  227. package/rust/installer/plugin.rs +0 -54
  228. package/rust/installer/utils.rs +0 -56
  229. package/rust/utils/file.rs +0 -38
  230. package/rust/utils/first_usage.rs +0 -76
  231. package/rust/utils/signature.rs +0 -19
  232. package/rust/utils/telemetry.rs +0 -292
  233. package/rust/utils/version.rs +0 -15
  234. /package/rust/{common → web}/mod.rs +0 -0
  235. /package/rust/{common → web}/sso.rs +0 -0
@@ -4,7 +4,7 @@ pub fn handle_colon_lexer(
4
4
  ch: char,
5
5
  _chars: &mut std::iter::Peekable<std::str::Chars>,
6
6
  current_indent: &mut usize,
7
- _indent_stack: &mut Vec<usize>,
7
+ _indent_stack: &mut [usize],
8
8
  tokens: &mut Vec<Token>,
9
9
  line: &mut usize,
10
10
  column: &mut usize,
@@ -4,7 +4,7 @@ pub fn handle_comment_lexer(
4
4
  _char: char,
5
5
  chars: &mut std::iter::Peekable<std::str::Chars>,
6
6
  current_indent: &mut usize,
7
- _indent_stack: &mut Vec<usize>,
7
+ _indent_stack: &mut [usize],
8
8
  tokens: &mut Vec<Token>,
9
9
  line: &mut usize,
10
10
  column: &mut usize,
@@ -4,7 +4,7 @@ pub fn handle_dot_lexer(
4
4
  ch: char,
5
5
  _chars: &mut std::iter::Peekable<std::str::Chars>,
6
6
  current_indent: &mut usize,
7
- _indent_stack: &mut Vec<usize>,
7
+ _indent_stack: &mut [usize],
8
8
  tokens: &mut Vec<Token>,
9
9
  line: &mut usize,
10
10
  column: &mut usize,
@@ -23,7 +23,7 @@ fn advance_char<I: Iterator<Item = char>>(
23
23
  _line: &mut usize,
24
24
  column: &mut usize,
25
25
  ) -> Option<char> {
26
- while let Some(c) = chars.next() {
26
+ for c in chars.by_ref() {
27
27
  if c == '\r' {
28
28
  continue;
29
29
  } else if c == '\n' {
@@ -4,7 +4,7 @@ pub fn handle_identifier_lexer(
4
4
  ch: char,
5
5
  chars: &mut std::iter::Peekable<std::str::Chars>,
6
6
  current_indent: &mut usize,
7
- _indent_stack: &mut Vec<usize>,
7
+ _indent_stack: &mut [usize],
8
8
  tokens: &mut Vec<Token>,
9
9
  line: &mut usize,
10
10
  column: &mut usize,
@@ -1,11 +1,10 @@
1
- pub mod driver;
2
-
3
1
  pub mod arrow;
4
2
  pub mod at;
5
3
  pub mod brace;
6
4
  pub mod colon;
7
5
  pub mod comment;
8
6
  pub mod dot;
7
+ pub mod driver;
9
8
  pub mod identifier;
10
9
  pub mod indent;
11
10
  pub mod newline;
@@ -4,7 +4,7 @@ pub fn handle_number_lexer(
4
4
  ch: char,
5
5
  chars: &mut std::iter::Peekable<std::str::Chars>,
6
6
  current_indent: &mut usize,
7
- _indent_stack: &mut Vec<usize>,
7
+ _indent_stack: &mut [usize],
8
8
  tokens: &mut Vec<Token>,
9
9
  line: &mut usize,
10
10
  column: &mut usize,
@@ -4,7 +4,7 @@ pub fn handle_operator_lexer(
4
4
  ch: char,
5
5
  chars: &mut std::iter::Peekable<std::str::Chars>,
6
6
  current_indent: &mut usize,
7
- _indent_stack: &mut Vec<usize>,
7
+ _indent_stack: &mut [usize],
8
8
  tokens: &mut Vec<Token>,
9
9
  line: &mut usize,
10
10
  column: &mut usize,
@@ -4,7 +4,7 @@ pub fn handle_rparen_lexer(
4
4
  ch: char,
5
5
  _chars: &mut std::iter::Peekable<std::str::Chars>,
6
6
  current_indent: &mut usize,
7
- _indent_stack: &mut Vec<usize>,
7
+ _indent_stack: &mut [usize],
8
8
  tokens: &mut Vec<Token>,
9
9
  line: &mut usize,
10
10
  column: &mut usize,
@@ -24,7 +24,7 @@ pub fn handle_lparen_lexer(
24
24
  ch: char,
25
25
  _chars: &mut std::iter::Peekable<std::str::Chars>,
26
26
  current_indent: &mut usize,
27
- _indent_stack: &mut Vec<usize>,
27
+ _indent_stack: &mut [usize],
28
28
  tokens: &mut Vec<Token>,
29
29
  line: &mut usize,
30
30
  column: &mut usize,
@@ -4,7 +4,7 @@ pub fn handle_slash_lexer(
4
4
  ch: char,
5
5
  _chars: &mut std::iter::Peekable<std::str::Chars>,
6
6
  current_indent: &mut usize,
7
- _indent_stack: &mut Vec<usize>,
7
+ _indent_stack: &mut [usize],
8
8
  tokens: &mut Vec<Token>,
9
9
  line: &mut usize,
10
10
  column: &mut usize,
@@ -4,7 +4,7 @@ pub fn handle_string_lexer(
4
4
  ch: char,
5
5
  chars: &mut std::iter::Peekable<std::str::Chars>,
6
6
  current_indent: &mut usize,
7
- _indent_stack: &mut Vec<usize>,
7
+ _indent_stack: &mut [usize],
8
8
  tokens: &mut Vec<Token>,
9
9
  line: &mut usize,
10
10
  column: &mut usize,
@@ -10,6 +10,12 @@ use std::path::Path;
10
10
 
11
11
  pub struct Lexer {}
12
12
 
13
+ impl Default for Lexer {
14
+ fn default() -> Self {
15
+ Self::new()
16
+ }
17
+ }
18
+
13
19
  impl Lexer {
14
20
  pub fn new() -> Self {
15
21
  Lexer {}
@@ -19,36 +25,40 @@ impl Lexer {
19
25
  handle_content_lexing(source.to_string())
20
26
  }
21
27
 
22
- pub fn lex_tokens(&self, entrypoint: &str) -> Vec<Token> {
28
+ pub fn lex_tokens(&self, entrypoint: &str) -> Result<Vec<Token>, String> {
23
29
  let path = normalize_path(entrypoint);
24
- let resolved_path = Self::resolve_entry_path(&path);
30
+ let resolved_path = Self::resolve_entry_path(&path)?;
25
31
 
26
- let file_content =
27
- fs::read_to_string(&resolved_path).expect("Failed to read the entrypoint file");
32
+ let file_content = fs::read_to_string(&resolved_path).map_err(|e| {
33
+ format!(
34
+ "Failed to read the entrypoint file '{}': {}",
35
+ resolved_path, e
36
+ )
37
+ })?;
28
38
 
29
- handle_content_lexing(file_content).expect("Failed to lex the content")
39
+ handle_content_lexing(file_content).map_err(|e| format!("Failed to lex the content: {}", e))
30
40
  }
31
41
 
32
- fn resolve_entry_path(path: &str) -> String {
42
+ fn resolve_entry_path(path: &str) -> Result<String, String> {
33
43
  let candidate = Path::new(path);
34
44
 
35
45
  if candidate.is_dir() {
36
46
  let index_path = candidate.join("index.deva");
37
47
  if index_path.exists() {
38
- return index_path.to_string_lossy().replace("\\", "/");
48
+ Ok(index_path.to_string_lossy().replace("\\", "/"))
39
49
  } else {
40
- panic!(
50
+ Err(format!(
41
51
  "Expected 'index.deva' in directory '{}', but it was not found",
42
52
  path
43
- );
53
+ ))
44
54
  }
45
55
  } else if candidate.is_file() {
46
- return path.to_string();
56
+ return Ok(path.to_string());
47
57
  } else {
48
- panic!(
58
+ return Err(format!(
49
59
  "Provided entrypoint '{}' is not a valid file or directory",
50
60
  path
51
- );
61
+ ));
52
62
  }
53
63
  }
54
64
  }
@@ -1,97 +1,90 @@
1
- use serde::{Deserialize, Serialize};
2
-
3
- #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
4
- pub struct Token {
5
- pub kind: TokenKind,
6
- pub lexeme: String,
7
- pub indent: usize,
8
- pub line: usize,
9
- pub column: usize,
10
- }
11
-
12
- impl Token {
13
- pub fn is_error(&self) -> bool {
14
- match &self.kind {
15
- TokenKind::Error(_) => {
16
- return true;
17
- }
18
- _ => {
19
- return false;
20
- }
21
- };
22
- }
23
- }
24
-
25
- #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
26
- pub enum TokenKind {
27
- // ───── Keywords ─────
28
- At,
29
- Tempo,
30
- Bank,
31
- Loop,
32
- Function,
33
- As,
34
- On,
35
- Emit,
36
-
37
- // ───── Instruments ─────
38
- Synth,
39
-
40
- // ───── Literals ─────
41
- Identifier,
42
- Number,
43
- String,
44
- Boolean,
45
- Arrow,
46
-
47
- // ───── Structures ─────
48
- Map,
49
- Array,
50
-
51
- // ───── Symbols ─────
52
- Colon,
53
- Comma,
54
- Equals,
55
- Dot,
56
- Slash,
57
- Plus,
58
- Asterisk,
59
- Minus,
60
-
61
- // ───── Operators ─────
62
- DoubleEquals,
63
- NotEquals,
64
- GreaterEqual,
65
- LessEqual,
66
- Greater,
67
- Less,
68
-
69
- // ───── Brackets ─────
70
- LBrace, // {
71
- RBrace, // }
72
- LBracket, // [
73
- RBracket, // ]
74
- LParen, // (
75
- RParen, // )
76
-
77
- // ───── Quotes ─────
78
- Quote, // '
79
- DbQuote, // "
80
-
81
- // ───── Formatting ─────
82
- Newline,
83
- Indent,
84
- Dedent,
85
- Comment,
86
-
87
- // ───── Conditions ─────
88
- If,
89
- Else,
90
- ElseIf,
91
-
92
- // ───── Special / Internal ─────
93
- Whitespace,
94
- Unknown,
95
- Error(String),
96
- EOF,
97
- }
1
+ use serde::{Deserialize, Serialize};
2
+
3
+ #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
4
+ pub struct Token {
5
+ pub kind: TokenKind,
6
+ pub lexeme: String,
7
+ pub indent: usize,
8
+ pub line: usize,
9
+ pub column: usize,
10
+ }
11
+
12
+ impl Token {
13
+ pub fn is_error(&self) -> bool {
14
+ matches!(&self.kind, TokenKind::Error(_))
15
+ }
16
+ }
17
+
18
+ #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
19
+ pub enum TokenKind {
20
+ // ───── Keywords ─────
21
+ At,
22
+ Tempo,
23
+ Bank,
24
+ Loop,
25
+ Function,
26
+ As,
27
+ On,
28
+ Emit,
29
+
30
+ // ───── Instruments ─────
31
+ Synth,
32
+
33
+ // ───── Literals ─────
34
+ Identifier,
35
+ Number,
36
+ String,
37
+ Boolean,
38
+ Arrow,
39
+
40
+ // ───── Structures ─────
41
+ Map,
42
+ Array,
43
+
44
+ // ───── Symbols ─────
45
+ Colon,
46
+ Comma,
47
+ Equals,
48
+ Dot,
49
+ Slash,
50
+ Plus,
51
+ Asterisk,
52
+ Minus,
53
+
54
+ // ───── Operators ─────
55
+ DoubleEquals,
56
+ NotEquals,
57
+ GreaterEqual,
58
+ LessEqual,
59
+ Greater,
60
+ Less,
61
+
62
+ // ───── Brackets ─────
63
+ LBrace, // {
64
+ RBrace, // }
65
+ LBracket, // [
66
+ RBracket, // ]
67
+ LParen, // (
68
+ RParen, // )
69
+
70
+ // ───── Quotes ─────
71
+ Quote, // '
72
+ DbQuote, // "
73
+
74
+ // ───── Formatting ─────
75
+ Newline,
76
+ Indent,
77
+ Dedent,
78
+ Comment,
79
+
80
+ // ───── Conditions ─────
81
+ If,
82
+ Else,
83
+ ElseIf,
84
+
85
+ // ───── Special / Internal ─────
86
+ Whitespace,
87
+ Unknown,
88
+ Error(String),
89
+ EOF,
90
+ }
package/rust/core/mod.rs CHANGED
@@ -6,6 +6,5 @@ pub mod lexer;
6
6
  pub mod parser;
7
7
  pub mod plugin;
8
8
  pub mod preprocessor;
9
- pub mod shared;
10
9
  pub mod store;
11
10
  pub mod utils;
@@ -1,3 +1,5 @@
1
+ use devalang_types::Value;
2
+
1
3
  use crate::core::{
2
4
  lexer::token::{Token, TokenKind},
3
5
  parser::{
@@ -7,13 +9,15 @@ use crate::core::{
7
9
  bank::parse_bank_token,
8
10
  condition::parse_condition_token,
9
11
  dot::parse_dot_token,
10
- identifier::{function::parse_function_token, parse_identifier_token},
12
+ identifier::{
13
+ emit::parse_emit_token, function::parse_function_token, on::parse_on_token,
14
+ parse_identifier_token,
15
+ },
11
16
  loop_::parse_loop_token,
12
17
  tempo::parse_tempo_token,
13
18
  },
14
19
  statement::Statement,
15
20
  },
16
- shared::value::Value,
17
21
  store::global::GlobalStore,
18
22
  };
19
23
 
@@ -26,6 +30,12 @@ pub struct Parser {
26
30
  pub previous: Option<Token>,
27
31
  }
28
32
 
33
+ impl Default for Parser {
34
+ fn default() -> Self {
35
+ Self::new()
36
+ }
37
+ }
38
+
29
39
  impl Parser {
30
40
  pub fn new() -> Self {
31
41
  Parser {
@@ -53,7 +63,7 @@ impl Parser {
53
63
  }
54
64
 
55
65
  pub fn peek_is(&self, expected: &str) -> bool {
56
- self.peek().map_or(false, |t| t.lexeme == expected)
66
+ self.peek().is_some_and(|t| t.lexeme == expected)
57
67
  }
58
68
 
59
69
  pub fn peek_nth(&self, n: usize) -> Option<&Token> {
@@ -69,7 +79,7 @@ impl Parser {
69
79
  }
70
80
 
71
81
  pub fn advance_if(&mut self, kind: TokenKind) -> bool {
72
- if self.match_token(kind) { true } else { false }
82
+ self.match_token(kind)
73
83
  }
74
84
 
75
85
  pub fn match_token(&mut self, kind: TokenKind) -> bool {
@@ -149,8 +159,8 @@ impl Parser {
149
159
  TokenKind::Loop => parse_loop_token(self, global_store),
150
160
  TokenKind::If => parse_condition_token(self, global_store),
151
161
  TokenKind::Function => parse_function_token(self, global_store),
152
- TokenKind::On => crate::core::parser::handler::identifier::on::parse_on_token(self, global_store),
153
- TokenKind::Emit => crate::core::parser::handler::identifier::emit::parse_emit_token(self, token.clone(), global_store),
162
+ TokenKind::On => parse_on_token(self, global_store),
163
+ TokenKind::Emit => parse_emit_token(self, token.clone(), global_store),
154
164
 
155
165
  | TokenKind::Else // Ignore else, already handled in `parse_condition_token`
156
166
  | TokenKind::Comment
@@ -173,7 +183,7 @@ impl Parser {
173
183
 
174
184
  _ => {
175
185
  self.advance();
176
- Statement::unknown_from_token(&token)
186
+ Statement::unknown_with_pos(token.indent, token.line, token.column)
177
187
  }
178
188
  };
179
189
 
@@ -184,7 +194,7 @@ impl Parser {
184
194
  }
185
195
 
186
196
  pub fn check_token(&self, kind: TokenKind) -> bool {
187
- self.peek().map_or(false, |t| t.kind == kind)
197
+ self.peek().is_some_and(|t| t.kind == kind)
188
198
  }
189
199
 
190
200
  pub fn peek_kind(&self) -> Option<TokenKind> {
@@ -285,8 +295,34 @@ impl Parser {
285
295
  }
286
296
 
287
297
  TokenKind::Identifier => {
298
+ // Support dotted identifiers in map values: alias.param or nested
299
+ let current_line = token.line;
300
+ let mut parts: Vec<String> = vec![token.lexeme.clone()];
288
301
  self.advance();
289
- Value::Identifier(token.lexeme.clone())
302
+ loop {
303
+ let Some(next) = self.peek_clone() else { break };
304
+ if next.line != current_line {
305
+ break;
306
+ }
307
+ if next.kind == TokenKind::Dot {
308
+ // Consume '.' and the following identifier/number on same line
309
+ self.advance(); // dot
310
+ if let Some(id2) = self.peek_clone() {
311
+ if id2.line == current_line
312
+ && (id2.kind == TokenKind::Identifier
313
+ || id2.kind == TokenKind::Number)
314
+ {
315
+ parts.push(id2.lexeme.clone());
316
+ self.advance(); // consume part
317
+ continue;
318
+ }
319
+ }
320
+ break;
321
+ } else {
322
+ break;
323
+ }
324
+ }
325
+ Value::Identifier(parts.join("."))
290
326
  }
291
327
  _ => {
292
328
  println!("Unexpected token in map value: {:?}", token);
@@ -430,7 +466,12 @@ impl Parser {
430
466
  if tok.indent <= base_indent && tok.kind != TokenKind::Newline {
431
467
  break;
432
468
  }
433
- tokens.push(self.advance().unwrap().clone());
469
+ if let Some(t) = self.advance() {
470
+ tokens.push(t.clone());
471
+ } else {
472
+ // Unexpected EOF while collecting block tokens: stop collecting
473
+ break;
474
+ }
434
475
  }
435
476
 
436
477
  tokens
@@ -448,7 +489,11 @@ impl Parser {
448
489
  if token.kind == TokenKind::EOF {
449
490
  break;
450
491
  }
451
- collected.push(self.advance().unwrap().clone());
492
+ if let Some(t) = self.advance() {
493
+ collected.push(t.clone());
494
+ } else {
495
+ break;
496
+ }
452
497
  }
453
498
 
454
499
  collected
@@ -470,7 +515,11 @@ impl Parser {
470
515
  if tok.lexeme == "else" && tok.indent == base_indent {
471
516
  break;
472
517
  }
473
- block_tokens.push(self.advance().unwrap().clone());
518
+ if let Some(t) = self.advance() {
519
+ block_tokens.push(t.clone());
520
+ } else {
521
+ break;
522
+ }
474
523
  }
475
524
 
476
525
  self.parse_block(block_tokens, global_store)
@@ -505,7 +554,11 @@ impl Parser {
505
554
  if tok.indent < base_indent && tok.kind != TokenKind::Newline {
506
555
  break;
507
556
  }
508
- tokens.push(self.advance().unwrap().clone());
557
+ if let Some(t) = self.advance() {
558
+ tokens.push(t.clone());
559
+ } else {
560
+ break;
561
+ }
509
562
  }
510
563
 
511
564
  self.parse_block(tokens, global_store)
@@ -4,9 +4,9 @@ use crate::core::{
4
4
  driver::Parser,
5
5
  statement::{Statement, StatementKind},
6
6
  },
7
- shared::value::Value,
8
7
  store::global::GlobalStore,
9
8
  };
9
+ use devalang_types::Value;
10
10
 
11
11
  fn parse_map_literal(parser: &mut Parser) -> Value {
12
12
  // Assumes '{' has already been consumed by caller
@@ -126,28 +126,48 @@ pub fn parse_arrow_call(parser: &mut Parser, _global_store: &mut GlobalStore) ->
126
126
 
127
127
  if target_token.kind != TokenKind::Identifier {
128
128
  parser.advance(); // consume target token
129
- return Statement::unknown_from_token(&target_token);
129
+ return Statement::unknown_with_pos(
130
+ target_token.indent,
131
+ target_token.line,
132
+ target_token.column,
133
+ );
130
134
  }
131
135
 
132
136
  let Some(arrow_token) = parser.peek_nth(1).cloned() else {
133
137
  parser.advance(); // consume arrow token
134
- return Statement::unknown_from_token(&target_token);
138
+ return Statement::unknown_with_pos(
139
+ target_token.indent,
140
+ target_token.line,
141
+ target_token.column,
142
+ );
135
143
  };
136
144
 
137
145
  if arrow_token.kind != TokenKind::Arrow {
138
146
  parser.advance(); // consume method token
139
- return Statement::unknown_from_token(&target_token);
147
+ return Statement::unknown_with_pos(
148
+ target_token.indent,
149
+ target_token.line,
150
+ target_token.column,
151
+ );
140
152
  }
141
153
 
142
154
  // We have a valid arrow call, so we consume the arrow token
143
155
  let Some(method_token) = parser.peek_nth(2).cloned() else {
144
156
  parser.advance();
145
- return Statement::unknown_from_token(&target_token);
157
+ return Statement::unknown_with_pos(
158
+ target_token.indent,
159
+ target_token.line,
160
+ target_token.column,
161
+ );
146
162
  };
147
163
 
148
164
  if method_token.kind != TokenKind::Identifier {
149
165
  parser.advance();
150
- return Statement::unknown_from_token(&method_token);
166
+ return Statement::unknown_with_pos(
167
+ method_token.indent,
168
+ method_token.line,
169
+ method_token.column,
170
+ );
151
171
  }
152
172
 
153
173
  // Consume the tokens for target, arrow, and method
@@ -202,10 +222,10 @@ pub fn parse_arrow_call(parser: &mut Parser, _global_store: &mut GlobalStore) ->
202
222
  TokenKind::Number => Value::Number(token.lexeme.parse::<f32>().unwrap_or(0.0)),
203
223
  TokenKind::LBrace => {
204
224
  // Handle map literal (supports nested maps)
205
- let map_val = parse_map_literal(parser);
225
+
206
226
  // We consumed the matching '}', so outer map_depth should be decremented
207
227
  // if the caller tracks it.
208
- map_val
228
+ parse_map_literal(parser)
209
229
  }
210
230
  _ => Value::Unknown,
211
231
  };