@devaloop/devalang 0.0.1-beta.2 → 0.0.1-beta.3

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 (159) hide show
  1. package/Cargo.toml +84 -81
  2. package/README.md +3 -2
  3. package/docs/CHANGELOG.md +41 -0
  4. package/docs/ROADMAP.md +3 -3
  5. package/examples/chain.deva +19 -0
  6. package/examples/plugin.deva +10 -10
  7. package/examples/routing.deva +23 -0
  8. package/out-tsc/bin/project-version.json +6 -0
  9. package/out-tsc/pkg/devalang_core_bg.wasm.d.ts +8 -8
  10. package/out-tsc/scripts/version/copy-to-binary.d.ts +1 -0
  11. package/out-tsc/scripts/version/copy-to-binary.js +79 -0
  12. package/package.json +23 -10
  13. package/project-version.json +3 -3
  14. package/rust/bindings/Cargo.toml +9 -0
  15. package/rust/bindings/src/lib.rs +86 -0
  16. package/rust/cli/addon/commands.rs +35 -0
  17. package/rust/cli/addon/download.rs +234 -0
  18. package/rust/cli/addon/install.rs +33 -0
  19. package/rust/cli/addon/list.rs +224 -0
  20. package/rust/cli/addon/metadata.rs +124 -0
  21. package/rust/cli/addon/mod.rs +8 -0
  22. package/rust/cli/addon/remove.rs +271 -0
  23. package/rust/cli/addon/update.rs +305 -0
  24. package/rust/cli/{install/addon.rs → addon/utils.rs} +109 -118
  25. package/rust/cli/build/commands.rs +153 -153
  26. package/rust/cli/build/process.rs +165 -165
  27. package/rust/cli/check/mod.rs +208 -208
  28. package/rust/cli/discover/commands.rs +275 -253
  29. package/rust/cli/discover/config.rs +109 -111
  30. package/rust/cli/discover/fs.rs +19 -19
  31. package/rust/cli/discover/install.rs +214 -103
  32. package/rust/cli/discover/metadata.rs +48 -48
  33. package/rust/cli/discover/mod.rs +5 -5
  34. package/rust/cli/me/commands.rs +52 -0
  35. package/rust/cli/me/mod.rs +1 -0
  36. package/rust/cli/mod.rs +12 -12
  37. package/rust/cli/parser.rs +30 -69
  38. package/rust/cli/play/commands.rs +375 -375
  39. package/rust/cli/play/process.rs +159 -159
  40. package/rust/core/audio/engine/driver.rs +19 -2
  41. package/rust/core/audio/engine/export.rs +169 -169
  42. package/rust/core/audio/engine/mod.rs +56 -56
  43. package/rust/core/audio/engine/notes/dsp.rs +88 -85
  44. package/rust/core/audio/engine/notes/mod.rs +53 -44
  45. package/rust/core/audio/engine/notes/params.rs +294 -294
  46. package/rust/core/audio/engine/sample/insert.rs +148 -47
  47. package/rust/core/audio/engine/sample/mod.rs +40 -40
  48. package/rust/core/audio/engine/sample/padding.rs +170 -170
  49. package/rust/core/audio/evaluator/condition.rs +61 -61
  50. package/rust/core/audio/evaluator/numeric.rs +152 -152
  51. package/rust/core/audio/evaluator/rhs.rs +16 -16
  52. package/rust/core/audio/evaluator/string_expr.rs +94 -94
  53. package/rust/core/audio/interpreter/driver.rs +574 -574
  54. package/rust/core/audio/interpreter/mod.rs +2 -2
  55. package/rust/core/audio/interpreter/statements/arrow_call/interprete.rs +9 -5
  56. package/rust/core/audio/interpreter/statements/arrow_call/methods/chord.rs +398 -384
  57. package/rust/core/audio/interpreter/statements/arrow_call/methods/effects.rs +323 -0
  58. package/rust/core/audio/interpreter/statements/arrow_call/methods/mod.rs +1 -0
  59. package/rust/core/audio/interpreter/statements/arrow_call/methods/note.rs +66 -11
  60. package/rust/core/audio/interpreter/statements/arrow_call/mod.rs +3 -3
  61. package/rust/core/audio/interpreter/statements/arrow_call/types/arp.rs +192 -192
  62. package/rust/core/audio/interpreter/statements/arrow_call/types/mod.rs +24 -24
  63. package/rust/core/audio/interpreter/statements/arrow_call/types/pad.rs +116 -116
  64. package/rust/core/audio/interpreter/statements/arrow_call/types/pluck.rs +97 -97
  65. package/rust/core/audio/interpreter/statements/arrow_call/types/sub.rs +100 -100
  66. package/rust/core/audio/interpreter/statements/automate.rs +16 -16
  67. package/rust/core/audio/interpreter/statements/call.rs +31 -1
  68. package/rust/core/audio/interpreter/statements/condition.rs +72 -72
  69. package/rust/core/audio/interpreter/statements/function.rs +24 -24
  70. package/rust/core/audio/interpreter/statements/let_.rs +36 -36
  71. package/rust/core/audio/interpreter/statements/load.rs +17 -17
  72. package/rust/core/audio/interpreter/statements/loop_.rs +115 -115
  73. package/rust/core/audio/interpreter/statements/spawn.rs +51 -2
  74. package/rust/core/audio/interpreter/statements/trigger.rs +242 -239
  75. package/rust/core/audio/loader/trigger.rs +98 -98
  76. package/rust/core/audio/player.rs +70 -70
  77. package/rust/core/audio/special/mod.rs +9 -9
  78. package/rust/core/builder/mod.rs +129 -129
  79. package/rust/core/debugger/lexer.rs +27 -27
  80. package/rust/core/debugger/logs.rs +52 -52
  81. package/rust/core/debugger/preprocessor.rs +27 -27
  82. package/rust/core/debugger/store.rs +38 -38
  83. package/rust/core/lexer/driver.rs +59 -59
  84. package/rust/core/lexer/handler/arrow.rs +82 -82
  85. package/rust/core/lexer/handler/at.rs +21 -21
  86. package/rust/core/lexer/handler/brace.rs +41 -41
  87. package/rust/core/lexer/handler/colon.rs +21 -21
  88. package/rust/core/lexer/handler/comment.rs +30 -30
  89. package/rust/core/lexer/handler/dot.rs +21 -21
  90. package/rust/core/lexer/handler/driver.rs +337 -337
  91. package/rust/core/lexer/handler/identifier.rs +47 -47
  92. package/rust/core/lexer/handler/indent.rs +66 -66
  93. package/rust/core/lexer/handler/mod.rs +15 -15
  94. package/rust/core/lexer/handler/newline.rs +23 -23
  95. package/rust/core/lexer/handler/number.rs +31 -31
  96. package/rust/core/lexer/handler/operator.rs +46 -46
  97. package/rust/core/lexer/handler/parenthesis.rs +41 -41
  98. package/rust/core/lexer/handler/slash.rs +21 -21
  99. package/rust/core/lexer/handler/string.rs +63 -63
  100. package/rust/core/lexer/mod.rs +3 -3
  101. package/rust/core/mod.rs +9 -9
  102. package/rust/core/parser/driver/block.rs +111 -111
  103. package/rust/core/parser/driver/cursor.rs +82 -82
  104. package/rust/core/parser/driver/driver_impl.rs +21 -1
  105. package/rust/core/parser/driver/mod.rs +6 -6
  106. package/rust/core/parser/driver/parse_array.rs +120 -120
  107. package/rust/core/parser/driver/parse_map.rs +247 -223
  108. package/rust/core/parser/driver/parser.rs +160 -160
  109. package/rust/core/parser/handler/arrow_call.rs +65 -14
  110. package/rust/core/parser/handler/identifier/synth.rs +171 -135
  111. package/rust/core/parser/handler/mod.rs +9 -9
  112. package/rust/core/parser/handler/pattern.rs +24 -1
  113. package/rust/core/plugin/loader.rs +137 -137
  114. package/rust/core/plugin/mod.rs +2 -2
  115. package/rust/core/plugin/runner/non_wasm.rs +481 -297
  116. package/rust/core/plugin/runner/wasm32.rs +1 -0
  117. package/rust/core/preprocessor/loader/inject.rs +313 -278
  118. package/rust/core/preprocessor/loader/loader_helpers.rs +110 -110
  119. package/rust/core/preprocessor/loader/mod.rs +235 -235
  120. package/rust/core/preprocessor/module.rs +55 -55
  121. package/rust/core/preprocessor/processor/handlers.rs +107 -107
  122. package/rust/core/preprocessor/resolver/bank.rs +49 -49
  123. package/rust/core/preprocessor/resolver/call.rs +124 -124
  124. package/rust/core/preprocessor/resolver/condition.rs +95 -95
  125. package/rust/core/preprocessor/resolver/driver.rs +324 -324
  126. package/rust/core/preprocessor/resolver/function.rs +69 -69
  127. package/rust/core/preprocessor/resolver/group.rs +122 -122
  128. package/rust/core/preprocessor/resolver/let_.rs +32 -32
  129. package/rust/core/preprocessor/resolver/loop_.rs +318 -318
  130. package/rust/core/preprocessor/resolver/mod.rs +16 -16
  131. package/rust/core/preprocessor/resolver/pattern.rs +95 -83
  132. package/rust/core/preprocessor/resolver/spawn.rs +99 -99
  133. package/rust/core/preprocessor/resolver/synth.rs +54 -54
  134. package/rust/core/preprocessor/resolver/tempo.rs +48 -48
  135. package/rust/core/preprocessor/resolver/trigger.rs +116 -116
  136. package/rust/core/preprocessor/resolver/value.rs +176 -176
  137. package/rust/core/store/global.rs +57 -57
  138. package/rust/lib.rs +323 -323
  139. package/rust/macros/Cargo.toml +14 -0
  140. package/rust/macros/src/lib.rs +52 -0
  141. package/rust/main.rs +311 -142
  142. package/rust/types/Cargo.toml +1 -1
  143. package/rust/types/src/addons.rs +3 -1
  144. package/rust/types/src/config.rs +1 -3
  145. package/rust/utils/Cargo.toml +5 -2
  146. package/rust/utils/src/file.rs +397 -14
  147. package/rust/utils/src/path.rs +31 -2
  148. package/rust/utils/src/version.rs +38 -7
  149. package/rust/web/auth.rs +5 -0
  150. package/rust/web/forge.rs +5 -0
  151. package/rust/web/mod.rs +5 -3
  152. package/typescript/scripts/version/copy-to-binary.ts +82 -0
  153. package/rust/cli/bank/api.rs +0 -122
  154. package/rust/cli/bank/commands.rs +0 -306
  155. package/rust/cli/bank/mod.rs +0 -29
  156. package/rust/cli/install/bank.rs +0 -72
  157. package/rust/cli/install/commands.rs +0 -35
  158. package/rust/cli/install/mod.rs +0 -4
  159. package/rust/cli/install/plugin.rs +0 -80
@@ -1,223 +1,247 @@
1
- use crate::core::lexer::token::TokenKind;
2
- use devalang_types::Value;
3
-
4
- pub fn parse_map_value(parser: &mut crate::core::parser::driver::parser::Parser) -> Option<Value> {
5
- let logger = devalang_utils::logger::Logger::new();
6
- use devalang_utils::logger::LogLevel;
7
- if !parser.match_token(TokenKind::LBrace) {
8
- return None;
9
- }
10
-
11
- let mut map = std::collections::HashMap::new();
12
-
13
- while !parser.check_token(TokenKind::RBrace) && !parser.is_eof() {
14
- // Skip separators and formatting before the key
15
- while parser.check_token(TokenKind::Newline)
16
- || parser.check_token(TokenKind::Whitespace)
17
- || parser.check_token(TokenKind::Indent)
18
- || parser.check_token(TokenKind::Dedent)
19
- || parser.check_token(TokenKind::Comma)
20
- {
21
- parser.advance();
22
- }
23
-
24
- // Check if we are at the closing brace of the map
25
- if parser.check_token(TokenKind::RBrace) {
26
- break;
27
- }
28
-
29
- let key = if let Some(token) = parser.advance() {
30
- match token.kind {
31
- TokenKind::Whitespace
32
- | TokenKind::Indent
33
- | TokenKind::Dedent
34
- | TokenKind::Newline => {
35
- continue;
36
- }
37
- _ => token.lexeme.clone(),
38
- }
39
- } else {
40
- break;
41
- };
42
-
43
- // Skip newlines and whitespace before colon
44
- while parser.check_token(TokenKind::Newline) || parser.check_token(TokenKind::Whitespace) {
45
- parser.advance();
46
- }
47
-
48
- if !parser.match_token(TokenKind::Colon) {
49
- logger.log_message(
50
- LogLevel::Error,
51
- &format!("Expected ':' after map key '{}'", key),
52
- );
53
- break;
54
- }
55
-
56
- // Skip separators and formatting before value
57
- while parser.check_token(TokenKind::Newline)
58
- || parser.check_token(TokenKind::Whitespace)
59
- || parser.check_token(TokenKind::Indent)
60
- || parser.check_token(TokenKind::Dedent)
61
- || parser.check_token(TokenKind::Comma)
62
- {
63
- parser.advance();
64
- }
65
-
66
- let value = if let Some(token) = parser.peek_clone() {
67
- match token.kind {
68
- TokenKind::String => {
69
- parser.advance();
70
- Value::String(token.lexeme.clone())
71
- }
72
- TokenKind::Number => {
73
- // Handle number, decimal number and optional fraction form (e.g., 1/4)
74
- let mut number_str = token.lexeme.clone();
75
- parser.advance(); // consume the first number
76
-
77
- // decimal support: number '.' number
78
- if let Some(dot_token) = parser.peek_clone() {
79
- if dot_token.kind == TokenKind::Dot {
80
- parser.advance(); // consume the dot
81
-
82
- if let Some(decimal_token) = parser.peek_clone() {
83
- if decimal_token.kind == TokenKind::Number {
84
- parser.advance(); // consume the number after the dot
85
- number_str.push('.');
86
- number_str.push_str(&decimal_token.lexeme);
87
- } else {
88
- logger.log_message(
89
- LogLevel::Error,
90
- &format!(
91
- "Expected number after dot, got {:?}",
92
- decimal_token
93
- ),
94
- );
95
- return Some(Value::Null);
96
- }
97
- } else {
98
- logger.log_message(
99
- LogLevel::Error,
100
- "Expected number after dot, but reached EOF",
101
- );
102
- return Some(Value::Null);
103
- }
104
- }
105
- }
106
-
107
- // Fraction support: number '/' number -> Duration::Beat("num/den")
108
- if let Some(slash_tok) = parser.peek_clone() {
109
- if slash_tok.kind == TokenKind::Slash {
110
- // consume '/'
111
- parser.advance();
112
- if let Some(den_tok) = parser.peek_clone() {
113
- match den_tok.kind {
114
- TokenKind::Number | TokenKind::Identifier => {
115
- let frac = format!("{}/{}", number_str, den_tok.lexeme);
116
- parser.advance();
117
- return Some(Value::Duration(
118
- devalang_types::Duration::Beat(frac),
119
- ));
120
- }
121
- _ => {
122
- logger.log_message(
123
- LogLevel::Error,
124
- &format!(
125
- "Expected number or identifier after '/', got {:?}",
126
- den_tok
127
- ),
128
- );
129
- return Some(Value::Null);
130
- }
131
- }
132
- } else {
133
- logger.log_message(
134
- LogLevel::Error,
135
- "Expected denominator after '/', but reached EOF",
136
- );
137
- return Some(Value::Null);
138
- }
139
- }
140
- }
141
-
142
- Value::Number(number_str.parse::<f32>().unwrap_or(0.0))
143
- }
144
-
145
- TokenKind::Identifier => {
146
- // Support dotted identifiers in map values: alias.param or nested
147
- let current_line = token.line;
148
- let mut parts: Vec<String> = vec![token.lexeme.clone()];
149
- parser.advance();
150
- loop {
151
- let Some(next) = parser.peek_clone() else {
152
- break;
153
- };
154
- if next.line != current_line {
155
- break;
156
- }
157
- if next.kind == TokenKind::Dot {
158
- // Consume '.' and the following identifier/number on same line
159
- parser.advance(); // dot
160
- if let Some(id2) = parser.peek_clone() {
161
- if id2.line == current_line
162
- && (id2.kind == TokenKind::Identifier
163
- || id2.kind == TokenKind::Number)
164
- {
165
- parts.push(id2.lexeme.clone());
166
- parser.advance(); // consume part
167
- continue;
168
- }
169
- }
170
- break;
171
- } else {
172
- break;
173
- }
174
- }
175
- Value::Identifier(parts.join("."))
176
- }
177
- TokenKind::LBracket => {
178
- // Allow arrays as map values
179
- if let Some(v) =
180
- crate::core::parser::driver::parse_array::parse_array_value(parser)
181
- {
182
- v
183
- } else {
184
- Value::Null
185
- }
186
- }
187
- TokenKind::LBrace => {
188
- // Allow inline nested maps as map values
189
- if let Some(v) = parse_map_value(parser) {
190
- v
191
- } else {
192
- Value::Null
193
- }
194
- }
195
- _ => {
196
- logger.log_message(
197
- LogLevel::Error,
198
- &format!("Unexpected token in map value: {:?}", token),
199
- );
200
- Value::Null
201
- }
202
- }
203
- } else {
204
- Value::Null
205
- };
206
-
207
- map.insert(key, value);
208
-
209
- // Optionally skip a trailing comma after the value
210
- while parser.check_token(TokenKind::Comma)
211
- || parser.check_token(TokenKind::Whitespace)
212
- || parser.check_token(TokenKind::Newline)
213
- {
214
- parser.advance();
215
- }
216
- }
217
-
218
- if !parser.match_token(TokenKind::RBrace) {
219
- logger.log_message(LogLevel::Error, "Expected '}' at end of map");
220
- }
221
-
222
- Some(Value::Map(map))
223
- }
1
+ use crate::core::lexer::token::TokenKind;
2
+ use devalang_types::Value;
3
+
4
+ pub fn parse_map_value(parser: &mut crate::core::parser::driver::parser::Parser) -> Option<Value> {
5
+ let logger = devalang_utils::logger::Logger::new();
6
+ use devalang_utils::logger::LogLevel;
7
+ if !parser.match_token(TokenKind::LBrace) {
8
+ return None;
9
+ }
10
+
11
+ let mut map = std::collections::HashMap::new();
12
+
13
+ while !parser.check_token(TokenKind::RBrace) && !parser.is_eof() {
14
+ // Skip separators and formatting before the key
15
+ while parser.check_token(TokenKind::Newline)
16
+ || parser.check_token(TokenKind::Whitespace)
17
+ || parser.check_token(TokenKind::Indent)
18
+ || parser.check_token(TokenKind::Dedent)
19
+ || parser.check_token(TokenKind::Comma)
20
+ {
21
+ parser.advance();
22
+ }
23
+
24
+ // Check if we are at the closing brace of the map
25
+ if parser.check_token(TokenKind::RBrace) {
26
+ break;
27
+ }
28
+
29
+ let key = if let Some(token) = parser.advance() {
30
+ match token.kind {
31
+ TokenKind::Whitespace
32
+ | TokenKind::Indent
33
+ | TokenKind::Dedent
34
+ | TokenKind::Newline => {
35
+ continue;
36
+ }
37
+ _ => token.lexeme.clone(),
38
+ }
39
+ } else {
40
+ break;
41
+ };
42
+
43
+ // Skip newlines and whitespace before colon
44
+ while parser.check_token(TokenKind::Newline) || parser.check_token(TokenKind::Whitespace) {
45
+ parser.advance();
46
+ }
47
+
48
+ // Accept both 'key: value' and short form 'key value' for convenience.
49
+ let mut saw_colon = false;
50
+ if parser.match_token(TokenKind::Colon) {
51
+ saw_colon = true;
52
+ } else {
53
+ // Peek to see if the next token looks like a value; if so, accept short form.
54
+ if let Some(peek) = parser.peek_clone() {
55
+ match peek.kind {
56
+ TokenKind::String
57
+ | TokenKind::Number
58
+ | TokenKind::Identifier
59
+ | TokenKind::LBracket
60
+ | TokenKind::LBrace => {
61
+ // short form accepted, do not consume here; value parsing will handle it
62
+ }
63
+ _ => {
64
+ logger.log_message(
65
+ LogLevel::Error,
66
+ &format!("Expected ':' after map key '{}'", key),
67
+ );
68
+ break;
69
+ }
70
+ }
71
+ } else {
72
+ logger.log_message(
73
+ LogLevel::Error,
74
+ &format!("Expected ':' after map key '{}'", key),
75
+ );
76
+ break;
77
+ }
78
+ }
79
+
80
+ // Skip separators and formatting before value
81
+ while parser.check_token(TokenKind::Newline)
82
+ || parser.check_token(TokenKind::Whitespace)
83
+ || parser.check_token(TokenKind::Indent)
84
+ || parser.check_token(TokenKind::Dedent)
85
+ || parser.check_token(TokenKind::Comma)
86
+ {
87
+ parser.advance();
88
+ }
89
+
90
+ let value = if let Some(token) = parser.peek_clone() {
91
+ match token.kind {
92
+ TokenKind::String => {
93
+ parser.advance();
94
+ Value::String(token.lexeme.clone())
95
+ }
96
+ TokenKind::Number => {
97
+ // Handle number, decimal number and optional fraction form (e.g., 1/4)
98
+ let mut number_str = token.lexeme.clone();
99
+ parser.advance(); // consume the first number
100
+
101
+ // decimal support: number '.' number
102
+ if let Some(dot_token) = parser.peek_clone() {
103
+ if dot_token.kind == TokenKind::Dot {
104
+ parser.advance(); // consume the dot
105
+
106
+ if let Some(decimal_token) = parser.peek_clone() {
107
+ if decimal_token.kind == TokenKind::Number {
108
+ parser.advance(); // consume the number after the dot
109
+ number_str.push('.');
110
+ number_str.push_str(&decimal_token.lexeme);
111
+ } else {
112
+ logger.log_message(
113
+ LogLevel::Error,
114
+ &format!(
115
+ "Expected number after dot, got {:?}",
116
+ decimal_token
117
+ ),
118
+ );
119
+ return Some(Value::Null);
120
+ }
121
+ } else {
122
+ logger.log_message(
123
+ LogLevel::Error,
124
+ "Expected number after dot, but reached EOF",
125
+ );
126
+ return Some(Value::Null);
127
+ }
128
+ }
129
+ }
130
+
131
+ // Fraction support: number '/' number -> Duration::Beat("num/den")
132
+ if let Some(slash_tok) = parser.peek_clone() {
133
+ if slash_tok.kind == TokenKind::Slash {
134
+ // consume '/'
135
+ parser.advance();
136
+ if let Some(den_tok) = parser.peek_clone() {
137
+ match den_tok.kind {
138
+ TokenKind::Number | TokenKind::Identifier => {
139
+ let frac = format!("{}/{}", number_str, den_tok.lexeme);
140
+ parser.advance();
141
+ return Some(Value::Duration(
142
+ devalang_types::Duration::Beat(frac),
143
+ ));
144
+ }
145
+ _ => {
146
+ logger.log_message(
147
+ LogLevel::Error,
148
+ &format!(
149
+ "Expected number or identifier after '/', got {:?}",
150
+ den_tok
151
+ ),
152
+ );
153
+ return Some(Value::Null);
154
+ }
155
+ }
156
+ } else {
157
+ logger.log_message(
158
+ LogLevel::Error,
159
+ "Expected denominator after '/', but reached EOF",
160
+ );
161
+ return Some(Value::Null);
162
+ }
163
+ }
164
+ }
165
+
166
+ Value::Number(number_str.parse::<f32>().unwrap_or(0.0))
167
+ }
168
+
169
+ TokenKind::Identifier => {
170
+ // Support dotted identifiers in map values: alias.param or nested
171
+ let current_line = token.line;
172
+ let mut parts: Vec<String> = vec![token.lexeme.clone()];
173
+ parser.advance();
174
+ loop {
175
+ let Some(next) = parser.peek_clone() else {
176
+ break;
177
+ };
178
+ if next.line != current_line {
179
+ break;
180
+ }
181
+ if next.kind == TokenKind::Dot {
182
+ // Consume '.' and the following identifier/number on same line
183
+ parser.advance(); // dot
184
+ if let Some(id2) = parser.peek_clone() {
185
+ if id2.line == current_line
186
+ && (id2.kind == TokenKind::Identifier
187
+ || id2.kind == TokenKind::Number)
188
+ {
189
+ parts.push(id2.lexeme.clone());
190
+ parser.advance(); // consume part
191
+ continue;
192
+ }
193
+ }
194
+ break;
195
+ } else {
196
+ break;
197
+ }
198
+ }
199
+ Value::Identifier(parts.join("."))
200
+ }
201
+ TokenKind::LBracket => {
202
+ // Allow arrays as map values
203
+ if let Some(v) =
204
+ crate::core::parser::driver::parse_array::parse_array_value(parser)
205
+ {
206
+ v
207
+ } else {
208
+ Value::Null
209
+ }
210
+ }
211
+ TokenKind::LBrace => {
212
+ // Allow inline nested maps as map values
213
+ if let Some(v) = parse_map_value(parser) {
214
+ v
215
+ } else {
216
+ Value::Null
217
+ }
218
+ }
219
+ _ => {
220
+ logger.log_message(
221
+ LogLevel::Error,
222
+ &format!("Unexpected token in map value: {:?}", token),
223
+ );
224
+ Value::Null
225
+ }
226
+ }
227
+ } else {
228
+ Value::Null
229
+ };
230
+
231
+ map.insert(key, value);
232
+
233
+ // Optionally skip a trailing comma after the value
234
+ while parser.check_token(TokenKind::Comma)
235
+ || parser.check_token(TokenKind::Whitespace)
236
+ || parser.check_token(TokenKind::Newline)
237
+ {
238
+ parser.advance();
239
+ }
240
+ }
241
+
242
+ if !parser.match_token(TokenKind::RBrace) {
243
+ logger.log_message(LogLevel::Error, "Expected '}' at end of map");
244
+ }
245
+
246
+ Some(Value::Map(map))
247
+ }