@devaloop/devalang 0.0.1-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.toml +45 -0
- package/LICENSE +21 -0
- package/README.md +161 -0
- package/docs/COMMANDS.md +31 -0
- package/docs/ROADMAP.md +27 -0
- package/docs/SYNTAX.md +148 -0
- package/docs/TODO.md +66 -0
- package/examples/exported.deva +7 -0
- package/examples/index.deva +9 -0
- package/examples/samples/kick-808.wav +0 -0
- package/out-tsc/bin/devalang.exe +0 -0
- package/out-tsc/bin/index.js +13 -0
- package/out-tsc/index.js +2 -0
- package/out-tsc/scripts/postbuild.js +11 -0
- package/out-tsc/scripts/version/bump.js +52 -0
- package/out-tsc/scripts/version/fetch.js +34 -0
- package/out-tsc/scripts/version/index.js +32 -0
- package/out-tsc/scripts/version/sync.js +32 -0
- package/package.json +43 -0
- package/project-version.json +6 -0
- package/rust/audio/mod.rs +1 -0
- package/rust/cli/build.rs +51 -0
- package/rust/cli/check.rs +124 -0
- package/rust/cli/mod.rs +3 -0
- package/rust/cli/new.rs +1 -0
- package/rust/core/builder/mod.rs +37 -0
- package/rust/core/debugger/mod.rs +57 -0
- package/rust/core/lexer/mod.rs +333 -0
- package/rust/core/mod.rs +6 -0
- package/rust/core/parser/at.rs +142 -0
- package/rust/core/parser/bank.rs +42 -0
- package/rust/core/parser/dot.rs +107 -0
- package/rust/core/parser/identifer.rs +91 -0
- package/rust/core/parser/loop_.rs +62 -0
- package/rust/core/parser/mod.rs +201 -0
- package/rust/core/parser/tempo.rs +42 -0
- package/rust/core/parser/variable.rs +129 -0
- package/rust/core/preprocessor/dependencies.rs +54 -0
- package/rust/core/preprocessor/mod.rs +26 -0
- package/rust/core/preprocessor/module.rs +70 -0
- package/rust/core/preprocessor/resolver/at.rs +24 -0
- package/rust/core/preprocessor/resolver/bank.rs +59 -0
- package/rust/core/preprocessor/resolver/loop_.rs +82 -0
- package/rust/core/preprocessor/resolver/mod.rs +113 -0
- package/rust/core/preprocessor/resolver/tempo.rs +70 -0
- package/rust/core/preprocessor/resolver/trigger.rs +176 -0
- package/rust/core/types/cli.rs +160 -0
- package/rust/core/types/mod.rs +7 -0
- package/rust/core/types/module.rs +41 -0
- package/rust/core/types/parser.rs +73 -0
- package/rust/core/types/statement.rs +105 -0
- package/rust/core/types/store.rs +116 -0
- package/rust/core/types/token.rs +83 -0
- package/rust/core/types/variable.rs +32 -0
- package/rust/lib.rs +1 -0
- package/rust/main.rs +49 -0
- package/rust/runner/executer.rs +44 -0
- package/rust/runner/mod.rs +1 -0
- package/rust/utils/loader.rs +19 -0
- package/rust/utils/logger.rs +49 -0
- package/rust/utils/mod.rs +5 -0
- package/rust/utils/path.rs +46 -0
- package/rust/utils/signature.rs +17 -0
- package/rust/utils/version.rs +15 -0
- package/tsconfig.json +113 -0
- package/typescript/bin/index.ts +14 -0
- package/typescript/index.ts +1 -0
- package/typescript/scripts/postbuild.ts +8 -0
- package/typescript/scripts/version/bump.ts +45 -0
- package/typescript/scripts/version/fetch.ts +23 -0
- package/typescript/scripts/version/index.ts +26 -0
- package/typescript/scripts/version/sync.ts +24 -0
package/rust/core/mod.rs
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
use crate::core::types::{
|
|
2
|
+
parser::Parser,
|
|
3
|
+
statement::{ Statement, StatementKind },
|
|
4
|
+
token::TokenKind,
|
|
5
|
+
variable::VariableValue,
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
pub fn parse_at(parser: &mut Parser) -> Result<Statement, String> {
|
|
9
|
+
let token = parser.peek().ok_or("Unexpected EOF")?.clone();
|
|
10
|
+
|
|
11
|
+
if token.kind != TokenKind::At {
|
|
12
|
+
return Err(format!("Expected '@', found {:?}", token.kind));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
parser.next();
|
|
16
|
+
|
|
17
|
+
let identifier_token = parser.peek().ok_or("Expected identifier after '@'")?.clone();
|
|
18
|
+
if identifier_token.kind != TokenKind::Identifier {
|
|
19
|
+
return Err(format!("Expected Identifier, found {:?}", identifier_token.kind));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
match identifier_token.lexeme.as_str() {
|
|
23
|
+
"export" => {
|
|
24
|
+
parser.next();
|
|
25
|
+
|
|
26
|
+
if let Some(next_token) = parser.peek() {
|
|
27
|
+
if next_token.kind == TokenKind::LBrace {
|
|
28
|
+
parser.next(); // Consomme le LBrace
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let exportable_tokens = parser.collect_until(|t| { t.kind == TokenKind::RBrace });
|
|
33
|
+
|
|
34
|
+
exportable_tokens.iter().for_each(|t| {
|
|
35
|
+
let variable_value = parser.variable_table
|
|
36
|
+
.get(&t.lexeme)
|
|
37
|
+
.cloned()
|
|
38
|
+
.unwrap_or_else(|| VariableValue::Text(t.lexeme.clone()));
|
|
39
|
+
|
|
40
|
+
parser.export_table.exports.insert(t.lexeme.clone(), variable_value);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
return Ok(Statement {
|
|
44
|
+
kind: StatementKind::Export,
|
|
45
|
+
value: VariableValue::Array(exportable_tokens),
|
|
46
|
+
indent: token.indent,
|
|
47
|
+
line: token.line,
|
|
48
|
+
column: token.column,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
"import" => {
|
|
52
|
+
parser.next();
|
|
53
|
+
|
|
54
|
+
if let Some(next_token) = parser.peek() {
|
|
55
|
+
if next_token.kind == TokenKind::LBrace {
|
|
56
|
+
parser.next();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let importable_tokens = parser.collect_until(|t| { t.kind == TokenKind::RBrace });
|
|
61
|
+
|
|
62
|
+
parser.next();
|
|
63
|
+
|
|
64
|
+
if let Some(from_token) = parser.peek() {
|
|
65
|
+
if from_token.kind == TokenKind::Identifier && from_token.lexeme == "from" {
|
|
66
|
+
parser.next();
|
|
67
|
+
} else {
|
|
68
|
+
return Err(format!("Expected 'from', found {:?}", from_token.kind));
|
|
69
|
+
}
|
|
70
|
+
} else {
|
|
71
|
+
return Err("Expected 'from' after import declaration".into());
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
let source_token = parser.peek().ok_or("Expected source after 'from'")?.clone();
|
|
75
|
+
if source_token.kind != TokenKind::String {
|
|
76
|
+
return Err(format!("Expected String, found {:?}", source_token.kind));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
let statement = Statement {
|
|
80
|
+
kind: StatementKind::Import {
|
|
81
|
+
names: importable_tokens
|
|
82
|
+
.iter()
|
|
83
|
+
.map(|t| t.lexeme.clone())
|
|
84
|
+
.collect(),
|
|
85
|
+
source: source_token.lexeme.clone(),
|
|
86
|
+
},
|
|
87
|
+
value: VariableValue::Array(importable_tokens),
|
|
88
|
+
indent: token.indent,
|
|
89
|
+
line: token.line,
|
|
90
|
+
column: token.column,
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
return Ok(statement);
|
|
94
|
+
}
|
|
95
|
+
"load" => {
|
|
96
|
+
parser.next();
|
|
97
|
+
|
|
98
|
+
let source_token = parser.peek().ok_or("Expected source after load")?.clone();
|
|
99
|
+
if source_token.kind != TokenKind::String {
|
|
100
|
+
return Err(format!("Expected String, found {:?}", source_token.kind));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
parser.next();
|
|
104
|
+
|
|
105
|
+
let as_token = parser.peek().ok_or("Expected 'as' after load")?.clone();
|
|
106
|
+
if as_token.kind != TokenKind::Identifier || as_token.lexeme != "as" {
|
|
107
|
+
return Err(format!("Expected 'as', found {:?}", as_token.kind));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
parser.next();
|
|
111
|
+
|
|
112
|
+
let alias_token = parser.peek().ok_or("Expected alias after load")?.clone();
|
|
113
|
+
if alias_token.kind != TokenKind::Identifier {
|
|
114
|
+
return Err(format!("Expected Identifier, found {:?}", alias_token.kind));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
parser.next();
|
|
118
|
+
|
|
119
|
+
let statement = Statement {
|
|
120
|
+
kind: StatementKind::Load {
|
|
121
|
+
source: source_token.lexeme.clone(),
|
|
122
|
+
alias: alias_token.lexeme.clone(),
|
|
123
|
+
},
|
|
124
|
+
value: VariableValue::Text(alias_token.lexeme.clone()),
|
|
125
|
+
indent: token.indent,
|
|
126
|
+
line: token.line,
|
|
127
|
+
column: token.column,
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
return Ok(statement);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
_ => {
|
|
134
|
+
return Err(
|
|
135
|
+
format!(
|
|
136
|
+
"Expected 'export', 'import' or 'load', found '{}'",
|
|
137
|
+
identifier_token.lexeme
|
|
138
|
+
)
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
use crate::core::types::{
|
|
2
|
+
parser::Parser,
|
|
3
|
+
statement::{ Statement, StatementKind },
|
|
4
|
+
store::GlobalStore,
|
|
5
|
+
token::TokenKind,
|
|
6
|
+
variable::VariableValue,
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
pub fn parse_bank(
|
|
10
|
+
parser: &mut Parser,
|
|
11
|
+
global_store: &mut GlobalStore
|
|
12
|
+
) -> Result<Statement, String> {
|
|
13
|
+
let token = parser.peek().ok_or("Unexpected EOF")?.clone();
|
|
14
|
+
|
|
15
|
+
let mut bank_name = String::new();
|
|
16
|
+
|
|
17
|
+
if parser.next().map(|t| t.kind.clone()) != Some(TokenKind::Bank) {
|
|
18
|
+
return Err("Expected 'bank' keyword".to_string());
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if let Some(token) = parser.next() {
|
|
22
|
+
if token.kind == TokenKind::Identifier {
|
|
23
|
+
bank_name = token.lexeme.clone();
|
|
24
|
+
} else if token.kind == TokenKind::String {
|
|
25
|
+
bank_name = token.lexeme.trim_matches('"').to_string();
|
|
26
|
+
} else if token.kind == TokenKind::Number {
|
|
27
|
+
bank_name = token.lexeme.clone();
|
|
28
|
+
} else {
|
|
29
|
+
return Err(format!("Expected bank name, found {:?}", token.kind));
|
|
30
|
+
}
|
|
31
|
+
} else {
|
|
32
|
+
return Err("Expected bank name after 'bank' keyword".to_string());
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
Ok(Statement {
|
|
36
|
+
kind: StatementKind::Bank,
|
|
37
|
+
value: VariableValue::Text(bank_name.clone()),
|
|
38
|
+
indent: token.indent,
|
|
39
|
+
line: token.line,
|
|
40
|
+
column: token.column,
|
|
41
|
+
})
|
|
42
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
use std::{ collections::HashMap, hash::Hash };
|
|
2
|
+
|
|
3
|
+
use crate::core::types::{
|
|
4
|
+
statement::{ Statement, StatementKind },
|
|
5
|
+
token::{ Token, TokenDuration, TokenKind, TokenParamValue },
|
|
6
|
+
variable::{ Variable, VariableValue },
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
pub fn parse_dot(
|
|
10
|
+
parser: &mut crate::core::parser::Parser,
|
|
11
|
+
global_store: &mut crate::core::types::store::GlobalStore
|
|
12
|
+
) -> Result<crate::core::types::statement::Statement, String> {
|
|
13
|
+
let token = parser.peek().ok_or("Unexpected EOF")?.clone();
|
|
14
|
+
let mut trigger_value: String = String::from("Unknown Trigger");
|
|
15
|
+
|
|
16
|
+
if token.kind != crate::core::types::token::TokenKind::Dot {
|
|
17
|
+
return Err(format!("Expected Dot, found {:?}", token.kind));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
parser.next();
|
|
21
|
+
|
|
22
|
+
let next_token = parser.peek().ok_or("Expected identifier after dot")?.clone();
|
|
23
|
+
if next_token.kind != crate::core::types::token::TokenKind::Identifier {
|
|
24
|
+
return Err(format!("Expected Identifier after Dot, found {:?}", next_token.kind));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
parser.next();
|
|
28
|
+
|
|
29
|
+
let duration_token = parser.peek().ok_or("Expected duration after identifier")?.clone();
|
|
30
|
+
let mut duration = TokenDuration::Unknown;
|
|
31
|
+
|
|
32
|
+
match duration_token.lexeme.as_str() {
|
|
33
|
+
"auto" => {
|
|
34
|
+
duration = TokenDuration::Auto;
|
|
35
|
+
}
|
|
36
|
+
"infinite" => {
|
|
37
|
+
duration = TokenDuration::Infinite;
|
|
38
|
+
}
|
|
39
|
+
_ => {
|
|
40
|
+
if let Ok(num) = duration_token.lexeme.parse::<f32>() {
|
|
41
|
+
duration = TokenDuration::Number(num);
|
|
42
|
+
} else if let Ok(boolean) = duration_token.lexeme.parse::<bool>() {
|
|
43
|
+
duration = TokenDuration::Unknown;
|
|
44
|
+
} else if duration_token.kind == TokenKind::Identifier {
|
|
45
|
+
duration = TokenDuration::Identifier(duration_token.lexeme.clone());
|
|
46
|
+
} else {
|
|
47
|
+
return Err(format!("Invalid duration format: {}", duration_token.lexeme));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
parser.next();
|
|
53
|
+
|
|
54
|
+
let dot_params: Vec<Token> = parser.collect_until(|t| {
|
|
55
|
+
t.kind == TokenKind::Newline
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
let mut params_value: VariableValue = VariableValue::Null;
|
|
59
|
+
|
|
60
|
+
for param in dot_params {
|
|
61
|
+
let token_value = match param.kind {
|
|
62
|
+
TokenKind::String => VariableValue::Text(param.lexeme),
|
|
63
|
+
TokenKind::Number => VariableValue::Number(param.lexeme.parse().unwrap_or(0.0)),
|
|
64
|
+
TokenKind::Boolean => VariableValue::Boolean(param.lexeme.parse().unwrap_or(false)),
|
|
65
|
+
TokenKind::Map => {
|
|
66
|
+
let mut map: HashMap<String, TokenParamValue> = HashMap::new();
|
|
67
|
+
let entries: Vec<&str> = param.lexeme.split(',').collect();
|
|
68
|
+
for entry in entries {
|
|
69
|
+
let parts: Vec<&str> = entry.split(':').collect();
|
|
70
|
+
if parts.len() == 2 {
|
|
71
|
+
let key = parts[0].trim().to_string();
|
|
72
|
+
let value = match parts[1].trim() {
|
|
73
|
+
"true" => TokenParamValue::Boolean(true),
|
|
74
|
+
"false" => TokenParamValue::Boolean(false),
|
|
75
|
+
_ => TokenParamValue::String(parts[1].trim().to_string()),
|
|
76
|
+
};
|
|
77
|
+
map.insert(key, value);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
VariableValue::Map(map)
|
|
81
|
+
}
|
|
82
|
+
TokenKind::Identifier => {
|
|
83
|
+
VariableValue::Text(param.lexeme.clone())
|
|
84
|
+
}
|
|
85
|
+
TokenKind::Unknown => {
|
|
86
|
+
Err(format!("Unsupported token type in dot parameters: {:?}", param.kind))?;
|
|
87
|
+
VariableValue::Null
|
|
88
|
+
},
|
|
89
|
+
_ => {
|
|
90
|
+
Err(format!("Unsupported token type in dot parameters: {:?}", param.kind))?;
|
|
91
|
+
VariableValue::Unknown
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
params_value = token_value;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
Ok(Statement {
|
|
98
|
+
kind: StatementKind::Trigger {
|
|
99
|
+
entity: next_token.lexeme.clone(),
|
|
100
|
+
duration: duration.clone(),
|
|
101
|
+
},
|
|
102
|
+
value: params_value,
|
|
103
|
+
indent: token.indent,
|
|
104
|
+
line: token.line,
|
|
105
|
+
column: token.column,
|
|
106
|
+
})
|
|
107
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
use crate::core::{
|
|
2
|
+
parser::{ bank::parse_bank, variable::parse_let_statement, Parser },
|
|
3
|
+
types::{
|
|
4
|
+
statement::{ Statement, StatementKind },
|
|
5
|
+
store::GlobalStore,
|
|
6
|
+
token::{ Token, TokenKind },
|
|
7
|
+
variable::VariableValue,
|
|
8
|
+
},
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
pub fn parse_identifier(
|
|
12
|
+
parser: &mut Parser,
|
|
13
|
+
global_store: &mut GlobalStore
|
|
14
|
+
) -> Result<Statement, String> {
|
|
15
|
+
let token = parser.peek().ok_or("Unexpected EOF")?.clone();
|
|
16
|
+
|
|
17
|
+
if token.kind != TokenKind::Identifier {
|
|
18
|
+
return Err(format!("Expected Identifier, found {:?}", token.kind));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
match token.lexeme.as_str() {
|
|
22
|
+
"let" => {
|
|
23
|
+
parser.next();
|
|
24
|
+
return parse_let_statement(parser);
|
|
25
|
+
}
|
|
26
|
+
"bank" => {
|
|
27
|
+
parser.next();
|
|
28
|
+
return parse_bank(parser, global_store);
|
|
29
|
+
}
|
|
30
|
+
_ => {
|
|
31
|
+
parser.next();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let statment_value = match token.kind {
|
|
36
|
+
TokenKind::Identifier => {
|
|
37
|
+
let var_name = &token.lexeme;
|
|
38
|
+
let current_module = global_store.modules
|
|
39
|
+
.get(&parser.current_module);
|
|
40
|
+
let mut variable_value = VariableValue::Unknown;
|
|
41
|
+
|
|
42
|
+
if current_module.is_none() {
|
|
43
|
+
return Err(format!("Module '{}' not found", parser.current_module));
|
|
44
|
+
} else {
|
|
45
|
+
variable_value = current_module.unwrap()
|
|
46
|
+
.variable_table
|
|
47
|
+
.variables
|
|
48
|
+
.get(var_name)
|
|
49
|
+
.cloned()
|
|
50
|
+
.unwrap_or(VariableValue::Unknown);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
println!("Trying to get variable '{}' in module '{}'", var_name, parser.current_module);
|
|
54
|
+
|
|
55
|
+
variable_value
|
|
56
|
+
}
|
|
57
|
+
TokenKind::Number => VariableValue::Number(token.lexeme.parse().unwrap_or(0.0)),
|
|
58
|
+
TokenKind::String => {
|
|
59
|
+
let var_name = &token.lexeme;
|
|
60
|
+
let current_module = global_store.modules
|
|
61
|
+
.get(&parser.current_module);
|
|
62
|
+
let mut variable_value = VariableValue::Unknown;
|
|
63
|
+
|
|
64
|
+
if current_module.is_none() {
|
|
65
|
+
return Err(format!("Module '{}' not found", parser.current_module));
|
|
66
|
+
} else {
|
|
67
|
+
variable_value = current_module.unwrap()
|
|
68
|
+
.variable_table
|
|
69
|
+
.variables
|
|
70
|
+
.get(var_name)
|
|
71
|
+
.cloned()
|
|
72
|
+
.unwrap_or(VariableValue::Unknown);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
println!("Trying to get variable '{}' in module '{}'", var_name, parser.current_module);
|
|
76
|
+
|
|
77
|
+
variable_value
|
|
78
|
+
}
|
|
79
|
+
_ => VariableValue::Unknown,
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
println!("Trying get variable : {:?}", global_store.modules);
|
|
83
|
+
|
|
84
|
+
Ok(Statement {
|
|
85
|
+
kind: StatementKind::Unknown,
|
|
86
|
+
value: statment_value,
|
|
87
|
+
indent: token.indent,
|
|
88
|
+
line: token.line,
|
|
89
|
+
column: token.column,
|
|
90
|
+
})
|
|
91
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
use std::{ collections::HashMap, iter };
|
|
2
|
+
|
|
3
|
+
use crate::core::types::{
|
|
4
|
+
statement::{ Statement, StatementIterator, StatementKind },
|
|
5
|
+
token::{ Token, TokenDuration, TokenKind, TokenParamValue },
|
|
6
|
+
variable::VariableValue,
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
pub fn parse_loop(
|
|
10
|
+
parser: &mut crate::core::parser::Parser,
|
|
11
|
+
global_store: &mut crate::core::types::store::GlobalStore
|
|
12
|
+
) -> Result<crate::core::types::statement::Statement, String> {
|
|
13
|
+
let token = parser.peek().ok_or("Unexpected EOF")?.clone();
|
|
14
|
+
|
|
15
|
+
parser.next();
|
|
16
|
+
|
|
17
|
+
let mut iterator = StatementIterator::Unknown;
|
|
18
|
+
|
|
19
|
+
let iterable_tokens: Vec<Token> = parser.collect_until(|t| { t.kind == TokenKind::Colon });
|
|
20
|
+
|
|
21
|
+
iterable_tokens.iter().for_each(|t| {
|
|
22
|
+
match t.kind {
|
|
23
|
+
TokenKind::Identifier => {
|
|
24
|
+
iterator = StatementIterator::Identifier(t.lexeme.clone());
|
|
25
|
+
}
|
|
26
|
+
TokenKind::Number => {
|
|
27
|
+
if let Ok(num) = t.lexeme.parse::<f32>() {
|
|
28
|
+
iterator = StatementIterator::Number(num);
|
|
29
|
+
} else {
|
|
30
|
+
eprintln!("⚠️ Invalid number in loop iterator: {}", t.lexeme);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
TokenKind::Array => {
|
|
34
|
+
println!("🔍 Parsing array in loop iterator: {:?}", t.lexeme);
|
|
35
|
+
iterator = StatementIterator::Array(vec![]);
|
|
36
|
+
}
|
|
37
|
+
TokenKind::Map => {
|
|
38
|
+
println!("🔍 Parsing map in loop iterator: {:?}", t.lexeme);
|
|
39
|
+
iterator = StatementIterator::Map(HashMap::new());
|
|
40
|
+
}
|
|
41
|
+
_ => {
|
|
42
|
+
eprintln!("⚠️ Unsupported token type in loop iterator: {:?}", t.kind);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
parser.next();
|
|
48
|
+
|
|
49
|
+
let loop_body_tokens: Vec<Token> = parser.collect_until(|t| { t.kind == TokenKind::Dedent });
|
|
50
|
+
|
|
51
|
+
let loop_statement = Statement {
|
|
52
|
+
kind: StatementKind::Loop {
|
|
53
|
+
iterator,
|
|
54
|
+
},
|
|
55
|
+
value: VariableValue::Array(loop_body_tokens),
|
|
56
|
+
line: token.line,
|
|
57
|
+
column: token.column,
|
|
58
|
+
indent: token.indent,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
Ok(loop_statement)
|
|
62
|
+
}
|
|
@@ -0,0 +1,201 @@
|
|
|
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;
|
|
8
|
+
|
|
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
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
use crate::core::types::{
|
|
2
|
+
parser::Parser,
|
|
3
|
+
statement::{ Statement, StatementKind },
|
|
4
|
+
store::GlobalStore,
|
|
5
|
+
token::TokenKind,
|
|
6
|
+
variable::VariableValue,
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
pub fn parse_tempo(
|
|
10
|
+
parser: &mut Parser,
|
|
11
|
+
global_store: &mut GlobalStore
|
|
12
|
+
) -> Result<Statement, String> {
|
|
13
|
+
let token = parser.peek().ok_or("Unexpected EOF")?.clone();
|
|
14
|
+
|
|
15
|
+
parser.next();
|
|
16
|
+
|
|
17
|
+
if let Some(token) = parser.next() {
|
|
18
|
+
|
|
19
|
+
if token.kind == TokenKind::Number {
|
|
20
|
+
let value = token.lexeme.parse::<f32>().map_err(|_| "Invalid tempo value".to_string())?;
|
|
21
|
+
return Ok(Statement {
|
|
22
|
+
kind: StatementKind::Tempo,
|
|
23
|
+
value: VariableValue::Number(value as f32),
|
|
24
|
+
indent: token.indent,
|
|
25
|
+
line: token.line,
|
|
26
|
+
column: token.column,
|
|
27
|
+
});
|
|
28
|
+
} else if token.kind == TokenKind::Identifier {
|
|
29
|
+
let value = token.lexeme.clone();
|
|
30
|
+
|
|
31
|
+
return Ok(Statement {
|
|
32
|
+
kind: StatementKind::Tempo,
|
|
33
|
+
value: VariableValue::Text(value),
|
|
34
|
+
indent: token.indent,
|
|
35
|
+
line: token.line,
|
|
36
|
+
column: token.column,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
Err(format!("Expected a number after tempo keyword, found {}", token.lexeme))
|
|
42
|
+
}
|