devalang_core/core/preprocessor/resolver/
condition.rs1use 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 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 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 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}