devalang_core/core/preprocessor/resolver/
pattern.rs

1use crate::core::{
2    parser::statement::{Statement, StatementKind},
3    preprocessor::module::Module,
4    store::global::GlobalStore,
5};
6use devalang_types::Value;
7use devalang_utils::logger::{LogLevel, Logger};
8
9pub fn resolve_pattern(
10    stmt: &Statement,
11    module: &Module,
12    path: &str,
13    global_store: &mut GlobalStore,
14) -> Statement {
15    let logger = Logger::new();
16
17    // Expecting pattern name stored on the Statement.kind; value may contain the string
18    if let StatementKind::Pattern { name, target } = &stmt.kind {
19        // Ensure name doesn't already exist
20        if global_store.variables.variables.contains_key(name) {
21            logger.log_error_with_stacktrace(
22                &format!("Pattern identifier '{}' already exists", name),
23                path,
24            );
25            return Statement {
26                kind: StatementKind::Error {
27                    message: format!("Pattern '{}' already exists", name),
28                },
29                ..stmt.clone()
30            };
31        }
32
33        // Resolve potential target and pattern string value
34        let resolved_value = resolve_value(&stmt.value, module, global_store);
35
36        // Build a map to store the pattern definition
37        let mut map = std::collections::HashMap::new();
38        map.insert("identifier".to_string(), Value::String(name.clone()));
39        if let Some(t) = target {
40            map.insert("target".to_string(), Value::String(t.clone()));
41        }
42        // Keep raw pattern in 'pattern' key if it's a string, or merge options map
43        match resolved_value.clone() {
44            Value::String(s) => {
45                map.insert("pattern".to_string(), Value::String(s));
46            }
47            Value::Map(m) => {
48                for (k, v) in m {
49                    map.insert(k, v);
50                }
51            }
52            _ => {
53                map.insert("pattern".to_string(), resolved_value.clone());
54            }
55        }
56
57        let resolved_stmt = Statement {
58            kind: StatementKind::Pattern {
59                name: name.clone(),
60                target: target.clone(),
61            },
62            value: resolved_value,
63            ..stmt.clone()
64        };
65
66        // Store into global variables as a Statement
67        global_store.variables.variables.insert(
68            name.clone(),
69            Value::Statement(Box::new(resolved_stmt.clone())),
70        );
71
72        return resolved_stmt;
73    }
74
75    logger.log_message(
76        LogLevel::Warning,
77        "resolve_pattern called on non-pattern statement",
78    );
79    stmt.clone()
80}
81
82fn resolve_value(value: &Value, module: &Module, global_store: &mut GlobalStore) -> Value {
83    // reuse driver::resolve_value logic; simple local resolution for pattern value
84    match value {
85        Value::String(s) => Value::String(s.clone()),
86        Value::Map(m) => {
87            let mut resolved = std::collections::HashMap::new();
88            for (k, v) in m {
89                resolved.insert(k.clone(), resolve_value(v, module, global_store));
90            }
91            Value::Map(resolved)
92        }
93        other => other.clone(),
94    }
95}