devalang_core/core/preprocessor/resolver/
condition.rs

1use 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    // Main body resolution
31    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    // Recursive resolution of next condition
37    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            // Body next resolution
48            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}