1use sim_kernel::{Diagnostic, Expr, HintMetadata, Symbol};
4
5pub fn expected_shape_diagnostic(
7 expected: impl Into<String>,
8 actual: impl Into<String>,
9) -> Diagnostic {
10 let expected = expected.into();
11 let actual = actual.into();
12 let message = format!("expected {expected}, found {actual}");
13 let hint = HintMetadata::new(
14 Symbol::qualified("shape-hint", "expected"),
15 "shape mismatch",
16 )
17 .with_detail(message.clone())
18 .with_tag(Symbol::qualified("shape", "expected"))
19 .with_tag(Symbol::qualified("shape", "actual"))
20 .with_argument(Symbol::new("value"));
21 hint.attach_to(Diagnostic::error(message).with_code(Symbol::qualified("shape", "expected")))
22}
23
24pub fn binding_failure_diagnostic(
26 binding: &Symbol,
27 expected: impl Into<String>,
28 actual: impl Into<String>,
29) -> Diagnostic {
30 let expected = expected.into();
31 let actual = actual.into();
32 let message = format!("binding {binding} expected {expected}, found {actual}");
33 let hint = HintMetadata::new(
34 Symbol::qualified("shape-hint", "binding"),
35 "binding mismatch",
36 )
37 .with_detail(message.clone())
38 .with_tag(Symbol::qualified("shape", "binding"))
39 .with_argument(binding.clone());
40 hint.attach_to(Diagnostic::error(message).with_code(Symbol::qualified("shape", "binding")))
41}
42
43pub fn callable_mismatch_diagnostic(
45 callable: &Symbol,
46 expected: impl Into<String>,
47 actual: impl Into<String>,
48) -> Diagnostic {
49 let expected = expected.into();
50 let actual = actual.into();
51 let message = format!("callable {callable} expected {expected}, found {actual}");
52 let hint = HintMetadata::new(
53 Symbol::qualified("shape-hint", "callable-mismatch"),
54 "callable mismatch",
55 )
56 .with_detail(message.clone())
57 .with_tag(Symbol::qualified("shape", "callable"))
58 .with_argument(callable.clone());
59 hint.attach_to(
60 Diagnostic::error(message).with_code(Symbol::qualified("shape", "callable-mismatch")),
61 )
62}
63
64pub fn overload_selection_diagnostic(function: &Symbol, reason: impl Into<String>) -> Diagnostic {
66 let reason = reason.into();
67 let message = format!("overload selection for {function}: {reason}");
68 let hint = HintMetadata::new(
69 Symbol::qualified("shape-hint", "overload-selection"),
70 "overload selection",
71 )
72 .with_detail(message.clone())
73 .with_tag(Symbol::qualified("shape", "overload"))
74 .with_argument(function.clone());
75 hint.attach_to(
76 Diagnostic::error(message).with_code(Symbol::qualified("shape", "overload-selection")),
77 )
78}
79
80pub(crate) fn expr_actual_label(expr: &Expr) -> String {
82 match expr {
83 Expr::Nil => "nil expression",
84 Expr::Bool(_) => "bool expression",
85 Expr::Number(_) => "number expression",
86 Expr::Symbol(_) | Expr::Local(_) => "symbol expression",
87 Expr::String(_) => "string expression",
88 Expr::Bytes(_) => "bytes expression",
89 Expr::List(_) => "list expression",
90 Expr::Vector(_) => "vector expression",
91 Expr::Map(_) => "map expression",
92 Expr::Set(_) => "set expression",
93 Expr::Call { .. } => "call expression",
94 Expr::Infix { .. } => "infix expression",
95 Expr::Prefix { .. } => "prefix expression",
96 Expr::Postfix { .. } => "postfix expression",
97 Expr::Block(_) => "block expression",
98 Expr::Quote { .. } => "quote expression",
99 Expr::Annotated { .. } => "annotated expression",
100 Expr::Extension { .. } => "extension expression",
101 }
102 .to_owned()
103}