macroonz-compiler 0.1.0

Deterministic Rust code generation for procedural macros: plan, render, close, explain, and bind one sealed expansion from declared input.
Documentation
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
//! The diagnostic home's declarations: one diagnostic, the typed parts of its one summary line, the registries a refusal reads its vocabulary off, and the trait a refusing step implements.
//!
//! Declarations only.
//! Every road that reaches a private field lives in `type_guard.rs`, this file's own child, so the seats a caller may not write have exactly one way in.

use crate::bounded::{Bounded, Capping};
use crate::identity::{
    Contract, HumanProjection, Identity, OwnerFact, RelatedBody, RelatedIssue, ServiceEntry,
};
use crate::token::{SourceCoordinate, SpanHandle, SpanResolutionRefusal, SpanTable};

#[path = "type_guard.rs"]
mod guard;
pub(crate) use guard::intrinsic_diagnostic;

/// Owner-declared repairs one diagnostic may carry.
pub const REPAIR_LIMIT: usize = 8;

/// Identities one diagnostic's related set may carry.
///
/// A step may establish a wider body, so a body that outruns this is a case the road meets rather than one the bounds rule out.
pub const RELATED_ISSUE_LIMIT: usize = 64;

// ---------------------------------------------------------------------------
// The families.
//
// A family here is one refusal's issue space, and its name is what keeps two
// spaces' identical bytes from deriving one identity. The name is namespaced
// like an identity stem — the declarer's own name ahead of the space's — so an
// adopter declares its families in its own crate and two crates' spaces cannot
// collide without one wearing the other's name. A name is preimage material:
// renaming a family renames every related identity derived in it.
// ---------------------------------------------------------------------------

/// One refusal's issue space, named by its declarer.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Family(&'static str);

/// One adopter-declared diagnostic vocabulary name.
///
/// The spelling is lowercase ASCII kebab-case by construction, so an adopter-defined refusal class or observation cannot publish a name outside the contract both rosters state.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DiagnosticName(&'static str);

/// How declaring one diagnostic vocabulary name refuses.
#[must_use = "a diagnostic-name refusal states why no kebab-case name was declared"]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum DiagnosticNameRefusal {
    /// The declaration supplied no name.
    Empty,
    /// The spelling is not lowercase ASCII kebab-case.
    NotKebabCase,
}

/// Planning a projection.
pub const PLANNING_FAMILY: Family = Family::declared("macroonz/planning");

/// Proving a rendering closes over its plan.
pub const CLOSURE_FAMILY: Family = Family::declared("macroonz/closure");

/// Covering a kind's questions with an explanation.
pub const EXPLANATION_FAMILY: Family = Family::declared("macroonz/explanation");

/// Materializing a planned member.
pub const RENDERING_FAMILY: Family = Family::declared("macroonz/rendering");

/// Sealing a plan, a closure, and an explanation as one expansion.
pub const BINDING_FAMILY: Family = Family::declared("macroonz/binding");

/// Composing closed outputs into one carrier.
pub const ASSEMBLY_FAMILY: Family = Family::declared("macroonz/assembly");

/// Rendering the carrier shell itself.
pub const SHELL_FAMILY: Family = Family::declared("macroonz/shell");

/// The carrier's own declaration vocabulary.
pub const DECLARATION_FAMILY: Family = Family::declared("macroonz/descriptor-declaration");

/// The support home's own declaration vocabulary, which is not the descriptor's however alike the two read.
pub const SUPPORT_DECLARATION_FAMILY: Family = Family::declared("macroonz/support-declaration");

/// The trial helper's captured grammar.
pub const FIRST_HELPER_FAMILY: Family = Family::declared("macroonz/trial-helper");

/// The mutation helper's captured grammar.
pub const SECOND_HELPER_FAMILY: Family = Family::declared("macroonz/mutation-helper");

/// The bench helper's captured grammar.
pub const BENCH_HELPER_FAMILY: Family = Family::declared("macroonz/bench-helper");

/// The shadow face's captured grammar.
pub const SHADOW_HELPER_FAMILY: Family = Family::declared("macroonz/shadow-helper");

/// The network declaration's captured grammar.
pub const NETWORK_HELPER_FAMILY: Family = Family::declared("macroonz/network-helper");

/// The concurrency declaration's captured grammar.
pub const CONCURRENCY_HELPER_FAMILY: Family = Family::declared("macroonz/concurrency-helper");

/// Reading a declared input into a captured surface.
pub const CAPTURE_FAMILY: Family = Family::declared("macroonz/capture");

/// A codec shape's own declaration vocabulary.
pub const CODEC_DECLARATION_FAMILY: Family = Family::declared("macroonz/codec-declaration");

/// Which step of the road was running when the disagreement was observed.
///
/// Declared in the order the steps run.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Phase {
    /// Reading the declared input into a captured surface.
    Capture,
    /// Naming the complete output set, before a token of Rust exists.
    Planning,
    /// Materializing a planned member.
    Rendering,
    /// Proving the rendering closes over the plan it claims to materialize.
    Closure,
    /// Answering the questions the kind owes.
    Explanation,
    /// Sealing the plan, the closure, and the explanation as one expansion.
    Binding,
    /// Composing closed outputs into one exported carrier.
    Assembly,
}

/// Which class of refusal one composed line is about.
///
/// The class is the second clause of every line and is READ off this roster rather than written at the seam that refused, so two seams reporting one class do not read as two.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum RefusalClass {
    /// The declared input was not read into a captured surface.
    DeclarationNotRead,
    /// Planning refused before a token of Rust existed.
    PlanNotStated,
    /// A renderer did not produce the unit the plan named.
    RenderingNotProduced,
    /// The rendering does not close over the plan it claims to materialize.
    RenderingNotClosed,
    /// The written explanation does not cover its kind's questions.
    ExplanationNotCovered,
    /// A rendering would have passed a declared magnitude.
    MagnitudeNotHeld,
    /// The three values a binding seals do not belong to one expansion.
    ExpansionNotBound,
    /// A set of closed outputs does not compose into one exported carrier.
    CarrierNotAssembled,
    /// The carrier's own vocabulary was not declared.
    CarrierNotDeclared,
    /// A class an adopter declared, for a refusal none of the rows above say.
    ///
    /// The two spellings are the adopter's own, and a line about it reads them exactly as a line about any row above reads that row's.
    Declared {
        /// The stable kebab-case name.
        name: DiagnosticName,
        /// The second clause of a composed line about it.
        described: &'static str,
    },
}

/// How what was observed differs from the contract that was expected.
///
/// A typed classification, never a sentence: the sentence is a projection of this.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Observed {
    /// A required seat was unfurnished.
    SeatAbsent,
    /// What was present disagrees with the expected contract.
    ContractDisagreement,
    /// An identity that had to match did not.
    IdentityDisagreement,
    /// The material was presented under a profile that does not offer it.
    ProfileDisagreement,
    /// A declared magnitude was exceeded.
    BoundExceeded,
    /// Generated material arrived with no origin.
    OriginAbsent,
    /// A difference an adopter declared, for an observation none of the rows above classify.
    Declared {
        /// The stable kebab-case name.
        name: DiagnosticName,
        /// How the difference reads in a composed line.
        described: &'static str,
    },
}

/// One declared magnitude a rendering can pass, and the thing it governs.
///
/// The prose belongs to the magnitude rather than to whichever refusal named it; the number belongs to the home that declares the bound, so a refusal carries it and this roster never restates it.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum RenderedMagnitude {
    /// The bytes one rendered unit may carry.
    RenderedBytes,
    /// The units one rendering may carry.
    RenderedUnits,
    /// The tokens one generated tree may carry at one nesting level.
    GeneratedTokens,
}

/// What one composed line is a summary OF.
///
/// A single-cause refusal establishes one cause and enumerates nothing: there is no remainder to count and no bound anything could have been capped at, so a line reporting "and 0 further issues, complete" would answer a question never asked of it.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum LineBody {
    /// One established cause, with nothing enumerated beside it.
    SingleCause,
    /// A body of independent issues.
    Body {
        /// Established issues past the one the line states in full.
        further: usize,
        /// Whether the body kept every issue it established.
        capping: Capping,
    },
}

/// The typed parts one compiler line is composed from.
///
/// They travel as one value because they are one line: a class handed to [`composed`](crate::diagnostic::composed) beside another refusal's first established issue composes a sentence that is well formed, complete-looking, and about nothing in particular.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Line<'issue> {
    /// Which class of refusal the line is about.
    pub class: RefusalClass,
    /// The first established issue, stated in full.
    pub first: &'issue str,
    /// What the line is a summary of.
    pub body: LineBody,
}

/// Whether a composed line says where the refusal sits.
///
/// Not an option: a whole-declaration refusal is a STATED posture and not a site somebody forgot to supply, and adding a position to its line would send a reader to an arbitrary spot inside a declaration the refusal is not about.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum LineSite {
    /// The refusal is about the declaration as a whole, and the line adds nothing.
    WholeDeclaration,
    /// The refusal sits somewhere the producer can name, and the line says where — or says that the producer's table does not reach it.
    At(SiteCoordinate),
}

/// Where one diagnostic's token sits, or why the producer's table could not say.
///
/// A seat that cannot be furnished states the posture rather than being filled with a stand-in: a coordinate written where a table did not reach would read exactly like a coordinate the table resolved, and the reader has no third value to compare it against.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum SiteCoordinate {
    /// The position the producer's table resolved, in the role it speaks.
    Resolved(SourceCoordinate),
    /// The producer's table does not reach this handle, and the refusal states how far it does reach.
    NotReached(SpanResolutionRefusal),
}

/// Where one diagnostic points.
///
/// A diagnostic about a CAPTURED declaration names the offending token in the producer's own span table, so the producer can put a compiler error on exactly that token rather than on the declaration's first one.
/// A diagnostic established BEFORE any capture has no token to name — no table was built and no handle was issued — and carries the byte it was born at instead.
/// A diagnostic about the declaration AS A WHOLE has nowhere narrower to point, and says exactly that: the whole-declaration arm carries no token and no coordinate, because any it carried would send a reader to a spot the refusal is not about.
///
/// # Nonclaims
///
/// **The pre-capture and whole-declaration arms mint no handle, and that is the substitution this sum removes.**
/// A required handle seat forces handle zero onto an observation that issued none, and handle zero reads exactly like an honest answer pointing at the declaration's first token.
#[must_use = "a site names the token it points at, the byte it was born at, or the whole declaration"]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Site {
    /// One token of a captured declaration, and where the producer's table put it.
    AtToken {
        /// The offending token, as a handle into the producer's own span table.
        token: SpanHandle,
        /// Where that token sits, or the typed statement that the table does not reach the handle.
        coordinate: SiteCoordinate,
    },
    /// One byte of the text a read refused on, before any capture existed to issue a handle.
    BeforeCapture {
        /// The byte the observation was born at, in the role its own text counts in.
        coordinate: SourceCoordinate,
    },
    /// The declaration as a whole: a stated posture with no token seat to fabricate one into.
    WholeDeclaration,
}

/// One identity a related set carries, at the level it is about.
///
/// The two levels are two types rather than two positions, because position is not a fact a reader can check and because one subject over two levels collides by construction: the body's preimage is the framing of its issues, so an issue whose own material happened to be that framing would derive the byte-for-byte identity of the body it aliased.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum RelatedIdentity {
    /// The whole refusal body, as one commitment to every issue it established.
    Body(Identity<RelatedBody>),
    /// One established issue, on its own.
    Issue(Identity<RelatedIssue>),
}

/// One diagnostic's related set: the identities it carries, married to how it was capped.
///
/// A capping that can be carried away from its set is a claim that can be told about a different one, so the set-building road is the only road in and the seats are private.
///
/// # Ordering
///
/// The body rides first, and a reader does not depend on that: an identity states its own level.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct RelatedSet {
    carried: Bounded<RelatedIdentity, RELATED_ISSUE_LIMIT>,
    capping: Capping,
}

/// One repair the owner declared, projected for a person to read.
///
/// The citation is the load-bearing member.
/// The text is a projection of it, and nothing here ever composes a repair the owner did not declare.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Repair {
    /// The owner fact that declares this repair.
    pub declared_by: OwnerFact,
    /// The repair rendered for a person.
    pub description: HumanProjection,
}

/// How to reach the same observation again.
///
/// The road is the callable entry point the door names, which needs no proc macro anywhere in the path.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Route {
    entry: Identity<ServiceEntry>,
}

/// Where one projected refusal sits.
///
/// A refusal about the DECLARATION has nowhere narrower to point, and a line naming a position inside it would send a reader to an arbitrary spot; a refusal about one CLAUSE of an authored attribute has exactly one place, and the reader is sent there.
#[derive(Debug, Clone, Copy)]
pub enum Placement<'table> {
    /// The refusal is about the declaration as a whole.
    WholeDeclaration,
    /// The refusal sits at one token, resolved through the producer's own table.
    AtToken {
        /// The token it sits at.
        token: SpanHandle,
        /// The table the producer resolves handles through.
        spans: &'table SpanTable,
    },
}

/// One diagnostic.
///
/// Every seat is required and every one of them is readable: a diagnostic that could omit its phase, its site, its expected contract, or its observed classification would be one that sometimes says less than it knows.
/// The seats a caller reads after deciding what refused ride behind one pointer, so every `Result` that answers with a diagnostic stays small on its passing side.
#[must_use = "a diagnostic carries the observation, its site, and the owner-declared repair"]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Diagnostic {
    phase: Phase,
    site: Site,
    observed: Observed,
    carried: Box<DiagnosticSeats>,
}

/// The seats one diagnostic carries behind its pointer.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct DiagnosticSeats {
    summary: String,
    expected: Identity<Contract>,
    related: RelatedSet,
    repairs: Bounded<Repair, REPAIR_LIMIT>,
    route: Route,
}

/// How one step of the road says no.
///
/// A step refuses in the vocabulary of the home that owns it and implements this to say how that vocabulary reads; [`Diagnostic::refused`] projects caller-placed refusals, while intrinsically placed refusal types expose their own typed diagnostic road.
/// The two associated constants are facts about the error's TYPE and not about a call site, for the reason this home's README gives.
pub trait Refused {
    /// The step of the road this refusal is raised at.
    const PHASE: Phase;

    /// The family whose issue space this refusal's related identities derive in.
    ///
    /// An adopter declares its own, under its own namespace; the compiler's are the [`Family`] constants beside this trait.
    const FAMILY: Family;

    /// Which class of refusal the summary line opens with.
    fn class(&self) -> RefusalClass;

    /// How the first established issue reads for a person.
    fn first(&self) -> String;

    /// How what was observed differs from the expected contract, read off that same first issue.
    fn observed(&self) -> Observed;

    /// What the summary line is a summary of.
    fn body(&self) -> LineBody;

    /// One canonical byte string per issue established BEYOND the primary cause, in the order the body established them.
    ///
    /// The primary cause is the summary's own subject and never a member of its related set, so a single-cause refusal answers with nothing — which is what [`LineBody::SingleCause`]'s "enumerates nothing" means, at the machine seat as well as in the line.
    /// Two bodies that differ in any typed member must answer with different bytes; that completeness is the implementing home's.
    fn related(&self) -> Vec<Vec<u8>>;

    /// The owner-declared repairs that apply.
    fn repairs(&self) -> Bounded<Repair, REPAIR_LIMIT>;
}

/// How a crate-owned refusal whose site is intrinsic carries that site into its diagnostic.
///
/// The refusal home's private projection implements this trait, so no caller supplies a second placement that can disagree with the refusal's own coordinate.
pub(crate) trait IntrinsicRefused: Refused {
    /// The site established by the same act that established the refusal.
    fn site(&self) -> Site;
}