devalang_core/core/preprocessor/resolver/
group.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::{LogLevel, Logger},
9};
10
11pub fn resolve_group(
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(group_map) = &stmt.value else {
20        return type_error(&logger, module, stmt, "Expected a map in group statement".to_string());
21    };
22
23    // Check for the presence of the identifier field
24    let identifier = match group_map.get("identifier") {
25        Some(Value::String(id)) => id.clone(),
26        _ => {
27            return type_error(
28                &logger,
29                module,
30                stmt,
31                "Group statement must have an 'identifier' field".to_string(),
32            )
33        }
34    };
35
36    // Ensure the identifier does not already exist
37    if global_store.variables.variables.contains_key(&identifier) {
38        return type_error(
39            &logger,
40            module,
41            stmt,
42            format!("Group identifier '{}' already exists", identifier),
43        );
44    }
45
46    // Resolve statements in the body
47    let mut resolved_map = group_map.clone();
48    if let Some(Value::Block(body)) = group_map.get("body") {
49        let resolved_body = resolve_block_statements(body, module, path, global_store);
50        resolved_map.insert("body".to_string(), Value::Block(resolved_body));
51    } else {
52        logger.log_message(LogLevel::Warning, "Group without a body");
53    }
54
55    // Build a complete Statement for the group
56    let resolved_group_stmt = Statement {
57        kind: StatementKind::Group,
58        value: Value::Map(resolved_map.clone()),
59        ..stmt.clone()
60    };
61
62    // Store the Statement directly in the global variable_table
63    global_store
64        .variables
65        .variables
66        .insert(identifier.clone(), Value::Statement(Box::new(resolved_group_stmt.clone())));
67
68    resolved_group_stmt
69}
70
71fn resolve_block_statements(
72    body: &[Statement],
73    module: &Module,
74    path: &str,
75    global_store: &mut GlobalStore,
76) -> Vec<Statement> {
77    body.iter()
78        .map(|stmt| resolve_statement(stmt, module, path, global_store))
79        .collect()
80}
81
82fn type_error(logger: &Logger, module: &Module, stmt: &Statement, message: String) -> Statement {
83    let stacktrace = format!("{}:{}:{}", module.path, stmt.line, stmt.column);
84    logger.log_error_with_stacktrace(&message, &stacktrace);
85
86    Statement {
87        kind: StatementKind::Error { message },
88        value: Value::Null,
89        ..stmt.clone()
90    }
91}