@devaloop/devalang 0.0.1-alpha.1 → 0.0.1-alpha.10

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 (155) hide show
  1. package/.devalang +4 -0
  2. package/Cargo.toml +49 -45
  3. package/README.md +127 -46
  4. package/docs/CHANGELOG.md +172 -0
  5. package/docs/COMMANDS.md +60 -6
  6. package/docs/CONFIG.md +30 -0
  7. package/docs/ROADMAP.md +10 -7
  8. package/docs/SYNTAX.md +100 -18
  9. package/docs/TODO.md +31 -28
  10. package/examples/condition.deva +20 -0
  11. package/examples/group.deva +12 -0
  12. package/examples/index.deva +13 -4
  13. package/examples/loop.deva +16 -0
  14. package/examples/samples/hat-808.wav +0 -0
  15. package/examples/synth.deva +14 -0
  16. package/examples/variables.deva +9 -0
  17. package/out-tsc/bin/devalang.exe +0 -0
  18. package/out-tsc/scripts/version/fetch.js +1 -5
  19. package/package.json +5 -4
  20. package/project-version.json +3 -3
  21. package/rust/cli/build.rs +114 -28
  22. package/rust/cli/check.rs +96 -103
  23. package/rust/cli/init.rs +79 -0
  24. package/rust/cli/mod.rs +203 -1
  25. package/rust/cli/play.rs +193 -0
  26. package/rust/cli/template.rs +57 -0
  27. package/rust/config/loader.rs +13 -0
  28. package/rust/config/mod.rs +16 -0
  29. package/rust/core/audio/engine.rs +214 -0
  30. package/rust/core/audio/evaluator.rs +31 -0
  31. package/rust/core/audio/interpreter/arrow_call.rs +129 -0
  32. package/rust/core/audio/interpreter/call.rs +70 -0
  33. package/rust/core/audio/interpreter/condition.rs +69 -0
  34. package/rust/core/audio/interpreter/driver.rs +236 -0
  35. package/rust/core/audio/interpreter/let_.rs +19 -0
  36. package/rust/core/audio/interpreter/load.rs +18 -0
  37. package/rust/core/audio/interpreter/loop_.rs +67 -0
  38. package/rust/core/audio/interpreter/mod.rs +12 -0
  39. package/rust/core/audio/interpreter/sleep.rs +36 -0
  40. package/rust/core/audio/interpreter/spawn.rs +84 -0
  41. package/rust/core/audio/interpreter/tempo.rs +16 -0
  42. package/rust/core/audio/interpreter/trigger.rs +69 -0
  43. package/rust/core/audio/loader/mod.rs +1 -0
  44. package/rust/core/audio/loader/trigger.rs +52 -0
  45. package/rust/core/audio/mod.rs +6 -0
  46. package/rust/core/audio/player.rs +54 -0
  47. package/rust/core/audio/renderer.rs +54 -0
  48. package/rust/core/builder/mod.rs +70 -27
  49. package/rust/core/debugger/lexer.rs +27 -0
  50. package/rust/core/debugger/mod.rs +13 -49
  51. package/rust/core/debugger/preprocessor.rs +27 -0
  52. package/rust/core/debugger/store.rs +25 -0
  53. package/rust/core/error/mod.rs +60 -0
  54. package/rust/core/lexer/handler/arrow.rs +31 -0
  55. package/rust/core/lexer/handler/at.rs +21 -0
  56. package/rust/core/lexer/handler/brace.rs +41 -0
  57. package/rust/core/lexer/handler/colon.rs +21 -0
  58. package/rust/core/lexer/handler/comment.rs +30 -0
  59. package/rust/core/lexer/handler/dot.rs +21 -0
  60. package/rust/core/lexer/handler/driver.rs +230 -0
  61. package/rust/core/lexer/handler/identifier.rs +41 -0
  62. package/rust/core/lexer/handler/indent.rs +52 -0
  63. package/rust/core/lexer/handler/mod.rs +14 -0
  64. package/rust/core/lexer/handler/newline.rs +23 -0
  65. package/rust/core/lexer/handler/number.rs +31 -0
  66. package/rust/core/lexer/handler/operator.rs +44 -0
  67. package/rust/core/lexer/handler/string.rs +63 -0
  68. package/rust/core/lexer/mod.rs +37 -319
  69. package/rust/core/lexer/token.rs +86 -0
  70. package/rust/core/mod.rs +6 -2
  71. package/rust/core/parser/driver.rs +331 -0
  72. package/rust/core/parser/handler/arrow_call.rs +126 -0
  73. package/rust/core/parser/handler/at.rs +162 -0
  74. package/rust/core/parser/handler/bank.rs +41 -0
  75. package/rust/core/parser/handler/condition.rs +74 -0
  76. package/rust/core/parser/handler/dot.rs +112 -0
  77. package/rust/core/parser/handler/identifier/call.rs +41 -0
  78. package/rust/core/parser/handler/identifier/group.rs +75 -0
  79. package/rust/core/parser/handler/identifier/let_.rs +133 -0
  80. package/rust/core/parser/handler/identifier/mod.rs +51 -0
  81. package/rust/core/parser/handler/identifier/sleep.rs +33 -0
  82. package/rust/core/parser/handler/identifier/spawn.rs +41 -0
  83. package/rust/core/parser/handler/identifier/synth.rs +65 -0
  84. package/rust/core/parser/handler/loop_.rs +72 -0
  85. package/rust/core/parser/handler/mod.rs +8 -0
  86. package/rust/core/parser/handler/tempo.rs +47 -0
  87. package/rust/core/parser/mod.rs +3 -200
  88. package/rust/core/parser/statement.rs +96 -0
  89. package/rust/core/preprocessor/loader.rs +229 -0
  90. package/rust/core/preprocessor/mod.rs +2 -24
  91. package/rust/core/preprocessor/module.rs +42 -56
  92. package/rust/core/preprocessor/processor.rs +76 -0
  93. package/rust/core/preprocessor/resolver/bank.rs +41 -51
  94. package/rust/core/preprocessor/resolver/call.rs +123 -0
  95. package/rust/core/preprocessor/resolver/condition.rs +92 -0
  96. package/rust/core/preprocessor/resolver/driver.rs +227 -0
  97. package/rust/core/preprocessor/resolver/group.rs +61 -0
  98. package/rust/core/preprocessor/resolver/let_.rs +31 -0
  99. package/rust/core/preprocessor/resolver/loop_.rs +76 -67
  100. package/rust/core/preprocessor/resolver/mod.rs +12 -111
  101. package/rust/core/preprocessor/resolver/spawn.rs +58 -0
  102. package/rust/core/preprocessor/resolver/synth.rs +50 -0
  103. package/rust/core/preprocessor/resolver/tempo.rs +40 -61
  104. package/rust/core/preprocessor/resolver/trigger.rs +90 -154
  105. package/rust/core/preprocessor/resolver/value.rs +78 -0
  106. package/rust/core/shared/duration.rs +8 -0
  107. package/rust/core/shared/mod.rs +2 -0
  108. package/rust/core/shared/value.rs +28 -0
  109. package/rust/core/store/export.rs +28 -0
  110. package/rust/core/store/global.rs +39 -0
  111. package/rust/core/store/import.rs +28 -0
  112. package/rust/core/store/mod.rs +4 -0
  113. package/rust/core/store/variable.rs +28 -0
  114. package/rust/core/utils/mod.rs +2 -0
  115. package/rust/core/utils/path.rs +31 -0
  116. package/rust/core/utils/validation.rs +37 -0
  117. package/rust/lib.rs +161 -1
  118. package/rust/main.rs +46 -30
  119. package/rust/utils/file.rs +35 -0
  120. package/rust/utils/logger.rs +108 -34
  121. package/rust/utils/mod.rs +3 -2
  122. package/rust/utils/{loader.rs → spinner.rs} +2 -0
  123. package/rust/utils/watcher.rs +33 -0
  124. package/templates/minimal/.devalang +5 -0
  125. package/templates/minimal/README.md +202 -0
  126. package/templates/minimal/src/index.deva +2 -0
  127. package/templates/welcome/.devalang +5 -0
  128. package/templates/welcome/README.md +202 -0
  129. package/templates/welcome/samples/kick-808.wav +0 -0
  130. package/templates/welcome/src/index.deva +13 -0
  131. package/templates/welcome/src/variables.deva +5 -0
  132. package/typescript/scripts/version/fetch.ts +1 -6
  133. package/examples/exported.deva +0 -7
  134. package/rust/audio/mod.rs +0 -1
  135. package/rust/cli/new.rs +0 -1
  136. package/rust/core/parser/at.rs +0 -142
  137. package/rust/core/parser/bank.rs +0 -42
  138. package/rust/core/parser/dot.rs +0 -107
  139. package/rust/core/parser/identifer.rs +0 -91
  140. package/rust/core/parser/loop_.rs +0 -62
  141. package/rust/core/parser/tempo.rs +0 -42
  142. package/rust/core/parser/variable.rs +0 -129
  143. package/rust/core/preprocessor/dependencies.rs +0 -54
  144. package/rust/core/preprocessor/resolver/at.rs +0 -24
  145. package/rust/core/types/cli.rs +0 -160
  146. package/rust/core/types/mod.rs +0 -7
  147. package/rust/core/types/module.rs +0 -41
  148. package/rust/core/types/parser.rs +0 -73
  149. package/rust/core/types/statement.rs +0 -105
  150. package/rust/core/types/store.rs +0 -116
  151. package/rust/core/types/token.rs +0 -83
  152. package/rust/core/types/variable.rs +0 -32
  153. package/rust/runner/executer.rs +0 -44
  154. package/rust/runner/mod.rs +0 -1
  155. package/rust/utils/path.rs +0 -46
@@ -0,0 +1,74 @@
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
+ }
@@ -0,0 +1,112 @@
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
+ }
@@ -0,0 +1,41 @@
1
+ use crate::core::{
2
+ lexer::token::{ Token, TokenKind },
3
+ parser::{ statement::{ Statement, StatementKind }, driver::Parser },
4
+ shared::value::Value,
5
+ store::global::GlobalStore,
6
+ };
7
+
8
+ pub fn parse_call_token(
9
+ parser: &mut Parser,
10
+ current_token: Token,
11
+ global_store: &mut GlobalStore
12
+ ) -> Statement {
13
+ parser.advance(); // consume "call"
14
+
15
+ let value = if let Some(token) = parser.peek_clone() {
16
+ parser.advance();
17
+ match token.kind {
18
+ TokenKind::Identifier => Value::Identifier(token.lexeme.clone()),
19
+ TokenKind::String => Value::String(token.lexeme.clone()),
20
+ _ => {
21
+ return Statement::error(
22
+ token,
23
+ "Expected identifier or string after 'call'".to_string()
24
+ );
25
+ }
26
+ }
27
+ } else {
28
+ return Statement::error(
29
+ current_token,
30
+ "Expected identifier or string after 'call'".to_string()
31
+ );
32
+ };
33
+
34
+ return Statement {
35
+ kind: StatementKind::Call,
36
+ value,
37
+ indent: current_token.indent,
38
+ line: current_token.line,
39
+ column: current_token.column,
40
+ };
41
+ }
@@ -0,0 +1,75 @@
1
+ use crate::core::{
2
+ lexer::token::{ Token, TokenKind },
3
+ parser::{ statement::{ Statement, StatementKind }, driver::Parser },
4
+ shared::value::Value,
5
+ store::global::GlobalStore,
6
+ };
7
+ use std::collections::HashMap;
8
+
9
+ pub fn parse_group_token(
10
+ parser: &mut Parser,
11
+ current_token: Token,
12
+ global_store: &mut GlobalStore
13
+ ) -> Statement {
14
+ parser.advance(); // consume "group"
15
+
16
+ let Some(identifier_token) = parser.peek_clone() else {
17
+ return Statement::error(current_token, "Expected identifier after 'group'".to_string());
18
+ };
19
+
20
+ if identifier_token.kind != TokenKind::Identifier && identifier_token.kind != TokenKind::String {
21
+ return Statement::error(identifier_token, "Expected valid identifier".to_string());
22
+ }
23
+
24
+ parser.advance(); // consume identifier
25
+
26
+ let Some(colon_token) = parser.peek_clone() else {
27
+ return Statement::error(
28
+ identifier_token,
29
+ "Expected ':' after group identifier".to_string()
30
+ );
31
+ };
32
+
33
+ if colon_token.kind != TokenKind::Colon {
34
+ return Statement::error(
35
+ colon_token.clone(),
36
+ "Expected ':' after group identifier".to_string()
37
+ );
38
+ }
39
+
40
+ parser.advance(); // consume ':'
41
+
42
+ let base_indent = current_token.indent;
43
+
44
+ // Clone without consuming tokens
45
+ let mut index = parser.token_index;
46
+ let mut tokens_inside_group = Vec::new();
47
+
48
+ while index < parser.tokens.len() {
49
+ let token = parser.tokens[index].clone();
50
+
51
+ if token.indent <= base_indent && token.kind != TokenKind::Newline {
52
+ break;
53
+ }
54
+
55
+ tokens_inside_group.push(token);
56
+ index += 1;
57
+ }
58
+
59
+ // Advance index once to skip the processed tokens
60
+ parser.token_index = index;
61
+
62
+ let body = parser.parse_block(tokens_inside_group, global_store);
63
+
64
+ let mut value_map = HashMap::new();
65
+ value_map.insert("identifier".to_string(), Value::String(identifier_token.lexeme.clone()));
66
+ value_map.insert("body".to_string(), Value::Block(body));
67
+
68
+ return Statement {
69
+ kind: StatementKind::Group,
70
+ value: Value::Map(value_map),
71
+ indent: current_token.indent,
72
+ line: current_token.line,
73
+ column: current_token.column,
74
+ };
75
+ }
@@ -0,0 +1,133 @@
1
+ use std::collections::HashMap;
2
+
3
+ use crate::core::{
4
+ lexer::token::{ Token, TokenKind },
5
+ parser::{
6
+ driver::Parser,
7
+ handler::identifier::synth::parse_synth_token,
8
+ statement::{ Statement, StatementKind },
9
+ },
10
+ shared::value::Value,
11
+ store::global::GlobalStore,
12
+ };
13
+
14
+ pub fn parse_let_token(
15
+ parser: &mut Parser,
16
+ current_token: Token,
17
+ global_store: &mut GlobalStore
18
+ ) -> Statement {
19
+ parser.advance(); // consume "let"
20
+
21
+ let identifier = if let Some(token) = parser.peek_clone() {
22
+ if token.kind == TokenKind::Identifier {
23
+ parser.advance();
24
+ token.lexeme.clone()
25
+ } else {
26
+ return Statement::error(token, "Expected identifier after 'let'".to_string());
27
+ }
28
+ } else {
29
+ return Statement::error(current_token, "Expected identifier after 'let'".to_string());
30
+ };
31
+
32
+ if !parser.match_token(TokenKind::Equals) {
33
+ return Statement::error(current_token, "Expected '=' after identifier".to_string());
34
+ }
35
+
36
+ if let Some(token) = parser.peek_clone() {
37
+ if token.kind == TokenKind::Synth {
38
+ let synth_stmt = parse_synth_token(parser, token.clone(), global_store);
39
+
40
+ return Statement {
41
+ kind: StatementKind::Let { name: identifier },
42
+ value: synth_stmt.value,
43
+ indent: current_token.indent,
44
+ line: current_token.line,
45
+ column: current_token.column,
46
+ };
47
+ }
48
+ }
49
+
50
+ let value = match parser.peek_clone() {
51
+ Some(token) if token.kind == TokenKind::Identifier => {
52
+ parser.advance();
53
+ Value::Identifier(token.lexeme.clone())
54
+ }
55
+ Some(token) if token.kind == TokenKind::String => {
56
+ parser.advance();
57
+ Value::String(token.lexeme.clone())
58
+ }
59
+ Some(token) if token.kind == TokenKind::Number => {
60
+ parser.advance();
61
+ Value::Number(token.lexeme.parse().unwrap_or(0.0))
62
+ }
63
+ Some(token) if token.kind == TokenKind::Boolean => {
64
+ parser.advance();
65
+ Value::Boolean(token.lexeme.parse().unwrap_or(false))
66
+ }
67
+ Some(token) if token.kind == TokenKind::LBrace => {
68
+ parser.advance(); // consume '{'
69
+ let mut map = HashMap::new();
70
+
71
+ while let Some(key_token) = parser.peek_clone() {
72
+ if key_token.kind == TokenKind::RBrace {
73
+ parser.advance(); // consume '}'
74
+ break;
75
+ }
76
+
77
+ if key_token.kind != TokenKind::Identifier {
78
+ return Statement::error(token, "Expected key identifier in map".to_string());
79
+ }
80
+ parser.advance();
81
+ let key = key_token.lexeme.clone();
82
+
83
+ if !parser.match_token(TokenKind::Colon) {
84
+ let message = format!("Expected ':' after key '{}'", key);
85
+ return Statement::error(token, message);
86
+ }
87
+
88
+ let val = match parser.peek_clone() {
89
+ Some(t) if t.kind == TokenKind::Number => {
90
+ parser.advance();
91
+ Value::Number(t.lexeme.parse().unwrap_or(0.0))
92
+ }
93
+ Some(t) if t.kind == TokenKind::String => {
94
+ parser.advance();
95
+ Value::String(t.lexeme.clone())
96
+ }
97
+ Some(t) if t.kind == TokenKind::Identifier => {
98
+ parser.advance();
99
+ Value::Identifier(t.lexeme.clone())
100
+ }
101
+ _ => Value::Null,
102
+ };
103
+
104
+ if val == Value::Null {
105
+ let message = format!("Invalid value for key '{}'", key);
106
+ return Statement::error(token, message);
107
+ }
108
+
109
+ map.insert(key, val);
110
+
111
+ if let Some(t) = parser.peek() {
112
+ if t.kind == TokenKind::Comma {
113
+ parser.advance(); // skip comma
114
+ }
115
+ }
116
+ }
117
+
118
+ Value::Map(map)
119
+ }
120
+ other => {
121
+ let message = format!("Unexpected value token in let: {:?}", other);
122
+ return Statement::error(current_token, message);
123
+ }
124
+ };
125
+
126
+ Statement {
127
+ kind: StatementKind::Let { name: identifier },
128
+ value,
129
+ indent: current_token.indent,
130
+ line: current_token.line,
131
+ column: current_token.column,
132
+ }
133
+ }
@@ -0,0 +1,51 @@
1
+ pub mod let_;
2
+ pub mod group;
3
+ pub mod call;
4
+ pub mod spawn;
5
+ pub mod sleep;
6
+ pub mod synth;
7
+
8
+ use crate::core::{
9
+ parser::{
10
+ driver::Parser,
11
+ handler::{
12
+ identifier::{
13
+ call::parse_call_token,
14
+ group::parse_group_token,
15
+ let_::parse_let_token,
16
+ sleep::parse_sleep_token,
17
+ spawn::parse_spawn_token,
18
+ synth::parse_synth_token
19
+ },
20
+ },
21
+ statement::Statement,
22
+ },
23
+ store::global::GlobalStore,
24
+ };
25
+
26
+ pub fn parse_identifier_token(parser: &mut Parser, global_store: &mut GlobalStore) -> Statement {
27
+ let Some(current_token) = parser.peek_clone() else {
28
+ return Statement::unknown();
29
+ };
30
+
31
+ let current_token_clone = current_token.clone();
32
+ let current_token_lexeme = current_token_clone.lexeme.clone();
33
+
34
+ let statement = match current_token_lexeme.as_str() {
35
+ "let" => parse_let_token(parser, current_token_clone, global_store),
36
+ "group" => parse_group_token(parser, current_token_clone, global_store),
37
+ "call" => parse_call_token(parser, current_token_clone, global_store),
38
+ "spawn" => parse_spawn_token(parser, current_token_clone, global_store),
39
+ "sleep" => parse_sleep_token(parser, current_token_clone, global_store),
40
+ "synth" => parse_synth_token(parser, current_token_clone, global_store),
41
+ _ => {
42
+ parser.advance(); // consume identifier
43
+
44
+ println!("Unrecognized identifier: {}", current_token_lexeme);
45
+
46
+ return Statement::error(current_token_clone, "Unexpected identifier".to_string());
47
+ }
48
+ };
49
+
50
+ return statement;
51
+ }
@@ -0,0 +1,33 @@
1
+ use crate::core::{
2
+ lexer::token::{ Token, TokenKind },
3
+ parser::{ statement::{ Statement, StatementKind }, driver::Parser },
4
+ shared::value::Value,
5
+ store::global::GlobalStore,
6
+ };
7
+
8
+ pub fn parse_sleep_token(
9
+ parser: &mut Parser,
10
+ current_token: Token,
11
+ global_store: &mut GlobalStore
12
+ ) -> Statement {
13
+ parser.advance(); // consume "sleep"
14
+
15
+ let duration = if let Some(token) = parser.peek_clone() {
16
+ if token.kind == TokenKind::Number {
17
+ parser.advance();
18
+ token.lexeme.parse().unwrap_or(0.0)
19
+ } else {
20
+ return Statement::error(token, "Expected number after 'sleep'".to_string());
21
+ }
22
+ } else {
23
+ return Statement::error(current_token, "Expected number after 'sleep'".to_string());
24
+ };
25
+
26
+ return Statement {
27
+ kind: StatementKind::Sleep,
28
+ value: Value::Number(duration),
29
+ indent: current_token.indent,
30
+ line: current_token.line,
31
+ column: current_token.column,
32
+ };
33
+ }
@@ -0,0 +1,41 @@
1
+ use crate::core::{
2
+ lexer::token::{ Token, TokenKind },
3
+ parser::{ statement::{ Statement, StatementKind }, driver::Parser },
4
+ shared::value::Value,
5
+ store::global::GlobalStore,
6
+ };
7
+
8
+ pub fn parse_spawn_token(
9
+ parser: &mut Parser,
10
+ current_token: Token,
11
+ global_store: &mut GlobalStore
12
+ ) -> Statement {
13
+ parser.advance(); // consume "spawn"
14
+
15
+ let value = if let Some(token) = parser.peek_clone() {
16
+ parser.advance();
17
+ match token.kind {
18
+ TokenKind::Identifier => Value::Identifier(token.lexeme.clone()),
19
+ TokenKind::String => Value::String(token.lexeme.clone()),
20
+ _ => {
21
+ return Statement::error(
22
+ token,
23
+ "Expected identifier or string after 'spawn'".to_string()
24
+ );
25
+ }
26
+ }
27
+ } else {
28
+ return Statement::error(
29
+ current_token,
30
+ "Expected identifier or string after 'spawn'".to_string()
31
+ );
32
+ };
33
+
34
+ return Statement {
35
+ kind: StatementKind::Spawn,
36
+ value,
37
+ indent: current_token.indent,
38
+ line: current_token.line,
39
+ column: current_token.column,
40
+ };
41
+ }
@@ -0,0 +1,65 @@
1
+ use std::collections::HashMap;
2
+
3
+ use crate::core::{
4
+ lexer::token::{ Token, TokenKind },
5
+ parser::{ driver::Parser, statement::{ Statement, StatementKind } },
6
+ shared::value::Value,
7
+ store::global::GlobalStore,
8
+ };
9
+
10
+ pub fn parse_synth_token(
11
+ parser: &mut Parser,
12
+ current_token: Token,
13
+ global_store: &mut GlobalStore
14
+ ) -> Statement {
15
+ parser.advance(); // consume 'synth'
16
+
17
+ let Some(synth_token) = parser.previous_clone() else {
18
+ return Statement::unknown();
19
+ };
20
+
21
+ // Expect an identifier (synth waveform)
22
+ let Some(identifier_token) = parser.peek_clone() else {
23
+ return Statement::error(synth_token, "Expected identifier after 'synth'".to_string());
24
+ };
25
+
26
+ let synth_waveform = identifier_token.lexeme.clone();
27
+
28
+ parser.advance(); // consume identifier
29
+
30
+ // Expect synth optional parameters map
31
+ let mut parameters = HashMap::new();
32
+
33
+ if let Some(params) = parser.parse_map_value() {
34
+ // If parameters are provided, we expect a map
35
+ if let Value::Map(map) = params {
36
+ parameters = map;
37
+ } else {
38
+ return Statement::error(synth_token, "Expected a map for synth parameters".to_string());
39
+ }
40
+ } else {
41
+ // If no parameters are provided, we can still create the statement with an empty map
42
+ parameters = HashMap::new();
43
+ }
44
+
45
+ Statement {
46
+ kind: StatementKind::Synth,
47
+ value: Value::Map(
48
+ HashMap::from([
49
+ ("entity".to_string(), Value::String("synth".to_string())),
50
+ (
51
+ "value".to_string(),
52
+ Value::Map(
53
+ HashMap::from([
54
+ ("waveform".to_string(), Value::String(synth_waveform)),
55
+ ("parameters".to_string(), Value::Map(parameters)),
56
+ ])
57
+ ),
58
+ ),
59
+ ])
60
+ ),
61
+ indent: synth_token.indent,
62
+ line: synth_token.line,
63
+ column: synth_token.column,
64
+ }
65
+ }