devalang_core/core/preprocessor/resolver/
condition.rs1use crate::{
2 core::{
3 parser::statement::{Statement, StatementKind},
4 preprocessor::{module::Module, resolver::driver::resolve_statement},
5 shared::value::Value,
6 store::global::GlobalStore,
7 },
8 utils::logger::Logger,
9};
10
11pub fn resolve_condition(
12 stmt: &Statement,
13 module: &Module,
14 path: &str,
15 global_store: &mut GlobalStore,
16) -> Statement {
17 let logger = Logger::new();
18
19 let Value::Map(condition_map) = &stmt.value else {
20 return type_error(
21 &logger,
22 module,
23 stmt,
24 "Expected a map in condition statement".to_string(),
25 );
26 };
27
28 let mut resolved_map = condition_map.clone();
29
30 if let Some(Value::Block(body)) = condition_map.get("body") {
32 let resolved_body = resolve_block_statements(body, module, path, global_store);
33 resolved_map.insert("body".to_string(), Value::Block(resolved_body));
34 }
35
36 if let Some(Value::Map(next_map)) = condition_map.get("next") {
38 let next_stmt = Statement {
39 kind: StatementKind::If,
40 value: Value::Map(next_map.clone()),
41 ..stmt.clone()
42 };
43
44 let resolved_next = resolve_condition(&next_stmt, module, path, global_store);
45
46 if let Value::Map(mut resolved_next_map) = resolved_next.value {
47 if let Some(Value::Block(body)) = resolved_next_map.get("body") {
49 let resolved_body = resolve_block_statements(body, module, path, global_store);
50 resolved_next_map.insert("body".to_string(), Value::Block(resolved_body));
51 }
52
53 resolved_map.insert("next".to_string(), Value::Map(resolved_next_map));
54 }
55 }
56
57 Statement {
58 kind: StatementKind::If,
59 value: Value::Map(resolved_map),
60 ..stmt.clone()
61 }
62}
63
64fn resolve_block_statements(
65 body: &[Statement],
66 module: &Module,
67 path: &str,
68 global_store: &mut GlobalStore,
69) -> Vec<Statement> {
70 body.iter()
71 .flat_map(|stmt| {
72 let resolved = resolve_statement(stmt, module, path, global_store);
73
74 if let StatementKind::Call { .. } = resolved.kind {
75 if let Value::Block(inner) = &resolved.value {
76 return inner
77 .iter()
78 .map(|s| resolve_statement(s, module, path, global_store))
79 .collect();
80 }
81 }
82
83 vec![resolved]
84 })
85 .collect()
86}
87
88fn type_error(logger: &Logger, module: &Module, stmt: &Statement, message: String) -> Statement {
89 let stacktrace = format!("{}:{}:{}", module.path, stmt.line, stmt.column);
90 logger.log_error_with_stacktrace(&message, &stacktrace);
91
92 Statement {
93 kind: StatementKind::Error { message },
94 value: Value::Null,
95 ..stmt.clone()
96 }
97}