@devaloop/devalang 0.0.1-alpha.2 → 0.0.1-alpha.4
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 +1 -1
- package/Cargo.toml +46 -46
- package/README.md +48 -30
- package/docs/CHANGELOG.md +28 -6
- package/docs/COMMANDS.md +31 -0
- package/docs/CONFIG.md +6 -4
- package/docs/ROADMAP.md +5 -1
- package/docs/TODO.md +10 -35
- package/examples/exported.deva +1 -1
- package/examples/index.deva +8 -1
- package/examples/samples/hat-808.wav +0 -0
- package/out-tsc/bin/devalang.exe +0 -0
- package/package.json +41 -42
- package/project-version.json +5 -5
- package/rust/audio/engine.rs +130 -0
- package/rust/audio/interpreter.rs +143 -0
- package/rust/audio/loader.rs +46 -0
- package/rust/audio/mod.rs +5 -1
- package/rust/audio/player.rs +54 -0
- package/rust/audio/render.rs +57 -0
- package/rust/cli/build.rs +73 -45
- package/rust/cli/check.rs +47 -111
- package/rust/cli/init.rs +1 -1
- package/rust/cli/mod.rs +203 -2
- package/rust/cli/play.rs +191 -0
- package/rust/{utils/config.rs → config/loader.rs} +3 -2
- package/rust/config/mod.rs +16 -0
- package/rust/core/builder/mod.rs +69 -27
- package/rust/core/debugger/lexer.rs +27 -0
- package/rust/core/debugger/mod.rs +12 -49
- package/rust/core/debugger/preprocessor.rs +27 -0
- package/rust/core/error/mod.rs +60 -0
- package/rust/core/lexer/{at.rs → handler/at.rs} +1 -1
- package/rust/core/lexer/{brace.rs → handler/brace.rs} +1 -1
- package/rust/core/lexer/{colon.rs → handler/colon.rs} +1 -1
- package/rust/core/lexer/{comment.rs → handler/comment.rs} +3 -3
- package/rust/core/lexer/{dot.rs → handler/dot.rs} +1 -1
- package/rust/core/lexer/{equal.rs → handler/equal.rs} +1 -1
- package/rust/core/lexer/{identifier.rs → handler/identifier.rs} +1 -1
- package/rust/core/lexer/{indent.rs → handler/indent.rs} +10 -5
- package/rust/core/lexer/handler/mod.rs +238 -0
- package/rust/core/lexer/{newline.rs → handler/newline.rs} +6 -10
- package/rust/core/lexer/{number.rs → handler/number.rs} +1 -1
- package/rust/core/lexer/handler/string.rs +66 -0
- package/rust/core/lexer/mod.rs +25 -14
- 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 +116 -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/bank.rs +38 -51
- package/rust/core/preprocessor/resolver/loop_.rs +126 -65
- package/rust/core/preprocessor/resolver/mod.rs +119 -80
- package/rust/core/preprocessor/resolver/tempo.rs +40 -61
- package/rust/core/preprocessor/resolver/trigger.rs +93 -155
- 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 +22 -18
- package/rust/utils/logger.rs +69 -34
- package/rust/utils/mod.rs +3 -5
- package/rust/utils/watcher.rs +10 -2
- package/templates/minimal/.devalang +1 -1
- package/templates/welcome/.devalang +1 -1
- package/rust/core/lexer/bracket.rs +0 -41
- package/rust/core/lexer/driver.rs +0 -286
- package/rust/core/lexer/quote.rs +0 -61
- package/rust/core/parser/at.rs +0 -142
- package/rust/core/parser/bank.rs +0 -42
- package/rust/core/parser/dot.rs +0 -137
- 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/types/cli.rs +0 -182
- package/rust/core/types/config.rs +0 -15
- package/rust/core/types/mod.rs +0 -8
- 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,113 +1,152 @@
|
|
|
1
|
-
pub mod
|
|
1
|
+
pub mod trigger;
|
|
2
2
|
pub mod loop_;
|
|
3
|
+
pub mod bank;
|
|
3
4
|
pub mod tempo;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
store::
|
|
20
|
-
|
|
5
|
+
|
|
6
|
+
use std::collections::HashMap;
|
|
7
|
+
use crate::{
|
|
8
|
+
core::{
|
|
9
|
+
parser::statement::{ self, Statement, StatementKind },
|
|
10
|
+
preprocessor::{
|
|
11
|
+
loader::ModuleLoader,
|
|
12
|
+
resolver::{
|
|
13
|
+
bank::resolve_bank,
|
|
14
|
+
loop_::resolve_loop,
|
|
15
|
+
tempo::resolve_tempo,
|
|
16
|
+
trigger::resolve_trigger,
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
shared::{ duration::Duration, value::Value },
|
|
20
|
+
store::global::GlobalStore,
|
|
21
|
+
utils::validation::{ is_valid_entity, is_valid_identifier },
|
|
21
22
|
},
|
|
23
|
+
utils::logger::Logger,
|
|
22
24
|
};
|
|
23
25
|
|
|
24
|
-
pub fn
|
|
25
|
-
|
|
26
|
+
pub fn resolve_all_modules(module_loader: &ModuleLoader, global_store: &mut GlobalStore) {
|
|
27
|
+
for module in global_store.clone().modules.values_mut() {
|
|
28
|
+
resolve_imports(module_loader, global_store);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
26
31
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if let Some(
|
|
33
|
-
|
|
32
|
+
pub fn resolve_imports(module_loader: &ModuleLoader, global_store: &mut GlobalStore) {
|
|
33
|
+
for (module_path, module) in global_store.clone().modules.iter_mut() {
|
|
34
|
+
for (name, source_path) in &module.import_table.imports {
|
|
35
|
+
match source_path {
|
|
36
|
+
Value::String(source_path) => {
|
|
37
|
+
if let Some(source_module) = global_store.modules.get(source_path) {
|
|
38
|
+
if let Some(value) = source_module.export_table.get_export(name) {
|
|
39
|
+
module.variable_table.set(name.clone(), value.clone());
|
|
40
|
+
} else {
|
|
41
|
+
println!(
|
|
42
|
+
"[warn] '{module_path}': '{name}' not found in exports of '{source_path}'"
|
|
43
|
+
);
|
|
44
|
+
}
|
|
34
45
|
} else {
|
|
35
|
-
|
|
46
|
+
println!(
|
|
47
|
+
"[warn] '{module_path}': cannot find source module '{source_path}'"
|
|
48
|
+
);
|
|
36
49
|
}
|
|
37
50
|
}
|
|
38
|
-
|
|
39
|
-
|
|
51
|
+
_ => {
|
|
52
|
+
println!(
|
|
53
|
+
"[warn] '{module_path}': expected string for import source, found {:?}",
|
|
54
|
+
source_path
|
|
55
|
+
);
|
|
56
|
+
}
|
|
40
57
|
}
|
|
41
58
|
}
|
|
42
59
|
}
|
|
43
|
-
|
|
44
|
-
export_table
|
|
45
60
|
}
|
|
46
61
|
|
|
47
|
-
pub fn
|
|
48
|
-
|
|
62
|
+
pub fn resolve_and_flatten_all_modules(
|
|
63
|
+
global_store: &mut GlobalStore
|
|
64
|
+
) -> HashMap<String, Vec<Statement>> {
|
|
65
|
+
let logger = Logger::new();
|
|
66
|
+
let snapshot = global_store.clone(); // pour éviter les emprunts mutables
|
|
49
67
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
68
|
+
// 1. Résolution des imports
|
|
69
|
+
for (module_path, module) in global_store.modules.iter_mut() {
|
|
70
|
+
for (name, source_path) in &module.import_table.imports {
|
|
71
|
+
if let Value::String(source_path_str) = source_path {
|
|
72
|
+
match snapshot.modules.get(source_path_str) {
|
|
73
|
+
Some(source_module) => {
|
|
74
|
+
if let Some(value) = source_module.export_table.get_export(name) {
|
|
75
|
+
module.variable_table.set(name.clone(), value.clone());
|
|
76
|
+
} else {
|
|
77
|
+
logger.log_error_with_stacktrace(
|
|
78
|
+
&format!("'{name}' not found in exports of '{source_path_str}'"),
|
|
79
|
+
module_path
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
None => {
|
|
84
|
+
logger.log_error_with_stacktrace(
|
|
85
|
+
&format!("Cannot find source module '{source_path_str}'"),
|
|
86
|
+
module_path
|
|
87
|
+
);
|
|
59
88
|
}
|
|
60
89
|
}
|
|
61
90
|
} else {
|
|
62
|
-
|
|
91
|
+
logger.log_error_with_stacktrace(
|
|
92
|
+
&format!("Expected string for import source, found {:?}", source_path),
|
|
93
|
+
module_path
|
|
94
|
+
);
|
|
63
95
|
}
|
|
64
96
|
}
|
|
65
97
|
}
|
|
66
98
|
|
|
67
|
-
|
|
68
|
-
|
|
99
|
+
// 2. Résolution des statements
|
|
100
|
+
let mut resolved_map = HashMap::new();
|
|
101
|
+
let store_snapshot = global_store.clone();
|
|
69
102
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
StatementKind::Loop { iterator } => {
|
|
73
|
-
resolve_loop_statement(stmt, iterator.clone(), module)
|
|
74
|
-
}
|
|
103
|
+
for (path, module) in &store_snapshot.modules {
|
|
104
|
+
let mut resolved = Vec::new();
|
|
75
105
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
106
|
+
for stmt in &module.statements {
|
|
107
|
+
let mut stmt = stmt.clone();
|
|
79
108
|
|
|
80
|
-
|
|
109
|
+
match &stmt.kind {
|
|
110
|
+
StatementKind::Trigger { entity, duration } => {
|
|
111
|
+
let resolved_stmt = resolve_trigger(
|
|
112
|
+
&stmt,
|
|
113
|
+
entity.as_str(),
|
|
114
|
+
&mut duration.clone(),
|
|
115
|
+
&module,
|
|
116
|
+
&path,
|
|
117
|
+
&store_snapshot
|
|
118
|
+
);
|
|
119
|
+
resolved.push(resolved_stmt);
|
|
120
|
+
}
|
|
81
121
|
|
|
82
|
-
|
|
122
|
+
StatementKind::Loop => {
|
|
123
|
+
let resolved_stmt = resolve_loop(&stmt, &module, &path, &store_snapshot);
|
|
124
|
+
resolved.push(resolved_stmt);
|
|
125
|
+
}
|
|
83
126
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
127
|
+
StatementKind::Bank => {
|
|
128
|
+
let resolved_stmt = resolve_bank(&stmt, &module, &path, &store_snapshot);
|
|
129
|
+
resolved.push(resolved_stmt);
|
|
130
|
+
}
|
|
87
131
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
indent: stmt.indent,
|
|
98
|
-
line: stmt.line,
|
|
99
|
-
column: stmt.column,
|
|
100
|
-
}
|
|
101
|
-
}
|
|
132
|
+
StatementKind::Tempo => {
|
|
133
|
+
let resolved_stmt = resolve_tempo(&stmt, &module, &path, &store_snapshot);
|
|
134
|
+
resolved.push(resolved_stmt);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
StatementKind::Import { .. } | StatementKind::Export { .. } => {
|
|
138
|
+
// Rien à faire
|
|
139
|
+
resolved.push(stmt.clone());
|
|
140
|
+
}
|
|
102
141
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
value: StatementResolvedValue::Unknown,
|
|
107
|
-
indent: stmt.indent,
|
|
108
|
-
line: stmt.line,
|
|
109
|
-
column: stmt.column,
|
|
142
|
+
_ => {
|
|
143
|
+
resolved.push(stmt);
|
|
144
|
+
}
|
|
110
145
|
}
|
|
111
146
|
}
|
|
147
|
+
|
|
148
|
+
resolved_map.insert(path.clone(), resolved);
|
|
112
149
|
}
|
|
150
|
+
|
|
151
|
+
resolved_map
|
|
113
152
|
}
|
|
@@ -1,70 +1,49 @@
|
|
|
1
|
-
use crate::
|
|
1
|
+
use crate::{
|
|
2
|
+
core::{
|
|
3
|
+
parser::statement::{ Statement, StatementKind },
|
|
4
|
+
preprocessor::module::Module,
|
|
5
|
+
shared::value::Value,
|
|
6
|
+
store::global::GlobalStore,
|
|
7
|
+
},
|
|
8
|
+
utils::logger::Logger,
|
|
9
|
+
};
|
|
2
10
|
|
|
3
|
-
pub fn
|
|
4
|
-
|
|
5
|
-
module: &Module
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
11
|
+
pub fn resolve_tempo(
|
|
12
|
+
stmt: &Statement,
|
|
13
|
+
module: &Module,
|
|
14
|
+
path: &str,
|
|
15
|
+
_global_store: &GlobalStore
|
|
16
|
+
) -> Statement {
|
|
17
|
+
let mut new_stmt = stmt.clone();
|
|
18
|
+
let logger = Logger::new();
|
|
19
|
+
|
|
20
|
+
match &stmt.value {
|
|
21
|
+
Value::Identifier(ident) => {
|
|
22
|
+
if let Some(val) = module.variable_table.get(ident) {
|
|
23
|
+
new_stmt.value = val.clone();
|
|
17
24
|
} else {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
column: tempo_statement.column,
|
|
25
|
-
}
|
|
25
|
+
let message = format!("Tempo identifier '{ident}' not found in variable table");
|
|
26
|
+
logger.log_error_with_stacktrace(&message, &module.path);
|
|
27
|
+
new_stmt.kind = StatementKind::Error {
|
|
28
|
+
message,
|
|
29
|
+
};
|
|
30
|
+
new_stmt.value = Value::Null;
|
|
26
31
|
}
|
|
27
32
|
}
|
|
28
|
-
VariableValue::Text(text) => {
|
|
29
|
-
if let Some(value) = module.variable_table.variables.get(text) {
|
|
30
|
-
let variable_value: StatementResolvedValue = match value {
|
|
31
|
-
VariableValue::Number(num) if *num > 0.0 => {
|
|
32
|
-
StatementResolvedValue::Number(*num)
|
|
33
|
-
}
|
|
34
|
-
VariableValue::Text(t) => StatementResolvedValue::String(t.clone()),
|
|
35
|
-
_ => {
|
|
36
|
-
eprintln!("⚠️ Unsupported variable type for Tempo: {:?}", value);
|
|
37
|
-
StatementResolvedValue::Unknown
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
33
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
value: variable_value,
|
|
44
|
-
indent: tempo_statement.indent,
|
|
45
|
-
line: tempo_statement.line,
|
|
46
|
-
column: tempo_statement.column,
|
|
47
|
-
}
|
|
48
|
-
} else {
|
|
49
|
-
eprintln!("⚠️ Tempo variable '{}' not found", text);
|
|
50
|
-
StatementResolved {
|
|
51
|
-
kind: StatementKind::Tempo,
|
|
52
|
-
value: StatementResolvedValue::Unknown,
|
|
53
|
-
indent: tempo_statement.indent,
|
|
54
|
-
line: tempo_statement.line,
|
|
55
|
-
column: tempo_statement.column,
|
|
56
|
-
}
|
|
57
|
-
}
|
|
34
|
+
Value::Number(_) => {
|
|
35
|
+
// Already resolved, no modification needed
|
|
58
36
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
37
|
+
|
|
38
|
+
other => {
|
|
39
|
+
let message = format!("Expected a number or identifier for tempo, found {:?}", other);
|
|
40
|
+
logger.log_error_with_stacktrace(&message, &module.path);
|
|
41
|
+
new_stmt.kind = StatementKind::Error {
|
|
42
|
+
message: "Expected a number or identifier for tempo".to_string(),
|
|
43
|
+
};
|
|
44
|
+
new_stmt.value = Value::Null;
|
|
68
45
|
}
|
|
69
46
|
}
|
|
47
|
+
|
|
48
|
+
new_stmt
|
|
70
49
|
}
|
|
@@ -1,176 +1,114 @@
|
|
|
1
1
|
use std::collections::HashMap;
|
|
2
2
|
|
|
3
|
-
use crate::
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
module::Module,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
use crate::{
|
|
4
|
+
core::{
|
|
5
|
+
parser::statement::{ Statement, StatementKind },
|
|
6
|
+
preprocessor::module::Module,
|
|
7
|
+
shared::{ duration::Duration, value::Value },
|
|
8
|
+
store::global::GlobalStore,
|
|
9
|
+
utils::validation::is_valid_entity,
|
|
10
10
|
},
|
|
11
|
+
utils::logger::Logger,
|
|
11
12
|
};
|
|
12
13
|
|
|
13
|
-
pub fn
|
|
14
|
+
pub fn resolve_trigger(
|
|
14
15
|
stmt: &Statement,
|
|
15
|
-
entity:
|
|
16
|
-
duration:
|
|
17
|
-
module: &Module
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
16
|
+
entity: &str,
|
|
17
|
+
duration: &mut Duration,
|
|
18
|
+
module: &Module,
|
|
19
|
+
path: &str,
|
|
20
|
+
global_store: &GlobalStore
|
|
21
|
+
) -> Statement {
|
|
22
|
+
let logger = Logger::new();
|
|
23
|
+
|
|
24
|
+
let mut final_duration = duration.clone();
|
|
25
|
+
let mut final_value = stmt.value.clone();
|
|
26
|
+
|
|
27
|
+
if !is_valid_entity(entity, module, global_store) {
|
|
28
|
+
let message = format!("Invalid entity '{}', expected a valid identifier", entity);
|
|
29
|
+
let stacktrace = format!("{}:{}:{}", module.path, stmt.line, stmt.column);
|
|
30
|
+
logger.log_error_with_stacktrace(&message, &stacktrace);
|
|
31
|
+
|
|
32
|
+
return Statement {
|
|
33
|
+
kind: stmt.kind.clone(),
|
|
34
|
+
value: Value::Null,
|
|
35
|
+
line: stmt.line,
|
|
36
|
+
column: stmt.column,
|
|
37
|
+
indent: stmt.indent,
|
|
38
|
+
};
|
|
25
39
|
}
|
|
26
40
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
let duration_variable_value = module.variable_table.variables.get(duration_raw_value);
|
|
36
|
-
let mut parsed_duration_value = TokenDuration::Unknown;
|
|
37
|
-
|
|
38
|
-
if duration_variable_value.is_some() {
|
|
39
|
-
parsed_duration_value = duration_variable_value
|
|
40
|
-
.as_ref()
|
|
41
|
-
.map_or(TokenDuration::Unknown, |value| {
|
|
42
|
-
match value {
|
|
43
|
-
VariableValue::Text(text) => TokenDuration::Identifier(text.clone()),
|
|
44
|
-
VariableValue::Number(num) => TokenDuration::Number(*num),
|
|
45
|
-
VariableValue::Boolean(_) => TokenDuration::Unknown,
|
|
46
|
-
_ => {
|
|
47
|
-
eprintln!("⚠️ Invalid duration type for Trigger: {:?}", value);
|
|
48
|
-
TokenDuration::Unknown
|
|
49
|
-
}
|
|
41
|
+
// ✅ Résolution de duration si c'est un identifiant
|
|
42
|
+
if let Duration::Identifier(ident) = duration {
|
|
43
|
+
if let Some(val) = module.variable_table.get(ident) {
|
|
44
|
+
match val {
|
|
45
|
+
Value::Number(num) => {
|
|
46
|
+
final_duration = Duration::Number(*num);
|
|
50
47
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
parsed_duration_value = TokenDuration::Number(num);
|
|
54
|
-
} else if duration_raw_value == "auto" {
|
|
55
|
-
parsed_duration_value = TokenDuration::Auto;
|
|
56
|
-
} else if duration_raw_value == "infinite" {
|
|
57
|
-
parsed_duration_value = TokenDuration::Infinite;
|
|
58
|
-
} else {
|
|
59
|
-
eprintln!("⚠️ Invalid duration format: {}", duration_raw_value);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
match &stmt.value {
|
|
63
|
-
VariableValue::Text(text) => {
|
|
64
|
-
if let Some(value) = module.variable_table.variables.get(text) {
|
|
65
|
-
let parsed_entity_value: StatementResolvedValue = match value {
|
|
66
|
-
VariableValue::Array(arr) => {
|
|
67
|
-
StatementResolvedValue::Array(
|
|
68
|
-
parse_with_resolving_with_module(arr.clone(), module)
|
|
69
|
-
)
|
|
70
|
-
}
|
|
71
|
-
VariableValue::Map(map) => {
|
|
72
|
-
let mut resolved_map = HashMap::new();
|
|
73
|
-
|
|
74
|
-
for (key, value) in map {
|
|
75
|
-
let resolved_value = match value {
|
|
76
|
-
TokenParamValue::String(text) =>
|
|
77
|
-
StatementResolvedValue::String(text.clone()),
|
|
78
|
-
TokenParamValue::Number(num) =>
|
|
79
|
-
StatementResolvedValue::Number(*num),
|
|
80
|
-
TokenParamValue::Boolean(b) => StatementResolvedValue::Boolean(*b),
|
|
81
|
-
_ => {
|
|
82
|
-
eprintln!(
|
|
83
|
-
"⚠️ Unsupported variable type for Trigger map: {:?}",
|
|
84
|
-
value
|
|
85
|
-
);
|
|
86
|
-
StatementResolvedValue::Unknown
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
resolved_map.insert(key.clone(), resolved_value);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
StatementResolvedValue::Map(resolved_map)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
| VariableValue::Text(_)
|
|
96
|
-
| VariableValue::Number(_)
|
|
97
|
-
| VariableValue::Boolean(_) => {
|
|
98
|
-
StatementResolvedValue::String(text.clone())
|
|
99
|
-
}
|
|
100
|
-
_ => {
|
|
101
|
-
eprintln!("⚠️ Unsupported variable type for Trigger entity: {:?}", value);
|
|
102
|
-
StatementResolvedValue::Unknown
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
StatementResolved {
|
|
107
|
-
kind: StatementKind::Trigger {
|
|
108
|
-
entity: entity.clone(),
|
|
109
|
-
duration: parsed_duration_value,
|
|
110
|
-
},
|
|
111
|
-
value: parsed_entity_value,
|
|
112
|
-
indent: stmt.indent,
|
|
113
|
-
line: stmt.line,
|
|
114
|
-
column: stmt.column,
|
|
48
|
+
Value::String(s) => {
|
|
49
|
+
final_duration = Duration::Identifier(s.clone());
|
|
115
50
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
StatementResolved {
|
|
119
|
-
kind: StatementKind::Trigger {
|
|
120
|
-
entity: entity.clone(),
|
|
121
|
-
duration: parsed_duration_value,
|
|
122
|
-
},
|
|
123
|
-
value: StatementResolvedValue::Unknown,
|
|
124
|
-
indent: stmt.indent,
|
|
125
|
-
line: stmt.line,
|
|
126
|
-
column: stmt.column,
|
|
51
|
+
Value::Identifier(id) if id == "auto" => {
|
|
52
|
+
final_duration = Duration::Auto;
|
|
127
53
|
}
|
|
54
|
+
_ => {}
|
|
128
55
|
}
|
|
129
56
|
}
|
|
130
|
-
|
|
131
|
-
let mut resolved_map = HashMap::new();
|
|
132
|
-
|
|
133
|
-
// TODO Handle nested maps and arrays
|
|
57
|
+
}
|
|
134
58
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
59
|
+
// ✅ Résolution de value (params, effets)
|
|
60
|
+
final_value = match &stmt.value {
|
|
61
|
+
Value::Identifier(ident) => {
|
|
62
|
+
match module.variable_table.get(ident) {
|
|
63
|
+
Some(val) => val.clone(),
|
|
64
|
+
None => {
|
|
65
|
+
let stacktrace = format!("{}:{}:{}", module.path, stmt.line, stmt.column);
|
|
66
|
+
let message = format!(
|
|
67
|
+
"'{path}': value identifier '{ident}' not found in variable table"
|
|
68
|
+
);
|
|
69
|
+
logger.log_error_with_stacktrace(&message, &stacktrace);
|
|
70
|
+
Value::Null
|
|
71
|
+
}
|
|
144
72
|
}
|
|
145
73
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
74
|
+
Value::Map(map) => {
|
|
75
|
+
let mut resolved_map = HashMap::new();
|
|
76
|
+
for (k, v) in map.iter() {
|
|
77
|
+
let resolved_v = match v {
|
|
78
|
+
Value::Identifier(id) => {
|
|
79
|
+
module.variable_table.get(id).cloned().unwrap_or(Value::Null)
|
|
80
|
+
}
|
|
81
|
+
other => other.clone(),
|
|
82
|
+
};
|
|
83
|
+
resolved_map.insert(k.clone(), resolved_v);
|
|
156
84
|
}
|
|
85
|
+
Value::Map(resolved_map)
|
|
157
86
|
}
|
|
87
|
+
other => other.clone(),
|
|
88
|
+
};
|
|
158
89
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
line: stmt.line,
|
|
172
|
-
column: stmt.column,
|
|
173
|
-
}
|
|
174
|
-
}
|
|
90
|
+
// ✅ On reconstruit le Statement avec Trigger résolu
|
|
91
|
+
if let StatementKind::Trigger { entity, .. } = &stmt.kind {
|
|
92
|
+
return Statement {
|
|
93
|
+
kind: StatementKind::Trigger {
|
|
94
|
+
entity: entity.to_string(),
|
|
95
|
+
duration: final_duration,
|
|
96
|
+
},
|
|
97
|
+
value: final_value,
|
|
98
|
+
line: stmt.line,
|
|
99
|
+
column: stmt.column,
|
|
100
|
+
indent: stmt.indent,
|
|
101
|
+
};
|
|
175
102
|
}
|
|
103
|
+
|
|
104
|
+
return Statement {
|
|
105
|
+
kind: StatementKind::Trigger {
|
|
106
|
+
entity: entity.to_string(),
|
|
107
|
+
duration: final_duration,
|
|
108
|
+
},
|
|
109
|
+
value: final_value,
|
|
110
|
+
line: stmt.line,
|
|
111
|
+
column: stmt.column,
|
|
112
|
+
indent: stmt.indent,
|
|
113
|
+
};
|
|
176
114
|
}
|
|
@@ -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
|
+
}
|