devalang_core/core/preprocessor/resolver/
group.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::{LogLevel, Logger};
8
9pub fn resolve_group(
10 stmt: &Statement,
11 module: &Module,
12 path: &str,
13 global_store: &mut GlobalStore,
14) -> Statement {
15 let logger = Logger::new();
16
17 let identifier = match extract_group_identifier(stmt, &logger, module) {
19 Ok(id) => id,
20 Err(err_stmt) => return err_stmt,
21 };
22
23 let group_map = match &stmt.value {
25 Value::Map(m) => m.clone(),
26 _ => std::collections::HashMap::new(),
27 };
28
29 if global_store.variables.variables.contains_key(&identifier) {
31 return type_error(
32 &logger,
33 module,
34 stmt,
35 format!("Group identifier '{}' already exists", identifier),
36 );
37 }
38
39 let mut resolved_map = group_map.clone();
41 if let Some(Value::Block(body)) = group_map.get("body") {
42 let resolved_body = resolve_block_statements(body, module, path, global_store);
43 resolved_map.insert("body".to_string(), Value::Block(resolved_body));
44 } else {
45 logger.log_message(LogLevel::Warning, "Group without a body");
46 }
47
48 let resolved_group_stmt = Statement {
50 kind: StatementKind::Group,
51 value: Value::Map(resolved_map.clone()),
52 ..stmt.clone()
53 };
54
55 global_store.variables.variables.insert(
57 identifier.clone(),
58 Value::Statement(Box::new(resolved_group_stmt.clone())),
59 );
60
61 resolved_group_stmt
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 .map(|stmt| resolve_statement(stmt, module, path, global_store))
72 .collect()
73}
74
75fn type_error(logger: &Logger, module: &Module, stmt: &Statement, message: String) -> Statement {
76 let stacktrace = format!("{}:{}:{}", module.path, stmt.line, stmt.column);
77 logger.log_error_with_stacktrace(&message, &stacktrace);
78
79 Statement {
80 kind: StatementKind::Error { message },
81 value: Value::Null,
82 ..stmt.clone()
83 }
84}
85
86fn extract_group_identifier(
88 stmt: &Statement,
89 logger: &Logger,
90 module: &Module,
91) -> Result<String, Statement> {
92 match &stmt.value {
93 Value::Map(map) => match map.get("identifier") {
94 Some(Value::String(s)) => Ok(s.clone()),
95 Some(Value::Identifier(s)) => Ok(s.clone()),
96 Some(Value::Number(n)) => Ok(n.to_string()),
97 Some(other) => Err(type_error(
98 logger,
99 module,
100 stmt,
101 format!("Unsupported type for 'identifier': {:?}", other),
102 )),
103 None => Err(type_error(
104 logger,
105 module,
106 stmt,
107 "Group statement must have an 'identifier' field".to_string(),
108 )),
109 },
110 Value::String(s) => Ok(s.clone()),
111 Value::Identifier(s) => Ok(s.clone()),
112 other => Err(type_error(
113 logger,
114 module,
115 stmt,
116 format!(
117 "Expected a map or string for group statement, found {:?}",
118 other
119 ),
120 )),
121 }
122}