Skip to main content

macroonz_compiler/render/
type_contract.rs

1//! The constant answers this home's refusal roster settles, and the contracts a rendering refusal stands under.
2//!
3//! Each table is total, so a row admitted later stops the compiler in every one of them until somebody says what that row's position, sentence, and classification are.
4
5use super::RenderError;
6use crate::bounded::{Bounded, Overflow};
7use crate::diagnostic::{
8    Family, LineBody, Observed, Phase, RENDERING_FAMILY, REPAIR_LIMIT, RefusalClass, Refused,
9    RenderedMagnitude, Repair,
10};
11use core::fmt;
12
13impl RenderError {
14    /// This row's position in the declared roster, written ahead of the refusal's own material.
15    ///
16    /// Appended and never renumbered: the byte is part of this refusal's public canonical encoding.
17    #[must_use]
18    pub const fn slot(&self) -> u8 {
19        match self {
20            Self::NothingRendered => 1,
21            Self::SeatUnplanned { .. } => 2,
22            Self::BytesUnbounded { .. } => 3,
23            Self::UnitsUnbounded { .. } => 4,
24            Self::TokensUnbounded { .. } => 5,
25        }
26    }
27}
28
29impl fmt::Display for RenderError {
30    fn fmt(&self, into: &mut fmt::Formatter<'_>) -> fmt::Result {
31        match self {
32            Self::NothingRendered => into.write_str("the renderer materialized no unit at all"),
33            Self::SeatUnplanned { role } => write!(
34                into,
35                "a unit was rendered under the seat {role}, which this plan declares no member for"
36            ),
37            Self::BytesUnbounded {
38                role,
39                bound,
40                observed,
41            } => write!(
42                into,
43                "the unit rendered under the seat {role} passed {}: {observed} offered where {bound} are declared",
44                RenderedMagnitude::RenderedBytes.described()
45            ),
46            Self::UnitsUnbounded { bound, observed } => write!(
47                into,
48                "the rendering passed {}: {observed} offered where {bound} are declared",
49                RenderedMagnitude::RenderedUnits.described()
50            ),
51            Self::TokensUnbounded { bound, observed } => write!(
52                into,
53                "a generated tree passed {}: {observed} offered where {bound} are declared",
54                RenderedMagnitude::GeneratedTokens.described()
55            ),
56        }
57    }
58}
59
60impl core::error::Error for RenderError {}
61
62impl From<Overflow> for RenderError {
63    /// The refusal a generated tree that outgrew its per-level magnitude makes.
64    ///
65    /// The one overflow a renderer meets, so `?` carries a composition helper's answer straight out of a renderer body.
66    fn from(overflow: Overflow) -> Self {
67        Self::TokensUnbounded {
68            bound: overflow.capacity,
69            observed: overflow.offered,
70        }
71    }
72}
73
74impl Refused for RenderError {
75    const PHASE: Phase = Phase::Rendering;
76    const FAMILY: Family = RENDERING_FAMILY;
77
78    fn class(&self) -> RefusalClass {
79        match self {
80            Self::NothingRendered | Self::SeatUnplanned { .. } => {
81                RefusalClass::RenderingNotProduced
82            }
83            Self::BytesUnbounded { .. }
84            | Self::UnitsUnbounded { .. }
85            | Self::TokensUnbounded { .. } => RefusalClass::MagnitudeNotHeld,
86        }
87    }
88
89    fn first(&self) -> String {
90        self.to_string()
91    }
92
93    fn observed(&self) -> Observed {
94        match self {
95            Self::NothingRendered => Observed::SeatAbsent,
96            Self::SeatUnplanned { .. } => Observed::ContractDisagreement,
97            Self::BytesUnbounded { .. }
98            | Self::UnitsUnbounded { .. }
99            | Self::TokensUnbounded { .. } => Observed::BoundExceeded,
100        }
101    }
102
103    /// Rendering establishes one cause and enumerates nothing.
104    ///
105    /// A unit that cannot be materialized is not a unit, and the units after it were never written, so there is no remainder for a line to count.
106    fn body(&self) -> LineBody {
107        LineBody::SingleCause
108    }
109
110    /// A single cause enumerates nothing: the primary cause is the summary's own subject, never a member of its related set.
111    fn related(&self) -> Vec<Vec<u8>> {
112        Vec::new()
113    }
114
115    /// This home declares no repair of its own.
116    ///
117    /// Every row above is about the renderer the caller wrote or the plan the caller declared, so the repair is one of those two; a sentence composed here would be this compiler citing a fact nobody declared.
118    fn repairs(&self) -> Bounded<Repair, REPAIR_LIMIT> {
119        Bounded::empty()
120    }
121}