1use super::framework::*;
4
5pub const NESTING_LIMIT: u16 = 100;
6
7pub use RepeatOver as RO;
8
9#[derive(Debug, Copy, Clone, Eq, PartialEq, Display)]
10#[strum(serialize_all = "snake_case")]
11pub enum RepeatOver {
12 Variants,
13 Fields,
14}
15
16#[derive(Debug, Clone)]
17struct RepeatOverInference {
18 over: RepeatOver,
19 span: Span,
20}
21
22#[derive(Default, Debug, Clone)]
23pub struct RepeatAnalysisVisitor {
24 over: Option<RepeatOverInference>,
25}
26
27pub trait AnalyseRepeat {
28 fn analyse_repeat(
29 &self,
30 visitor: &mut RepeatAnalysisVisitor,
31 ) -> syn::Result<()>;
32}
33
34#[derive(Debug, Eq, PartialEq)]
38pub enum Fname<'r> {
39 Name(&'r syn::Ident),
40 Index(syn::Index),
41}
42
43impl RepeatAnalysisVisitor {
44 fn set_over(&mut self, over: RepeatOverInference) -> syn::Result<()> {
45 match &self.over {
46 None => self.over = Some(over),
47 Some(already) => {
48 if already.over != over.over {
49 let mut e1 = already.span.error(format_args!(
50 "inconsistent repetition depth: firstly, {} inferred here",
51 already.over,
52 ));
53 let e2 = over.span.error(format_args!(
54 "inconsistent repetition depth: secondly, {} inferred here",
55 over.over,
56 ));
57 e1.combine(e2);
58 return Err(e1);
59 }
60 }
61 }
62 Ok(())
63 }
64
65 pub fn finish(self, start: DelimSpan) -> Result<RepeatOver, syn::Error> {
66 Ok(self
67 .over
68 .ok_or_else(|| {
69 start.error(
70 "no contained expansion field determined what to repeat here"
71 )
72 })?
73 .over)
74 }
75}
76
77impl<O: SubstParseContext> AnalyseRepeat for SubstIf<O> {
78 fn analyse_repeat(
79 &self,
80 visitor: &mut RepeatAnalysisVisitor,
81 ) -> syn::Result<()> {
82 for (cond, _) in &self.tests {
83 cond.analyse_repeat(visitor)?;
84 }
93 if let Some(consequence) = &self.otherwise {
94 consequence.analyse_repeat(visitor)?;
95 }
96 Ok(())
97 }
98}
99
100impl<O: SubstParseContext> AnalyseRepeat for Template<O> {
101 fn analyse_repeat(
103 &self,
104 visitor: &mut RepeatAnalysisVisitor,
105 ) -> syn::Result<()> {
106 for element in &self.elements {
107 element.analyse_repeat(visitor)?;
108 }
109 Ok(())
110 }
111}
112
113impl<O: SubstParseContext> AnalyseRepeat for TemplateElement<O> {
114 fn analyse_repeat(
115 &self,
116 visitor: &mut RepeatAnalysisVisitor,
117 ) -> syn::Result<()> {
118 match self {
119 TE::Ident(..) => {}
120 TE::Literal(..) => {}
121 TE::LitStr(_) => {}
122 TE::Punct(..) => {}
123 TE::Repeat(_) => {}
124 TE::Group { template, .. } => template.analyse_repeat(visitor)?,
125 TE::Subst(exp) => exp.analyse_repeat(visitor)?,
126 }
127 Ok(())
128 }
129}
130
131impl<O: SubstParseContext> AnalyseRepeat for Subst<O> {
132 fn analyse_repeat(
133 &self,
134 visitor: &mut RepeatAnalysisVisitor,
135 ) -> syn::Result<()> {
136 macro_rules! recurse { { $v:expr } => { {
137 $v.analyse_repeat(visitor)?;
138 None
139 } } }
140
141 let over = match &self.sd {
142 SD::tname(..) => None,
143 SD::vname(..) => Some(RO::Variants),
144 SD::fname(..) => Some(RO::Fields),
145 SD::ttype(..) => None,
146 SD::tdeftype(..) => None,
147 SD::ftype(..) => Some(RO::Fields),
148 SD::fpatname(_) => Some(RO::Fields),
149 SD::vindex(..) => Some(RO::Variants),
150 SD::findex(..) => Some(RO::Fields),
151 SD::Vis(SubstVis::T, ..) => None,
152 SD::Vis(SubstVis::F, ..) => Some(RO::Fields),
153 SD::Vis(SubstVis::FD, ..) => Some(RO::Fields),
154 SD::Xmeta(sm) => sm.repeat_over(),
155 SD::tattrs(..) => None,
156 SD::vattrs(..) => Some(RO::Variants),
157 SD::fattrs(..) => Some(RO::Fields),
158 SD::tgens(..) => None,
159 SD::tdefgens(..) => None,
160 SD::tgnames(..) => None,
161 SD::twheres(..) => None,
162 SD::vpat(..) => Some(RO::Variants),
163 SD::vtype(..) => Some(RO::Variants),
164 SD::tdefkwd(..) => None,
165 SD::is_struct(..) => None,
166 SD::is_enum(..) => None,
167 SD::is_union(..) => None,
168 SD::v_is_unit(..) => Some(RO::Variants),
169 SD::v_is_tuple(..) => Some(RO::Variants),
170 SD::v_is_named(..) => Some(RO::Variants),
171 SD::tdefvariants(..) => None,
172 SD::fdefine(..) => Some(RO::Fields),
173 SD::vdefbody(..) => Some(RO::Variants),
174 SD::paste(body, ..) => recurse!(body),
175 SD::paste_spanned(span, content, ..) => {
176 span.analyse_repeat(visitor)?;
177 content.analyse_repeat(visitor)?;
178 None
179 }
180 SD::ChangeCase(body, ..) => recurse!(body),
181 SD::concat(body, ..) => recurse!(body),
182 SD::when(..) => None, SD::define(..) => None,
184 SD::defcond(..) => None,
185 SD::UserDefined(..) => None,
186 SD::is_empty(_, content) => recurse!(content),
187 SD::approx_equal(_, ab) => {
188 for x in ab {
189 x.analyse_repeat(visitor)?;
190 }
191 None
192 }
193 SD::not(cond, _) => recurse!(cond),
194 SD::If(conds, ..) | SD::select1(conds, ..) => recurse!(conds),
195 SD::any(conds, _) | SD::all(conds, _) => {
196 for c in conds.iter() {
197 c.analyse_repeat(visitor)?;
198 }
199 None
200 }
201 SD::For(..) => None,
203 SD::False(..) | SD::True(..) => None, SD::error(ee, _) => {
205 ee.message.analyse_repeat(visitor)?;
206 if let Some((span, _)) = &ee.span {
207 span.analyse_repeat(visitor)?;
208 }
209 None
210 }
211 SD::require_beta(..) => None,
212 SD::ignore(content, _) => recurse!(content),
213 SD::dbg(ddr) => recurse!(ddr.content_parsed),
214 SD::dbg_all_keywords(..) => None,
215 SD::Crate(..) => None,
216 };
217 if let Some(over) = over {
218 let over = RepeatOverInference {
219 over,
220 span: self.kw_span,
221 };
222 visitor.set_over(over)?;
223 }
224 Ok(())
225 }
226}
227
228pub trait WithinRepeatLevel<'w>: 'w {
232 fn level_display_name() -> &'static str;
233
234 fn current(ctx: &'w Context) -> Option<&'w Self>;
235
236 fn for_each<'c, F, E>(ctx: &'c Context<'c>, call: F) -> Result<(), E>
242 where
243 'c: 'w,
244 F: FnMut(&Context, &Self) -> Result<(), E>;
245
246 fn missing_repeat_level_special_error(
247 _ctx: &'w Context,
248 _span: Span,
249 ) -> Option<syn::Error> {
250 None
251 }
252}
253
254impl<'w> WithinRepeatLevel<'w> for WithinVariant<'w> {
255 fn level_display_name() -> &'static str {
256 "variant"
257 }
258
259 fn current(ctx: &'w Context) -> Option<&'w WithinVariant<'w>> {
260 ctx.variant
261 }
262
263 fn for_each<'c, F, E>(ctx: &'c Context<'c>, mut call: F) -> Result<(), E>
264 where
265 'c: 'w,
266 F: FnMut(&Context, &WithinVariant<'w>) -> Result<(), E>,
267 {
268 let mut within_variant =
269 |index, variant, ppv: &'c PreprocessedVariant| {
270 let fields = &ppv.fields;
271 let pmetas = &ppv.pmetas;
272 let pfields = &ppv.pfields;
273 let wv = WithinVariant {
274 variant,
275 fields,
276 pmetas,
277 pfields,
278 index,
279 };
280 let wv = &wv;
281 let ctx = Context {
282 variant: Some(wv),
283 ..*ctx
284 };
285 call(&ctx, wv)
286 };
287 match &ctx.top.data {
288 syn::Data::Enum(syn::DataEnum { variants, .. }) => {
289 for (index, (variant, pvariant)) in
290 izip!(variants, ctx.pvariants).enumerate()
291 {
292 let index = index.try_into().expect(">=2^32 variants!");
293 within_variant(index, Some(variant), pvariant)?;
294 }
295 }
296 syn::Data::Struct(_) | syn::Data::Union(_) => {
297 within_variant(0, None, &ctx.pvariants[0])?;
298 }
299 }
300 Ok(())
301 }
302}
303
304impl<'w> WithinRepeatLevel<'w> for WithinField<'w> {
305 fn level_display_name() -> &'static str {
306 "field"
307 }
308
309 fn current(ctx: &'w Context) -> Option<&'w WithinField<'w>> {
310 ctx.field
311 }
312
313 fn for_each<'c, F, E>(ctx: &'c Context<'c>, mut call: F) -> Result<(), E>
314 where
315 'c: 'w,
316 F: FnMut(&Context, &WithinField<'w>) -> Result<(), E>,
317 {
318 ctx.for_with_within(|ctx, variant: &WithinVariant| {
319 for (index, (field, pfield)) in
320 izip!(variant.fields, variant.pfields,).enumerate()
321 {
322 let index = index.try_into().expect(">=2^32 fields!");
327 let wf = WithinField {
328 field,
329 index,
330 pfield,
331 };
332 let wf = &wf;
333 let ctx = Context {
334 field: Some(wf),
335 ..*ctx
336 };
337 call(&ctx, wf)?;
338 }
339 Ok(())
340 })
341 }
342
343 fn missing_repeat_level_special_error(
344 ctx: &'w Context,
345 span: Span,
346 ) -> Option<syn::Error> {
347 if let Some(wv) = &ctx.variant {
348 return Some(span.error(
349 if wv.variant.is_some() {
350 "must be within a field, so within a field repeat group; but, is only within a variant repeat group"
352 } else {
353 "must be within a field, so within a field repeat group"
357 }
358 ));
359 }
360 None
361 }
362}
363
364impl<'c> Context<'c> {
365 pub fn error_loc(&self) -> ErrorLoc<'static> {
367 if let Some(field) = &self.field {
368 (field.field.span(), "in this field")
369 } else if let Some(variant) =
370 &self.variant.and_then(|variant| variant.variant.as_ref())
371 {
372 (variant.span(), "in this variant")
373 } else {
374 (self.top.span(), "in this data structure")
375 }
376 }
377
378 pub fn for_with_within<'w, W, F, E>(&'c self, mut call: F) -> Result<(), E>
383 where
384 'c: 'w,
385 W: WithinRepeatLevel<'w>,
386 F: FnMut(&Context, &W) -> Result<(), E>,
387 {
388 let ctx = self;
389 if let Some(w) = W::current(ctx) {
390 call(ctx, w)?;
391 } else {
392 W::for_each(ctx, call)?;
393 }
394 Ok(())
395 }
396
397 fn within_level<W>(&'c self, why: &dyn Spanned) -> syn::Result<&'c W>
402 where
403 W: WithinRepeatLevel<'c>,
404 {
405 W::current(self).ok_or_else(|| {
406 let span = why.span();
407 W::missing_repeat_level_special_error(self, span).unwrap_or_else(
408 || {
409 span.error(format_args!(
410 "must be within a {} (so, in a repeat group)",
411 W::level_display_name(),
412 ))
413 },
414 )
415 })
416 }
417
418 pub fn field(&self, why: &dyn Spanned) -> syn::Result<&WithinField<'_>> {
420 self.within_level(why)
421 }
422 pub fn variant(
424 &self,
425 why: &dyn Spanned,
426 ) -> syn::Result<&WithinVariant<'_>> {
427 self.within_level(why)
428 }
429 pub fn syn_variant(
431 &self,
432 why: &dyn Spanned,
433 ) -> syn::Result<&syn::Variant> {
434 let r = self.variant(why)?.variant.as_ref().ok_or_else(|| {
435 why.span().error("expansion only valid in enums")
436 })?;
437 Ok(r)
438 }
439}
440
441impl<'w> WithinField<'w> {
444 pub fn fname(&self, tspan: Span) -> Fname<'_> {
446 if let Some(fname) = &self.field.ident {
447 Fname::Name(fname)
449 } else {
450 Fname::Index(syn::Index {
451 index: self.index,
452 span: tspan,
453 })
454 }
455 }
456}
457
458impl IdentFrag for Fname<'_> {
459 type BadIdent = IdentFragInfallible;
460 fn frag_to_tokens(
461 &self,
462 out: &mut TokenStream,
463 ) -> Result<(), IdentFragInfallible> {
464 Ok(self.to_tokens(out))
465 }
466 fn fragment(&self) -> String {
467 self.to_string()
468 }
469}
470impl Display for Fname<'_> {
471 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
472 match self {
473 Fname::Name(v) => quote::IdentFragment::fmt(v, f),
474 Fname::Index(v) => quote::IdentFragment::fmt(v, f),
475 }
476 }
477}
478impl ToTokens for Fname<'_> {
479 fn to_tokens(&self, out: &mut TokenStream) {
480 match self {
481 Fname::Name(v) => v.to_tokens(out),
482 Fname::Index(v) => v.to_tokens(out),
483 }
484 }
485}
486
487impl<'w> WithinVariant<'w> {
490 pub fn is_struct_toplevel_as_variant(&self) -> bool {
491 self.variant.is_none()
492 }
493}
494
495impl<'c> GeneralContext<'c> {
498 pub fn find_definition<B>(
499 &'c self,
500 call: &'c DefinitionName,
501 ) -> syn::Result<Option<(&'c Definition<B>, GeneralContextBuf<'c>)>>
502 where
503 Definitions<'c>: AsRef<[&'c Definition<B>]>,
504 B: 'static,
505 {
506 let def = match self.defs().defs.find_raw(call) {
507 Some(y) => y,
508 None => return Ok(None),
509 };
510
511 let defs = self.defs().find_definition_deeper(&def.name, call)?;
512 let mut self_ = self.clone_buf();
513 *self_.as_mut() = defs;
514 Ok(Some((def, self_)))
515 }
516}
517
518impl<'c> DefinitionsContext<'c> {
519 pub fn find_definition_deeper(
521 &'c self,
522 def: &'c DefinitionName,
523 call: &'c DefinitionName,
524 ) -> syn::Result<DefinitionsContext<'c>> {
525 let nesting_depth = self.nesting_depth + 1;
526 let stack_entry = (self, call);
527 if nesting_depth > NESTING_LIMIT {
528 let mut errs = def.error(format_args!(
530 "probably-recursive user-defined expansion/condition (more than {} deep)",
531 NESTING_LIMIT
532 ));
533 let calls = {
535 let mut ascend = Some(stack_entry);
536 iter::from_fn(|| {
537 let (ctx, call) = ascend?;
538 ascend = ctx.nesting_parent;
539 Some((call, ctx.nesting_depth))
540 })
541 .collect_vec()
542 };
543
544 let calls = calls
549 .iter()
550 .rev()
551 .unique_by(
552 |(call, _)| *call as *const DefinitionName,
556 )
557 .collect_vec();
558
559 for (call, depth) in calls.iter().rev() {
563 errs.combine(call.error(format_args!(
564 "reference involved in too-deep expansion/condition, depth {}",
565 depth,
566 )));
567 }
568 return Err(errs);
569 }
570 Ok(DefinitionsContext {
571 nesting_depth,
572 nesting_parent: Some(stack_entry),
573 ..*self
574 })
575 }
576}
577
578pub struct DefinitionsIter<'c, B>(
579 Option<&'c Definitions<'c>>,
580 PhantomData<&'c B>,
581);
582
583impl<'c, B> Iterator for DefinitionsIter<'c, B>
584where
585 Definitions<'c>: AsRef<[&'c Definition<B>]>,
586{
587 type Item = &'c [&'c Definition<B>];
588 fn next(&mut self) -> Option<Self::Item> {
589 let here = self.0?;
590 let r = here.as_ref();
591 self.0 = here.earlier;
592 Some(r)
593 }
594}
595
596impl<'c> Definitions<'c> {
597 pub fn iter<B>(&'c self) -> DefinitionsIter<'c, B>
598 where
599 Definitions<'c>: AsRef<[&'c Definition<B>]>,
600 {
601 DefinitionsIter(Some(self), PhantomData)
602 }
603
604 pub fn find_raw<B>(
608 &'c self,
609 name: &DefinitionName,
610 ) -> Option<&'c Definition<B>>
611 where
612 Definitions<'c>: AsRef<[&'c Definition<B>]>,
613 B: 'static,
614 {
615 self.iter()
616 .map(|l| l.iter().rev())
617 .flatten()
618 .find(|def| &def.name == name)
619 .cloned()
620 }
621}
622
623impl<'c> AsRef<[&'c Definition<DefinitionBody>]> for Definitions<'c> {
624 fn as_ref(&self) -> &[&'c Definition<DefinitionBody>] {
625 self.here
626 }
627}
628impl<'c> AsRef<[&'c Definition<DefCondBody>]> for Definitions<'c> {
629 fn as_ref(&self) -> &[&'c Definition<DefCondBody>] {
630 self.conds
631 }
632}