@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,72 @@
1
+ use std::collections::HashMap;
2
+
3
+ use crate::core::{
4
+ lexer::{ token::TokenKind },
5
+ parser::{ statement::{ Statement, StatementKind }, driver::Parser },
6
+ shared::value::Value,
7
+ store::global::GlobalStore,
8
+ };
9
+
10
+ pub fn parse_loop_token(parser: &mut Parser, global_store: &mut GlobalStore) -> Statement {
11
+ parser.advance(); // consume 'loop'
12
+ let Some(loop_token) = parser.previous_clone() else {
13
+ return Statement::unknown();
14
+ };
15
+
16
+ let Some(iterator_token) = parser.peek_clone() else {
17
+ return Statement::error(loop_token, "Expected number or identifier after 'loop'".to_string());
18
+ };
19
+
20
+ let iterator_value = match iterator_token.kind {
21
+ TokenKind::Number => {
22
+ let val = iterator_token.lexeme.parse::<f32>().unwrap_or(1.0);
23
+ parser.advance();
24
+ Value::Number(val)
25
+ }
26
+ TokenKind::Identifier => {
27
+ let val = iterator_token.lexeme.clone();
28
+ parser.advance();
29
+ Value::Identifier(val)
30
+ }
31
+ _ => {
32
+ return Statement::error(
33
+ iterator_token.clone(),
34
+ "Expected a number or identifier as loop count".to_string()
35
+ );
36
+ }
37
+ };
38
+
39
+ // Expect colon
40
+ let Some(colon_token) = parser.peek_clone() else {
41
+ return Statement::error(iterator_token.clone(), "Expected ':' after loop count".to_string());
42
+ };
43
+
44
+ if colon_token.kind != TokenKind::Colon {
45
+ let message = format!("Expected ':' after loop count, got {:?}", colon_token.kind);
46
+ return Statement::error(colon_token.clone(), message);
47
+ }
48
+
49
+ parser.advance(); // consume ':'
50
+
51
+ // Collect body
52
+ let tokens = parser.collect_until(|t| t.kind == TokenKind::Dedent || t.kind == TokenKind::EOF);
53
+ let loop_body = parser.parse_block(tokens.clone(), global_store);
54
+
55
+ if let Some(token) = parser.peek() {
56
+ if token.kind == TokenKind::Dedent {
57
+ parser.advance();
58
+ }
59
+ }
60
+
61
+ let mut value_map = HashMap::new();
62
+ value_map.insert("iterator".to_string(), iterator_value);
63
+ value_map.insert("body".to_string(), Value::Block(loop_body.clone()));
64
+
65
+ Statement {
66
+ kind: StatementKind::Loop,
67
+ value: Value::Map(value_map),
68
+ indent: loop_token.indent,
69
+ line: loop_token.line,
70
+ column: loop_token.column,
71
+ }
72
+ }
@@ -0,0 +1,8 @@
1
+ pub mod at;
2
+ pub mod identifier;
3
+ pub mod dot;
4
+ pub mod tempo;
5
+ pub mod bank;
6
+ pub mod loop_;
7
+ pub mod condition;
8
+ pub mod arrow_call;
@@ -0,0 +1,47 @@
1
+ use crate::core::{
2
+ lexer::token::TokenKind,
3
+ parser::{ statement::{ Statement, StatementKind }, driver::Parser },
4
+ shared::value::Value,
5
+ store::global::GlobalStore,
6
+ };
7
+
8
+ pub fn parse_tempo_token(parser: &mut Parser, _global_store: &mut GlobalStore) -> Statement {
9
+ parser.advance(); // consume 'bpm'
10
+
11
+ let Some(tempo_token) = parser.previous_clone() else {
12
+ return Statement::unknown();
13
+ };
14
+
15
+ // Expect a number or identifier
16
+ let Some(value_token) = parser.peek_clone() else {
17
+ return Statement::error(
18
+ tempo_token,
19
+ "Expected a number or identifier after 'bpm'".to_string()
20
+ );
21
+ };
22
+
23
+ let value = match value_token.kind {
24
+ TokenKind::Number => {
25
+ parser.advance();
26
+ Value::Number(value_token.lexeme.parse().unwrap_or(0.0))
27
+ }
28
+ TokenKind::Identifier => {
29
+ parser.advance();
30
+ Value::Identifier(value_token.lexeme.clone())
31
+ }
32
+ _ => {
33
+ return Statement::error(
34
+ value_token.clone(),
35
+ format!("Expected a number or identifier after 'bpm', got {:?}", value_token.kind)
36
+ );
37
+ }
38
+ };
39
+
40
+ Statement {
41
+ kind: StatementKind::Tempo,
42
+ value,
43
+ indent: tempo_token.indent,
44
+ line: tempo_token.line,
45
+ column: tempo_token.column,
46
+ }
47
+ }
@@ -1,201 +1,4 @@
1
- pub mod identifer;
2
- pub mod variable;
3
- pub mod at;
4
- pub mod dot;
5
- pub mod bank;
6
- pub mod loop_;
7
- pub mod tempo;
1
+ pub mod driver;
8
2
 
9
- use crate::{
10
- core::{
11
- parser::{
12
- at::parse_at,
13
- bank::parse_bank,
14
- dot::parse_dot,
15
- identifer::parse_identifier,
16
- loop_::parse_loop,
17
- tempo::parse_tempo,
18
- },
19
- preprocessor::resolver::resolve_statement,
20
- types::{
21
- module::Module,
22
- parser::Parser,
23
- statement::{ Statement, StatementKind, StatementResolved },
24
- store::{ GlobalStore },
25
- token::{ Token, TokenKind },
26
- variable::VariableValue,
27
- },
28
- },
29
- utils::logger::log_message,
30
- };
31
-
32
- pub fn parse_without_resolving(
33
- tokens: Vec<Token>,
34
- mut parser: &mut Parser,
35
- global_store: &mut GlobalStore
36
- ) -> Vec<Statement> {
37
- let mut statements = Vec::new();
38
-
39
- while !parser.is_eof() {
40
- let mut error_statement = Statement {
41
- kind: StatementKind::Error,
42
- value: VariableValue::Null,
43
- line: parser.peek().map_or(0, |t| t.line),
44
- column: parser.peek().map_or(0, |t| t.column),
45
- indent: parser.peek().map_or(0, |t| t.indent),
46
- };
47
-
48
- match parser.peek().map(|t| t.kind.clone()) {
49
- Some(TokenKind::Identifier) => {
50
- match parse_identifier(&mut parser, global_store) {
51
- Ok(statement) => statements.push(statement),
52
- Err(e) => {
53
- error_statement.value = VariableValue::Text(e.to_string());
54
- statements.push(error_statement);
55
- }
56
- }
57
- }
58
-
59
- Some(TokenKind::Bank) => {
60
- match parse_bank(&mut parser, global_store) {
61
- Ok(statement) => statements.push(statement),
62
- Err(e) => {
63
- error_statement.value = VariableValue::Text(e.to_string());
64
- statements.push(error_statement);
65
- }
66
- }
67
- }
68
-
69
- Some(TokenKind::At) => {
70
- match parse_at(&mut parser) {
71
- Ok(statement) => statements.push(statement),
72
- Err(e) => {
73
- error_statement.value = VariableValue::Text(e.to_string());
74
- statements.push(error_statement);
75
- }
76
- }
77
- }
78
-
79
- Some(TokenKind::Dot) => {
80
- match parse_dot(&mut parser, global_store) {
81
- Ok(statement) => statements.push(statement),
82
- Err(e) => {
83
- error_statement.value = VariableValue::Text(e.to_string());
84
- statements.push(error_statement);
85
- }
86
- }
87
- }
88
-
89
- Some(TokenKind::Loop) => {
90
- match parse_loop(&mut parser, global_store) {
91
- Ok(statement) => statements.push(statement),
92
- Err(e) => {
93
- error_statement.value = VariableValue::Text(e.to_string());
94
- statements.push(error_statement);
95
- }
96
- }
97
- }
98
-
99
- Some(TokenKind::Tempo) => {
100
- match parse_tempo(&mut parser, global_store) {
101
- Ok(statement) => statements.push(statement),
102
- Err(e) => {
103
- error_statement.value = VariableValue::Text(e.to_string());
104
- statements.push(error_statement);
105
- }
106
- }
107
- }
108
-
109
- | Some(TokenKind::LBrace)
110
- | Some(TokenKind::RBrace)
111
- | Some(TokenKind::LBracket)
112
- | Some(TokenKind::RBracket)
113
- | Some(TokenKind::DbQuote)
114
- | Some(TokenKind::Quote)
115
- | Some(TokenKind::Number)
116
- | Some(TokenKind::String)
117
- | Some(TokenKind::Newline)
118
- | Some(TokenKind::Indent)
119
- | Some(TokenKind::Dedent) => {
120
- parser.next();
121
- }
122
- Some(_) => {
123
- parser.next();
124
- }
125
- None => {
126
- break;
127
- }
128
- }
129
- }
130
-
131
- statements
132
- }
133
-
134
- pub fn parse_without_resolving_with_module(tokens: Vec<Token>, module: &Module) -> Vec<Statement> {
135
- let mut parser = Parser::new(tokens.clone());
136
-
137
- parser.current_module = module.path.clone();
138
-
139
- let mut global_store = GlobalStore::new();
140
- global_store.insert_module(module.path.clone(), module.clone());
141
-
142
- let statements = parse_without_resolving(tokens, &mut parser, &mut global_store);
143
-
144
- let mut updated_module = module.clone();
145
- updated_module.statements = statements.clone();
146
-
147
- let mut errors: Vec<String> = Vec::new();
148
-
149
- statements.iter().for_each(|statement| {
150
- match &statement.kind {
151
- StatementKind::Error => {
152
- let error_message = match &statement.value {
153
- VariableValue::Text(text) => text.clone(),
154
- _ => "Unknown error".to_string(),
155
- };
156
-
157
- errors.push(format!(
158
- "Error in module '{}': {} at line {}, column {}",
159
- updated_module.path,
160
- error_message,
161
- statement.line,
162
- statement.column
163
- ));
164
-
165
- log_message(&format!("Error: {}", error_message), "ERROR");
166
- }
167
- _ => {}
168
- }
169
- });
170
-
171
- if errors.len() > 0 {
172
- log_message(&format!("{} error(s) found. Parsing stopped.", errors.len()), "INFO");
173
-
174
- statements
175
- } else {
176
- statements
177
- }
178
- }
179
-
180
- pub fn parse_with_resolving_with_module(
181
- tokens: Vec<Token>,
182
- module: &Module
183
- ) -> Vec<StatementResolved> {
184
- let mut parser = Parser::new(tokens.clone());
185
-
186
- parser.current_module = module.path.clone();
187
-
188
- let mut global_store = GlobalStore::new();
189
- global_store.insert_module(module.path.clone(), module.clone());
190
-
191
- let statements = parse_without_resolving(tokens, &mut parser, &mut global_store);
192
-
193
- let mut resolved_statements = Vec::new();
194
-
195
- for statement in statements {
196
- let resolved_statement = resolve_statement(&statement, &mut module.clone());
197
- resolved_statements.push(resolved_statement);
198
- }
199
-
200
- return resolved_statements;
201
- }
3
+ pub mod statement;
4
+ pub mod handler;
@@ -0,0 +1,96 @@
1
+ use serde::{ Deserialize, Serialize };
2
+ use crate::core::{ lexer::token::Token, shared::{ duration::Duration, value::Value } };
3
+
4
+ #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
5
+ pub struct Statement {
6
+ pub kind: StatementKind,
7
+ pub value: Value,
8
+ pub indent: usize,
9
+ pub line: usize,
10
+ pub column: usize,
11
+ }
12
+
13
+ impl Statement {
14
+ pub fn unknown() -> Self {
15
+ Statement {
16
+ kind: StatementKind::Unknown,
17
+ value: Value::Null,
18
+ indent: 0,
19
+ line: 0,
20
+ column: 0,
21
+ }
22
+ }
23
+
24
+ pub fn error(token: Token, message: String) -> Self {
25
+ Statement {
26
+ kind: StatementKind::Error { message },
27
+ value: Value::Null,
28
+ indent: token.indent,
29
+ line: token.line,
30
+ column: token.column,
31
+ }
32
+ }
33
+ }
34
+
35
+ #[derive(Debug, Serialize, Clone, Deserialize, PartialEq)]
36
+ pub enum StatementKind {
37
+ // ───── Core Instructions ─────
38
+ Tempo,
39
+ Bank,
40
+ Load {
41
+ source: String,
42
+ alias: String,
43
+ },
44
+ Let {
45
+ name: String,
46
+ },
47
+ ArrowCall {
48
+ target: String,
49
+ method: String,
50
+ args: Vec<Value>,
51
+ },
52
+
53
+ // ───── Instruments ─────
54
+ Synth,
55
+
56
+ // ───── Playback / Scheduling ─────
57
+ Trigger {
58
+ entity: String,
59
+ duration: Duration,
60
+ },
61
+ Sleep,
62
+ Call,
63
+ Spawn,
64
+ Loop,
65
+
66
+ // ───── Structure & Logic ─────
67
+ Group,
68
+
69
+ // ───── Module System ─────
70
+ Include(String),
71
+ Export {
72
+ names: Vec<String>,
73
+ source: String,
74
+ },
75
+ Import {
76
+ names: Vec<String>,
77
+ source: String,
78
+ },
79
+
80
+ // ───── Conditions ─────
81
+ If,
82
+ Else,
83
+ ElseIf,
84
+
85
+ // ───── Internal / Utility ─────
86
+ Comment,
87
+ Indent,
88
+ Dedent,
89
+ NewLine,
90
+
91
+ // ───── Error Handling ─────
92
+ Unknown,
93
+ Error {
94
+ message: String,
95
+ },
96
+ }
@@ -0,0 +1,229 @@
1
+ use std::{ collections::HashMap, path::Path };
2
+ use crate::{
3
+ core::{
4
+ error::ErrorHandler,
5
+ lexer::{ token::Token, Lexer },
6
+ parser::{ statement::{ Statement, StatementKind }, driver::Parser },
7
+ preprocessor::{ module::Module, processor::process_modules },
8
+ store::global::GlobalStore,
9
+ utils::path::normalize_path,
10
+ },
11
+ utils::logger::Logger,
12
+ };
13
+ use crate::core::preprocessor::resolver::driver::{
14
+ resolve_all_modules,
15
+ resolve_and_flatten_all_modules,
16
+ };
17
+ use crate::core::utils::path::resolve_relative_path;
18
+
19
+ pub struct ModuleLoader {
20
+ pub entry: String,
21
+ pub output: String,
22
+ pub base_dir: String,
23
+ }
24
+
25
+ impl ModuleLoader {
26
+ pub fn new(entry: &str, output: &str) -> Self {
27
+ let base_dir = Path::new(entry)
28
+ .parent()
29
+ .unwrap_or(Path::new(""))
30
+ .to_string_lossy()
31
+ .replace('\\', "/");
32
+
33
+ Self {
34
+ entry: entry.to_string(),
35
+ output: output.to_string(),
36
+ base_dir: base_dir,
37
+ }
38
+ }
39
+
40
+ pub fn from_raw_source(
41
+ entry_path: &str,
42
+ output_path: &str,
43
+ content: &str,
44
+ global_store: &mut GlobalStore
45
+ ) -> Self {
46
+ let normalized_entry_path = normalize_path(entry_path);
47
+
48
+ let mut module = Module::new(&entry_path);
49
+ module.content = content.to_string();
50
+
51
+ global_store.insert_module(normalized_entry_path.to_string(), module);
52
+
53
+ Self {
54
+ entry: normalized_entry_path.to_string(),
55
+ output: output_path.to_string(),
56
+ base_dir: "".to_string(),
57
+ }
58
+ }
59
+
60
+ pub fn extract_statements_map(
61
+ &self,
62
+ global_store: &GlobalStore
63
+ ) -> HashMap<String, Vec<Statement>> {
64
+ global_store.modules
65
+ .iter()
66
+ .map(|(path, module)| (path.clone(), module.statements.clone()))
67
+ .collect()
68
+ }
69
+
70
+ pub fn load_single_module(&self, global_store: &mut GlobalStore) -> Result<Module, String> {
71
+ let mut module = global_store.modules
72
+ .remove(&self.entry)
73
+ .ok_or_else(|| format!("Module not found in store for path: {}", self.entry))?;
74
+
75
+ // SECTION Lexing the module content
76
+ let lexer = Lexer::new();
77
+ let tokens = lexer
78
+ .lex_from_source(&module.content)
79
+ .map_err(|e| format!("Lexer failed: {}", e))?;
80
+
81
+ module.tokens = tokens.clone();
82
+
83
+ // SECTION Parsing tokens into statements
84
+ let mut parser = Parser::new();
85
+ parser.set_current_module(self.entry.clone());
86
+ let statements = parser.parse_tokens(tokens, global_store);
87
+ module.statements = statements;
88
+
89
+ // SECTION Error handling
90
+ let mut error_handler = ErrorHandler::new();
91
+ error_handler.detect_from_statements(&mut parser, &module.statements);
92
+
93
+ global_store.modules.insert(self.entry.clone(), module.clone());
94
+
95
+ Ok(module)
96
+ }
97
+
98
+ pub fn load_wasm_module(&self, global_store: &mut GlobalStore) -> Result<(), String> {
99
+ // Step one : Load the module from the global store
100
+ let module = {
101
+ let module_ref = global_store.modules
102
+ .get(&self.entry)
103
+ .ok_or_else(|| format!("❌ Module not found for path: {}", self.entry))?;
104
+
105
+ Module::from_existing(&self.entry, module_ref.content.clone())
106
+ };
107
+
108
+ // Step two : lexing
109
+ let lexer = Lexer::new();
110
+ let tokens = lexer
111
+ .lex_from_source(&module.content)
112
+ .map_err(|e| format!("Lexer failed: {}", e))?;
113
+
114
+ // Step three : parsing
115
+ let mut parser = Parser::new();
116
+ parser.set_current_module(self.entry.clone());
117
+
118
+ let statements = parser.parse_tokens(tokens.clone(), global_store);
119
+
120
+ let mut updated_module = module;
121
+ updated_module.tokens = tokens;
122
+ updated_module.statements = statements;
123
+
124
+ // Step four : error handling
125
+ let mut error_handler = ErrorHandler::new();
126
+ error_handler.detect_from_statements(&mut parser, &updated_module.statements);
127
+
128
+ // Final step : insert the updated module back into the global store
129
+ global_store.modules.insert(self.entry.clone(), updated_module);
130
+
131
+ Ok(())
132
+ }
133
+
134
+ #[cfg(feature = "cli")]
135
+ pub fn load_all_modules(
136
+ &self,
137
+ global_store: &mut GlobalStore
138
+ ) -> (HashMap<String, Vec<Token>>, HashMap<String, Vec<Statement>>) {
139
+ // SECTION Load the entry module and its dependencies
140
+
141
+ let tokens_by_module = self.load_module_recursively(&self.entry, global_store);
142
+
143
+ // SECTION Process and resolve modules
144
+ process_modules(self, global_store);
145
+ resolve_all_modules(self, global_store);
146
+
147
+ let statemnts_by_module = resolve_and_flatten_all_modules(global_store);
148
+
149
+ (tokens_by_module, statemnts_by_module)
150
+ }
151
+
152
+ #[cfg(feature = "cli")]
153
+ fn load_module_recursively(
154
+ &self,
155
+ raw_path: &str,
156
+ global_store: &mut GlobalStore
157
+ ) -> HashMap<String, Vec<Token>> {
158
+ let path = normalize_path(raw_path);
159
+
160
+ // Check if already loaded
161
+ if global_store.modules.contains_key(&path) {
162
+ return HashMap::new();
163
+ }
164
+
165
+ let lexer = Lexer::new();
166
+ let tokens = lexer.lex_tokens(&path);
167
+
168
+ let mut parser = Parser::new();
169
+ parser.set_current_module(path.clone());
170
+
171
+ let statements = parser.parse_tokens(tokens.clone(), global_store);
172
+
173
+ // Error handling
174
+ let mut error_handler = ErrorHandler::new();
175
+ error_handler.detect_from_statements(&mut parser, &statements);
176
+
177
+ if error_handler.has_errors() {
178
+ let logger = Logger::new();
179
+ for error in error_handler.get_errors() {
180
+ let trace = format!("{}:{}:{}", path, error.line, error.column);
181
+ logger.log_error_with_stacktrace(&error.message, &trace);
182
+ }
183
+ }
184
+
185
+ // Insert module into store
186
+ let mut module = Module::new(&path);
187
+ module.tokens = tokens.clone();
188
+ module.statements = statements.clone();
189
+ global_store.insert_module(path.clone(), module);
190
+
191
+ // Load dependencies
192
+ self.load_module_imports(&path, global_store);
193
+
194
+ // Return tokens per module
195
+ global_store.modules
196
+ .iter()
197
+ .map(|(p, m)| (p.clone(), m.tokens.clone()))
198
+ .collect()
199
+ }
200
+
201
+ #[cfg(feature = "cli")]
202
+ fn load_module_imports(&self, path: &String, global_store: &mut GlobalStore) {
203
+ let import_paths: Vec<String> = {
204
+ let current_module = match global_store.modules.get(path) {
205
+ Some(module) => module,
206
+ None => {
207
+ eprintln!("[warn] Cannot resolve imports: module '{}' not found in store", path);
208
+ return;
209
+ }
210
+ };
211
+
212
+ current_module.statements
213
+ .iter()
214
+ .filter_map(|stmt| {
215
+ if let StatementKind::Import { source, .. } = &stmt.kind {
216
+ Some(source.clone())
217
+ } else {
218
+ None
219
+ }
220
+ })
221
+ .collect()
222
+ };
223
+
224
+ for import_path in import_paths {
225
+ let resolved = resolve_relative_path(path, &import_path);
226
+ self.load_module_recursively(&resolved, global_store);
227
+ }
228
+ }
229
+ }
@@ -1,26 +1,4 @@
1
1
  pub mod module;
2
- pub mod dependencies;
2
+ pub mod loader;
3
3
  pub mod resolver;
4
-
5
- use crate::core::{
6
- preprocessor::{
7
- dependencies::collect_dependencies_recursively,
8
- module::load_module_into_global_store,
9
- },
10
- types::{ store::GlobalStore },
11
- };
12
-
13
- pub fn preprocess(entry_file: &str) -> GlobalStore {
14
- println!("📦 Collecting dependencies for: {}", entry_file);
15
-
16
- let files = collect_dependencies_recursively(entry_file);
17
- let mut store = GlobalStore::default();
18
-
19
- for file in &files {
20
- if let Err(e) = load_module_into_global_store(file, &mut store) {
21
- eprintln!("❌ Error while loading {}: {}", file, e);
22
- }
23
- }
24
-
25
- store
26
- }
4
+ pub mod processor;