devalang_core/core/preprocessor/resolver/
condition.rs

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