1use proc_macro2::{Delimiter, Span};
2use syn::{Pat, parse::discouraged::AnyDelimiter, punctuated::Punctuated, *};
3
4#[cfg(feature = "printing")]
5use quote::IdentFragment;
6#[cfg(feature = "printing")]
7use std::fmt::{self, Display};
8use std::hash::{Hash, Hasher};
9#[cfg(feature = "parsing")]
10use std::mem;
11
12mod kw {
13 syn::custom_keyword!(forall);
14 syn::custom_keyword!(exists);
15 syn::custom_keyword!(dead);
16 syn::custom_keyword!(trigger);
17 syn::custom_keyword!(pearlite);
18 syn::custom_keyword!(seq);
19 syn::custom_keyword!(proof_assert);
20}
21
22ast_enum_of_structs! {
23 pub enum Term {
27 Array(TermArray),
29
30 Binary(TermBinary),
32
33 Block(TermBlock),
35
36 Call(TermCall),
38
39 Cast(TermCast),
41
42 Field(TermField),
45
46 Group(TermGroup),
52
53 If(TermIf),
59
60 Index(TermIndex),
62
63 Let(TermLet),
65
66 Lit(TermLit),
68
69 Match(TermMatch),
71
72 MethodCall(TermMethodCall),
74
75 Paren(TermParen),
77
78 Path(TermPath),
83
84 Range(TermRange),
86
87 Reference(TermReference),
89
90 Repeat(TermRepeat),
92
93 Struct(TermStruct),
98
99 Tuple(TermTuple),
101
102 Type(TermType),
104
105 Unary(TermUnary),
107
108 Final(TermFinal),
110
111 View(TermView),
113
114 Impl(TermImpl),
116
117 Quant(TermQuant),
119
120 Dead(TermDead),
122
123 Pearlite(TermPearlite),
125
126 ProofAssert(TermProofAssert),
128
129 Seq(TermSeq),
131
132 Closure(TermClosure),
134
135 #[doc(hidden)]
136 __Nonexhaustive,
137 }
138}
139
140ast_enum_of_structs! {
141 pub enum EnsuresTerm {
142 TermWithTriggers(TermWithTriggers),
143 EnsuresClosure(EnsuresClosure),
144 }
145}
146
147ast_struct! {
148 pub struct EnsuresClosure {
149 pub or1_token: Token![|],
150 pub result: Pat,
151 pub or2_token: Token![|],
152 pub body: Box<TermWithTriggers>,
153 }
154}
155
156ast_struct! {
157 pub struct TermBlock {
159 pub brace_token: token::Brace,
160 pub stmts: Vec<TermStmt>,
162 }
163}
164
165ast_enum! {
166 #[derive(Debug)]
168 pub enum TermStmt {
169 Local(TLocal),
171
172 Item(Item),
174
175 Expr(Term),
177
178 Semi(Term, Token![;]),
180
181 Empty(Token![;]),
183 }
184}
185
186ast_struct! {
187 pub struct TLocal {
189 pub let_token: Token![let],
190 pub pat: Pat,
191 pub init: Option<(Token![=], Box<Term>)>,
192 pub semi_token: Token![;],
193 }
194}
195
196ast_struct! {
197 pub struct TermArray #full {
199 pub bracket_token: token::Bracket,
200 pub elems: Punctuated<Term, Token![,]>,
201 }
202}
203
204ast_struct! {
205 pub struct TermBinary {
207 pub left: Box<Term>,
208 pub op: BinOp,
209 pub right: Box<Term>,
210 }
211}
212
213ast_struct! {
214 pub struct TermCall {
216 pub func: Box<Term>,
217 pub paren_token: token::Paren,
218 pub args: Punctuated<Term, Token![,]>,
219 }
220}
221
222ast_struct! {
223 pub struct TermCast {
225 pub expr: Box<Term>,
226 pub as_token: Token![as],
227 pub ty: Box<Type>,
228 }
229}
230
231ast_struct! {
232 pub struct TermClosure #full {
234 pub attrs: Vec<Attribute>,
235 pub or1_token: Token![|],
236 pub inputs: Punctuated<Pat, Token![,]>,
237 pub or2_token: Token![|],
238 pub output: ReturnType,
239 pub body: Box<Term>,
240 }
241}
242
243ast_struct! {
244 pub struct TermField {
247 pub base: Box<Term>,
248 pub dot_token: Token![.],
249 pub member: Member,
250 }
251}
252
253ast_struct! {
254 pub struct TermGroup #full {
260 pub group_token: token::Group,
261 pub expr: Box<Term>,
262 }
263}
264
265ast_struct! {
266 pub struct TermIf #full {
272 pub if_token: Token![if],
273 pub cond: Box<Term>,
274 pub then_branch: TermBlock,
275 pub else_branch: Option<(Token![else], Box<Term>)>,
276 }
277}
278
279ast_struct! {
280 pub struct TermIndex {
282 pub expr: Box<Term>,
283 pub bracket_token: token::Bracket,
284 pub index: Box<Term>,
285 }
286}
287
288ast_struct! {
289 pub struct TermLet #full {
291 pub let_token: Token![let],
292 pub pat: Pat,
293 pub eq_token: Token![=],
294 pub expr: Box<Term>,
295 }
296}
297
298ast_struct! {
299 pub struct TermLit {
301 pub lit: Lit,
302 }
303}
304
305ast_struct! {
306 pub struct TermMatch #full {
308 pub match_token: Token![match],
309 pub expr: Box<Term>,
310 pub brace_token: token::Brace,
311 pub arms: Vec<TermArm>,
312 }
313}
314
315ast_struct! {
316 pub struct TermMethodCall #full {
318 pub receiver: Box<Term>,
319 pub dot_token: Token![.],
320 pub method: Ident,
321 pub turbofish: Option<TermMethodTurbofish>,
322 pub paren_token: token::Paren,
323 pub args: Punctuated<Term, Token![,]>,
324 }
325}
326
327ast_struct! {
328 pub struct TermParen {
330 pub paren_token: token::Paren,
331 pub expr: Box<Term>,
332 }
333}
334
335ast_struct! {
336 pub struct TermPath {
341 pub inner: ExprPath,
342 }
345}
346
347ast_struct! {
348 pub struct TermRange #full {
350 pub from: Option<Box<Term>>,
351 pub limits: RangeLimits,
352 pub to: Option<Box<Term>>,
353 }
354}
355
356ast_struct! {
357 pub struct TermReference #full {
359 pub and_token: Token![&],
360 pub mutability: Option<Token![mut]>,
361 pub expr: Box<Term>,
362 }
363}
364
365ast_struct! {
366 pub struct TermRepeat #full {
368 pub bracket_token: token::Bracket,
369 pub expr: Box<Term>,
370 pub semi_token: Token![;],
371 pub len: Box<Term>,
372 }
373}
374
375ast_struct! {
376 pub struct TermStruct #full {
381 pub path: Path,
382 pub brace_token: token::Brace,
383 pub fields: Punctuated<TermFieldValue, Token![,]>,
384 pub dot2_token: Option<Token![..]>,
385 pub rest: Option<Box<Term>>,
386 }
387}
388
389ast_struct! {
390 pub struct TermTuple #full {
392 pub paren_token: token::Paren,
393 pub elems: Punctuated<Term, Token![,]>,
394 }
395}
396
397ast_struct! {
398 pub struct TermType #full {
400 pub expr: Box<Term>,
401 pub colon_token: Token![:],
402 pub ty: Box<Type>,
403 }
404}
405
406ast_struct! {
407 pub struct TermUnary {
409 pub op: UnOp,
410 pub expr: Box<Term>,
411 }
412}
413
414ast_struct! {
415 pub struct TermImpl {
416 pub hyp: Box<Term>,
417 pub eqeq_token: Token![==],
418 pub gt_token: Token![>],
419 pub cons: Box<Term>,
420 }
421}
422
423ast_struct! {
424 pub struct TermFinal {
425 pub final_token: Token![^],
426 pub term: Box<Term>
427 }
428}
429
430ast_struct! {
431 pub struct TermView {
432 pub term: Box<Term>,
433 pub at_token: Token![@],
434 }
435}
436
437ast_struct! {
438 pub struct TermQuant {
439 pub quant_token: QuantToken,
440 pub lt_token: Token![<],
441 pub args: Punctuated<QuantArg, Token![,]>,
442 pub gt_token: Token![>],
443 pub term: TermWithTriggers
444 }
445}
446
447ast_struct! {
448 pub struct TermWithTriggers {
449 pub trigger: Vec<Trigger>,
450 pub term: Box<Term>
451 }
452}
453
454use kw::{exists, forall};
455ast_enum_of_structs! {
456 pub enum QuantToken {
457 Forall(forall),
458 Exists(exists),
459 }
460}
461
462ast_struct! {
463 pub struct QuantArg {
464 pub ident: Ident,
465 pub ty: Option<(Token![:], Box<Type>)>,
466 }
467}
468
469ast_struct! {
470 pub struct Trigger {
471 pub pound_token: Token![#],
472 pub bracket_token: token::Bracket,
473 pub trigger_token: kw::trigger,
474 pub paren_token: token::Paren,
475 pub terms: Punctuated<Term, Token![,]>,
476 }
477}
478
479ast_struct! {
480 pub struct TermDead {
481 pub dead_token: kw::dead
482 }
483}
484
485ast_struct! {
486 pub struct TermPearlite {
487 pub pearlite_token: kw::pearlite,
488 pub bang_token: Token![!],
489 pub block: TermBlock,
490 }
491}
492
493ast_struct! {
494 pub struct TermProofAssert {
495 pub proof_assert_token: kw::proof_assert,
496 pub bang_token: Token![!],
497 pub block: TermBlock,
498 }
499}
500
501ast_struct! {
502 pub struct TermSeq {
503 pub seq_token: kw::seq,
504 pub bang_token: Token![!],
505 pub bracket_token: token::Bracket,
506 pub terms: Punctuated<Term, Token![,]>,
507 }
508}
509
510ast_struct! {
511 pub struct Index {
513 pub index: u32,
514 pub span: Span,
515 }
516}
517
518impl From<usize> for Index {
519 fn from(index: usize) -> Index {
520 assert!(index < u32::MAX as usize);
521 Index { index: index as u32, span: Span::call_site() }
522 }
523}
524
525impl Eq for Index {}
526
527impl PartialEq for Index {
528 fn eq(&self, other: &Self) -> bool {
529 self.index == other.index
530 }
531}
532
533impl Hash for Index {
534 fn hash<H: Hasher>(&self, state: &mut H) {
535 self.index.hash(state);
536 }
537}
538
539#[cfg(feature = "printing")]
540impl IdentFragment for Index {
541 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
542 Display::fmt(&self.index, formatter)
543 }
544
545 fn span(&self) -> Option<Span> {
546 Some(self.span)
547 }
548}
549
550#[cfg(feature = "full")]
551ast_struct! {
552 pub struct TermMethodTurbofish {
555 pub colon2_token: Token![::],
556 pub lt_token: Token![<],
557 pub args: Punctuated<TermGenericMethodArgument, Token![,]>,
558 pub gt_token: Token![>],
559 }
560}
561
562#[cfg(feature = "full")]
563ast_enum! {
564 #[derive(Debug)]
567 pub enum TermGenericMethodArgument {
568 Type(Type),
570 Const(Term),
575 }
576}
577
578#[cfg(feature = "full")]
579ast_struct! {
580 pub struct TermFieldValue {
582 pub member: Member,
584
585 pub colon_token: Option<Token![:]>,
588
589 pub expr: Term,
591 }
592}
593
594#[cfg(feature = "full")]
595ast_struct! {
596 pub struct TermArm {
614 pub pat: Pat,
615 pub guard: Option<(Token![if], Box<Term>)>,
616 pub fat_arrow_token: Token![=>],
617 pub body: Box<Term>,
618 pub comma: Option<Token![,]>,
619 }
620}
621
622#[cfg(any(feature = "parsing", feature = "printing"))]
623#[cfg(feature = "full")]
624pub(crate) fn requires_terminator(expr: &Term) -> bool {
625 !matches!(*expr, Term::Block(..) | Term::If(..) | Term::Match(..))
627}
628
629#[cfg(feature = "parsing")]
630pub(crate) mod parsing {
631 use super::*;
632 use std::cmp::Ordering;
633 use syn::{
634 parse::{Parse, ParseStream, Result},
635 spanned::Spanned,
636 };
637
638 syn::custom_keyword!(raw);
639
640 pub struct AllowStruct(bool);
646
647 enum Precedence {
648 Any,
649 Assign,
650 Impl,
651 Range,
652 Or,
653 And,
654 Compare,
655 BitOr,
656 BitXor,
657 BitAnd,
658 Shift,
659 Arithmetic,
660 Term,
661 Cast,
662 }
663
664 impl Precedence {
665 fn of(op: &BinOp) -> Self {
666 match *op {
667 BinOp::Add(_) | BinOp::Sub(_) => Precedence::Arithmetic,
668 BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Term,
669 BinOp::And(_) => Precedence::And,
670 BinOp::Or(_) => Precedence::Or,
671 BinOp::BitXor(_) => Precedence::BitXor,
672 BinOp::BitAnd(_) => Precedence::BitAnd,
673 BinOp::BitOr(_) => Precedence::BitOr,
674 BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
675 BinOp::Eq(_)
676 | BinOp::Lt(_)
677 | BinOp::Le(_)
678 | BinOp::Ne(_)
679 | BinOp::Ge(_)
680 | BinOp::Gt(_) => Precedence::Compare,
681 BinOp::AddAssign(_)
682 | BinOp::SubAssign(_)
683 | BinOp::MulAssign(_)
684 | BinOp::DivAssign(_)
685 | BinOp::RemAssign(_)
686 | BinOp::BitXorAssign(_)
687 | BinOp::BitAndAssign(_)
688 | BinOp::BitOrAssign(_)
689 | BinOp::ShlAssign(_)
690 | BinOp::ShrAssign(_) => Precedence::Assign,
691 _ => unimplemented!(),
692 }
693 }
694 }
695
696 impl TermBlock {
697 pub fn parse_within(input: ParseStream) -> Result<Vec<TermStmt>> {
698 let mut stmts = Vec::new();
699 loop {
700 while let Some(semi) = input.parse::<Option<Token![;]>>()? {
701 stmts.push(TermStmt::Empty(semi));
702 }
703 if input.is_empty() {
704 break;
705 }
706 let s = parse_stmt(input, true)?;
707 let requires_semicolon =
708 if let TermStmt::Expr(s) = &s { super::requires_terminator(s) } else { false };
709 stmts.push(s);
710 if input.is_empty() {
711 break;
712 } else if requires_semicolon {
713 return Err(input.error("unexpected token"));
714 }
715 }
716 Ok(stmts)
717 }
718 }
719
720 impl Parse for TermBlock {
721 fn parse(input: ParseStream) -> Result<Self> {
722 let content;
723 Ok(TermBlock {
724 brace_token: braced!(content in input),
725 stmts: content.call(TermBlock::parse_within)?,
726 })
727 }
728 }
729
730 impl Parse for TermStmt {
731 fn parse(input: ParseStream) -> Result<Self> {
732 parse_stmt(input, false)
733 }
734 }
735
736 pub(crate) fn replace_attrs(item: &mut Item, new: Vec<Attribute>) -> Vec<Attribute> {
737 match item {
738 Item::Const(ItemConst { attrs, .. })
739 | Item::Enum(ItemEnum { attrs, .. })
740 | Item::ExternCrate(ItemExternCrate { attrs, .. })
741 | Item::Fn(ItemFn { attrs, .. })
742 | Item::ForeignMod(ItemForeignMod { attrs, .. })
743 | Item::Impl(ItemImpl { attrs, .. })
744 | Item::Macro(ItemMacro { attrs, .. })
745 | Item::Mod(ItemMod { attrs, .. })
746 | Item::Static(ItemStatic { attrs, .. })
747 | Item::Struct(ItemStruct { attrs, .. })
748 | Item::Trait(ItemTrait { attrs, .. })
749 | Item::TraitAlias(ItemTraitAlias { attrs, .. })
750 | Item::Type(ItemType { attrs, .. })
751 | Item::Union(ItemUnion { attrs, .. })
752 | Item::Use(ItemUse { attrs, .. }) => mem::replace(attrs, new),
753 Item::Verbatim(_) | _ => Vec::new(),
754 }
755 }
756
757 fn parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<TermStmt> {
758 let mut attrs = input.call(Attribute::parse_outer)?;
759 if input.peek(Token![let]) {
760 stmt_local(input).map(TermStmt::Local)
761 } else if input.peek(Token![use]) {
762 let item: Item = input.parse()?;
763 Ok(TermStmt::Item(item))
764 } else if input.peek(Token![pub])
765 || input.peek(Token![crate]) && !input.peek2(Token![::])
766 || input.peek(Token![use])
767 || input.peek(Token![fn])
768 || input.peek(Token![mod])
769 || input.peek(Token![type])
770 || input.peek(Token![struct])
771 || input.peek(Token![enum])
772 || input.peek(Token![union]) && input.peek2(Ident)
773 || input.peek(Token![trait])
774 || input.peek(Token![impl])
775 {
776 let mut item: Item = input.parse()?;
777 attrs.extend(replace_attrs(&mut item, Vec::new()));
778 replace_attrs(&mut item, attrs);
779 Ok(TermStmt::Item(item))
780 } else {
781 stmt_expr(input, allow_nosemi)
782 }
783 }
784
785 fn stmt_local(input: ParseStream) -> Result<TLocal> {
786 Ok(TLocal {
787 let_token: input.parse()?,
788 pat: {
789 let mut pat = Pat::parse_single(input)?;
791 if input.peek(Token![:]) {
792 let colon_token: Token![:] = input.parse()?;
793 let ty: Type = input.parse()?;
794 pat = Pat::Type(PatType {
795 attrs: Vec::new(),
796 pat: Box::new(pat),
797 colon_token,
798 ty: Box::new(ty),
799 });
800 }
801 pat
802 },
803 init: {
804 if input.peek(Token![=]) {
805 let eq_token: Token![=] = input.parse()?;
806 let init: Term = input.parse()?;
807 Some((eq_token, Box::new(init)))
808 } else {
809 None
810 }
811 },
812 semi_token: input.parse()?,
813 })
814 }
815
816 fn stmt_expr(input: ParseStream, allow_nosemi: bool) -> Result<TermStmt> {
817 let e = term_early(input)?;
818
819 if input.peek(Token![;]) {
820 return Ok(TermStmt::Semi(e, input.parse()?));
821 }
822
823 if allow_nosemi || !super::requires_terminator(&e) {
824 Ok(TermStmt::Expr(e))
825 } else {
826 Err(input.error("expected semicolon"))
827 }
828 }
829
830 impl Parse for Term {
831 fn parse(input: ParseStream) -> Result<Self> {
832 ambiguous_term(input, AllowStruct(true))
833 }
834 }
835
836 impl Term {
837 pub fn parse_without_eager_brace(input: ParseStream) -> Result<Term> {
918 ambiguous_term(input, AllowStruct(false))
919 }
920 }
921
922 impl Copy for AllowStruct {}
923
924 impl Clone for AllowStruct {
925 fn clone(&self) -> Self {
926 *self
927 }
928 }
929
930 impl Copy for Precedence {}
931
932 impl Clone for Precedence {
933 fn clone(&self) -> Self {
934 *self
935 }
936 }
937
938 impl PartialEq for Precedence {
939 fn eq(&self, other: &Self) -> bool {
940 *self as u8 == *other as u8
941 }
942 }
943
944 impl PartialOrd for Precedence {
945 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
946 let this = *self as u8;
947 let other = *other as u8;
948 Some(this.cmp(&other))
949 }
950 }
951
952 fn parse_term(
953 input: ParseStream,
954 mut lhs: Term,
955 allow_struct: AllowStruct,
956 base: Precedence,
957 ) -> Result<Term> {
958 loop {
959 if Precedence::Impl >= base && input.peek(Token![==]) && input.peek3(Token![>]) {
960 let eqeq_token: Token![==] = input.parse()?;
962 let gt_token: Token![>] = input.parse()?;
963 let precedence = Precedence::Impl;
964 let mut rhs = unary_term(input, allow_struct)?;
965 loop {
966 let next = peek_precedence(input);
967 if next >= precedence {
968 rhs = parse_term(input, rhs, allow_struct, next)?;
969 } else {
970 break;
971 }
972 }
973 lhs = Term::Impl(TermImpl {
974 hyp: Box::new(lhs),
975 eqeq_token,
976 gt_token,
977 cons: Box::new(rhs),
978 });
979 } else if Precedence::Range >= base && input.peek(Token![..]) || input.peek(Token![..=])
980 {
981 let limits: RangeLimits = input.parse()?;
982 let precedence = Precedence::Range;
983 if input.is_empty() {
984 if matches!(limits, RangeLimits::Closed(_)) {
985 return Err(input.error("expected expression after ..="));
986 }
987 return Ok(Term::Range(TermRange { from: Some(lhs.into()), limits, to: None }));
988 }
989 let mut rhs = unary_term(input, allow_struct)?;
990 loop {
991 let next = peek_precedence(input);
992 if next >= precedence {
993 rhs = parse_term(input, rhs, allow_struct, next)?;
994 } else {
995 break;
996 }
997 }
998 lhs =
999 Term::Range(TermRange { from: Some(lhs.into()), limits, to: Some(rhs.into()) })
1000 } else if input
1001 .fork()
1002 .parse::<BinOp>()
1003 .ok()
1004 .is_some_and(|op| Precedence::of(&op) >= base)
1005 && !(input.peek(Token![==]) && input.peek3(Token![>]))
1006 {
1007 let op: BinOp = input.parse()?;
1008 let precedence = Precedence::of(&op);
1009 let mut rhs = unary_term(input, allow_struct)?;
1010 loop {
1011 let next = peek_precedence(input);
1012 if next > precedence || next == precedence && precedence == Precedence::Assign {
1013 rhs = parse_term(input, rhs, allow_struct, next)?;
1014 } else {
1015 break;
1016 }
1017 }
1018 lhs = Term::Binary(TermBinary { left: Box::new(lhs), op, right: Box::new(rhs) });
1019 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1020 let as_token: Token![as] = input.parse()?;
1021 let ty = input.call(Type::without_plus)?;
1022 lhs = Term::Cast(TermCast { expr: Box::new(lhs), as_token, ty: Box::new(ty) });
1023 } else if Precedence::Cast >= base && input.peek(Token![:]) && !input.peek(Token![::]) {
1024 let colon_token: Token![:] = input.parse()?;
1025 let ty = input.call(Type::without_plus)?;
1026 lhs = Term::Type(TermType { expr: Box::new(lhs), colon_token, ty: Box::new(ty) });
1027 } else {
1028 break;
1029 }
1030 }
1031
1032 Ok(lhs)
1033 }
1034
1035 fn peek_precedence(input: ParseStream) -> Precedence {
1036 if input.peek(Token![==]) && input.peek3(Token![>]) {
1037 Precedence::Impl
1038 } else if let Ok(op) = input.fork().parse() {
1039 Precedence::of(&op)
1040 } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
1041 Precedence::Assign
1042 } else if input.peek(Token![..]) {
1043 Precedence::Range
1044 } else if input.peek(Token![as]) || input.peek(Token![:]) && !input.peek(Token![::]) {
1045 Precedence::Cast
1046 } else {
1047 Precedence::Any
1048 }
1049 }
1050
1051 fn ambiguous_term(input: ParseStream, allow_struct: AllowStruct) -> Result<Term> {
1053 let lhs = unary_term(input, allow_struct)?;
1054 parse_term(input, lhs, allow_struct, Precedence::Any)
1055 }
1056
1057 fn unary_term(input: ParseStream, allow_struct: AllowStruct) -> Result<Term> {
1058 if input.peek(Token![&]) {
1059 Ok(Term::Reference(TermReference {
1060 and_token: input.parse()?,
1061 mutability: input.parse()?,
1062 expr: Box::new(unary_term(input, allow_struct)?),
1063 }))
1064 } else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
1065 Ok(Term::Unary(TermUnary {
1067 op: input.parse()?,
1068 expr: Box::new(unary_term(input, allow_struct)?),
1069 }))
1070 } else if input.peek(Token![^]) {
1071 Ok(Term::Final(TermFinal {
1073 final_token: input.parse()?,
1074 term: Box::new(unary_term(input, allow_struct)?),
1075 }))
1076 } else {
1077 trailer_term(input, allow_struct)
1078 }
1079 }
1080
1081 fn trailer_term(input: ParseStream, allow_struct: AllowStruct) -> Result<Term> {
1088 let atom = atom_term(input, allow_struct)?;
1089 let e = trailer_helper(input, atom)?;
1090 Ok(e)
1091 }
1092
1093 fn trailer_helper(input: ParseStream, mut e: Term) -> Result<Term> {
1094 loop {
1095 if input.peek(token::Paren) {
1096 let content;
1097 e = Term::Call(TermCall {
1098 func: Box::new(e),
1099 paren_token: parenthesized!(content in input),
1100 args: content.parse_terminated(Term::parse, Token![,])?,
1101 });
1102 } else if input.peek(Token![.]) && !input.peek(Token![..]) {
1103 let mut dot_token: Token![.] = input.parse()?;
1104
1105 let float_token: Option<LitFloat> = input.parse()?;
1106 if let Some(float_token) = float_token {
1107 if multi_index(&mut e, &mut dot_token, float_token)? {
1108 continue;
1109 }
1110 }
1111
1112 let member: Member = input.parse()?;
1113 let turbofish = if matches!(member, Member::Named(_)) && input.peek(Token![::]) {
1114 Some(TermMethodTurbofish {
1115 colon2_token: input.parse()?,
1116 lt_token: input.parse()?,
1117 args: {
1118 let mut args = Punctuated::new();
1119 loop {
1120 if input.peek(Token![>]) {
1121 break;
1122 }
1123 let value = input.call(generic_method_argument)?;
1124 args.push_value(value);
1125 if input.peek(Token![>]) {
1126 break;
1127 }
1128 let punct = input.parse()?;
1129 args.push_punct(punct);
1130 }
1131 args
1132 },
1133 gt_token: input.parse()?,
1134 })
1135 } else {
1136 None
1137 };
1138
1139 if turbofish.is_some() || input.peek(token::Paren) {
1140 if let Member::Named(method) = member {
1141 let content;
1142 e = Term::MethodCall(TermMethodCall {
1143 receiver: Box::new(e),
1144 dot_token,
1145 method,
1146 turbofish,
1147 paren_token: parenthesized!(content in input),
1148 args: content.parse_terminated(Term::parse, Token![,])?,
1149 });
1150 continue;
1151 }
1152 }
1153
1154 e = Term::Field(TermField { base: Box::new(e), dot_token, member });
1155 } else if input.peek(token::Bracket) {
1156 let content;
1157 e = Term::Index(TermIndex {
1158 expr: Box::new(e),
1159 bracket_token: bracketed!(content in input),
1160 index: content.parse()?,
1161 });
1162 } else if input.peek(Token![@]) {
1163 e = Term::View(TermView { term: Box::new(e), at_token: input.parse()? });
1164 } else {
1165 break;
1166 }
1167 }
1168 Ok(e)
1169 }
1170
1171 fn atom_term(input: ParseStream, allow_struct: AllowStruct) -> Result<Term> {
1174 if input.peek(token::Group)
1175 && !input.peek2(Token![::])
1176 && !input.peek2(Token![!])
1177 && !input.peek2(token::Brace)
1178 {
1179 input.call(term_group).map(Term::Group)
1180 } else if input.peek(Lit) {
1181 input.parse().map(Term::Lit)
1182 } else if input.peek(Token![|]) {
1183 term_closure(input, allow_struct).map(Term::Closure)
1184 } else if (input.peek(Ident)
1185 && !(input.peek(kw::forall)
1186 || input.peek(kw::exists)
1187 || input.peek(kw::dead)
1188 || input.peek(kw::pearlite)))
1189 || input.peek(Token![::])
1190 || input.peek(Token![<])
1191 || input.peek(Token![self])
1192 || input.peek(Token![Self])
1193 || input.peek(Token![super])
1194 || input.peek(Token![crate])
1195 {
1196 path_or_macro_or_struct(input, allow_struct)
1197 } else if input.peek(token::Paren) {
1198 paren_or_tuple(input)
1199 } else if input.peek(token::Bracket) {
1200 array_or_repeat(input)
1201 } else if input.peek(Token![let]) {
1202 input.call(term_let).map(Term::Let)
1203 } else if input.peek(Token![if]) {
1204 input.parse().map(Term::If)
1205 } else if input.peek(kw::forall) || input.peek(kw::exists) {
1206 input.parse().map(Term::Quant)
1207 } else if input.peek(kw::dead) {
1208 input.parse().map(Term::Dead)
1209 } else if input.peek(kw::pearlite) {
1210 input.parse().map(Term::Pearlite)
1211 } else if input.peek(Token![match]) {
1212 input.parse().map(Term::Match)
1213 } else if input.peek(token::Brace) {
1214 input.call(term_block).map(Term::Block)
1215 } else if input.peek(Token![..]) {
1216 term_range(input, allow_struct).map(Term::Range)
1217 } else {
1218 Err(input.error("expected term"))
1219 }
1220 }
1221
1222 fn is_mod_style(p: &Path) -> bool {
1223 p.segments.iter().all(|segment| segment.arguments.is_none())
1224 }
1225
1226 fn path_or_macro_or_struct(input: ParseStream, allow_struct: AllowStruct) -> Result<Term> {
1227 let expr: TermPath = input.parse()?;
1228
1229 if expr.inner.qself.is_none()
1230 && input.peek(Token![!])
1231 && !input.peek(Token![!=])
1232 && is_mod_style(&expr.inner.path)
1233 {
1234 let bang_token: Token![!] = input.parse()?;
1235
1236 let (_, span_delim, tokens) = input.parse_any_delimiter()?;
1237
1238 if expr.inner.path.is_ident("proof_assert") {
1244 return Ok(Term::ProofAssert(TermProofAssert {
1245 proof_assert_token: kw::proof_assert(expr.inner.span()),
1246 bang_token,
1247 block: TermBlock {
1248 brace_token: token::Brace(span_delim),
1249 stmts: TermBlock::parse_within(&tokens)?,
1250 },
1251 }));
1252 } else if expr.inner.path.is_ident("pearlite") {
1253 return Ok(Term::Pearlite(TermPearlite {
1254 pearlite_token: kw::pearlite(expr.inner.span()),
1255 bang_token,
1256 block: TermBlock {
1257 brace_token: token::Brace(span_delim),
1258 stmts: TermBlock::parse_within(&tokens)?,
1259 },
1260 }));
1261 } else if expr.inner.path.is_ident("seq") {
1262 return Ok(Term::Seq(TermSeq {
1263 seq_token: kw::seq(expr.inner.span()),
1264 bang_token,
1265 bracket_token: token::Bracket(span_delim),
1266 terms: Punctuated::parse_terminated(&tokens)?,
1267 }));
1268 } else {
1269 return Err(Error::new_spanned(
1270 expr,
1271 " Unsupported expression: macros other than `pearlite!`, `proof_assert!` or `seq!` are unsupported in Pearlite code.",
1272 ));
1273 }
1274 }
1275
1276 if allow_struct.0 && input.peek(token::Brace) {
1277 term_struct_helper(input, expr.inner.path).map(Term::Struct)
1278 } else {
1279 Ok(Term::Path(expr))
1280 }
1281 }
1282
1283 fn paren_or_tuple(input: ParseStream) -> Result<Term> {
1284 let content;
1285 let paren_token = parenthesized!(content in input);
1286 if content.is_empty() {
1287 return Ok(Term::Tuple(TermTuple { paren_token, elems: Punctuated::new() }));
1288 }
1289
1290 let first: Term = content.parse()?;
1291 if content.is_empty() {
1292 return Ok(Term::Paren(TermParen { paren_token, expr: Box::new(first) }));
1293 }
1294
1295 let mut elems = Punctuated::new();
1296 elems.push_value(first);
1297 while !content.is_empty() {
1298 let punct = content.parse()?;
1299 elems.push_punct(punct);
1300 if content.is_empty() {
1301 break;
1302 }
1303 let value = content.parse()?;
1304 elems.push_value(value);
1305 }
1306 Ok(Term::Tuple(TermTuple { paren_token, elems }))
1307 }
1308
1309 fn array_or_repeat(input: ParseStream) -> Result<Term> {
1310 let content;
1311 let bracket_token = bracketed!(content in input);
1312 if content.is_empty() {
1313 return Ok(Term::Array(TermArray { bracket_token, elems: Punctuated::new() }));
1314 }
1315
1316 let first: Term = content.parse()?;
1317 if content.is_empty() || content.peek(Token![,]) {
1318 let mut elems = Punctuated::new();
1319 elems.push_value(first);
1320 while !content.is_empty() {
1321 let punct = content.parse()?;
1322 elems.push_punct(punct);
1323 if content.is_empty() {
1324 break;
1325 }
1326 let value = content.parse()?;
1327 elems.push_value(value);
1328 }
1329 Ok(Term::Array(TermArray { bracket_token, elems }))
1330 } else if content.peek(Token![;]) {
1331 let semi_token: Token![;] = content.parse()?;
1332 let len: Term = content.parse()?;
1333 Ok(Term::Repeat(TermRepeat {
1334 bracket_token,
1335 expr: Box::new(first),
1336 semi_token,
1337 len: Box::new(len),
1338 }))
1339 } else {
1340 Err(content.error("expected `,` or `;`"))
1341 }
1342 }
1343
1344 pub(crate) fn term_early(input: ParseStream) -> Result<Term> {
1345 let mut expr = if input.peek(Token![if]) {
1346 Term::If(input.parse()?)
1347 } else if input.peek(Token![match]) {
1348 Term::Match(input.parse()?)
1349 } else if input.peek(token::Brace) {
1350 Term::Block(input.call(term_block)?)
1351 } else {
1352 let allow_struct = AllowStruct(true);
1353 let expr = unary_term(input, allow_struct)?;
1354
1355 return parse_term(input, expr, allow_struct, Precedence::Any);
1356 };
1357
1358 if input.peek(Token![.]) && !input.peek(Token![..]) || input.peek(Token![?]) {
1359 expr = trailer_helper(input, expr)?;
1360
1361 let allow_struct = AllowStruct(true);
1362 return parse_term(input, expr, allow_struct, Precedence::Any);
1363 }
1364
1365 Ok(expr)
1366 }
1367
1368 impl Parse for TermLit {
1369 fn parse(input: ParseStream) -> Result<Self> {
1370 Ok(TermLit { lit: input.parse()? })
1371 }
1372 }
1373
1374 fn term_group(input: ParseStream) -> Result<TermGroup> {
1375 input.parse_any_delimiter().and_then(|(delim, span, content)| {
1376 assert_eq!(delim, Delimiter::None);
1377 Ok(TermGroup { group_token: token::Group(span.join()), expr: content.parse()? })
1378 })
1379 }
1380
1381 fn generic_method_argument(input: ParseStream) -> Result<TermGenericMethodArgument> {
1382 if input.peek(Lit) {
1383 let lit = input.parse()?;
1384 return Ok(TermGenericMethodArgument::Const(Term::Lit(lit)));
1385 }
1386
1387 if input.peek(token::Brace) {
1388 let block = input.call(super::parsing::term_block)?;
1389 return Ok(TermGenericMethodArgument::Const(Term::Block(block)));
1390 }
1391
1392 input.parse().map(TermGenericMethodArgument::Type)
1393 }
1394
1395 fn term_let(input: ParseStream) -> Result<TermLet> {
1396 Ok(TermLet {
1397 let_token: input.parse()?,
1398 pat: Pat::parse_single(input)?,
1399 eq_token: input.parse()?,
1401 expr: Box::new(input.call(Term::parse_without_eager_brace)?),
1402 })
1403 }
1404
1405 impl Parse for TermIf {
1406 fn parse(input: ParseStream) -> Result<Self> {
1407 Ok(TermIf {
1408 if_token: input.parse()?,
1409 cond: Box::new(input.call(Term::parse_without_eager_brace)?),
1410 then_branch: input.parse()?,
1411 else_branch: {
1412 if input.peek(Token![else]) { Some(input.call(else_block)?) } else { None }
1413 },
1414 })
1415 }
1416 }
1417
1418 fn else_block(input: ParseStream) -> Result<(Token![else], Box<Term>)> {
1419 let else_token: Token![else] = input.parse()?;
1420
1421 let lookahead = input.lookahead1();
1422 let else_branch = if input.peek(Token![if]) {
1423 input.parse().map(Term::If)?
1424 } else if input.peek(token::Brace) {
1425 Term::Block(input.parse()?)
1426 } else {
1427 return Err(lookahead.error());
1428 };
1429
1430 Ok((else_token, Box::new(else_branch)))
1431 }
1432
1433 impl Parse for TermMatch {
1434 fn parse(input: ParseStream) -> Result<Self> {
1435 let match_token: Token![match] = input.parse()?;
1436 let expr = Term::parse_without_eager_brace(input)?;
1437
1438 let content;
1439 let brace_token = braced!(content in input);
1440
1441 let mut arms = Vec::new();
1442 while !content.is_empty() {
1443 arms.push(content.call(TermArm::parse)?);
1444 }
1445
1446 Ok(TermMatch { match_token, expr: Box::new(expr), brace_token, arms })
1447 }
1448 }
1449
1450 impl Parse for TermQuant {
1451 fn parse(input: ParseStream) -> Result<Self> {
1452 let quant_token = input.parse()?;
1453 let lt_token: Token![<] = input.parse()?;
1454
1455 let mut args = Punctuated::new();
1456 while !input.peek(Token![>]) {
1457 let quantarg = input.parse()?;
1458 args.push_value(quantarg);
1459 if input.peek(Token![>]) {
1460 break;
1461 }
1462
1463 let punct = input.parse()?;
1464 args.push_punct(punct);
1465 }
1466
1467 let gt_token: Token![>] = input.parse()?;
1468
1469 let term = input.parse()?;
1470
1471 Ok(TermQuant { quant_token, lt_token, args, gt_token, term })
1472 }
1473 }
1474
1475 impl Parse for TermWithTriggers {
1476 fn parse(input: ParseStream) -> Result<Self> {
1477 let mut trigger = vec![];
1478
1479 while input.peek(Token![#]) {
1480 trigger.push(input.parse()?)
1481 }
1482
1483 let term = input.parse()?;
1484 Ok(TermWithTriggers { trigger, term })
1485 }
1486 }
1487
1488 impl Parse for EnsuresClosure {
1489 fn parse(input: ParseStream) -> Result<Self> {
1490 Ok(EnsuresClosure {
1491 or1_token: input.parse()?,
1492 result: Pat::parse_single(input)?,
1493 or2_token: input.parse()?,
1494 body: input.parse()?,
1495 })
1496 }
1497 }
1498
1499 impl Parse for EnsuresTerm {
1500 fn parse(input: ParseStream) -> Result<Self> {
1501 if input.peek(Token![|]) {
1502 Ok(EnsuresTerm::EnsuresClosure(input.parse()?))
1503 } else {
1504 Ok(EnsuresTerm::TermWithTriggers(input.parse()?))
1505 }
1506 }
1507 }
1508
1509 impl Parse for QuantToken {
1510 fn parse(input: ParseStream) -> Result<Self> {
1511 if input.peek(kw::forall) {
1512 Ok(QuantToken::Forall(input.parse()?))
1513 } else {
1514 Ok(QuantToken::Exists(input.parse()?))
1515 }
1516 }
1517 }
1518
1519 impl Parse for QuantArg {
1520 fn parse(input: ParseStream) -> Result<Self> {
1521 let ident = input.parse()?;
1522 if input.peek(Token![:]) {
1523 Ok(QuantArg { ident, ty: Some((input.parse()?, input.parse()?)) })
1524 } else {
1525 Ok(QuantArg { ident, ty: None })
1526 }
1527 }
1528 }
1529
1530 impl Parse for Trigger {
1531 fn parse(input: ParseStream) -> Result<Self> {
1532 let mut content;
1533 Ok(Trigger {
1534 pound_token: input.parse()?,
1535 bracket_token: bracketed!(content in input),
1536 trigger_token: content.parse()?,
1537 paren_token: parenthesized!(content in content),
1538 terms: Punctuated::parse_separated_nonempty(&content)?,
1539 })
1540 }
1541 }
1542
1543 impl Parse for TermDead {
1544 fn parse(input: ParseStream) -> Result<Self> {
1545 Ok(TermDead { dead_token: input.parse()? })
1546 }
1547 }
1548
1549 impl Parse for TermPearlite {
1550 fn parse(input: ParseStream) -> Result<Self> {
1551 Ok(TermPearlite {
1552 pearlite_token: input.parse()?,
1553 bang_token: input.parse()?,
1554 block: input.parse()?,
1555 })
1556 }
1557 }
1558
1559 macro_rules! impl_by_parsing_term {
1560 (
1561 $(
1562 $term_type:ty, $variant:ident, $msg:expr,
1563 )*
1564 ) => {
1565 $(
1566 #[cfg(all(feature = "full", feature = "printing"))]
1567 impl Parse for $term_type {
1568 fn parse(input: ParseStream) -> Result<Self> {
1569 let mut expr: Term = input.parse()?;
1570 loop {
1571 match expr {
1572 Term::$variant(inner) => return Ok(inner),
1573 Term::Group(next) => expr = *next.expr,
1574 _ => return Err(Error::new_spanned(expr, $msg)),
1575 }
1576 }
1577 }
1578 }
1579 )*
1580 };
1581 }
1582
1583 impl_by_parsing_term! {
1584 TermArray, Array, "expected slice literal term",
1585 TermCall, Call, "expected function call term",
1586 TermMethodCall, MethodCall, "expected method call term",
1587 TermTuple, Tuple, "expected tuple term",
1588 TermBinary, Binary, "expected binary operation",
1589 TermUnary, Unary, "expected unary operation",
1590 TermCast, Cast, "expected cast term",
1591 TermType, Type, "expected type ascription term",
1592 TermLet, Let, "expected let guard",
1593 TermField, Field, "expected struct field access",
1594 TermIndex, Index, "expected indexing term",
1595 TermRange, Range, "expected range term",
1596 TermReference, Reference, "expected reference term",
1597 TermStruct, Struct, "expected struct literal term",
1598 TermRepeat, Repeat, "expected array literal constructed from one repeated element",
1599 TermParen, Paren, "expected parenthesized term",
1600 }
1601
1602 impl Parse for TermFieldValue {
1603 fn parse(input: ParseStream) -> Result<Self> {
1604 let member: Member = input.parse()?;
1605 let (colon_token, value) =
1606 if input.peek(Token![:]) || !matches!(member, Member::Named(_)) {
1607 let colon_token: Token![:] = input.parse()?;
1608 let value: Term = input.parse()?;
1609 (Some(colon_token), value)
1610 } else if let Member::Named(ident) = &member {
1611 let value = Term::Path(TermPath {
1612 inner: ExprPath {
1613 qself: None,
1614 path: Path::from(ident.clone()),
1615 attrs: Vec::new(),
1616 },
1617 });
1618 (None, value)
1619 } else {
1620 unreachable!()
1621 };
1622
1623 Ok(TermFieldValue { member, colon_token, expr: value })
1624 }
1625 }
1626
1627 fn term_struct_helper(input: ParseStream, path: Path) -> Result<TermStruct> {
1628 let content;
1629 let brace_token = braced!(content in input);
1630
1631 let mut fields = Punctuated::new();
1632 while !content.is_empty() {
1633 if content.peek(Token![..]) {
1634 return Ok(TermStruct {
1635 brace_token,
1636 path,
1637 fields,
1638 dot2_token: Some(content.parse()?),
1639 rest: Some(Box::new(content.parse()?)),
1640 });
1641 }
1642
1643 fields.push(content.parse()?);
1644 if content.is_empty() {
1645 break;
1646 }
1647 let punct: Token![,] = content.parse()?;
1648 fields.push_punct(punct);
1649 }
1650
1651 Ok(TermStruct { brace_token, path, fields, dot2_token: None, rest: None })
1652 }
1653
1654 pub fn term_block(input: ParseStream) -> Result<TermBlock> {
1655 let content;
1656 let brace_token = braced!(content in input);
1657 let stmts = content.call(TermBlock::parse_within)?;
1658
1659 Ok(TermBlock { brace_token, stmts })
1660 }
1661
1662 fn term_range(input: ParseStream, allow_struct: AllowStruct) -> Result<TermRange> {
1663 Ok(TermRange {
1664 from: None,
1665 limits: input.parse()?,
1666 to: {
1667 if input.is_empty()
1668 || input.peek(Token![,])
1669 || input.peek(Token![;])
1670 || !allow_struct.0 && input.peek(token::Brace)
1671 {
1672 None
1673 } else {
1674 let to = ambiguous_term(input, allow_struct)?;
1675 Some(Box::new(to))
1676 }
1677 },
1678 })
1679 }
1680
1681 impl Parse for TermPath {
1682 fn parse(input: ParseStream) -> Result<Self> {
1683 let exp_path: ExprPath = input.parse()?;
1684
1685 Ok(TermPath { inner: exp_path })
1688 }
1689 }
1690
1691 impl Parse for TermArm {
1692 fn parse(input: ParseStream) -> Result<TermArm> {
1693 let requires_comma;
1694 Ok(TermArm {
1695 pat: Pat::parse_multi_with_leading_vert(input)?,
1696 guard: {
1697 if input.peek(Token![if]) {
1698 let if_token: Token![if] = input.parse()?;
1699 let guard: Term = input.parse()?;
1700 Some((if_token, Box::new(guard)))
1701 } else {
1702 None
1703 }
1704 },
1705 fat_arrow_token: input.parse()?,
1706 body: {
1707 let body = input.call(term_early)?;
1708 requires_comma = requires_terminator(&body);
1709 Box::new(body)
1710 },
1711 comma: {
1712 if requires_comma && !input.is_empty() {
1713 Some(input.parse()?)
1714 } else {
1715 input.parse()?
1716 }
1717 },
1718 })
1719 }
1720 }
1721
1722 impl Parse for super::Index {
1723 fn parse(input: ParseStream) -> Result<Self> {
1724 let lit: LitInt = input.parse()?;
1725 if lit.suffix().is_empty() {
1726 Ok(super::Index {
1727 index: lit
1728 .base10_digits()
1729 .parse()
1730 .map_err(|err| Error::new(lit.span(), err))?,
1731 span: lit.span(),
1732 })
1733 } else {
1734 Err(Error::new(lit.span(), "expected unsuffixed integer"))
1735 }
1736 }
1737 }
1738
1739 fn multi_index(e: &mut Term, dot_token: &mut Token![.], float: LitFloat) -> Result<bool> {
1740 let mut float_repr = float.to_string();
1741 let trailing_dot = float_repr.ends_with('.');
1742 if trailing_dot {
1743 float_repr.truncate(float_repr.len() - 1);
1744 }
1745 for part in float_repr.split('.') {
1746 let index = syn::parse_str(part).map_err(|err| Error::new(float.span(), err))?;
1747 let base = mem::replace(e, Term::__Nonexhaustive);
1748 *e = Term::Field(TermField {
1749 base: Box::new(base),
1750 dot_token: Token,
1751 member: Member::Unnamed(index),
1752 });
1753 *dot_token = Token);
1754 }
1755 Ok(!trailing_dot)
1756 }
1757
1758 fn term_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<TermClosure> {
1759 let or1_token: Token![|] = input.parse()?;
1760
1761 let mut inputs = Punctuated::new();
1762 loop {
1763 if input.peek(Token![|]) {
1764 break;
1765 }
1766 let value = closure_arg(input)?;
1767 inputs.push_value(value);
1768 if input.peek(Token![|]) {
1769 break;
1770 }
1771 let punct: Token![,] = input.parse()?;
1772 inputs.push_punct(punct);
1773 }
1774
1775 let or2_token: Token![|] = input.parse()?;
1776
1777 let (output, body) = if input.peek(Token![->]) {
1778 let arrow_token: Token![->] = input.parse()?;
1779 let ty: Type = input.parse()?;
1780 let body: TermBlock = input.parse()?;
1781 let output = ReturnType::Type(arrow_token, Box::new(ty));
1782 let block = Term::Block(body);
1783 (output, block)
1784 } else {
1785 let body = ambiguous_term(input, allow_struct)?;
1786 (ReturnType::Default, body)
1787 };
1788
1789 Ok(TermClosure {
1790 attrs: Vec::new(),
1791 or1_token,
1792 inputs,
1793 or2_token,
1794 output,
1795 body: Box::new(body),
1796 })
1797 }
1798
1799 fn closure_arg(input: ParseStream) -> Result<Pat> {
1800 let attrs = input.call(Attribute::parse_outer)?;
1801 let mut pat = Pat::parse_single(input)?;
1802
1803 if input.peek(Token![:]) {
1804 Ok(Pat::Type(PatType {
1805 attrs,
1806 pat: Box::new(pat),
1807 colon_token: input.parse()?,
1808 ty: input.parse()?,
1809 }))
1810 } else {
1811 match &mut pat {
1812 Pat::Const(pat) => pat.attrs = attrs,
1813 Pat::Ident(pat) => pat.attrs = attrs,
1814 Pat::Lit(pat) => pat.attrs = attrs,
1815 Pat::Macro(pat) => pat.attrs = attrs,
1816 Pat::Or(pat) => pat.attrs = attrs,
1817 Pat::Paren(pat) => pat.attrs = attrs,
1818 Pat::Path(pat) => pat.attrs = attrs,
1819 Pat::Range(pat) => pat.attrs = attrs,
1820 Pat::Reference(pat) => pat.attrs = attrs,
1821 Pat::Rest(pat) => pat.attrs = attrs,
1822 Pat::Slice(pat) => pat.attrs = attrs,
1823 Pat::Struct(pat) => pat.attrs = attrs,
1824 Pat::Tuple(pat) => pat.attrs = attrs,
1825 Pat::TupleStruct(pat) => pat.attrs = attrs,
1826 Pat::Wild(pat) => pat.attrs = attrs,
1827 Pat::Type(_) => unreachable!(),
1828 Pat::Verbatim(_) => {}
1829 _ => unimplemented!(),
1830 }
1831 Ok(pat)
1832 }
1833 }
1834}
1835
1836#[cfg(feature = "printing")]
1837pub(crate) mod printing {
1838 use super::*;
1839 use crate::print::TokensOrDefault;
1840 use proc_macro2::{Literal, TokenStream};
1841 use quote::{ToTokens, TokenStreamExt};
1842
1843 fn wrap_bare_struct(tokens: &mut TokenStream, e: &Term) {
1846 if let Term::Struct(_) = *e {
1847 token::Paren::default().surround(tokens, |tokens| {
1848 e.to_tokens(tokens);
1849 });
1850 } else {
1851 e.to_tokens(tokens);
1852 }
1853 }
1854
1855 impl ToTokens for TermBlock {
1856 fn to_tokens(&self, tokens: &mut TokenStream) {
1857 self.brace_token.surround(tokens, |tokens| {
1858 tokens.append_all(&self.stmts);
1859 });
1860 }
1861 }
1862
1863 impl ToTokens for TermStmt {
1864 fn to_tokens(&self, tokens: &mut TokenStream) {
1865 match self {
1866 TermStmt::Local(local) => local.to_tokens(tokens),
1867 TermStmt::Expr(expr) => expr.to_tokens(tokens),
1868 TermStmt::Semi(expr, semi) => {
1869 expr.to_tokens(tokens);
1870 semi.to_tokens(tokens);
1871 }
1872 TermStmt::Item(i) => i.to_tokens(tokens),
1873 TermStmt::Empty(semi) => semi.to_tokens(tokens),
1874 }
1875 }
1876 }
1877
1878 impl ToTokens for TLocal {
1879 fn to_tokens(&self, tokens: &mut TokenStream) {
1880 self.let_token.to_tokens(tokens);
1881 self.pat.to_tokens(tokens);
1882 if let Some((eq_token, init)) = &self.init {
1883 eq_token.to_tokens(tokens);
1884 init.to_tokens(tokens);
1885 }
1886 self.semi_token.to_tokens(tokens);
1887 }
1888 }
1889
1890 impl ToTokens for TermArray {
1891 fn to_tokens(&self, tokens: &mut TokenStream) {
1892 self.bracket_token.surround(tokens, |tokens| {
1893 self.elems.to_tokens(tokens);
1894 })
1895 }
1896 }
1897
1898 impl ToTokens for TermCall {
1899 fn to_tokens(&self, tokens: &mut TokenStream) {
1900 self.func.to_tokens(tokens);
1901 self.paren_token.surround(tokens, |tokens| {
1902 self.args.to_tokens(tokens);
1903 })
1904 }
1905 }
1906
1907 impl ToTokens for TermMethodCall {
1908 fn to_tokens(&self, tokens: &mut TokenStream) {
1909 self.receiver.to_tokens(tokens);
1910 self.dot_token.to_tokens(tokens);
1911 self.method.to_tokens(tokens);
1912 self.turbofish.to_tokens(tokens);
1913 self.paren_token.surround(tokens, |tokens| {
1914 self.args.to_tokens(tokens);
1915 });
1916 }
1917 }
1918
1919 impl ToTokens for TermClosure {
1920 fn to_tokens(&self, tokens: &mut TokenStream) {
1921 tokens.append_all(&self.attrs);
1922 self.or1_token.to_tokens(tokens);
1923 self.inputs.to_tokens(tokens);
1924 self.or2_token.to_tokens(tokens);
1925 self.output.to_tokens(tokens);
1926 self.body.to_tokens(tokens);
1927 }
1928 }
1929
1930 impl ToTokens for TermMethodTurbofish {
1931 fn to_tokens(&self, tokens: &mut TokenStream) {
1932 self.colon2_token.to_tokens(tokens);
1933 self.lt_token.to_tokens(tokens);
1934 self.args.to_tokens(tokens);
1935 self.gt_token.to_tokens(tokens);
1936 }
1937 }
1938
1939 impl ToTokens for TermGenericMethodArgument {
1940 fn to_tokens(&self, tokens: &mut TokenStream) {
1941 match self {
1942 TermGenericMethodArgument::Type(t) => t.to_tokens(tokens),
1943 TermGenericMethodArgument::Const(c) => c.to_tokens(tokens),
1944 }
1945 }
1946 }
1947
1948 impl ToTokens for TermTuple {
1949 fn to_tokens(&self, tokens: &mut TokenStream) {
1950 self.paren_token.surround(tokens, |tokens| {
1951 self.elems.to_tokens(tokens);
1952 if self.elems.len() == 1 && !self.elems.trailing_punct() {
1955 <Token![,]>::default().to_tokens(tokens);
1956 }
1957 })
1958 }
1959 }
1960
1961 impl ToTokens for TermBinary {
1962 fn to_tokens(&self, tokens: &mut TokenStream) {
1963 self.left.to_tokens(tokens);
1964 self.op.to_tokens(tokens);
1965 self.right.to_tokens(tokens);
1966 }
1967 }
1968
1969 impl ToTokens for TermUnary {
1970 fn to_tokens(&self, tokens: &mut TokenStream) {
1971 self.op.to_tokens(tokens);
1972 self.expr.to_tokens(tokens);
1973 }
1974 }
1975
1976 impl ToTokens for TermFinal {
1977 fn to_tokens(&self, tokens: &mut TokenStream) {
1978 self.final_token.to_tokens(tokens);
1979 self.term.to_tokens(tokens);
1980 }
1981 }
1982
1983 impl ToTokens for TermView {
1984 fn to_tokens(&self, tokens: &mut TokenStream) {
1985 self.term.to_tokens(tokens);
1986 self.at_token.to_tokens(tokens);
1987 }
1988 }
1989
1990 impl ToTokens for TermLit {
1991 fn to_tokens(&self, tokens: &mut TokenStream) {
1992 self.lit.to_tokens(tokens);
1993 }
1994 }
1995
1996 impl ToTokens for TermCast {
1997 fn to_tokens(&self, tokens: &mut TokenStream) {
1998 self.expr.to_tokens(tokens);
1999 self.as_token.to_tokens(tokens);
2000 self.ty.to_tokens(tokens);
2001 }
2002 }
2003
2004 impl ToTokens for TermType {
2005 fn to_tokens(&self, tokens: &mut TokenStream) {
2006 self.expr.to_tokens(tokens);
2007 self.colon_token.to_tokens(tokens);
2008 self.ty.to_tokens(tokens);
2009 }
2010 }
2011
2012 impl ToTokens for TermImpl {
2013 fn to_tokens(&self, tokens: &mut TokenStream) {
2014 self.hyp.to_tokens(tokens);
2015 self.eqeq_token.to_tokens(tokens);
2016 self.gt_token.to_tokens(tokens);
2017 self.cons.to_tokens(tokens);
2018 }
2019 }
2020
2021 impl ToTokens for TermQuant {
2022 fn to_tokens(&self, tokens: &mut TokenStream) {
2023 self.quant_token.to_tokens(tokens);
2024 self.lt_token.to_tokens(tokens);
2025 for input in self.args.pairs() {
2026 input.to_tokens(tokens);
2027 }
2028 self.gt_token.to_tokens(tokens);
2029 self.term.to_tokens(tokens);
2030 }
2031 }
2032
2033 impl ToTokens for TermWithTriggers {
2034 fn to_tokens(&self, tokens: &mut TokenStream) {
2035 for trigger in self.trigger.iter() {
2036 trigger.to_tokens(tokens);
2037 }
2038 self.term.to_tokens(tokens);
2039 }
2040 }
2041
2042 impl ToTokens for EnsuresClosure {
2043 fn to_tokens(&self, tokens: &mut TokenStream) {
2044 self.or1_token.to_tokens(tokens);
2045 self.result.to_tokens(tokens);
2046 self.or2_token.to_tokens(tokens);
2047 self.body.to_tokens(tokens);
2048 }
2049 }
2050
2051 impl ToTokens for QuantArg {
2052 fn to_tokens(&self, tokens: &mut TokenStream) {
2053 self.ident.to_tokens(tokens);
2054 if let Some((colon_token, ty)) = &self.ty {
2055 colon_token.to_tokens(tokens);
2056 ty.to_tokens(tokens);
2057 }
2058 }
2059 }
2060
2061 impl ToTokens for Trigger {
2062 fn to_tokens(&self, tokens: &mut TokenStream) {
2063 self.pound_token.to_tokens(tokens);
2064 self.bracket_token.surround(tokens, |tokens| {
2065 self.trigger_token.to_tokens(tokens);
2066 self.paren_token.surround(tokens, |tokens| {
2067 self.terms.to_tokens(tokens);
2068 if !self.terms.empty_or_trailing() {
2069 <Token![,] as Default>::default().to_tokens(tokens)
2070 }
2071 })
2072 })
2073 }
2074 }
2075
2076 impl ToTokens for TermDead {
2077 fn to_tokens(&self, tokens: &mut TokenStream) {
2078 self.dead_token.to_tokens(tokens);
2079 }
2080 }
2081
2082 impl ToTokens for TermPearlite {
2083 fn to_tokens(&self, tokens: &mut TokenStream) {
2084 self.pearlite_token.to_tokens(tokens);
2085 self.bang_token.to_tokens(tokens);
2086 self.block.to_tokens(tokens);
2087 }
2088 }
2089
2090 impl ToTokens for TermProofAssert {
2091 fn to_tokens(&self, tokens: &mut TokenStream) {
2092 self.proof_assert_token.to_tokens(tokens);
2093 self.bang_token.to_tokens(tokens);
2094 self.block.to_tokens(tokens);
2095 }
2096 }
2097
2098 impl ToTokens for TermSeq {
2099 fn to_tokens(&self, tokens: &mut TokenStream) {
2100 self.seq_token.to_tokens(tokens);
2101 self.bang_token.to_tokens(tokens);
2102 self.bracket_token.surround(tokens, |tokens| self.terms.to_tokens(tokens));
2103 }
2104 }
2105
2106 fn maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Term>)>) {
2107 if let Some((else_token, else_)) = else_ {
2108 else_token.to_tokens(tokens);
2109
2110 match **else_ {
2113 Term::If(_) | Term::Block(_) => {
2114 else_.to_tokens(tokens);
2115 }
2116 _ => {
2117 token::Brace::default().surround(tokens, |tokens| {
2118 else_.to_tokens(tokens);
2119 });
2120 }
2121 }
2122 }
2123 }
2124
2125 impl ToTokens for TermLet {
2126 fn to_tokens(&self, tokens: &mut TokenStream) {
2127 self.let_token.to_tokens(tokens);
2128 self.pat.to_tokens(tokens);
2129 self.eq_token.to_tokens(tokens);
2130 wrap_bare_struct(tokens, &self.expr);
2131 }
2132 }
2133
2134 impl ToTokens for TermIf {
2135 fn to_tokens(&self, tokens: &mut TokenStream) {
2136 self.if_token.to_tokens(tokens);
2137 wrap_bare_struct(tokens, &self.cond);
2138 self.then_branch.to_tokens(tokens);
2139 maybe_wrap_else(tokens, &self.else_branch);
2140 }
2141 }
2142
2143 impl ToTokens for TermMatch {
2144 fn to_tokens(&self, tokens: &mut TokenStream) {
2145 self.match_token.to_tokens(tokens);
2146 wrap_bare_struct(tokens, &self.expr);
2147 self.brace_token.surround(tokens, |tokens| {
2148 for (i, arm) in self.arms.iter().enumerate() {
2149 arm.to_tokens(tokens);
2150 let is_last = i == self.arms.len() - 1;
2153 if !is_last && requires_terminator(&arm.body) && arm.comma.is_none() {
2154 <Token![,]>::default().to_tokens(tokens);
2155 }
2156 }
2157 });
2158 }
2159 }
2160
2161 impl ToTokens for TermField {
2162 fn to_tokens(&self, tokens: &mut TokenStream) {
2163 self.base.to_tokens(tokens);
2164 self.dot_token.to_tokens(tokens);
2165 self.member.to_tokens(tokens);
2166 }
2167 }
2168
2169 impl ToTokens for super::Index {
2171 fn to_tokens(&self, tokens: &mut TokenStream) {
2172 let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
2173 lit.set_span(self.span);
2174 tokens.append(lit);
2175 }
2176 }
2177
2178 impl ToTokens for TermIndex {
2179 fn to_tokens(&self, tokens: &mut TokenStream) {
2180 self.expr.to_tokens(tokens);
2181 self.bracket_token.surround(tokens, |tokens| {
2182 self.index.to_tokens(tokens);
2183 });
2184 }
2185 }
2186
2187 impl ToTokens for TermRange {
2188 fn to_tokens(&self, tokens: &mut TokenStream) {
2189 self.from.to_tokens(tokens);
2190 match &self.limits {
2191 RangeLimits::HalfOpen(t) => t.to_tokens(tokens),
2192 RangeLimits::Closed(t) => t.to_tokens(tokens),
2193 }
2194 self.to.to_tokens(tokens);
2195 }
2196 }
2197
2198 impl ToTokens for TermReference {
2199 fn to_tokens(&self, tokens: &mut TokenStream) {
2200 self.and_token.to_tokens(tokens);
2201 self.mutability.to_tokens(tokens);
2202 self.expr.to_tokens(tokens);
2203 }
2204 }
2205
2206 impl ToTokens for TermPath {
2207 fn to_tokens(&self, tokens: &mut TokenStream) {
2208 self.inner.to_tokens(tokens)
2209 }
2211 }
2212
2213 impl ToTokens for TermStruct {
2214 fn to_tokens(&self, tokens: &mut TokenStream) {
2215 self.path.to_tokens(tokens);
2216 self.brace_token.surround(tokens, |tokens| {
2217 self.fields.to_tokens(tokens);
2218 if self.rest.is_some() {
2219 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
2220 self.rest.to_tokens(tokens);
2221 }
2222 })
2223 }
2224 }
2225
2226 impl ToTokens for TermRepeat {
2227 fn to_tokens(&self, tokens: &mut TokenStream) {
2228 self.bracket_token.surround(tokens, |tokens| {
2229 self.expr.to_tokens(tokens);
2230 self.semi_token.to_tokens(tokens);
2231 self.len.to_tokens(tokens);
2232 })
2233 }
2234 }
2235
2236 impl ToTokens for TermGroup {
2237 fn to_tokens(&self, tokens: &mut TokenStream) {
2238 self.group_token.surround(tokens, |tokens| {
2239 self.expr.to_tokens(tokens);
2240 });
2241 }
2242 }
2243
2244 impl ToTokens for TermParen {
2245 fn to_tokens(&self, tokens: &mut TokenStream) {
2246 self.paren_token.surround(tokens, |tokens| {
2247 self.expr.to_tokens(tokens);
2248 });
2249 }
2250 }
2251
2252 impl ToTokens for TermFieldValue {
2253 fn to_tokens(&self, tokens: &mut TokenStream) {
2254 self.member.to_tokens(tokens);
2255 if let Some(colon_token) = &self.colon_token {
2256 colon_token.to_tokens(tokens);
2257 self.expr.to_tokens(tokens);
2258 }
2259 }
2260 }
2261
2262 impl ToTokens for TermArm {
2263 fn to_tokens(&self, tokens: &mut TokenStream) {
2264 self.pat.to_tokens(tokens);
2265 if let Some((if_token, guard)) = &self.guard {
2266 if_token.to_tokens(tokens);
2267 guard.to_tokens(tokens);
2268 }
2269 self.fat_arrow_token.to_tokens(tokens);
2270 self.body.to_tokens(tokens);
2271 self.comma.to_tokens(tokens);
2272 }
2273 }
2274}