@devaloop/devalang 0.0.1-alpha.9 → 0.0.1-beta.1

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 (271) hide show
  1. package/.cargo/config.toml +2 -0
  2. package/.devalang +10 -4
  3. package/.github/workflows/ci.yml +103 -0
  4. package/Cargo.toml +80 -48
  5. package/README.md +135 -154
  6. package/docs/CHANGELOG.md +386 -1
  7. package/docs/CONTRIBUTING.md +101 -0
  8. package/docs/ROADMAP.md +10 -7
  9. package/docs/TODO.md +21 -9
  10. package/examples/automation.deva +42 -0
  11. package/examples/bank.deva +7 -0
  12. package/examples/duration.deva +9 -0
  13. package/examples/events.deva +12 -0
  14. package/examples/function.deva +15 -0
  15. package/examples/index.deva +57 -12
  16. package/examples/loop.deva +5 -12
  17. package/examples/pattern.deva +8 -0
  18. package/examples/plugin.deva +16 -0
  19. package/examples/variables.deva +1 -1
  20. package/out-tsc/bin/index.d.ts +2 -0
  21. package/out-tsc/bin/index.js +51 -7
  22. package/out-tsc/core/functions/index.d.ts +37 -0
  23. package/out-tsc/core/functions/index.js +76 -0
  24. package/out-tsc/core/index.d.ts +6 -0
  25. package/out-tsc/core/index.js +22 -0
  26. package/out-tsc/core/types/index.d.ts +4 -0
  27. package/out-tsc/core/types/index.js +20 -0
  28. package/out-tsc/core/types/plugin.d.ts +18 -0
  29. package/out-tsc/core/types/plugin.js +2 -0
  30. package/out-tsc/core/types/result.d.ts +27 -0
  31. package/out-tsc/core/types/result.js +2 -0
  32. package/out-tsc/core/types/statement.d.ts +106 -0
  33. package/out-tsc/core/types/statement.js +2 -0
  34. package/out-tsc/core/types/value.d.ts +43 -0
  35. package/out-tsc/core/types/value.js +2 -0
  36. package/out-tsc/index.d.ts +7 -0
  37. package/out-tsc/index.js +42 -1
  38. package/out-tsc/pkg/devalang_core.d.ts +13 -0
  39. package/out-tsc/pkg/devalang_core.js +50 -0
  40. package/out-tsc/pkg/devalang_core_bg.wasm.d.ts +33 -0
  41. package/out-tsc/scripts/copy-wasm-dts.d.ts +1 -0
  42. package/out-tsc/scripts/copy-wasm-dts.js +73 -0
  43. package/out-tsc/scripts/postinstall.d.ts +1 -0
  44. package/out-tsc/scripts/postinstall.js +83 -0
  45. package/out-tsc/scripts/version/bump.d.ts +1 -0
  46. package/out-tsc/scripts/version/fetch.d.ts +1 -0
  47. package/out-tsc/scripts/version/index.d.ts +1 -0
  48. package/out-tsc/scripts/version/sync.d.ts +1 -0
  49. package/package.json +28 -7
  50. package/project-version.json +4 -4
  51. package/rust/cli/bank/api.rs +122 -0
  52. package/rust/cli/bank/commands.rs +275 -0
  53. package/rust/cli/bank/mod.rs +29 -0
  54. package/rust/cli/build/commands.rs +103 -0
  55. package/rust/cli/build/mod.rs +2 -0
  56. package/rust/cli/build/process.rs +146 -0
  57. package/rust/cli/check/mod.rs +208 -0
  58. package/rust/cli/discover/commands.rs +253 -0
  59. package/rust/cli/discover/config.rs +111 -0
  60. package/rust/cli/discover/fs.rs +19 -0
  61. package/rust/cli/discover/install.rs +103 -0
  62. package/rust/cli/discover/metadata.rs +48 -0
  63. package/rust/cli/discover/mod.rs +5 -0
  64. package/rust/cli/{init.rs → init/commands.rs} +32 -23
  65. package/rust/cli/init/mod.rs +1 -0
  66. package/rust/cli/install/addon.rs +118 -0
  67. package/rust/cli/install/bank.rs +53 -0
  68. package/rust/cli/install/commands.rs +35 -0
  69. package/rust/cli/install/mod.rs +4 -0
  70. package/rust/cli/install/plugin.rs +61 -0
  71. package/rust/cli/login/commands.rs +124 -0
  72. package/rust/cli/login/mod.rs +1 -0
  73. package/rust/cli/mod.rs +12 -205
  74. package/rust/cli/parser.rs +314 -0
  75. package/rust/cli/play/commands.rs +324 -0
  76. package/rust/cli/play/io.rs +17 -0
  77. package/rust/cli/play/mod.rs +5 -0
  78. package/rust/cli/play/process.rs +150 -0
  79. package/rust/cli/play/realtime.rs +91 -0
  80. package/rust/cli/play/utils.rs +23 -0
  81. package/rust/cli/telemetry/commands.rs +22 -0
  82. package/rust/cli/telemetry/event_creator.rs +80 -0
  83. package/rust/cli/telemetry/mod.rs +3 -0
  84. package/rust/cli/telemetry/send.rs +51 -0
  85. package/rust/cli/{template.rs → template/commands.rs} +69 -57
  86. package/rust/cli/template/mod.rs +1 -0
  87. package/rust/cli/update/commands.rs +6 -0
  88. package/rust/cli/update/mod.rs +1 -0
  89. package/rust/config/driver.rs +103 -0
  90. package/rust/config/mod.rs +3 -16
  91. package/rust/config/ops.rs +26 -0
  92. package/rust/config/settings.rs +101 -0
  93. package/rust/core/audio/engine/helpers.rs +170 -0
  94. package/rust/core/audio/engine/mod.rs +7 -0
  95. package/rust/core/audio/engine/sample.rs +366 -0
  96. package/rust/core/audio/engine/synth.rs +325 -0
  97. package/rust/core/audio/evaluator.rs +310 -31
  98. package/rust/core/audio/interpreter/arrow_call.rs +311 -129
  99. package/rust/core/audio/interpreter/automate.rs +18 -0
  100. package/rust/core/audio/interpreter/call.rs +294 -64
  101. package/rust/core/audio/interpreter/condition.rs +71 -69
  102. package/rust/core/audio/interpreter/driver.rs +542 -216
  103. package/rust/core/audio/interpreter/function.rs +26 -0
  104. package/rust/core/audio/interpreter/let_.rs +38 -19
  105. package/rust/core/audio/interpreter/load.rs +19 -18
  106. package/rust/core/audio/interpreter/loop_.rs +114 -67
  107. package/rust/core/audio/interpreter/mod.rs +14 -12
  108. package/rust/core/audio/interpreter/sleep.rs +28 -36
  109. package/rust/core/audio/interpreter/spawn.rs +252 -66
  110. package/rust/core/audio/interpreter/tempo.rs +40 -16
  111. package/rust/core/audio/interpreter/trigger.rs +239 -69
  112. package/rust/core/audio/loader/mod.rs +1 -1
  113. package/rust/core/audio/loader/trigger.rs +97 -52
  114. package/rust/core/audio/mod.rs +7 -6
  115. package/rust/core/audio/player.rs +70 -54
  116. package/rust/core/audio/renderer.rs +54 -54
  117. package/rust/core/audio/special/easing.rs +189 -0
  118. package/rust/core/audio/special/env.rs +45 -0
  119. package/rust/core/audio/special/math.rs +134 -0
  120. package/rust/core/audio/special/mod.rs +9 -0
  121. package/rust/core/audio/special/modulator.rs +143 -0
  122. package/rust/core/builder/mod.rs +86 -80
  123. package/rust/core/debugger/lexer.rs +27 -27
  124. package/rust/core/debugger/mod.rs +30 -21
  125. package/rust/core/debugger/module.rs +55 -0
  126. package/rust/core/debugger/preprocessor.rs +27 -27
  127. package/rust/core/debugger/store.rs +40 -25
  128. package/rust/core/error/mod.rs +269 -60
  129. package/rust/core/lexer/driver.rs +61 -0
  130. package/rust/core/lexer/handler/arrow.rs +82 -31
  131. package/rust/core/lexer/handler/at.rs +21 -21
  132. package/rust/core/lexer/handler/brace.rs +41 -41
  133. package/rust/core/lexer/handler/colon.rs +21 -21
  134. package/rust/core/lexer/handler/comment.rs +30 -30
  135. package/rust/core/lexer/handler/dot.rs +21 -21
  136. package/rust/core/lexer/handler/driver.rs +337 -226
  137. package/rust/core/lexer/handler/identifier.rs +47 -41
  138. package/rust/core/lexer/handler/indent.rs +66 -52
  139. package/rust/core/lexer/handler/mod.rs +15 -14
  140. package/rust/core/lexer/handler/newline.rs +23 -23
  141. package/rust/core/lexer/handler/number.rs +31 -31
  142. package/rust/core/lexer/handler/operator.rs +46 -44
  143. package/rust/core/lexer/handler/parenthesis.rs +41 -0
  144. package/rust/core/lexer/handler/slash.rs +21 -0
  145. package/rust/core/lexer/handler/string.rs +63 -63
  146. package/rust/core/lexer/mod.rs +3 -51
  147. package/rust/core/lexer/token.rs +17 -12
  148. package/rust/core/mod.rs +10 -10
  149. package/rust/core/parser/driver.rs +584 -331
  150. package/rust/core/parser/handler/arrow_call.rs +253 -126
  151. package/rust/core/parser/handler/at.rs +279 -162
  152. package/rust/core/parser/handler/bank.rs +104 -41
  153. package/rust/core/parser/handler/condition.rs +83 -74
  154. package/rust/core/parser/handler/dot.rs +148 -112
  155. package/rust/core/parser/handler/identifier/automate.rs +254 -0
  156. package/rust/core/parser/handler/identifier/call.rs +91 -41
  157. package/rust/core/parser/handler/identifier/emit.rs +70 -0
  158. package/rust/core/parser/handler/identifier/function.rs +113 -0
  159. package/rust/core/parser/handler/identifier/group.rs +89 -75
  160. package/rust/core/parser/handler/identifier/let_.rs +173 -133
  161. package/rust/core/parser/handler/identifier/mod.rs +55 -51
  162. package/rust/core/parser/handler/identifier/on.rs +107 -0
  163. package/rust/core/parser/handler/identifier/print.rs +49 -0
  164. package/rust/core/parser/handler/identifier/sleep.rs +43 -33
  165. package/rust/core/parser/handler/identifier/spawn.rs +91 -41
  166. package/rust/core/parser/handler/identifier/synth.rs +135 -65
  167. package/rust/core/parser/handler/loop_.rs +194 -72
  168. package/rust/core/parser/handler/mod.rs +9 -8
  169. package/rust/core/parser/handler/pattern.rs +74 -0
  170. package/rust/core/parser/handler/tempo.rs +57 -47
  171. package/rust/core/parser/mod.rs +3 -4
  172. package/rust/core/parser/statement.rs +11 -96
  173. package/rust/core/plugin/loader.rs +137 -0
  174. package/rust/core/plugin/mod.rs +2 -0
  175. package/rust/core/plugin/runner.rs +347 -0
  176. package/rust/core/preprocessor/loader.rs +637 -193
  177. package/rust/core/preprocessor/mod.rs +4 -4
  178. package/rust/core/preprocessor/module.rs +60 -50
  179. package/rust/core/preprocessor/processor.rs +114 -76
  180. package/rust/core/preprocessor/resolver/bank.rs +49 -47
  181. package/rust/core/preprocessor/resolver/call.rs +124 -123
  182. package/rust/core/preprocessor/resolver/condition.rs +95 -92
  183. package/rust/core/preprocessor/resolver/driver.rs +324 -227
  184. package/rust/core/preprocessor/resolver/function.rs +69 -0
  185. package/rust/core/preprocessor/resolver/group.rs +94 -61
  186. package/rust/core/preprocessor/resolver/let_.rs +32 -31
  187. package/rust/core/preprocessor/resolver/loop_.rs +318 -91
  188. package/rust/core/preprocessor/resolver/mod.rs +16 -14
  189. package/rust/core/preprocessor/resolver/pattern.rs +83 -0
  190. package/rust/core/preprocessor/resolver/spawn.rs +99 -58
  191. package/rust/core/preprocessor/resolver/synth.rs +54 -50
  192. package/rust/core/preprocessor/resolver/tempo.rs +48 -49
  193. package/rust/core/preprocessor/resolver/trigger.rs +116 -112
  194. package/rust/core/preprocessor/resolver/value.rs +176 -78
  195. package/rust/core/store/export.rs +28 -28
  196. package/rust/core/store/function.rs +40 -0
  197. package/rust/core/store/global.rs +61 -39
  198. package/rust/core/store/import.rs +28 -28
  199. package/rust/core/store/mod.rs +5 -4
  200. package/rust/core/store/variable.rs +51 -28
  201. package/rust/core/utils/mod.rs +1 -2
  202. package/rust/core/utils/path.rs +37 -31
  203. package/rust/lib.rs +308 -117
  204. package/rust/main.rs +364 -65
  205. package/rust/types/Cargo.toml +11 -0
  206. package/rust/types/src/addons.rs +55 -0
  207. package/rust/types/src/ast.rs +202 -0
  208. package/rust/types/src/config.rs +74 -0
  209. package/rust/types/src/lib.rs +12 -0
  210. package/rust/types/src/telemetry.rs +85 -0
  211. package/rust/utils/Cargo.toml +26 -0
  212. package/rust/utils/src/error.rs +186 -0
  213. package/rust/utils/src/file.rs +94 -0
  214. package/rust/utils/src/first_usage.rs +97 -0
  215. package/rust/utils/{mod.rs → src/lib.rs} +9 -6
  216. package/rust/utils/{logger.rs → src/logger.rs} +200 -123
  217. package/rust/utils/src/path.rs +88 -0
  218. package/rust/utils/src/signature.rs +41 -0
  219. package/rust/utils/{spinner.rs → src/spinner.rs} +20 -21
  220. package/rust/utils/src/version.rs +27 -0
  221. package/rust/utils/{watcher.rs → src/watcher.rs} +46 -33
  222. package/rust/web/api.rs +5 -0
  223. package/rust/web/cdn.rs +34 -0
  224. package/rust/web/mod.rs +3 -0
  225. package/rust/web/sso.rs +5 -0
  226. package/templates/minimal/README.md +143 -127
  227. package/templates/welcome/README.md +143 -127
  228. package/templates/welcome/src/index.deva +56 -8
  229. package/templates/welcome/src/variables.deva +2 -4
  230. package/tests/integration.rs +21 -0
  231. package/tests/rust/cli_check_build.rs +21 -0
  232. package/tests/rust/cli_help.rs +12 -0
  233. package/tests/rust/cli_template_list.rs +10 -0
  234. package/tests/rust/cli_version.rs +11 -0
  235. package/tests/typescript/index.spec.ts +136 -0
  236. package/tests/typescript/playhead.spec.ts +36 -0
  237. package/tests/typescript/render_e2e.spec.ts +77 -0
  238. package/tsconfig.json +12 -10
  239. package/typescript/bin/index.ts +19 -5
  240. package/typescript/core/functions/index.ts +83 -0
  241. package/typescript/core/index.ts +6 -0
  242. package/typescript/core/types/index.ts +4 -0
  243. package/typescript/core/types/plugin.ts +19 -0
  244. package/typescript/core/types/result.ts +29 -0
  245. package/typescript/core/types/statement.ts +47 -0
  246. package/typescript/core/types/value.ts +29 -0
  247. package/typescript/index.ts +8 -1
  248. package/typescript/pkg/devalang_core.d.ts +4 -0
  249. package/typescript/pkg/devalang_core.ts +49 -0
  250. package/typescript/scripts/copy-wasm-dts.ts +41 -0
  251. package/typescript/scripts/postinstall.ts +85 -0
  252. package/typescript/scripts/version/bump.ts +0 -1
  253. package/typescript/scripts/version/index.ts +0 -1
  254. package/docs/COMMANDS.md +0 -85
  255. package/docs/CONFIG.md +0 -30
  256. package/docs/SYNTAX.md +0 -210
  257. package/out-tsc/bin/devalang.exe +0 -0
  258. package/out-tsc/scripts/postbuild.js +0 -11
  259. package/rust/cli/build.rs +0 -137
  260. package/rust/cli/check.rs +0 -117
  261. package/rust/cli/play.rs +0 -193
  262. package/rust/config/loader.rs +0 -13
  263. package/rust/core/audio/engine.rs +0 -203
  264. package/rust/core/shared/duration.rs +0 -8
  265. package/rust/core/shared/mod.rs +0 -2
  266. package/rust/core/shared/value.rs +0 -18
  267. package/rust/core/utils/validation.rs +0 -37
  268. package/rust/utils/file.rs +0 -35
  269. package/rust/utils/signature.rs +0 -17
  270. package/rust/utils/version.rs +0 -15
  271. package/typescript/scripts/postbuild.ts +0 -8
@@ -1,74 +1,83 @@
1
- use std::collections::HashMap;
2
- use crate::core::{
3
- lexer::token::TokenKind,
4
- parser::{statement::{Statement, StatementKind}, driver::Parser},
5
- shared::value::Value,
6
- store::global::GlobalStore,
7
- };
8
-
9
- pub fn parse_condition_token(parser: &mut Parser, global_store: &mut GlobalStore) -> Statement {
10
- parser.advance(); // consume 'if'
11
- let Some(if_token) = parser.previous_clone() else {
12
- return Statement::unknown();
13
- };
14
-
15
- let Some(condition) = parser.parse_condition_until_colon() else {
16
- return Statement::error(if_token, "Expected condition after 'if'".to_string());
17
- };
18
-
19
- parser.advance_if(TokenKind::Colon);
20
- let base_indent = if_token.indent;
21
-
22
- let if_body = parser.parse_block_until_else_or_dedent(base_indent, global_store);
23
-
24
- let mut root_map = HashMap::new();
25
- root_map.insert("condition".to_string(), condition);
26
- root_map.insert("body".to_string(), Value::Block(if_body));
27
-
28
- let mut current = &mut root_map;
29
-
30
- // Loop for else / else if
31
- while let Some(tok) = parser.peek_clone() {
32
- // Only continue if we see `else` at same indent level
33
- if tok.lexeme != "else" || tok.indent != base_indent {
34
- break;
35
- }
36
-
37
- parser.advance(); // consume 'else'
38
-
39
- // Check if it's an 'else if'
40
- let next_condition = if parser.peek_is("if") {
41
- parser.advance(); // consume 'if'
42
- let Some(cond) = parser.parse_condition_until_colon() else {
43
- return Statement::error(tok.clone(), "Expected condition after 'else if'".to_string());
44
- };
45
- parser.advance_if(TokenKind::Colon);
46
- Some(cond)
47
- } else {
48
- parser.advance_if(TokenKind::Colon);
49
- None
50
- };
51
-
52
- let body = parser.parse_block_until_else_or_dedent(base_indent, global_store);
53
-
54
- let mut next_map = HashMap::new();
55
- if let Some(cond) = next_condition {
56
- next_map.insert("condition".to_string(), cond);
57
- }
58
- next_map.insert("body".to_string(), Value::Block(body));
59
-
60
- current.insert("next".to_string(), Value::Map(next_map));
61
- current = match current.get_mut("next") {
62
- Some(Value::Map(map)) => map,
63
- _ => break,
64
- };
65
- }
66
-
67
- Statement {
68
- kind: StatementKind::If,
69
- value: Value::Map(root_map),
70
- indent: if_token.indent,
71
- line: if_token.line,
72
- column: if_token.column,
73
- }
74
- }
1
+ use crate::core::{
2
+ lexer::token::TokenKind,
3
+ parser::{
4
+ driver::Parser,
5
+ statement::{Statement, StatementKind},
6
+ },
7
+ store::global::GlobalStore,
8
+ };
9
+ use devalang_types::Value;
10
+ use std::collections::HashMap;
11
+
12
+ pub fn parse_condition_token(parser: &mut Parser, global_store: &mut GlobalStore) -> Statement {
13
+ parser.advance(); // consume 'if'
14
+ let Some(if_token) = parser.previous_clone() else {
15
+ return Statement::unknown();
16
+ };
17
+
18
+ let Some(condition) = parser.parse_condition_until_colon() else {
19
+ return crate::core::parser::statement::error_from_token(
20
+ if_token,
21
+ "Expected condition after 'if'".to_string(),
22
+ );
23
+ };
24
+
25
+ parser.advance_if(TokenKind::Colon);
26
+ let base_indent = if_token.indent;
27
+
28
+ let if_body = parser.parse_block_until_else_or_dedent(base_indent, global_store);
29
+
30
+ let mut root_map = HashMap::new();
31
+ root_map.insert("condition".to_string(), condition);
32
+ root_map.insert("body".to_string(), Value::Block(if_body));
33
+
34
+ let mut current = &mut root_map;
35
+
36
+ // Loop for else / else if
37
+ while let Some(tok) = parser.peek_clone() {
38
+ // Only continue if we see `else` at same indent level
39
+ if tok.lexeme != "else" || tok.indent != base_indent {
40
+ break;
41
+ }
42
+
43
+ parser.advance(); // consume 'else'
44
+
45
+ // Check if it's an 'else if'
46
+ let next_condition = if parser.peek_is("if") {
47
+ parser.advance(); // consume 'if'
48
+ let Some(cond) = parser.parse_condition_until_colon() else {
49
+ return crate::core::parser::statement::error_from_token(
50
+ tok.clone(),
51
+ "Expected condition after 'else if'".to_string(),
52
+ );
53
+ };
54
+ parser.advance_if(TokenKind::Colon);
55
+ Some(cond)
56
+ } else {
57
+ parser.advance_if(TokenKind::Colon);
58
+ None
59
+ };
60
+
61
+ let body = parser.parse_block_until_else_or_dedent(base_indent, global_store);
62
+
63
+ let mut next_map = HashMap::new();
64
+ if let Some(cond) = next_condition {
65
+ next_map.insert("condition".to_string(), cond);
66
+ }
67
+ next_map.insert("body".to_string(), Value::Block(body));
68
+
69
+ current.insert("next".to_string(), Value::Map(next_map));
70
+ current = match current.get_mut("next") {
71
+ Some(Value::Map(map)) => map,
72
+ _ => break,
73
+ };
74
+ }
75
+
76
+ Statement {
77
+ kind: StatementKind::If,
78
+ value: Value::Map(root_map),
79
+ indent: if_token.indent,
80
+ line: if_token.line,
81
+ column: if_token.column,
82
+ }
83
+ }
@@ -1,112 +1,148 @@
1
- use crate::core::{
2
- lexer::token::TokenKind,
3
- parser::{ statement::{ Statement, StatementKind }, driver::Parser },
4
- shared::{ duration::Duration, value::Value },
5
- store::global::GlobalStore,
6
- };
7
-
8
- pub fn parse_dot_token(parser: &mut Parser, _global_store: &mut GlobalStore) -> Statement {
9
- parser.advance(); // consume the dot token
10
-
11
- let Some(dot_token) = parser.previous_clone() else {
12
- return Statement::unknown();
13
- };
14
-
15
- // .kick
16
- let Some(entity_token) = parser.peek_clone() else {
17
- return Statement {
18
- kind: StatementKind::Trigger {
19
- entity: String::new(),
20
- duration: Duration::Auto,
21
- },
22
- value: Value::Null,
23
- indent: dot_token.indent,
24
- line: dot_token.line,
25
- column: dot_token.column,
26
- };
27
- };
28
-
29
- parser.advance(); // consume entity
30
- let entity = entity_token.lexeme.clone();
31
-
32
- // Check if there's a duration
33
- let next = parser.peek_clone();
34
-
35
- let (duration, value) = match next {
36
- // If no more tokens, it's just `.kick`
37
- None => (Duration::Auto, Value::Null),
38
-
39
- Some(token) =>
40
- match token.kind {
41
- TokenKind::Newline | TokenKind::EOF => { (Duration::Auto, Value::Null) }
42
-
43
- TokenKind::Number => {
44
- let duration_lexeme = token.lexeme.clone();
45
- parser.advance(); // consume duration
46
-
47
- // Try to parse optional value (ex: .kick 250 params)
48
- match parser.peek_clone() {
49
- Some(param_token) if param_token.kind == TokenKind::Identifier => {
50
- parser.advance();
51
- (
52
- parse_duration(duration_lexeme),
53
- Value::Identifier(param_token.lexeme.clone()),
54
- )
55
- }
56
-
57
- Some(param_token) if param_token.kind == TokenKind::LBrace => {
58
- // Handle value as Map
59
- let map = parser.parse_map_value(); // Assumes you have a helper for map
60
- (parse_duration(duration_lexeme), map.unwrap_or(Value::Null))
61
- }
62
-
63
- _ => (parse_duration(duration_lexeme), Value::Null),
64
- }
65
- }
66
-
67
- TokenKind::Identifier => {
68
- let duration_lexeme = token.lexeme.clone();
69
- parser.advance(); // consume duration
70
-
71
- // Try to parse optional value (ex: .kick auto params)
72
- match parser.peek_clone() {
73
- Some(param_token) if param_token.kind == TokenKind::Identifier => {
74
- parser.advance();
75
- (
76
- parse_duration(duration_lexeme),
77
- Value::Identifier(param_token.lexeme.clone()),
78
- )
79
- }
80
-
81
- Some(param_token) if param_token.kind == TokenKind::LBrace => {
82
- // Handle value as Map
83
- let map = parser.parse_map_value(); // Assumes you have a helper for map
84
- (parse_duration(duration_lexeme), map.unwrap_or(Value::Null))
85
- }
86
-
87
- _ => (parse_duration(duration_lexeme), Value::Null),
88
- }
89
- }
90
-
91
- _ => (Duration::Auto, Value::Null),
92
- }
93
- };
94
-
95
- Statement {
96
- kind: StatementKind::Trigger { entity, duration },
97
- value,
98
- indent: dot_token.indent,
99
- line: dot_token.line,
100
- column: dot_token.column,
101
- }
102
- }
103
-
104
- fn parse_duration(s: String) -> Duration {
105
- if s == "auto" {
106
- Duration::Auto
107
- } else if s.parse::<f32>().is_ok() {
108
- Duration::Number(s.parse().unwrap())
109
- } else {
110
- Duration::Identifier(s)
111
- }
112
- }
1
+ use devalang_types::{Duration, Value};
2
+
3
+ use crate::core::{
4
+ lexer::token::TokenKind,
5
+ parser::{
6
+ driver::Parser,
7
+ statement::{Statement, StatementKind},
8
+ },
9
+ };
10
+
11
+ pub fn parse_dot_token(
12
+ parser: &mut Parser,
13
+ _global_store: &mut crate::core::store::global::GlobalStore,
14
+ ) -> Statement {
15
+ parser.advance(); // consume '.'
16
+ let logger = devalang_utils::logger::Logger::new();
17
+ use devalang_utils::logger::LogLevel;
18
+ let Some(dot_token) = parser.previous_clone() else {
19
+ return Statement::unknown();
20
+ };
21
+
22
+ // Parse a single entity (namespace-friendly, stops at newline)
23
+ let mut parts = Vec::new();
24
+ let current_line = dot_token.line;
25
+
26
+ while let Some(token) = parser.peek_clone() {
27
+ // Never cross a newline
28
+ if token.line != current_line {
29
+ break;
30
+ }
31
+ match token.kind {
32
+ TokenKind::Identifier | TokenKind::Number => {
33
+ parts.push(token.lexeme.clone());
34
+ parser.advance();
35
+ // The separator must be a '.' on the same line, otherwise stop
36
+ if let Some(next) = parser.peek_clone() {
37
+ if next.line != current_line || next.kind != TokenKind::Dot {
38
+ break;
39
+ }
40
+ } else {
41
+ break;
42
+ }
43
+ }
44
+ TokenKind::Dot => {
45
+ parser.advance();
46
+ }
47
+ TokenKind::Newline | TokenKind::EOF | TokenKind::Indent | TokenKind::Dedent => {
48
+ break; // Stop at newline or dedent
49
+ }
50
+ _ => {
51
+ break;
52
+ }
53
+ }
54
+ }
55
+
56
+ // Build entity name properly
57
+ let entity = if !parts.is_empty() {
58
+ parts.join(".") // only join within the same line
59
+ } else {
60
+ logger.log_message(
61
+ LogLevel::Warning,
62
+ &format!("Empty entity after '.' at line {}", dot_token.line),
63
+ );
64
+ String::new()
65
+ };
66
+
67
+ // Optional duration and effects map
68
+ let mut duration = Duration::Auto;
69
+ let mut value = Value::Null;
70
+
71
+ if let Some(token) = parser.peek_clone() {
72
+ // Duration and effects map are only valid on the same line
73
+ if token.line == current_line {
74
+ match token.kind {
75
+ TokenKind::Number => {
76
+ let numerator = token.lexeme.clone();
77
+ parser.advance();
78
+ if let Some(peek) = parser.peek_clone() {
79
+ if peek.line == current_line {
80
+ if let Some(TokenKind::Slash) = parser.peek_kind() {
81
+ parser.advance();
82
+ if let Some(denominator_token) = parser.peek_clone() {
83
+ if denominator_token.line == current_line
84
+ && denominator_token.kind == TokenKind::Number
85
+ {
86
+ let denominator = denominator_token.lexeme.clone();
87
+ parser.advance();
88
+ duration = Duration::Beat(format!(
89
+ "{}/{}",
90
+ numerator, denominator
91
+ ));
92
+ }
93
+ }
94
+ } else {
95
+ duration = parse_duration(numerator);
96
+ }
97
+ } else {
98
+ duration = parse_duration(numerator);
99
+ }
100
+ } else {
101
+ duration = parse_duration(numerator);
102
+ }
103
+ if let Some(next) = parser.peek_clone() {
104
+ if next.line == current_line && next.kind == TokenKind::LBrace {
105
+ value = parser.parse_map_value().unwrap_or(Value::Null);
106
+ }
107
+ }
108
+ }
109
+ TokenKind::Identifier => {
110
+ let id = token.lexeme.clone();
111
+ parser.advance();
112
+ duration = parse_duration(id);
113
+ if let Some(next) = parser.peek_clone() {
114
+ if next.line == current_line && next.kind == TokenKind::LBrace {
115
+ value = parser.parse_map_value().unwrap_or(Value::Null);
116
+ }
117
+ }
118
+ }
119
+ TokenKind::LBrace => {
120
+ value = parser.parse_map_value().unwrap_or(Value::Null);
121
+ }
122
+ _ => {}
123
+ }
124
+ }
125
+ }
126
+
127
+ Statement {
128
+ kind: StatementKind::Trigger {
129
+ entity,
130
+ duration,
131
+ effects: Some(value.clone()),
132
+ },
133
+ value: Value::Null,
134
+ indent: dot_token.indent,
135
+ line: dot_token.line,
136
+ column: dot_token.column,
137
+ }
138
+ }
139
+
140
+ fn parse_duration(s: String) -> Duration {
141
+ if s == "auto" {
142
+ Duration::Auto
143
+ } else if let Ok(num) = s.parse::<f32>() {
144
+ Duration::Number(num)
145
+ } else {
146
+ Duration::Identifier(s)
147
+ }
148
+ }