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
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
//! Reading one authored bench declaration out of a typed token tree.
//!
//! # The authored grammar
//!
//! ```text
//! #[<helper>(
//!     support = <exported name>,
//!     table_function = <table function name>,
//!     table = named("<namespace>", "<stem>"),
//!     reporter = <reporter module name>,
//!
//!     <lens> {
//!         workload = named("<namespace>", "<stem>"),
//!         preflight = named("<namespace>", "<stem>"),
//!         planted_worse = named("<namespace>", "<stem>"),
//!         complexity = named("<namespace>", "<stem>"),
//!         axis = [<size>, <size>, ...],
//!         samples = <count>,
//!         warmups = <count>,
//!         ratio_numerator = <count>,
//!         ratio_denominator = <count>,
//!         formula = "<work formula>",
//!         observe = [named("<namespace>", "<stem>"), ...],
//!     },
//! )]
//! ```
//!
//! The helper's own spelling is the caller's, which is why `<helper>` stands where a word would: a door registers the attribute it wants and hands the same [`Grammar`] to this reading, so a refusal names the word an author actually wrote.
//!
//! `formula` may be left out; every other row clause is required.
//! An operation that declares no work formula states that by carrying none.
//!
//! Every count is one unsuffixed decimal literal, because a count that arrives typed, based, or separated is a spelling this reading would have to interpret, and interpreting a spelling is deciding what an author meant by a value it could not read.
//!
//! Callables, the judge, the complete preflight, and the report reader are target-owned expressions and therefore are not authored here.
//!
//! # What has no clause, and why
//!
//! The contention posture has none, because one arm is all the declared facts support and a clause with one lawful value is a sentence that says what silence already says.
//! The producer's own act and the consumption target's host facts have none, on the trial grammar's own terms: the first is composed inside the rendering from the emitter the caller declares, and the second arrives as expressions at the carrier's invocation.
//!
//! # Order
//!
//! Clause order inside a body is free and is read by key.
//! Order between ROSTER members is meaning and is preserved: the rows in the order they were written, each axis in the order its sizes were written, and each observation roster in the order its references were written.

use super::{
    BenchCaptureError, BenchmarkDeclaration, Budgets, ContentionPosture, Measurement, References,
    Reporter, Row, WorkFormula,
};
use crate::descriptor::{
    CaptureCause, DeclarationError, FunctionName, Grammar, ModuleName, Name, SupportName,
};
use crate::token::{CapturedDelimiter, CapturedTokenTree, SpanHandle};

/// The clause naming the exported support name.
const SUPPORT: &str = "support";

/// The clause naming the stamped table function.
const TABLE_FUNCTION: &str = "table_function";

/// The clause naming the authored table.
const TABLE: &str = "table";

/// The clause naming the report-reader module.
const REPORTER: &str = "reporter";

/// The road every namespaced reference in this grammar is spelled by.
const NAMED: &str = "named";

/// The row clause naming what is measured.
const WORKLOAD: &str = "workload";

/// The row clause naming the correctness preflight's reference.
const PREFLIGHT: &str = "preflight";

/// The row clause naming the planted-worse falsifier's reference.
const PLANTED_WORSE: &str = "planted_worse";

/// The row clause naming the neutral complexity claim.
const COMPLEXITY: &str = "complexity";

/// The row clause stating the input-size axis.
const AXIS: &str = "axis";

/// The row clause stating how many samples the gate takes at each point.
const SAMPLES: &str = "samples";

/// The row clause stating how many warmup iterations run before sampling.
const WARMUPS: &str = "warmups";

/// The row clause stating the exact gap ratio's numerator.
const RATIO_NUMERATOR: &str = "ratio_numerator";

/// The row clause stating the exact gap ratio's denominator.
const RATIO_DENOMINATOR: &str = "ratio_denominator";

/// The row clause stating the declared work formula.
const FORMULA: &str = "formula";

/// The row clause stating the work observations the gate reads.
const OBSERVE: &str = "observe";

/// The clause keys this grammar declares at a declaration's own level.
const DECLARABLE: [&str; 4] = [SUPPORT, TABLE_FUNCTION, TABLE, REPORTER];

/// The clause keys one row admits.
///
/// Its own roster rather than the declaration level's, because the two levels admit different keys and one roster standing for both would let a table's clause be written inside a row and read as lawful.
const DECLARABLE_ROW: [&str; 11] = [
    WORKLOAD,
    PREFLIGHT,
    PLANTED_WORSE,
    COMPLEXITY,
    AXIS,
    SAMPLES,
    WARMUPS,
    RATIO_NUMERATOR,
    RATIO_DENOMINATOR,
    FORMULA,
    OBSERVE,
];

/// Read one bench payload out of the helper attribute's body.
///
/// # Errors
///
/// Returns [`BenchCaptureError`] where the tokens do not say a bench declaration, and where the values they say are not a lawful declaration — each at the token the clause it was established at sits at.
pub fn captured(
    body: &[&CapturedTokenTree],
    at: SpanHandle,
    grammar: Grammar,
) -> Result<BenchmarkDeclaration, BenchCaptureError> {
    let clauses = declaration_clauses(grammar, body)?;
    let support = SupportName::declared(identifier(grammar, &clauses, SUPPORT, at)?)
        .map_err(|refusal| carried(grammar, refusal, at))?;
    let table_function = FunctionName::declared(identifier(grammar, &clauses, TABLE_FUNCTION, at)?)
        .map_err(|refusal| carried(grammar, refusal, at))?;
    let table = named_reference(grammar, &clauses, TABLE, at)?;
    let reporter_module = ModuleName::declared(identifier(grammar, &clauses, REPORTER, at)?)
        .map_err(|refusal| carried(grammar, refusal, at))?;

    let mut rows: Vec<Row> = Vec::new();
    for clause in &clauses {
        if let Clause::Row {
            lens,
            body: stated,
            at: site,
        } = clause
        {
            rows.push(row(grammar, lens, stated, *site)?);
        }
    }
    BenchmarkDeclaration::declared(
        support,
        table_function,
        table,
        rows,
        Reporter::declared(reporter_module),
    )
    .map_err(|refusal| carried(grammar, refusal, at))
}

/// One established grammar refusal at one token.
const fn refused(grammar: Grammar, cause: CaptureCause, at: SpanHandle) -> BenchCaptureError {
    BenchCaptureError::grammar_refused(grammar, cause, at)
}

/// One vocabulary refusal carried whole, at the token the value was read from.
const fn carried(grammar: Grammar, refusal: DeclarationError, at: SpanHandle) -> BenchCaptureError {
    BenchCaptureError::vocabulary_refused(grammar, refusal, at)
}

/// One clause of a bench declaration's body, as the split read it.
///
/// Two shapes rather than one, because the grammar has two: an assignment states one key and one value, and a row states a lens and a body of row clauses.
enum Clause<'trees> {
    /// `<key> = <value tokens>`.
    Assigned {
        /// The key the clause names.
        key: &'trees str,
        /// The tokens the value is spelled from.
        value: Vec<&'trees CapturedTokenTree>,
        /// The token the key sits at.
        at: SpanHandle,
    },
    /// `<lens> { <row clauses> }`.
    Row {
        /// The lens the row is declared under.
        lens: &'trees str,
        /// The trees inside the row body.
        body: Vec<&'trees CapturedTokenTree>,
        /// The token the lens sits at.
        at: SpanHandle,
    },
}

/// Cut one declaration body into its comma-separated clauses, refusing a separator that separates nothing.
///
/// A trailing comma after the last clause is ordinary Rust and lawful; a leading or doubled comma makes an empty group this reader would otherwise silently drop, so it refuses at the comma's own token.
fn declaration_clauses<'trees>(
    grammar: Grammar,
    body: &[&'trees CapturedTokenTree],
) -> Result<Vec<Clause<'trees>>, BenchCaptureError> {
    let mut clauses: Vec<Clause<'trees>> = Vec::new();
    let mut group: Vec<&CapturedTokenTree> = Vec::new();
    for tree in body {
        if tree.punct() == Some(',') {
            if group.is_empty() {
                return Err(refused(
                    grammar,
                    CaptureCause::SeparatorDangling,
                    tree.span(),
                ));
            }
            close(grammar, &group, &mut clauses)?;
            group.clear();
        } else {
            group.push(tree);
        }
    }
    close(grammar, &group, &mut clauses)?;
    distinct(grammar, &clauses)?;
    Ok(clauses)
}

/// Close one of a declaration body's comma-separated groups.
///
/// An empty group is a trailing comma and is lawful; an empty group standing at a comma was refused before this road is reached.
/// A group of one word and one brace body is a row; anything else is read as an assignment against the declaration level's keys.
fn close<'trees>(
    grammar: Grammar,
    group: &[&'trees CapturedTokenTree],
    clauses: &mut Vec<Clause<'trees>>,
) -> Result<(), BenchCaptureError> {
    let Some((head, rest)) = group.split_first() else {
        return Ok(());
    };
    if let [body] = rest
        && let Some(lens) = head.word()
        && let Some((CapturedDelimiter::Brace, inner)) = body.group()
    {
        clauses.push(Clause::Row {
            lens,
            body: inner.iter().collect(),
            at: head.span(),
        });
        return Ok(());
    }
    clauses.push(assignment(grammar, head, rest, &DECLARABLE)?);
    Ok(())
}

/// Read one `<key> = <value>` assignment, admitted against the roster its own level declares.
fn assignment<'trees>(
    grammar: Grammar,
    head: &'trees CapturedTokenTree,
    rest: &[&'trees CapturedTokenTree],
    declarable: &[&str],
) -> Result<Clause<'trees>, BenchCaptureError> {
    let opening = head.span();
    let Some(key) = head.word() else {
        return Err(refused(grammar, CaptureCause::ClauseUnread, opening));
    };
    let Some((assigned_by, value)) = rest.split_first() else {
        return Err(refused(grammar, CaptureCause::ClauseUnread, opening));
    };
    if assigned_by.punct() != Some('=') || value.is_empty() {
        return Err(refused(
            grammar,
            CaptureCause::ClauseUnread,
            assigned_by.span(),
        ));
    }
    if !declarable.contains(&key) {
        return Err(refused(grammar, CaptureCause::ClauseUndeclared, opening));
    }
    Ok(Clause::Assigned {
        key,
        value: value.to_vec(),
        at: opening,
    })
}

/// Refuse where one clause key is stated twice.
///
/// Assigned clauses alone: two rows are two lenses, and the payload's own lens-namespace law is what tells one from another.
fn distinct(grammar: Grammar, clauses: &[Clause<'_>]) -> Result<(), BenchCaptureError> {
    for (position, clause) in clauses.iter().enumerate() {
        let Clause::Assigned { key, at, .. } = clause else {
            continue;
        };
        let earlier = clauses.iter().take(position).any(|other| match *other {
            Clause::Assigned { key: seen, .. } => seen == *key,
            Clause::Row { .. } => false,
        });
        if earlier {
            return Err(refused(grammar, CaptureCause::ClauseDoubled, *at));
        }
    }
    Ok(())
}

/// The value tokens one assigned clause carries, and the token its key sits at.
fn assigned<'trees, 'clauses>(
    clauses: &'clauses [Clause<'trees>],
    key: &str,
) -> Option<(&'clauses [&'trees CapturedTokenTree], SpanHandle)> {
    clauses.iter().find_map(|clause| match *clause {
        Clause::Assigned {
            key: named,
            ref value,
            at,
        } if named == key => Some((value.as_slice(), at)),
        Clause::Assigned { .. } | Clause::Row { .. } => None,
    })
}

/// One identifier a clause assigns.
fn identifier<'trees>(
    grammar: Grammar,
    clauses: &[Clause<'trees>],
    key: &str,
    at: SpanHandle,
) -> Result<&'trees str, BenchCaptureError> {
    let (value, clause) =
        assigned(clauses, key).ok_or_else(|| refused(grammar, CaptureCause::ClauseAbsent, at))?;
    let [only] = value else {
        return Err(refused(grammar, CaptureCause::ClauseUnread, clause));
    };
    only.word()
        .ok_or_else(|| refused(grammar, CaptureCause::ClauseUnread, only.span()))
}

/// One unsuffixed decimal count a clause assigns.
fn count<Number: core::str::FromStr>(
    grammar: Grammar,
    clauses: &[Clause<'_>],
    key: &str,
    at: SpanHandle,
) -> Result<Number, BenchCaptureError> {
    let (value, clause) =
        assigned(clauses, key).ok_or_else(|| refused(grammar, CaptureCause::ClauseAbsent, at))?;
    let [only] = value else {
        return Err(refused(grammar, CaptureCause::ClauseUnread, clause));
    };
    number(grammar, only)
}

/// One unsuffixed decimal literal, read at the exact width of the seat it fills.
fn number<Number: core::str::FromStr>(
    grammar: Grammar,
    tree: &CapturedTokenTree,
) -> Result<Number, BenchCaptureError> {
    let spelling = tree
        .number()
        .ok_or_else(|| refused(grammar, CaptureCause::ClauseUnread, tree.span()))?;
    if !spelling.bytes().all(|byte| byte.is_ascii_digit()) {
        return Err(refused(grammar, CaptureCause::ClauseUnread, tree.span()));
    }
    spelling
        .parse::<Number>()
        .map_err(|_| refused(grammar, CaptureCause::NumberBeyondSeat, tree.span()))
}

/// One `named(<namespace>, <stem>)` reference a clause assigns.
fn named_reference(
    grammar: Grammar,
    clauses: &[Clause<'_>],
    key: &str,
    at: SpanHandle,
) -> Result<Name, BenchCaptureError> {
    let (value, clause) =
        assigned(clauses, key).ok_or_else(|| refused(grammar, CaptureCause::ClauseAbsent, at))?;
    named_value(grammar, value, clause)
}

/// One `named(<namespace>, <stem>)` reference, read off the tokens that spell it.
fn named_value(
    grammar: Grammar,
    value: &[&CapturedTokenTree],
    at: SpanHandle,
) -> Result<Name, BenchCaptureError> {
    let [word, arguments] = value else {
        return Err(refused(grammar, CaptureCause::ReferenceUnread, at));
    };
    if word.word() != Some(NAMED) {
        return Err(refused(grammar, CaptureCause::ReferenceUnread, word.span()));
    }
    let Some((CapturedDelimiter::Parenthesis, inner)) = arguments.group() else {
        return Err(refused(
            grammar,
            CaptureCause::ReferenceUnread,
            arguments.span(),
        ));
    };
    let parts: Vec<&CapturedTokenTree> = inner.iter().collect();
    let [namespace, separator, stem] = parts.as_slice() else {
        return Err(refused(
            grammar,
            CaptureCause::ReferenceUnread,
            arguments.span(),
        ));
    };
    if separator.punct() != Some(',') {
        return Err(refused(
            grammar,
            CaptureCause::ReferenceUnread,
            separator.span(),
        ));
    }
    let (Some(owner), Some(spelling)) = (namespace.text(), stem.text()) else {
        return Err(refused(
            grammar,
            CaptureCause::ReferenceUnread,
            arguments.span(),
        ));
    };
    Name::named(owner, spelling).map_err(|refusal| carried(grammar, refusal, arguments.span()))
}

/// The bracketed axis of input sizes a row states.
fn axis(
    grammar: Grammar,
    clauses: &[Clause<'_>],
    at: SpanHandle,
) -> Result<Vec<u64>, BenchCaptureError> {
    let (value, clause) =
        assigned(clauses, AXIS).ok_or_else(|| refused(grammar, CaptureCause::ClauseAbsent, at))?;
    let [bracketed] = value else {
        return Err(refused(grammar, CaptureCause::RosterUnread, clause));
    };
    let Some((CapturedDelimiter::Bracket, inner)) = bracketed.group() else {
        return Err(refused(
            grammar,
            CaptureCause::RosterUnread,
            bracketed.span(),
        ));
    };
    let mut sizes: Vec<u64> = Vec::new();
    let mut group: Vec<&CapturedTokenTree> = Vec::new();
    for tree in inner {
        if tree.punct() == Some(',') {
            match group.as_slice() {
                [] => {
                    return Err(refused(
                        grammar,
                        CaptureCause::SeparatorDangling,
                        tree.span(),
                    ));
                }
                [only] => sizes.push(number::<u64>(grammar, only)?),
                [first, ..] => {
                    return Err(refused(grammar, CaptureCause::RosterUnread, first.span()));
                }
            }
            group.clear();
        } else {
            group.push(tree);
        }
    }
    match group.as_slice() {
        [] => {}
        [only] => sizes.push(number::<u64>(grammar, only)?),
        [first, ..] => return Err(refused(grammar, CaptureCause::RosterUnread, first.span())),
    }
    Ok(sizes)
}

/// The declared work formula, where the row states one.
fn formula(
    grammar: Grammar,
    clauses: &[Clause<'_>],
) -> Result<Option<WorkFormula>, BenchCaptureError> {
    let Some((value, at)) = assigned(clauses, FORMULA) else {
        return Ok(None);
    };
    let [only] = value else {
        return Err(refused(grammar, CaptureCause::ClauseUnread, at));
    };
    let text = only
        .text()
        .ok_or_else(|| refused(grammar, CaptureCause::ClauseUnread, only.span()))?;
    WorkFormula::encoded(text.as_bytes().to_vec())
        .map(Some)
        .map_err(|refusal| carried(grammar, refusal, only.span()))
}

/// The required bracketed roster of work-observation references a row states.
fn observations(
    grammar: Grammar,
    clauses: &[Clause<'_>],
    at: SpanHandle,
) -> Result<Vec<Name>, BenchCaptureError> {
    let (value, at) = assigned(clauses, OBSERVE)
        .ok_or_else(|| refused(grammar, CaptureCause::ClauseAbsent, at))?;
    let [bracketed] = value else {
        return Err(refused(grammar, CaptureCause::RosterUnread, at));
    };
    let Some((CapturedDelimiter::Bracket, inner)) = bracketed.group() else {
        return Err(refused(
            grammar,
            CaptureCause::RosterUnread,
            bracketed.span(),
        ));
    };
    let mut observed: Vec<Name> = Vec::new();
    let mut group: Vec<&CapturedTokenTree> = Vec::new();
    for tree in inner {
        if tree.punct() == Some(',') {
            if group.is_empty() {
                return Err(refused(
                    grammar,
                    CaptureCause::SeparatorDangling,
                    tree.span(),
                ));
            }
            observed.push(named_value(grammar, &group, bracketed.span())?);
            group.clear();
        } else {
            group.push(tree);
        }
    }
    if !group.is_empty() {
        observed.push(named_value(grammar, &group, bracketed.span())?);
    }
    Ok(observed)
}

/// One row: the lens it is declared under, and everything it states about how one workload is measured.
fn row(
    grammar: Grammar,
    lens: &str,
    body: &[&CapturedTokenTree],
    at: SpanHandle,
) -> Result<Row, BenchCaptureError> {
    let named = FunctionName::declared(lens).map_err(|refusal| carried(grammar, refusal, at))?;
    let clauses = row_clauses(grammar, body)?;
    let references = References {
        workload: named_reference(grammar, &clauses, WORKLOAD, at)?,
        correctness_preflight: named_reference(grammar, &clauses, PREFLIGHT, at)?,
        planted_worse: named_reference(grammar, &clauses, PLANTED_WORSE, at)?,
        complexity_claim: named_reference(grammar, &clauses, COMPLEXITY, at)?,
    };
    let sizes = axis(grammar, &clauses, at)?;
    let measurement = Measurement {
        budgets: Budgets {
            samples: count(grammar, &clauses, SAMPLES, at)?,
            warmups: count(grammar, &clauses, WARMUPS, at)?,
            ratio_numerator: count(grammar, &clauses, RATIO_NUMERATOR, at)?,
            ratio_denominator: count(grammar, &clauses, RATIO_DENOMINATOR, at)?,
        },
        contention: ContentionPosture::NoDeclaredContention,
        work_formula: formula(grammar, &clauses)?,
    };
    Row::declared(
        named,
        references,
        sizes,
        measurement,
        observations(grammar, &clauses, at)?,
    )
    .map_err(|refusal| carried(grammar, refusal, at))
}

/// Cut one row body into its comma-separated assignments.
///
/// A row admits no nested row, so the walk reads assignments alone and a lens written inside a row reaches the undeclarable-clause cause with every other key this level does not admit.
fn row_clauses<'trees>(
    grammar: Grammar,
    body: &[&'trees CapturedTokenTree],
) -> Result<Vec<Clause<'trees>>, BenchCaptureError> {
    let mut clauses: Vec<Clause<'trees>> = Vec::new();
    let mut group: Vec<&CapturedTokenTree> = Vec::new();
    for tree in body {
        if tree.punct() == Some(',') {
            let Some((head, rest)) = group.split_first() else {
                return Err(refused(
                    grammar,
                    CaptureCause::SeparatorDangling,
                    tree.span(),
                ));
            };
            clauses.push(assignment(grammar, head, rest, &DECLARABLE_ROW)?);
            group.clear();
        } else {
            group.push(tree);
        }
    }
    if let Some((head, rest)) = group.split_first() {
        clauses.push(assignment(grammar, head, rest, &DECLARABLE_ROW)?);
    }
    distinct(grammar, &clauses)?;
    Ok(clauses)
}