@devaloop/devalang 0.0.1-alpha.1 → 0.0.1-alpha.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.
- package/.devalang +4 -0
- package/Cargo.toml +46 -45
- package/README.md +35 -10
- package/docs/CHANGELOG.md +58 -0
- package/docs/COMMANDS.md +29 -6
- package/docs/CONFIG.md +28 -0
- package/docs/ROADMAP.md +6 -2
- package/docs/TODO.md +21 -18
- package/examples/exported.deva +1 -1
- package/examples/index.deva +2 -1
- package/out-tsc/bin/devalang.exe +0 -0
- package/package.json +2 -3
- package/project-version.json +4 -4
- package/rust/cli/build.rs +99 -29
- package/rust/cli/check.rs +95 -103
- package/rust/cli/init.rs +77 -0
- package/rust/cli/mod.rs +174 -1
- package/rust/cli/template.rs +56 -0
- package/rust/config/loader.rs +14 -0
- package/rust/config/mod.rs +15 -0
- package/rust/core/builder/mod.rs +21 -27
- package/rust/core/debugger/lexer.rs +12 -0
- package/rust/core/debugger/mod.rs +12 -49
- package/rust/core/debugger/preprocessor.rs +23 -0
- package/rust/core/error/mod.rs +60 -0
- package/rust/core/lexer/handler/at.rs +21 -0
- package/rust/core/lexer/handler/brace.rs +41 -0
- package/rust/core/lexer/handler/colon.rs +21 -0
- package/rust/core/lexer/handler/comment.rs +30 -0
- package/rust/core/lexer/handler/dot.rs +21 -0
- package/rust/core/lexer/handler/equal.rs +32 -0
- package/rust/core/lexer/handler/identifier.rs +38 -0
- package/rust/core/lexer/handler/indent.rs +52 -0
- package/rust/core/lexer/handler/mod.rs +238 -0
- package/rust/core/lexer/handler/newline.rs +19 -0
- package/rust/core/lexer/handler/number.rs +31 -0
- package/rust/core/lexer/handler/string.rs +66 -0
- package/rust/core/lexer/mod.rs +16 -324
- package/rust/core/lexer/token.rs +55 -0
- package/rust/core/mod.rs +5 -2
- package/rust/core/parser/handler/at.rs +166 -0
- package/rust/core/parser/handler/bank.rs +38 -0
- package/rust/core/parser/handler/dot.rs +112 -0
- package/rust/core/parser/handler/identifier.rs +134 -0
- package/rust/core/parser/handler/loop_.rs +55 -0
- package/rust/core/parser/handler/mod.rs +6 -0
- package/rust/core/parser/handler/tempo.rs +47 -0
- package/rust/core/parser/mod.rs +204 -166
- package/rust/core/parser/statement.rs +91 -0
- package/rust/core/preprocessor/loader.rs +105 -0
- package/rust/core/preprocessor/mod.rs +2 -24
- package/rust/core/preprocessor/module.rs +37 -56
- package/rust/core/preprocessor/processor.rs +41 -0
- package/rust/core/preprocessor/resolver.rs +372 -0
- package/rust/core/shared/duration.rs +8 -0
- package/rust/core/shared/mod.rs +2 -0
- package/rust/core/shared/value.rs +18 -0
- package/rust/core/store/export.rs +28 -0
- package/rust/core/store/global.rs +39 -0
- package/rust/core/store/import.rs +28 -0
- package/rust/core/store/mod.rs +4 -0
- package/rust/core/store/variable.rs +28 -0
- package/rust/core/utils/mod.rs +2 -0
- package/rust/core/utils/validation.rs +35 -0
- package/rust/lib.rs +0 -1
- package/rust/main.rs +39 -30
- package/rust/utils/file.rs +35 -0
- package/rust/utils/logger.rs +69 -34
- package/rust/utils/mod.rs +3 -2
- package/rust/utils/watcher.rs +25 -0
- package/templates/minimal/.devalang +4 -0
- package/templates/minimal/src/index.deva +2 -0
- package/templates/welcome/.devalang +4 -0
- package/templates/welcome/README.md +185 -0
- package/templates/welcome/samples/kick-808.wav +0 -0
- package/templates/welcome/src/index.deva +13 -0
- package/templates/welcome/src/variables.deva +5 -0
- package/rust/audio/mod.rs +0 -1
- package/rust/cli/new.rs +0 -1
- package/rust/core/parser/at.rs +0 -142
- package/rust/core/parser/bank.rs +0 -42
- package/rust/core/parser/dot.rs +0 -107
- package/rust/core/parser/identifer.rs +0 -91
- package/rust/core/parser/loop_.rs +0 -62
- package/rust/core/parser/tempo.rs +0 -42
- package/rust/core/parser/variable.rs +0 -129
- package/rust/core/preprocessor/dependencies.rs +0 -54
- package/rust/core/preprocessor/resolver/at.rs +0 -24
- package/rust/core/preprocessor/resolver/bank.rs +0 -59
- package/rust/core/preprocessor/resolver/loop_.rs +0 -82
- package/rust/core/preprocessor/resolver/mod.rs +0 -113
- package/rust/core/preprocessor/resolver/tempo.rs +0 -70
- package/rust/core/preprocessor/resolver/trigger.rs +0 -176
- package/rust/core/types/cli.rs +0 -160
- package/rust/core/types/mod.rs +0 -7
- package/rust/core/types/module.rs +0 -41
- package/rust/core/types/parser.rs +0 -73
- package/rust/core/types/statement.rs +0 -105
- package/rust/core/types/store.rs +0 -116
- package/rust/core/types/token.rs +0 -83
- package/rust/core/types/variable.rs +0 -32
- package/rust/runner/executer.rs +0 -44
- package/rust/runner/mod.rs +0 -1
- /package/rust/{utils → core/utils}/path.rs +0 -0
- /package/rust/utils/{loader.rs → spinner.rs} +0 -0
package/rust/core/parser/mod.rs
CHANGED
|
@@ -1,201 +1,239 @@
|
|
|
1
|
-
pub mod
|
|
2
|
-
pub mod
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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,
|
|
1
|
+
pub mod statement;
|
|
2
|
+
pub mod handler;
|
|
3
|
+
|
|
4
|
+
use crate::core::{
|
|
5
|
+
lexer::token::{ Token, TokenKind },
|
|
6
|
+
parser::{
|
|
7
|
+
handler::{
|
|
8
|
+
at::parse_at_token,
|
|
9
|
+
bank::parse_bank_token,
|
|
10
|
+
dot::parse_dot_token,
|
|
11
|
+
identifier::parse_identifier_token,
|
|
12
|
+
loop_::parse_loop_token,
|
|
13
|
+
tempo::parse_tempo_token,
|
|
27
14
|
},
|
|
15
|
+
statement::{ Statement, StatementKind },
|
|
28
16
|
},
|
|
29
|
-
|
|
17
|
+
shared::value::Value,
|
|
18
|
+
store::global::GlobalStore,
|
|
30
19
|
};
|
|
31
20
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
-
}
|
|
21
|
+
#[derive(Debug, Clone, PartialEq)]
|
|
22
|
+
pub struct Parser {
|
|
23
|
+
pub resolve_modules: bool,
|
|
24
|
+
pub tokens: Vec<Token>,
|
|
25
|
+
pub token_index: usize,
|
|
26
|
+
pub current_module: String,
|
|
27
|
+
pub previous: Option<Token>,
|
|
28
|
+
}
|
|
58
29
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
30
|
+
impl Parser {
|
|
31
|
+
pub fn new() -> Self {
|
|
32
|
+
Parser {
|
|
33
|
+
resolve_modules: false,
|
|
34
|
+
tokens: Vec::new(),
|
|
35
|
+
token_index: 0,
|
|
36
|
+
current_module: String::new(),
|
|
37
|
+
previous: None,
|
|
38
|
+
}
|
|
39
|
+
}
|
|
68
40
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
Err(e) => {
|
|
73
|
-
error_statement.value = VariableValue::Text(e.to_string());
|
|
74
|
-
statements.push(error_statement);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
41
|
+
pub fn set_current_module(&mut self, module_path: String) {
|
|
42
|
+
self.current_module = module_path;
|
|
43
|
+
}
|
|
78
44
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
error_statement.value = VariableValue::Text(e.to_string());
|
|
84
|
-
statements.push(error_statement);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
45
|
+
pub fn advance(&mut self) -> Option<&Token> {
|
|
46
|
+
if self.is_eof() {
|
|
47
|
+
return None;
|
|
48
|
+
}
|
|
88
49
|
|
|
89
|
-
|
|
90
|
-
|
|
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
|
-
}
|
|
50
|
+
self.previous = self.tokens.get(self.token_index).cloned(); // mémorise avant de bouger
|
|
51
|
+
self.token_index += 1;
|
|
98
52
|
|
|
99
|
-
|
|
100
|
-
|
|
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
|
-
}
|
|
53
|
+
self.tokens.get(self.token_index - 1)
|
|
54
|
+
}
|
|
108
55
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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;
|
|
56
|
+
pub fn match_token(&mut self, kind: TokenKind) -> bool {
|
|
57
|
+
if let Some(tok) = self.peek() {
|
|
58
|
+
if tok.kind == kind {
|
|
59
|
+
self.advance();
|
|
60
|
+
return true;
|
|
127
61
|
}
|
|
128
62
|
}
|
|
63
|
+
false
|
|
129
64
|
}
|
|
130
65
|
|
|
131
|
-
|
|
132
|
-
|
|
66
|
+
pub fn previous_clone(&self) -> Option<Token> {
|
|
67
|
+
self.previous.clone()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
pub fn parse_block(
|
|
71
|
+
&self,
|
|
72
|
+
tokens: Vec<Token>,
|
|
73
|
+
global_store: &mut GlobalStore
|
|
74
|
+
) -> Vec<Statement> {
|
|
75
|
+
let mut inner_parser = Parser {
|
|
76
|
+
resolve_modules: self.resolve_modules,
|
|
77
|
+
tokens,
|
|
78
|
+
token_index: 0,
|
|
79
|
+
current_module: self.current_module.clone(),
|
|
80
|
+
previous: None,
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
inner_parser.parse_tokens(inner_parser.tokens.clone(), global_store)
|
|
84
|
+
}
|
|
133
85
|
|
|
134
|
-
pub fn
|
|
135
|
-
|
|
86
|
+
pub fn parse_tokens(
|
|
87
|
+
&mut self,
|
|
88
|
+
tokens: Vec<Token>,
|
|
89
|
+
global_store: &mut GlobalStore
|
|
90
|
+
) -> Vec<Statement> {
|
|
91
|
+
self.tokens = tokens;
|
|
92
|
+
self.token_index = 0;
|
|
93
|
+
|
|
94
|
+
let mut statements = Vec::new();
|
|
95
|
+
|
|
96
|
+
while !self.is_eof() {
|
|
97
|
+
let token = match self.peek() {
|
|
98
|
+
Some(t) => t.clone(),
|
|
99
|
+
None => {
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
let mut statement = match &token.kind {
|
|
105
|
+
TokenKind::At => parse_at_token(self, global_store),
|
|
106
|
+
TokenKind::Identifier => parse_identifier_token(self, global_store),
|
|
107
|
+
TokenKind::Dot => parse_dot_token(self, global_store),
|
|
108
|
+
TokenKind::Tempo => parse_tempo_token(self, global_store),
|
|
109
|
+
TokenKind::Bank => parse_bank_token(self, global_store),
|
|
110
|
+
TokenKind::Loop => parse_loop_token(self, global_store),
|
|
111
|
+
|
|
112
|
+
| TokenKind::Comment
|
|
113
|
+
| TokenKind::Equals
|
|
114
|
+
| TokenKind::Colon
|
|
115
|
+
| TokenKind::Number
|
|
116
|
+
| TokenKind::String
|
|
117
|
+
| TokenKind::LBrace
|
|
118
|
+
| TokenKind::RBrace
|
|
119
|
+
| TokenKind::Comma
|
|
120
|
+
| TokenKind::Newline
|
|
121
|
+
| TokenKind::Dedent
|
|
122
|
+
| TokenKind::Indent => {
|
|
123
|
+
self.advance();
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
136
126
|
|
|
137
|
-
|
|
127
|
+
TokenKind::EOF => {
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
138
130
|
|
|
139
|
-
|
|
140
|
-
|
|
131
|
+
_ => {
|
|
132
|
+
println!("Unhandled token: {:?}", token);
|
|
133
|
+
self.advance();
|
|
134
|
+
Statement::unknown()
|
|
135
|
+
}
|
|
136
|
+
};
|
|
141
137
|
|
|
142
|
-
|
|
138
|
+
statements.push(statement);
|
|
139
|
+
}
|
|
143
140
|
|
|
144
|
-
|
|
145
|
-
|
|
141
|
+
statements
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
pub fn check_token(&self, kind: TokenKind) -> bool {
|
|
145
|
+
self.peek().map_or(false, |t| t.kind == kind)
|
|
146
|
+
}
|
|
146
147
|
|
|
147
|
-
|
|
148
|
+
pub fn parse_map_value(&mut self) -> Option<Value> {
|
|
149
|
+
if !self.match_token(TokenKind::LBrace) {
|
|
150
|
+
return None;
|
|
151
|
+
}
|
|
148
152
|
|
|
149
|
-
|
|
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
|
-
};
|
|
153
|
+
let mut map = std::collections::HashMap::new();
|
|
156
154
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
));
|
|
155
|
+
while !self.check_token(TokenKind::RBrace) && !self.is_eof() {
|
|
156
|
+
let key = if let Some(token) = self.advance() {
|
|
157
|
+
token.lexeme.clone()
|
|
158
|
+
} else {
|
|
159
|
+
break;
|
|
160
|
+
};
|
|
164
161
|
|
|
165
|
-
|
|
162
|
+
if !self.match_token(TokenKind::Colon) {
|
|
163
|
+
println!("Expected ':' after map key '{}'", key);
|
|
164
|
+
break;
|
|
166
165
|
}
|
|
167
|
-
_ => {}
|
|
168
|
-
}
|
|
169
|
-
});
|
|
170
166
|
|
|
171
|
-
|
|
172
|
-
|
|
167
|
+
let value = if let Some(token) = self.peek_clone() {
|
|
168
|
+
match token.kind {
|
|
169
|
+
TokenKind::String => {
|
|
170
|
+
self.advance();
|
|
171
|
+
Value::String(token.lexeme.clone())
|
|
172
|
+
}
|
|
173
|
+
TokenKind::Number => {
|
|
174
|
+
self.advance();
|
|
175
|
+
Value::Number(token.lexeme.parse().unwrap_or(0.0))
|
|
176
|
+
}
|
|
177
|
+
TokenKind::Identifier => {
|
|
178
|
+
self.advance();
|
|
179
|
+
Value::Identifier(token.lexeme.clone())
|
|
180
|
+
}
|
|
181
|
+
_ => {
|
|
182
|
+
println!("Unexpected token in map value: {:?}", token);
|
|
183
|
+
Value::Null
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
} else {
|
|
187
|
+
Value::Null
|
|
188
|
+
};
|
|
173
189
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
statements
|
|
177
|
-
}
|
|
178
|
-
}
|
|
190
|
+
map.insert(key, value);
|
|
191
|
+
}
|
|
179
192
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
) -> Vec<StatementResolved> {
|
|
184
|
-
let mut parser = Parser::new(tokens.clone());
|
|
193
|
+
if !self.match_token(TokenKind::RBrace) {
|
|
194
|
+
println!("Expected '}}' at end of map");
|
|
195
|
+
}
|
|
185
196
|
|
|
186
|
-
|
|
197
|
+
Some(Value::Map(map))
|
|
198
|
+
}
|
|
187
199
|
|
|
188
|
-
|
|
189
|
-
|
|
200
|
+
pub fn peek(&self) -> Option<&Token> {
|
|
201
|
+
self.tokens.get(self.token_index)
|
|
202
|
+
}
|
|
190
203
|
|
|
191
|
-
|
|
204
|
+
pub fn peek_clone(&self) -> Option<Token> {
|
|
205
|
+
self.tokens.get(self.token_index).cloned()
|
|
206
|
+
}
|
|
192
207
|
|
|
193
|
-
|
|
208
|
+
pub fn expect(&mut self, kind: TokenKind) -> Result<&Token, String> {
|
|
209
|
+
let tok = self.advance().ok_or("Unexpected end of input")?;
|
|
210
|
+
if tok.kind == kind {
|
|
211
|
+
Ok(tok)
|
|
212
|
+
} else {
|
|
213
|
+
Err(format!("Expected {:?}, got {:?}", kind, tok.kind))
|
|
214
|
+
}
|
|
215
|
+
}
|
|
194
216
|
|
|
195
|
-
|
|
196
|
-
let
|
|
197
|
-
|
|
217
|
+
pub fn collect_until<F>(&mut self, condition: F) -> Vec<Token> where F: Fn(&Token) -> bool {
|
|
218
|
+
let mut collected = Vec::new();
|
|
219
|
+
while let Some(token) = self.peek() {
|
|
220
|
+
if token.kind == TokenKind::Newline || token.kind == TokenKind::Indent {
|
|
221
|
+
self.advance(); // Skip newlines and indents
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
if token.kind == TokenKind::EOF {
|
|
225
|
+
break;
|
|
226
|
+
}
|
|
227
|
+
if condition(token) {
|
|
228
|
+
self.advance(); // Consume the token that matches the condition
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
231
|
+
collected.push(self.advance().unwrap().clone());
|
|
232
|
+
}
|
|
233
|
+
collected
|
|
198
234
|
}
|
|
199
235
|
|
|
200
|
-
|
|
236
|
+
pub fn is_eof(&self) -> bool {
|
|
237
|
+
self.token_index >= self.tokens.len()
|
|
238
|
+
}
|
|
201
239
|
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
use serde::{ Deserialize, Serialize };
|
|
2
|
+
|
|
3
|
+
use crate::core::{ lexer::token::Token, shared::{ duration::Duration, value::Value } };
|
|
4
|
+
|
|
5
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
|
6
|
+
pub struct Statement {
|
|
7
|
+
pub kind: StatementKind,
|
|
8
|
+
pub value: Value,
|
|
9
|
+
pub indent: usize,
|
|
10
|
+
pub line: usize,
|
|
11
|
+
pub column: usize,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
impl Statement {
|
|
15
|
+
pub fn unknown() -> Self {
|
|
16
|
+
Statement {
|
|
17
|
+
kind: StatementKind::Unknown,
|
|
18
|
+
value: Value::Null,
|
|
19
|
+
indent: 0,
|
|
20
|
+
line: 0,
|
|
21
|
+
column: 0,
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
pub fn error(token: Token, message: String) -> Self {
|
|
26
|
+
Statement {
|
|
27
|
+
kind: StatementKind::Error { message },
|
|
28
|
+
value: Value::Null,
|
|
29
|
+
indent: token.indent,
|
|
30
|
+
line: token.line,
|
|
31
|
+
column: token.column,
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
#[derive(Debug, Serialize, Clone, Deserialize, PartialEq)]
|
|
37
|
+
/// Represents the kind of a statement
|
|
38
|
+
pub enum StatementKind {
|
|
39
|
+
// Trigger statements
|
|
40
|
+
Trigger {
|
|
41
|
+
entity: String,
|
|
42
|
+
duration: Duration,
|
|
43
|
+
// params: Vec<TokenParam>,
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
// Variable statements
|
|
47
|
+
Let {
|
|
48
|
+
name: String,
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
// Loop statements
|
|
52
|
+
Loop,
|
|
53
|
+
|
|
54
|
+
// Conditional statements
|
|
55
|
+
// If {
|
|
56
|
+
// // condition: ConditionParts,
|
|
57
|
+
// condition_state: bool,
|
|
58
|
+
// body: Vec<Statement>,
|
|
59
|
+
// },
|
|
60
|
+
|
|
61
|
+
// Keyword statements
|
|
62
|
+
Tempo,
|
|
63
|
+
Bank,
|
|
64
|
+
|
|
65
|
+
// At (@) statements
|
|
66
|
+
Include(String),
|
|
67
|
+
Export {
|
|
68
|
+
names: Vec<String>,
|
|
69
|
+
source: String,
|
|
70
|
+
},
|
|
71
|
+
Import {
|
|
72
|
+
names: Vec<String>,
|
|
73
|
+
source: String,
|
|
74
|
+
},
|
|
75
|
+
Load {
|
|
76
|
+
source: String,
|
|
77
|
+
alias: String,
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
// Error & Unknown statements
|
|
81
|
+
Unknown,
|
|
82
|
+
Error {
|
|
83
|
+
message: String,
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
// Empty or ignored statements
|
|
87
|
+
Comment,
|
|
88
|
+
Indent,
|
|
89
|
+
Dedent,
|
|
90
|
+
NewLine,
|
|
91
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
use std::collections::HashMap;
|
|
2
|
+
|
|
3
|
+
use crate::{
|
|
4
|
+
core::{
|
|
5
|
+
debugger::{ lexer::write_lexer_log_file, preprocessor::write_preprocessor_log_file },
|
|
6
|
+
error::ErrorHandler,
|
|
7
|
+
lexer::Lexer,
|
|
8
|
+
parser::{ statement::{ Statement, StatementKind }, Parser },
|
|
9
|
+
preprocessor::{
|
|
10
|
+
module::Module,
|
|
11
|
+
processor::process_modules,
|
|
12
|
+
resolver::{ resolve_all_modules, resolve_and_flatten_all_modules },
|
|
13
|
+
},
|
|
14
|
+
store::global::GlobalStore,
|
|
15
|
+
},
|
|
16
|
+
utils::logger::{ LogLevel, Logger },
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
pub struct ModuleLoader {
|
|
20
|
+
pub entry: String,
|
|
21
|
+
pub output: String,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
impl ModuleLoader {
|
|
25
|
+
pub fn new(entry: &str, output: &str) -> Self {
|
|
26
|
+
Self {
|
|
27
|
+
entry: entry.to_string(),
|
|
28
|
+
output: output.to_string(),
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
pub fn load_all(&self, global_store: &mut GlobalStore) -> HashMap<String, Vec<Statement>> {
|
|
33
|
+
// SECTION Load the entry module and its dependencies
|
|
34
|
+
self.load_module_recursively(&self.entry, global_store);
|
|
35
|
+
|
|
36
|
+
// SECTION Process and resolve modules
|
|
37
|
+
process_modules(self, global_store);
|
|
38
|
+
resolve_all_modules(self, global_store);
|
|
39
|
+
|
|
40
|
+
let resolved = resolve_and_flatten_all_modules(global_store);
|
|
41
|
+
|
|
42
|
+
// SECTION Write resolved statements to log file
|
|
43
|
+
write_preprocessor_log_file(&self.output, "resolved_statements.log", resolved.clone());
|
|
44
|
+
|
|
45
|
+
// Return the resolved statements
|
|
46
|
+
resolved
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
fn load_module_recursively(&self, path: &str, global_store: &mut GlobalStore) {
|
|
50
|
+
if global_store.modules.contains_key(path) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let lexer = Lexer::new();
|
|
55
|
+
let tokens = lexer.lex_tokens(path);
|
|
56
|
+
|
|
57
|
+
let mut parser = Parser::new();
|
|
58
|
+
parser.set_current_module(path.to_string());
|
|
59
|
+
|
|
60
|
+
let statements = parser.parse_tokens(tokens.clone(), global_store);
|
|
61
|
+
|
|
62
|
+
// SECTION Error handling
|
|
63
|
+
let mut error_handler = ErrorHandler::new();
|
|
64
|
+
error_handler.detect_from_statements(&mut parser, &statements);
|
|
65
|
+
|
|
66
|
+
error_handler.has_errors().then(|| {
|
|
67
|
+
let logger = Logger::new();
|
|
68
|
+
let errors = error_handler.get_errors();
|
|
69
|
+
|
|
70
|
+
for error in errors {
|
|
71
|
+
let stacktrace = format!("{}:{}:{}", path, error.line, error.column);
|
|
72
|
+
logger.log_error_with_stacktrace(&error.message, &stacktrace);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// SECTION Module creation
|
|
77
|
+
let mut module = Module::new(path);
|
|
78
|
+
module.tokens = tokens;
|
|
79
|
+
module.statements = statements;
|
|
80
|
+
|
|
81
|
+
global_store.insert_module(path.to_string(), module);
|
|
82
|
+
|
|
83
|
+
// Then load the imports recursively
|
|
84
|
+
self.load_module_imports(&path.to_string(), global_store);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
fn load_module_imports(&self, path: &String, global_store: &mut GlobalStore) {
|
|
88
|
+
let imports = global_store.modules
|
|
89
|
+
.get(path)
|
|
90
|
+
.unwrap()
|
|
91
|
+
.statements.iter()
|
|
92
|
+
.filter_map(|stmt| {
|
|
93
|
+
if let StatementKind::Import { source, .. } = &stmt.kind {
|
|
94
|
+
Some(source.clone())
|
|
95
|
+
} else {
|
|
96
|
+
None
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
.collect::<Vec<_>>();
|
|
100
|
+
|
|
101
|
+
for import_path in imports {
|
|
102
|
+
self.load_module_recursively(&import_path, global_store);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -1,26 +1,4 @@
|
|
|
1
1
|
pub mod module;
|
|
2
|
-
pub mod
|
|
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;
|