@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
|
@@ -1,70 +1,51 @@
|
|
|
1
1
|
use crate::core::{
|
|
2
|
-
lexer::
|
|
3
|
-
parser::
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
lexer::token::Token,
|
|
3
|
+
parser::statement::Statement,
|
|
4
|
+
store::{
|
|
5
|
+
export::ExportTable,
|
|
6
|
+
global::GlobalStore,
|
|
7
|
+
import::ImportTable,
|
|
8
|
+
variable::VariableTable,
|
|
7
9
|
},
|
|
8
|
-
types::{ module::Module, parser::Parser, store::{ ExportTable, GlobalStore, ImportTable } },
|
|
9
10
|
};
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
#[derive(Debug, Clone)]
|
|
13
|
+
pub struct Module {
|
|
14
|
+
pub path: String,
|
|
15
|
+
pub resolved: bool,
|
|
16
|
+
pub tokens: Vec<Token>,
|
|
17
|
+
pub statements: Vec<Statement>,
|
|
18
|
+
pub variable_table: VariableTable,
|
|
19
|
+
pub export_table: ExportTable,
|
|
20
|
+
pub import_table: ImportTable,
|
|
21
|
+
}
|
|
14
22
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
23
|
+
impl Module {
|
|
24
|
+
pub fn new(path: &str) -> Self {
|
|
25
|
+
Module {
|
|
26
|
+
path: path.to_string(),
|
|
27
|
+
tokens: Vec::new(),
|
|
28
|
+
statements: Vec::new(),
|
|
29
|
+
variable_table: VariableTable::new(),
|
|
30
|
+
export_table: ExportTable::new(),
|
|
31
|
+
import_table: ImportTable::new(),
|
|
32
|
+
resolved: false,
|
|
18
33
|
}
|
|
19
34
|
}
|
|
20
35
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
let imports = resolve_imports(module, &mut global_store);
|
|
24
|
-
module.import_table = imports.clone();
|
|
25
|
-
|
|
26
|
-
let global_store_module = global_store.modules.get(&file.clone().to_string());
|
|
27
|
-
if let Some(global_store_module_found) = global_store_module {
|
|
28
|
-
global_store.insert_module(file.to_string(), module.clone());
|
|
29
|
-
} else {
|
|
30
|
-
eprintln!("❌ Module {} not found in global store after import resolution", file);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
36
|
+
pub fn is_resolved(&self) -> bool {
|
|
37
|
+
self.resolved
|
|
33
38
|
}
|
|
34
39
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
pub fn load_module_into_global_store(
|
|
39
|
-
path: &str,
|
|
40
|
-
global_store: &mut GlobalStore
|
|
41
|
-
) -> Result<(), String> {
|
|
42
|
-
if global_store.modules.contains_key(path) {
|
|
43
|
-
return Ok(());
|
|
40
|
+
pub fn set_resolved(&mut self, resolved: bool) {
|
|
41
|
+
self.resolved = resolved;
|
|
44
42
|
}
|
|
45
43
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
let mut parser = Parser::new(tokens.clone());
|
|
51
|
-
|
|
52
|
-
parser.current_module = path.to_string();
|
|
53
|
-
|
|
54
|
-
let raw_statements = parse_without_resolving(tokens.clone(), &mut parser, global_store);
|
|
55
|
-
|
|
56
|
-
let export_table = resolve_exports(&raw_statements, &mut parser);
|
|
57
|
-
|
|
58
|
-
let mut module = Module {
|
|
59
|
-
path: path.to_string(),
|
|
60
|
-
tokens: tokens.clone(),
|
|
61
|
-
statements: raw_statements,
|
|
62
|
-
variable_table: parser.variable_table.clone(),
|
|
63
|
-
export_table: export_table.clone(),
|
|
64
|
-
import_table: parser.import_table.clone(),
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
global_store.insert_module(path.to_string(), module.clone());
|
|
44
|
+
pub fn add_token(&mut self, token: Token) {
|
|
45
|
+
self.tokens.push(token);
|
|
46
|
+
}
|
|
68
47
|
|
|
69
|
-
|
|
48
|
+
pub fn add_statement(&mut self, statement: Statement) {
|
|
49
|
+
self.statements.push(statement);
|
|
50
|
+
}
|
|
70
51
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
use crate::core::{
|
|
2
|
+
parser::{ statement::StatementKind, Parser },
|
|
3
|
+
preprocessor::loader::ModuleLoader,
|
|
4
|
+
shared::value::Value,
|
|
5
|
+
store::global::GlobalStore,
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
pub fn process_modules(module_loader: &ModuleLoader, global_store: &mut GlobalStore) {
|
|
9
|
+
for module in global_store.modules.values_mut() {
|
|
10
|
+
for stmt in &module.statements {
|
|
11
|
+
match &stmt.kind {
|
|
12
|
+
StatementKind::Let { name } => {
|
|
13
|
+
module.variable_table.variables.insert(name.clone(), stmt.value.clone());
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
StatementKind::Load { source, alias } => {
|
|
17
|
+
module.variable_table.variables.insert(
|
|
18
|
+
alias.clone(),
|
|
19
|
+
Value::Sample(source.clone())
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
StatementKind::Export { names, source } => {
|
|
24
|
+
for name in names {
|
|
25
|
+
if let Some(val) = module.variable_table.get(name) {
|
|
26
|
+
module.export_table.add_export(name.clone(), val.clone());
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
StatementKind::Import { names, source } => {
|
|
32
|
+
for name in names {
|
|
33
|
+
module.import_table.add_import(name.clone(), Value::String(source.clone()));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
_ => {}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
use std::collections::HashMap;
|
|
2
|
+
|
|
3
|
+
use crate::{
|
|
4
|
+
core::{
|
|
5
|
+
parser::statement::{ self, Statement, StatementKind },
|
|
6
|
+
preprocessor::loader::ModuleLoader,
|
|
7
|
+
shared::{ duration::Duration, value::Value },
|
|
8
|
+
store::global::GlobalStore,
|
|
9
|
+
utils::validation::{ is_valid_entity, is_valid_identifier },
|
|
10
|
+
},
|
|
11
|
+
utils::logger::Logger,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
pub fn resolve_all_modules(module_loader: &ModuleLoader, global_store: &mut GlobalStore) {
|
|
15
|
+
for module in global_store.clone().modules.values_mut() {
|
|
16
|
+
resolve_imports(module_loader, global_store);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
pub fn resolve_imports(module_loader: &ModuleLoader, global_store: &mut GlobalStore) {
|
|
21
|
+
for (module_path, module) in global_store.clone().modules.iter_mut() {
|
|
22
|
+
for (name, source_path) in &module.import_table.imports {
|
|
23
|
+
match source_path {
|
|
24
|
+
Value::String(source_path) => {
|
|
25
|
+
if let Some(source_module) = global_store.modules.get(source_path) {
|
|
26
|
+
if let Some(value) = source_module.export_table.get_export(name) {
|
|
27
|
+
module.variable_table.set(name.clone(), value.clone());
|
|
28
|
+
} else {
|
|
29
|
+
println!(
|
|
30
|
+
"[warn] '{module_path}': '{name}' not found in exports of '{source_path}'"
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
} else {
|
|
34
|
+
println!(
|
|
35
|
+
"[warn] '{module_path}': cannot find source module '{source_path}'"
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
_ => {
|
|
40
|
+
println!(
|
|
41
|
+
"[warn] '{module_path}': expected string for import source, found {:?}",
|
|
42
|
+
source_path
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
pub fn resolve_and_flatten_all_modules(
|
|
51
|
+
global_store: &mut GlobalStore
|
|
52
|
+
) -> HashMap<String, Vec<Statement>> {
|
|
53
|
+
let logger = Logger::new();
|
|
54
|
+
|
|
55
|
+
// 1. Imports resolving
|
|
56
|
+
let global_store_clone = global_store.clone();
|
|
57
|
+
for (module_path, module) in global_store.modules.iter_mut() {
|
|
58
|
+
for (name, source_path) in &module.import_table.imports {
|
|
59
|
+
match source_path {
|
|
60
|
+
Value::String(source_path) => {
|
|
61
|
+
if let Some(source_module) = global_store_clone.modules.get(source_path) {
|
|
62
|
+
if let Some(value) = source_module.export_table.get_export(name) {
|
|
63
|
+
module.variable_table.set(name.clone(), value.clone());
|
|
64
|
+
} else {
|
|
65
|
+
let message = format!(
|
|
66
|
+
"'{name}' not found in exports of '{source_path}'"
|
|
67
|
+
);
|
|
68
|
+
logger.log_error_with_stacktrace(&message, module_path);
|
|
69
|
+
}
|
|
70
|
+
} else {
|
|
71
|
+
let message = format!("cannot find source module '{source_path}'");
|
|
72
|
+
logger.log_error_with_stacktrace(&message, module_path);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
_ => {
|
|
76
|
+
let message = format!(
|
|
77
|
+
"expected string for import source, found {:?}",
|
|
78
|
+
source_path
|
|
79
|
+
);
|
|
80
|
+
logger.log_error_with_stacktrace(&message, module_path);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// 2. Full statement resolution
|
|
87
|
+
let mut resolved_map = HashMap::new();
|
|
88
|
+
|
|
89
|
+
for (path, module) in &global_store.modules {
|
|
90
|
+
let mut resolved = Vec::new();
|
|
91
|
+
|
|
92
|
+
for mut stmt in module.statements.clone() {
|
|
93
|
+
match &mut stmt.kind {
|
|
94
|
+
StatementKind::Bank => {
|
|
95
|
+
if let Value::Identifier(ident) = &stmt.value {
|
|
96
|
+
if let Some(val) = module.variable_table.get(ident) {
|
|
97
|
+
stmt.value = val.clone();
|
|
98
|
+
} else {
|
|
99
|
+
let message = format!(
|
|
100
|
+
"Bank identifier '{ident}' not found in variable table"
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
logger.log_error_with_stacktrace(&message, &module.path);
|
|
104
|
+
|
|
105
|
+
stmt.kind = StatementKind::Error {
|
|
106
|
+
message: format!(
|
|
107
|
+
"Bank identifier '{ident}' not found in variable table"
|
|
108
|
+
),
|
|
109
|
+
};
|
|
110
|
+
stmt.value = Value::Null;
|
|
111
|
+
}
|
|
112
|
+
} else if let Value::String(_) = &stmt.value {
|
|
113
|
+
// Value is already a string, no need to modify
|
|
114
|
+
} else {
|
|
115
|
+
let message = format!(
|
|
116
|
+
"Expected a string or identifier for bank, found {:?}",
|
|
117
|
+
stmt.value
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
logger.log_error_with_stacktrace(&message, &module.path);
|
|
121
|
+
|
|
122
|
+
stmt.kind = StatementKind::Error {
|
|
123
|
+
message: "Expected a string or identifier for bank".to_string(),
|
|
124
|
+
};
|
|
125
|
+
stmt.value = Value::Null;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
StatementKind::Tempo => {
|
|
130
|
+
if let Value::Identifier(ident) = &stmt.value {
|
|
131
|
+
if let Some(val) = module.variable_table.get(ident) {
|
|
132
|
+
stmt.value = val.clone();
|
|
133
|
+
} else {
|
|
134
|
+
let message = format!(
|
|
135
|
+
"Tempo identifier '{ident}' not found in variable table"
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
logger.log_error_with_stacktrace(&message, &module.path);
|
|
139
|
+
|
|
140
|
+
stmt.kind = StatementKind::Error {
|
|
141
|
+
message: format!(
|
|
142
|
+
"Tempo identifier '{ident}' not found in variable table"
|
|
143
|
+
),
|
|
144
|
+
};
|
|
145
|
+
stmt.value = Value::Null;
|
|
146
|
+
}
|
|
147
|
+
} else if let Value::Number(_) = &stmt.value {
|
|
148
|
+
// Value is already a number, no need to modify
|
|
149
|
+
} else {
|
|
150
|
+
let message = format!(
|
|
151
|
+
"Expected a number or identifier for tempo, found {:?}",
|
|
152
|
+
stmt.value
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
logger.log_error_with_stacktrace(&message, &module.path);
|
|
156
|
+
|
|
157
|
+
stmt.kind = StatementKind::Error {
|
|
158
|
+
message: "Expected a number or identifier for tempo".to_string(),
|
|
159
|
+
};
|
|
160
|
+
stmt.value = Value::Null;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
StatementKind::Trigger { entity, duration } => {
|
|
165
|
+
if !is_valid_entity(entity, module, global_store) {
|
|
166
|
+
let message =
|
|
167
|
+
format!("Invalid entity '{}', expected a valid identifier", entity);
|
|
168
|
+
|
|
169
|
+
let stacktrace = format!("{}:{}:{}", module.path, stmt.line, stmt.column);
|
|
170
|
+
logger.log_error_with_stacktrace(&message, &stacktrace);
|
|
171
|
+
|
|
172
|
+
stmt.kind = StatementKind::Error {
|
|
173
|
+
message: format!("Invalid entity '{}'", entity),
|
|
174
|
+
};
|
|
175
|
+
stmt.value = Value::Null;
|
|
176
|
+
|
|
177
|
+
resolved.push(stmt);
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Duration resolution
|
|
182
|
+
if let Duration::Identifier(ident) = duration {
|
|
183
|
+
if let Some(val) = module.variable_table.get(ident) {
|
|
184
|
+
match val {
|
|
185
|
+
Value::Number(num) => {
|
|
186
|
+
*duration = Duration::Number(*num);
|
|
187
|
+
}
|
|
188
|
+
Value::String(s) => {
|
|
189
|
+
*duration = Duration::Identifier(s.clone());
|
|
190
|
+
}
|
|
191
|
+
Value::Identifier(id) if id == "auto" => {
|
|
192
|
+
*duration = Duration::Auto;
|
|
193
|
+
}
|
|
194
|
+
_ => {}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Associated value resolution
|
|
200
|
+
if let Value::Identifier(ident) = &stmt.value {
|
|
201
|
+
if let Some(val) = module.variable_table.get(ident) {
|
|
202
|
+
stmt.value = val.clone();
|
|
203
|
+
} else {
|
|
204
|
+
let stacktrace = format!(
|
|
205
|
+
"{}:{}:{}",
|
|
206
|
+
module.path,
|
|
207
|
+
stmt.line,
|
|
208
|
+
stmt.column
|
|
209
|
+
);
|
|
210
|
+
let message = format!(
|
|
211
|
+
"'{path}': value identifier '{ident}' not found in variable table"
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
logger.log_error_with_stacktrace(&message, &stacktrace);
|
|
215
|
+
|
|
216
|
+
stmt.kind = StatementKind::Error {
|
|
217
|
+
message: format!(
|
|
218
|
+
"Value identifier '{ident}' not found in variable table"
|
|
219
|
+
),
|
|
220
|
+
};
|
|
221
|
+
stmt.value = Value::Null;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
StatementKind::Let { .. } => {
|
|
227
|
+
if let Value::Identifier(ident) = &stmt.value {
|
|
228
|
+
if let Some(val) = module.variable_table.get(ident) {
|
|
229
|
+
stmt.value = val.clone();
|
|
230
|
+
} else {
|
|
231
|
+
if !is_valid_identifier(ident, module) {
|
|
232
|
+
let message = format!(
|
|
233
|
+
"'{path}': value identifier '{ident}' not found in variable table"
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
logger.log_error_with_stacktrace(&message, &module.path);
|
|
237
|
+
|
|
238
|
+
stmt.kind = StatementKind::Error {
|
|
239
|
+
message: format!(
|
|
240
|
+
"Value identifier '{ident}' not found in variable table"
|
|
241
|
+
),
|
|
242
|
+
};
|
|
243
|
+
stmt.value = Value::Null;
|
|
244
|
+
} else {
|
|
245
|
+
stmt.value = Value::Identifier(ident.clone());
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
StatementKind::Loop => {
|
|
252
|
+
if let Value::Map(value_map) = &stmt.value {
|
|
253
|
+
let iterator_value = match value_map.get("iterator") {
|
|
254
|
+
Some(Value::Identifier(ident)) => {
|
|
255
|
+
if let Some(val) = module.variable_table.get(ident) {
|
|
256
|
+
match val {
|
|
257
|
+
Value::Number(n) => Value::Number(*n),
|
|
258
|
+
_ => {
|
|
259
|
+
let message = format!(
|
|
260
|
+
"Loop iterator '{ident}' must resolve to a number"
|
|
261
|
+
);
|
|
262
|
+
let stacktrace = format!(
|
|
263
|
+
"{}:{}:{}",
|
|
264
|
+
module.path,
|
|
265
|
+
stmt.line,
|
|
266
|
+
stmt.column
|
|
267
|
+
);
|
|
268
|
+
logger.log_error_with_stacktrace(&message, &stacktrace);
|
|
269
|
+
|
|
270
|
+
stmt.kind = StatementKind::Error {
|
|
271
|
+
message,
|
|
272
|
+
};
|
|
273
|
+
Value::Null
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
} else {
|
|
277
|
+
let message = format!(
|
|
278
|
+
"'{path}': loop iterator '{ident}' not found in variable table"
|
|
279
|
+
);
|
|
280
|
+
let stacktrace = format!(
|
|
281
|
+
"{}:{}:{}",
|
|
282
|
+
module.path,
|
|
283
|
+
stmt.line,
|
|
284
|
+
stmt.column
|
|
285
|
+
);
|
|
286
|
+
logger.log_error_with_stacktrace(&message, &stacktrace);
|
|
287
|
+
|
|
288
|
+
stmt.kind = StatementKind::Error {
|
|
289
|
+
message: format!("Loop iterator '{ident}' not found"),
|
|
290
|
+
};
|
|
291
|
+
Value::Null
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
Some(Value::Number(n)) => Value::Number(*n),
|
|
296
|
+
|
|
297
|
+
Some(v) => {
|
|
298
|
+
let message = format!(
|
|
299
|
+
"Unexpected value for loop iterator: {:?}, expected number or identifier",
|
|
300
|
+
v
|
|
301
|
+
);
|
|
302
|
+
let stacktrace = format!(
|
|
303
|
+
"{}:{}:{}",
|
|
304
|
+
module.path,
|
|
305
|
+
stmt.line,
|
|
306
|
+
stmt.column
|
|
307
|
+
);
|
|
308
|
+
logger.log_error_with_stacktrace(&message, &stacktrace);
|
|
309
|
+
|
|
310
|
+
stmt.kind = StatementKind::Error {
|
|
311
|
+
message,
|
|
312
|
+
};
|
|
313
|
+
Value::Null
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
None => {
|
|
317
|
+
let message = format!(
|
|
318
|
+
"Missing 'iterator' key in loop statement map"
|
|
319
|
+
);
|
|
320
|
+
let stacktrace = format!(
|
|
321
|
+
"{}:{}:{}",
|
|
322
|
+
module.path,
|
|
323
|
+
stmt.line,
|
|
324
|
+
stmt.column
|
|
325
|
+
);
|
|
326
|
+
logger.log_error_with_stacktrace(&message, &stacktrace);
|
|
327
|
+
|
|
328
|
+
stmt.kind = StatementKind::Error {
|
|
329
|
+
message,
|
|
330
|
+
};
|
|
331
|
+
Value::Null
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
let body_value = value_map.get("body").cloned().unwrap_or(Value::Null);
|
|
336
|
+
|
|
337
|
+
let mut loop_map = std::collections::HashMap::new();
|
|
338
|
+
loop_map.insert("iterator".to_string(), iterator_value);
|
|
339
|
+
loop_map.insert("body".to_string(), body_value);
|
|
340
|
+
|
|
341
|
+
stmt.value = Value::Map(loop_map);
|
|
342
|
+
} else {
|
|
343
|
+
let message = format!(
|
|
344
|
+
"'{path}': expected a map for loop value, found {:?}",
|
|
345
|
+
stmt.value
|
|
346
|
+
);
|
|
347
|
+
let stacktrace = format!("{}:{}:{}", module.path, stmt.line, stmt.column);
|
|
348
|
+
|
|
349
|
+
logger.log_error_with_stacktrace(&message, &stacktrace);
|
|
350
|
+
|
|
351
|
+
stmt.kind = StatementKind::Error {
|
|
352
|
+
message: "Expected a map for loop value".to_string(),
|
|
353
|
+
};
|
|
354
|
+
stmt.value = Value::Null;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
StatementKind::Import { names, source } => {}
|
|
359
|
+
|
|
360
|
+
StatementKind::Export { names, source } => {}
|
|
361
|
+
|
|
362
|
+
_ => {}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
resolved.push(stmt);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
resolved_map.insert(path.clone(), resolved);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
resolved_map
|
|
372
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
use std::collections::HashMap;
|
|
2
|
+
use serde::{ Deserialize, Serialize };
|
|
3
|
+
|
|
4
|
+
use crate::core::parser::statement::Statement;
|
|
5
|
+
|
|
6
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
|
7
|
+
pub enum Value {
|
|
8
|
+
Boolean(bool),
|
|
9
|
+
Number(f32),
|
|
10
|
+
Identifier(String),
|
|
11
|
+
String(String),
|
|
12
|
+
Array(Vec<Value>),
|
|
13
|
+
Map(HashMap<String, Value>),
|
|
14
|
+
Block(Vec<Statement>),
|
|
15
|
+
Sample(String),
|
|
16
|
+
Unknown,
|
|
17
|
+
Null,
|
|
18
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
use std::collections::HashMap;
|
|
2
|
+
|
|
3
|
+
use crate::core::shared::value::Value;
|
|
4
|
+
|
|
5
|
+
#[derive(Debug, Default, Clone, PartialEq)]
|
|
6
|
+
pub struct ExportTable {
|
|
7
|
+
pub exports: HashMap<String, Value>,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
impl ExportTable {
|
|
11
|
+
pub fn new() -> Self {
|
|
12
|
+
ExportTable {
|
|
13
|
+
exports: HashMap::new(),
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
pub fn add_export(&mut self, name: String, value: Value) {
|
|
18
|
+
self.exports.insert(name, value);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
pub fn get_export(&self, name: &str) -> Option<&Value> {
|
|
22
|
+
self.exports.get(name)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
pub fn remove_export(&mut self, name: &str) -> Option<Value> {
|
|
26
|
+
self.exports.remove(name)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
use std::collections::HashMap;
|
|
2
|
+
use crate::core::preprocessor::module::Module;
|
|
3
|
+
|
|
4
|
+
#[derive(Debug, Default, Clone)]
|
|
5
|
+
pub struct GlobalStore {
|
|
6
|
+
pub modules: HashMap<String, Module>,
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
impl GlobalStore {
|
|
10
|
+
pub fn new() -> Self {
|
|
11
|
+
GlobalStore {
|
|
12
|
+
modules: HashMap::new(),
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
pub fn resolve_all_imports(&mut self) {
|
|
17
|
+
for module in self.modules.values_mut() {
|
|
18
|
+
for (name, source_path) in &module.import_table.imports {
|
|
19
|
+
println!("Resolving import: {} from {:?}", name, source_path);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
pub fn insert_module(&mut self, path: String, module: Module) {
|
|
25
|
+
self.modules.insert(path, module);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
pub fn modules_mut(&mut self) -> &mut HashMap<String, Module> {
|
|
29
|
+
&mut self.modules
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
pub fn get_module(&self, path: &str) -> Option<&Module> {
|
|
33
|
+
self.modules.get(path)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
pub fn remove_module(&mut self, path: &str) -> Option<Module> {
|
|
37
|
+
self.modules.remove(path)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
use std::collections::HashMap;
|
|
2
|
+
|
|
3
|
+
use crate::core::shared::value::Value;
|
|
4
|
+
|
|
5
|
+
#[derive(Debug, Default, Clone, PartialEq)]
|
|
6
|
+
pub struct ImportTable {
|
|
7
|
+
pub imports: HashMap<String, Value>,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
impl ImportTable {
|
|
11
|
+
pub fn new() -> Self {
|
|
12
|
+
ImportTable {
|
|
13
|
+
imports: HashMap::new(),
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
pub fn add_import(&mut self, name: String, value: Value) {
|
|
18
|
+
self.imports.insert(name, value);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
pub fn get_import(&self, name: &str) -> Option<&Value> {
|
|
22
|
+
self.imports.get(name)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
pub fn remove_import(&mut self, name: &str) -> Option<Value> {
|
|
26
|
+
self.imports.remove(name)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
use std::collections::HashMap;
|
|
2
|
+
|
|
3
|
+
use crate::core::shared::value::Value;
|
|
4
|
+
|
|
5
|
+
#[derive(Debug, Default, Clone, PartialEq)]
|
|
6
|
+
pub struct VariableTable {
|
|
7
|
+
pub variables: HashMap<String, Value>,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
impl VariableTable {
|
|
11
|
+
pub fn new() -> Self {
|
|
12
|
+
VariableTable {
|
|
13
|
+
variables: HashMap::new(),
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
pub fn set(&mut self, name: String, value: Value) {
|
|
18
|
+
self.variables.insert(name, value);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
pub fn get(&self, name: &str) -> Option<&Value> {
|
|
22
|
+
self.variables.get(name)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
pub fn remove(&mut self, name: &str) -> Option<Value> {
|
|
26
|
+
self.variables.remove(name)
|
|
27
|
+
}
|
|
28
|
+
}
|