devalang_core/core/preprocessor/resolver/
group.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::{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 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 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 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 let resolved_group_stmt = Statement {
57 kind: StatementKind::Group,
58 value: Value::Map(resolved_map.clone()),
59 ..stmt.clone()
60 };
61
62 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}