1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use std::ops::Range;

use ariadne::{ColorGenerator, Label, Report, ReportKind};
use edlang_lowering::errors::LoweringError;
use edlang_session::Session;

/// Creates a report from a lowering error.
pub fn lowering_error_to_report(
    error: LoweringError,
    session: &Session,
) -> Report<(String, Range<usize>)> {
    let path = session.file_path.display().to_string();
    let mut colors = ColorGenerator::new();
    colors.next();
    match error {
        LoweringError::ModuleNotFound { span, module } => {
            let offset = span.lo;
            Report::build(ReportKind::Error, path.clone(), offset)
                .with_code("E1")
                .with_label(
                    Label::new((path, span.into()))
                        .with_message(format!("Module {module:?} not found."))
                        .with_color(colors.next()),
                )
                .with_message("Unresolved import.")
                .finish()
        }
        LoweringError::FunctionNotFound { span, function } => {
            Report::build(ReportKind::Error, path.clone(), span.lo)
            .with_code("EFNNOTFOUND")
            .with_label(
                Label::new((path, span.into()))
                    .with_message(format!("Function {function:?} not found."))
                    .with_color(colors.next()),
            )
            .finish()
        },
        LoweringError::ImportNotFound { import_span, module_span, symbol } => {
                let offset = symbol.span.lo;
                Report::build(ReportKind::Error, path.clone(), offset)
                    .with_code("E2")
                    .with_label(
                        Label::new((path.clone(), module_span.into()))
                            .with_message("In module this module."),
                    )
                    .with_label(
                        Label::new((path.clone(), import_span.into()))
                            .with_message("In this import statement"),
                    )
                    .with_label(
                        Label::new((path, symbol.span.into()))
                            .with_message(format!("Failed to find symbol {:?}", symbol.name))
                            .with_color(colors.next()),
                    )
                    .with_message("Unresolved import.")
                    .finish()
        },
        LoweringError::BorrowNotMutable { span, name, type_span } => {
            let mut labels = vec![
                Label::new((path.clone(), span.into()))
            .with_message(format!("Can't mutate {name:?} because it's behind a immutable borrow"))
            .with_color(colors.next())
            ];

            if let Some(type_span) = type_span {
                labels.push(Label::new((path.clone(), type_span.into()))
                .with_message(format!("Variable {name:?} has this type"))
                .with_color(colors.next()));
            }

            Report::build(ReportKind::Error, path.clone(), span.lo)
            .with_code("EREFMUT")
            .with_labels(labels)
            .finish()
        },
        LoweringError::UnrecognizedType { span, name } => {
            Report::build(ReportKind::Error, path.clone(), span.lo)
                .with_code("E3")
                .with_label(
                    Label::new((path, span.into()))
                        .with_message(format!("Failed to find type {:?}", name))
                        .with_color(colors.next()),
                )
                .with_message(format!("Unresolved type {:?}.", name))
                .finish()
        },
        LoweringError::IdNotFound { span, id } => {
            Report::build(ReportKind::Error, path.clone(), span.lo)
                .with_code("E_ID")
                .with_label(
                    Label::new((path, span.into()))
                        .with_message("Failed to definition id")
                        .with_color(colors.next()),
                )
                .with_message(format!("Failed to find definition id {id:?}, this is most likely a compiler bug or a unimplemented lowering"))
                .finish()
        },
        LoweringError::NotYetImplemented { span, message } => {
            Report::build(ReportKind::Error, path.clone(), span.lo)
                .with_code("TODO")
                .with_label(
                    Label::new((path, span.into()))
                        .with_message(message)
                        .with_color(colors.next()),
                )
                .finish()
        },
    }
}