Skip to main content

meta_language/translation/
aborts.rs

1//! The message a source program aborts with, in the words of the source
2//! language, so every target aborts where the source does with the message
3//! the source prints.
4//!
5//! Machine integers are Rust's, whose arithmetic panics (overflow checks on,
6//! as in a debug build) with these messages; `BigInt` division by zero is
7//! JavaScript's `RangeError`; a natural parameter is a JavaScript `BigInt`
8//! parameter whose leading guard throws its own message.
9//!
10//! Mirrors `js/src/translation/aborts.js`.
11
12use super::types::Type;
13
14/// The panic of a machine-integer operation whose result is out of range:
15/// `op` is `add`, `sub`, `mul`, `div`, `rem` or `neg`.
16///
17/// # Panics
18/// On any other operation, which cannot overflow.
19#[must_use]
20pub fn overflow_message(op: &str) -> &'static str {
21    match op {
22        "add" => "attempt to add with overflow",
23        "sub" => "attempt to subtract with overflow",
24        "mul" => "attempt to multiply with overflow",
25        "div" => "attempt to divide with overflow",
26        "rem" => "attempt to calculate the remainder with overflow",
27        "neg" => "attempt to negate with overflow",
28        other => panic!("{other} does not overflow"),
29    }
30}
31
32/// The abort of an integer division or remainder by zero.
33#[must_use]
34pub fn zero_divisor_message(op: &str, ty: &Type) -> &'static str {
35    if !matches!(ty, Type::Fixed { .. }) {
36        return "Division by zero";
37    }
38    if op == "rem" {
39        "attempt to calculate the remainder with a divisor of zero"
40    } else {
41        "attempt to divide by zero"
42    }
43}
44
45/// The abort of a checked conversion of a negative integer to a natural: the guard's own message.
46#[must_use]
47pub fn cast_message(message: Option<&str>) -> &str {
48    message.unwrap_or("conversion of a negative integer to a natural")
49}
50
51/// The message of `panic!`, `unreachable!`, `unimplemented!` and `todo!`, with an optional literal message.
52#[must_use]
53pub fn rust_macro_message(name: &str, message: Option<&str>) -> String {
54    let prefix = match name {
55        "unreachable" => Some("internal error: entered unreachable code"),
56        "unimplemented" => Some("not implemented"),
57        "todo" => Some("not yet implemented"),
58        _ => None,
59    };
60    match (prefix, message) {
61        (prefix, None) => prefix.unwrap_or("explicit panic").to_owned(),
62        (None, Some(message)) => message.to_owned(),
63        (Some(prefix), Some(message)) => format!("{prefix}: {message}"),
64    }
65}