devalang_core/utils/
error.rs

1use crate::core::{
2    error::ErrorResult,
3    parser::statement::{Statement, StatementKind},
4    shared::value::Value,
5};
6
7/// Recursively collects errors from a list of statements.
8///
9/// This function traverses the provided statements and aggregates any
10/// `Unknown` or explicit `Error` statements into a flat vector.
11/// It also descends into loop bodies to ensure nested errors are
12/// surfaced.
13pub fn collect_errors_recursively(statements: &[Statement]) -> Vec<ErrorResult> {
14    let mut errors: Vec<ErrorResult> = Vec::new();
15
16    for stmt in statements {
17        match &stmt.kind {
18            StatementKind::Unknown => {
19                errors.push(ErrorResult {
20                    message: format!("Unknown statement at line {}:{}", stmt.line, stmt.column),
21                    line: stmt.line,
22                    column: stmt.column,
23                });
24            }
25            StatementKind::Error { message } => {
26                errors.push(ErrorResult {
27                    message: message.clone(),
28                    line: stmt.line,
29                    column: stmt.column,
30                });
31            }
32            StatementKind::Loop => {
33                if let Some(body_statements) = extract_loop_body_statements(&stmt.value) {
34                    errors.extend(collect_errors_recursively(body_statements));
35                }
36            }
37            _ => {}
38        }
39    }
40
41    errors
42}
43
44fn extract_loop_body_statements(value: &Value) -> Option<&[Statement]> {
45    if let Value::Map(map) = value {
46        if let Some(Value::Block(statements)) = map.get("body") {
47            return Some(statements);
48        }
49    }
50    None
51}