1#[doc(hidden)]
11pub use crate::helpers::{CodeLocation, OptionalCodeLocation};
12
13#[cfg(feature = "pt-serde")]
14use serde::{Deserialize, Serialize};
15
16#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
18#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
19pub enum Loc {
20 Builtin,
22 CommandLine,
24 Implicit,
26 Codegen,
28 File(usize, usize, usize),
30}
31
32impl Default for Loc {
33 fn default() -> Self {
34 Self::File(0, 0, 0)
35 }
36}
37
38#[inline(never)]
39#[cold]
40#[track_caller]
41fn not_a_file() -> ! {
42 panic!("location is not a file")
43}
44
45impl Loc {
46 #[inline]
48 pub fn begin_range(&self) -> Self {
49 match self {
50 Loc::File(file_no, start, _) => Loc::File(*file_no, *start, *start),
51 loc => *loc,
52 }
53 }
54
55 #[inline]
57 pub fn end_range(&self) -> Self {
58 match self {
59 Loc::File(file_no, _, end) => Loc::File(*file_no, *end, *end),
60 loc => *loc,
61 }
62 }
63
64 #[track_caller]
70 #[inline]
71 pub fn file_no(&self) -> usize {
72 match self {
73 Loc::File(file_no, _, _) => *file_no,
74 _ => not_a_file(),
75 }
76 }
77
78 #[inline]
80 pub fn try_file_no(&self) -> Option<usize> {
81 match self {
82 Loc::File(file_no, _, _) => Some(*file_no),
83 _ => None,
84 }
85 }
86
87 #[track_caller]
93 #[inline]
94 pub fn start(&self) -> usize {
95 match self {
96 Loc::File(_, start, _) => *start,
97 _ => not_a_file(),
98 }
99 }
100
101 #[track_caller]
107 #[inline]
108 pub fn end(&self) -> usize {
109 match self {
110 Loc::File(_, _, end) => *end,
111 _ => not_a_file(),
112 }
113 }
114
115 #[track_caller]
123 #[inline]
124 pub fn exclusive_end(&self) -> usize {
125 self.end() + 1
126 }
127
128 #[track_caller]
134 #[inline]
135 pub fn use_start_from(&mut self, other: &Loc) {
136 match (self, other) {
137 (Loc::File(_, start, _), Loc::File(_, other_start, _)) => {
138 *start = *other_start;
139 }
140 _ => not_a_file(),
141 }
142 }
143
144 #[track_caller]
150 #[inline]
151 pub fn use_end_from(&mut self, other: &Loc) {
152 match (self, other) {
153 (Loc::File(_, _, end), Loc::File(_, _, other_end)) => {
154 *end = *other_end;
155 }
156 _ => not_a_file(),
157 }
158 }
159
160 #[track_caller]
166 #[inline]
167 pub fn with_start_from(mut self, other: &Self) -> Self {
168 self.use_start_from(other);
169 self
170 }
171
172 #[track_caller]
178 #[inline]
179 pub fn with_end_from(mut self, other: &Self) -> Self {
180 self.use_end_from(other);
181 self
182 }
183
184 #[track_caller]
190 #[inline]
191 pub fn with_start(self, start: usize) -> Self {
192 match self {
193 Self::File(no, _, end) => Self::File(no, start, end),
194 _ => not_a_file(),
195 }
196 }
197
198 #[track_caller]
204 #[inline]
205 pub fn with_end(self, end: usize) -> Self {
206 match self {
207 Self::File(no, start, _) => Self::File(no, start, end),
208 _ => not_a_file(),
209 }
210 }
211
212 #[track_caller]
218 #[inline]
219 pub fn range(self) -> std::ops::Range<usize> {
220 match self {
221 Self::File(_, start, end) => start..end,
222 _ => not_a_file(),
223 }
224 }
225
226 pub fn union(&mut self, other: &Self) {
228 match (self, other) {
229 (Self::File(r_file, r_start, r_end), Self::File(l_file, l_start, l_end)) => {
230 assert_eq!(r_file, l_file, "cannot perform union in different files");
231 *r_start = std::cmp::min(*r_start, *l_start);
232 *r_end = std::cmp::max(*r_end, *l_end);
233 }
234
235 _ => unimplemented!("cannot perform union in non File Loc"),
236 }
237 }
238}
239
240#[derive(Debug, PartialEq, Eq, Clone)]
244#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
245pub struct Identifier {
246 pub loc: Loc,
248 pub name: String,
250}
251
252impl Identifier {
253 pub fn new(s: impl Into<String>) -> Self {
255 Self {
256 loc: Loc::default(),
257 name: s.into(),
258 }
259 }
260}
261
262#[derive(Debug, PartialEq, Eq, Clone)]
266#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
267pub struct IdentifierPath {
268 pub loc: Loc,
270 pub identifiers: Vec<Identifier>,
272}
273
274#[derive(Debug, PartialEq, Eq, Clone)]
278#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
279pub enum Comment {
280 Line(Loc, String),
284
285 Block(Loc, String),
289
290 DocLine(Loc, String),
294
295 DocBlock(Loc, String),
303}
304
305impl Comment {
306 #[inline]
308 pub const fn value(&self) -> &String {
309 match self {
310 Self::Line(_, s) | Self::Block(_, s) | Self::DocLine(_, s) | Self::DocBlock(_, s) => s,
311 }
312 }
313
314 #[inline]
316 pub const fn is_doc(&self) -> bool {
317 matches!(self, Self::DocLine(..) | Self::DocBlock(..))
318 }
319
320 #[inline]
322 pub const fn is_line(&self) -> bool {
323 matches!(self, Self::Line(..) | Self::DocLine(..))
324 }
325
326 #[inline]
328 pub const fn is_block(&self) -> bool {
329 !self.is_line()
330 }
331}
332
333#[derive(Debug, PartialEq, Eq, Clone)]
337#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
338pub struct SourceUnit(pub Vec<SourceUnitPart>);
339
340#[derive(Debug, PartialEq, Eq, Clone)]
342#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
343pub enum SourceUnitPart {
344 PragmaDirective(Box<PragmaDirective>),
350
351 ImportDirective(Import),
353
354 ContractDefinition(Box<ContractDefinition>),
356
357 EnumDefinition(Box<EnumDefinition>),
359
360 StructDefinition(Box<StructDefinition>),
362
363 EventDefinition(Box<EventDefinition>),
365
366 ErrorDefinition(Box<ErrorDefinition>),
368
369 FunctionDefinition(Box<FunctionDefinition>),
371
372 VariableDefinition(Box<VariableDefinition>),
374
375 TypeDefinition(Box<TypeDefinition>),
377
378 Annotation(Box<Annotation>),
380
381 Using(Box<Using>),
383
384 StraySemicolon(Loc),
386}
387
388#[derive(Debug, PartialEq, Eq, Clone)]
390#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
391pub enum Import {
392 Plain(ImportPath, Loc),
394
395 GlobalSymbol(ImportPath, Identifier, Loc),
401
402 Rename(ImportPath, Vec<(Identifier, Option<Identifier>)>, Loc),
404}
405
406#[derive(Debug, PartialEq, Eq, Clone)]
408#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
409pub enum ImportPath {
410 Filename(StringLiteral),
412 Path(IdentifierPath),
414}
415
416impl Import {
417 #[inline]
419 pub const fn literal(&self) -> Option<&StringLiteral> {
420 match self {
421 Self::Plain(ImportPath::Filename(literal), _)
422 | Self::GlobalSymbol(ImportPath::Filename(literal), _, _)
423 | Self::Rename(ImportPath::Filename(literal), _, _) => Some(literal),
424 _ => None,
425 }
426 }
427}
428
429pub type ParameterList = Vec<(Loc, Option<Parameter>)>;
431
432#[derive(Debug, PartialEq, Eq, Clone)]
434#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
435pub enum Type {
436 Address,
438
439 AddressPayable,
441
442 Payable,
446
447 Bool,
449
450 String,
452
453 Int(u16),
455
456 Uint(u16),
458
459 Bytes(u8),
461
462 Rational,
464
465 DynamicBytes,
467
468 Mapping {
470 loc: Loc,
472 key: Box<Expression>,
476 key_name: Option<Identifier>,
478 value: Box<Expression>,
480 value_name: Option<Identifier>,
482 },
483
484 Function {
486 params: ParameterList,
488 attributes: Vec<FunctionAttribute>,
490 returns: Option<(ParameterList, Vec<FunctionAttribute>)>,
492 },
493}
494
495#[derive(Debug, PartialEq, Eq, Clone)]
497#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
498pub enum StorageLocation {
499 Memory(Loc),
501
502 Storage(Loc),
504
505 Calldata(Loc),
507
508 Transient(Loc),
510}
511
512#[derive(Debug, PartialEq, Eq, Clone)]
516#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
517pub struct VariableDeclaration {
518 pub loc: Loc,
520 pub ty: Expression,
522 pub storage: Option<StorageLocation>,
524 pub name: Option<Identifier>,
528}
529
530#[derive(Debug, PartialEq, Eq, Clone)]
534#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
535pub struct StructDefinition {
536 pub loc: Loc,
538 pub name: Option<Identifier>,
542 pub fields: Vec<VariableDeclaration>,
544}
545
546#[derive(Debug, PartialEq, Eq, Clone)]
548#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
549pub enum ContractPart {
550 StructDefinition(Box<StructDefinition>),
552
553 EventDefinition(Box<EventDefinition>),
555
556 EnumDefinition(Box<EnumDefinition>),
558
559 ErrorDefinition(Box<ErrorDefinition>),
561
562 VariableDefinition(Box<VariableDefinition>),
564
565 FunctionDefinition(Box<FunctionDefinition>),
567
568 TypeDefinition(Box<TypeDefinition>),
570
571 Annotation(Box<Annotation>),
573
574 Using(Box<Using>),
576
577 StraySemicolon(Loc),
579}
580
581#[derive(Debug, PartialEq, Eq, Clone)]
583#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
584pub enum PragmaDirective {
585 Identifier(Loc, Option<Identifier>, Option<Identifier>),
587 StringLiteral(Loc, Identifier, StringLiteral),
589 Version(Loc, Identifier, Vec<VersionComparator>),
591}
592
593#[derive(Debug, PartialEq, Eq, Clone)]
595#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
596pub enum VersionComparator {
597 Plain {
599 loc: Loc,
601 version: Vec<String>,
603 },
604 Operator {
606 loc: Loc,
608 op: VersionOp,
610 version: Vec<String>,
612 },
613 Or {
615 loc: Loc,
617 left: Box<VersionComparator>,
619 right: Box<VersionComparator>,
621 },
622 Range {
624 loc: Loc,
626 from: Vec<String>,
628 to: Vec<String>,
630 },
631}
632
633#[derive(Debug, PartialEq, Eq, Copy, Clone)]
635#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
636pub enum VersionOp {
637 Exact,
639 Greater,
641 GreaterEq,
643 Less,
645 LessEq,
647 Tilde,
649 Caret,
651 Wildcard,
653}
654
655#[derive(Debug, PartialEq, Eq, Clone)]
657#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
658pub enum UsingList {
659 Library(IdentifierPath),
661
662 Functions(Vec<UsingFunction>),
666
667 Error,
669}
670
671#[derive(Debug, PartialEq, Eq, Clone)]
675#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
676pub struct UsingFunction {
677 pub loc: Loc,
679 pub path: IdentifierPath,
681 pub oper: Option<UserDefinedOperator>,
683}
684
685#[derive(Clone, Copy, Debug, PartialEq, Eq)]
691#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
692pub enum UserDefinedOperator {
693 BitwiseAnd,
695 BitwiseNot,
698 Negate,
702 BitwiseOr,
704 BitwiseXor,
706 Add,
708 Divide,
710 Modulo,
712 Multiply,
714 Subtract,
716 Equal,
718 More,
720 MoreEqual,
722 Less,
724 LessEqual,
726 NotEqual,
728}
729
730impl UserDefinedOperator {
731 #[inline]
733 pub const fn args(&self) -> usize {
734 match self {
735 UserDefinedOperator::BitwiseNot | UserDefinedOperator::Negate => 1,
736 _ => 2,
737 }
738 }
739
740 #[inline]
742 pub const fn is_unary(&self) -> bool {
743 matches!(self, Self::BitwiseNot | Self::Negate)
744 }
745
746 #[inline]
748 pub const fn is_binary(&self) -> bool {
749 !self.is_unary()
750 }
751
752 #[inline]
754 pub const fn is_bitwise(&self) -> bool {
755 matches!(
756 self,
757 Self::BitwiseAnd | Self::BitwiseOr | Self::BitwiseXor | Self::BitwiseNot
758 )
759 }
760
761 #[inline]
763 pub const fn is_arithmetic(&self) -> bool {
764 matches!(
765 self,
766 Self::Add | Self::Subtract | Self::Multiply | Self::Divide | Self::Modulo
767 )
768 }
769
770 #[inline]
772 pub const fn is_comparison(&self) -> bool {
773 matches!(
774 self,
775 Self::Equal
776 | Self::NotEqual
777 | Self::Less
778 | Self::LessEqual
779 | Self::More
780 | Self::MoreEqual
781 )
782 }
783}
784
785#[derive(Debug, PartialEq, Eq, Clone)]
791#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
792pub struct Using {
793 pub loc: Loc,
795 pub list: UsingList,
797 pub ty: Option<Expression>,
801 pub global: Option<Identifier>,
803}
804
805#[derive(Debug, PartialEq, Eq, Clone)]
807#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
808pub enum ContractTy {
809 Abstract(Loc),
811
812 Contract(Loc),
814
815 Interface(Loc),
817
818 Library(Loc),
820}
821
822#[derive(Debug, PartialEq, Eq, Clone)]
829#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
830pub struct Base {
831 pub loc: Loc,
833 pub name: IdentifierPath,
835 pub args: Option<Vec<Expression>>,
837}
838
839#[derive(Debug, PartialEq, Eq, Clone)]
843#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
844pub struct ContractDefinition {
845 pub loc: Loc,
847 pub ty: ContractTy,
849 pub name: Option<Identifier>,
853 pub base: Vec<Base>,
855 pub layout: Option<Box<Expression>>,
857 pub parts: Vec<ContractPart>,
859}
860
861impl ContractDefinition {
862 pub(crate) fn new(
863 loc: Loc,
864 ty: ContractTy,
865 name: Option<Identifier>,
866 attrs: Vec<ContractAttribute>,
867 parts: Vec<ContractPart>,
868 ) -> Self {
869 let mut base = Vec::new();
870 let mut layout = None;
871 for attr in attrs {
872 match attr {
873 ContractAttribute::Bases(b) => base.extend(b),
874 ContractAttribute::Layout(l) => layout = Some(l),
875 }
876 }
877 Self {
878 loc,
879 ty,
880 name,
881 base,
882 layout: layout.map(Box::new),
883 parts,
884 }
885 }
886}
887
888pub(crate) enum ContractAttribute {
889 Bases(Vec<Base>),
890 Layout(Expression),
891}
892
893#[derive(Debug, PartialEq, Eq, Clone)]
897#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
898pub struct EventParameter {
899 pub loc: Loc,
901 pub ty: Expression,
903 pub indexed: bool,
905 pub name: Option<Identifier>,
907}
908
909#[derive(Debug, PartialEq, Eq, Clone)]
913#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
914pub struct EventDefinition {
915 pub loc: Loc,
917 pub name: Option<Identifier>,
921 pub fields: Vec<EventParameter>,
923 pub anonymous: bool,
925}
926
927#[derive(Debug, PartialEq, Eq, Clone)]
931#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
932pub struct ErrorParameter {
933 pub loc: Loc,
935 pub ty: Expression,
937 pub name: Option<Identifier>,
939}
940
941#[derive(Debug, PartialEq, Eq, Clone)]
945#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
946pub struct ErrorDefinition {
947 pub loc: Loc,
949 pub keyword: Expression,
951 pub name: Option<Identifier>,
955 pub fields: Vec<ErrorParameter>,
957}
958
959#[derive(Debug, PartialEq, Eq, Clone)]
963#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
964pub struct EnumDefinition {
965 pub loc: Loc,
967 pub name: Option<Identifier>,
971 pub values: Vec<Option<Identifier>>,
975}
976
977#[derive(Debug, PartialEq, Eq, Clone)]
979#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
980#[repr(u8)] pub enum VariableAttribute {
982 Visibility(Visibility),
986
987 Constant(Loc),
989
990 Immutable(Loc),
992
993 Override(Loc, Vec<IdentifierPath>),
995
996 StorageType(StorageType),
998}
999
1000#[derive(Debug, PartialEq, Eq, Clone)]
1002#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1003#[repr(u8)] pub enum StorageType {
1005 Temporary(Option<Loc>),
1007
1008 Persistent(Option<Loc>),
1010
1011 Instance(Option<Loc>),
1013}
1014
1015#[derive(Debug, PartialEq, Eq, Clone)]
1019#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1020pub struct VariableDefinition {
1021 pub loc: Loc,
1023 pub ty: Expression,
1025 pub attrs: Vec<VariableAttribute>,
1027 pub name: Option<Identifier>,
1031 pub initializer: Option<Expression>,
1033}
1034
1035#[derive(Debug, PartialEq, Eq, Clone)]
1039#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1040pub struct TypeDefinition {
1041 pub loc: Loc,
1043 pub name: Identifier,
1045 pub ty: Expression,
1047}
1048
1049#[derive(Debug, PartialEq, Eq, Clone)]
1053#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1054pub struct Annotation {
1055 pub loc: Loc,
1057 pub id: Identifier,
1059 pub value: Option<Expression>,
1061}
1062
1063#[derive(Debug, PartialEq, Eq, Clone)]
1067#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1068pub struct StringLiteral {
1069 pub loc: Loc,
1071 pub unicode: bool,
1073 pub string: String,
1077}
1078
1079#[derive(Debug, PartialEq, Eq, Clone)]
1083#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1084pub struct HexLiteral {
1085 pub loc: Loc,
1087 pub hex: String,
1091}
1092
1093#[derive(Debug, PartialEq, Eq, Clone)]
1097#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1098pub struct NamedArgument {
1099 pub loc: Loc,
1101 pub name: Identifier,
1103 pub expr: Expression,
1105}
1106
1107#[derive(Debug, PartialEq, Eq, Clone)]
1109#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1110pub enum Expression {
1111 PostIncrement(Loc, Box<Expression>),
1113 PostDecrement(Loc, Box<Expression>),
1115 New(Loc, Box<Expression>),
1117 ArraySubscript(Loc, Box<Expression>, Option<Box<Expression>>),
1119 ArraySlice(
1121 Loc,
1122 Box<Expression>,
1123 Option<Box<Expression>>,
1124 Option<Box<Expression>>,
1125 ),
1126 Parenthesis(Loc, Box<Expression>),
1128 MemberAccess(Loc, Box<Expression>, Identifier),
1130 FunctionCall(Loc, Box<Expression>, Vec<Expression>),
1132 FunctionCallBlock(Loc, Box<Expression>, Box<Statement>),
1134 NamedFunctionCall(Loc, Box<Expression>, Vec<NamedArgument>),
1136 Not(Loc, Box<Expression>),
1138 BitwiseNot(Loc, Box<Expression>),
1140 Delete(Loc, Box<Expression>),
1142 PreIncrement(Loc, Box<Expression>),
1144 PreDecrement(Loc, Box<Expression>),
1146 UnaryPlus(Loc, Box<Expression>),
1150 Negate(Loc, Box<Expression>),
1152
1153 Power(Loc, Box<Expression>, Box<Expression>),
1155 Multiply(Loc, Box<Expression>, Box<Expression>),
1157 Divide(Loc, Box<Expression>, Box<Expression>),
1159 Modulo(Loc, Box<Expression>, Box<Expression>),
1161 Add(Loc, Box<Expression>, Box<Expression>),
1163 Subtract(Loc, Box<Expression>, Box<Expression>),
1165 ShiftLeft(Loc, Box<Expression>, Box<Expression>),
1167 ShiftRight(Loc, Box<Expression>, Box<Expression>),
1169 BitwiseAnd(Loc, Box<Expression>, Box<Expression>),
1171 BitwiseXor(Loc, Box<Expression>, Box<Expression>),
1173 BitwiseOr(Loc, Box<Expression>, Box<Expression>),
1175 Less(Loc, Box<Expression>, Box<Expression>),
1177 More(Loc, Box<Expression>, Box<Expression>),
1179 LessEqual(Loc, Box<Expression>, Box<Expression>),
1181 MoreEqual(Loc, Box<Expression>, Box<Expression>),
1183 Equal(Loc, Box<Expression>, Box<Expression>),
1185 NotEqual(Loc, Box<Expression>, Box<Expression>),
1187 And(Loc, Box<Expression>, Box<Expression>),
1189 Or(Loc, Box<Expression>, Box<Expression>),
1191 ConditionalOperator(Loc, Box<Expression>, Box<Expression>, Box<Expression>),
1195 Assign(Loc, Box<Expression>, Box<Expression>),
1197 AssignOr(Loc, Box<Expression>, Box<Expression>),
1199 AssignAnd(Loc, Box<Expression>, Box<Expression>),
1201 AssignXor(Loc, Box<Expression>, Box<Expression>),
1203 AssignShiftLeft(Loc, Box<Expression>, Box<Expression>),
1205 AssignShiftRight(Loc, Box<Expression>, Box<Expression>),
1207 AssignAdd(Loc, Box<Expression>, Box<Expression>),
1209 AssignSubtract(Loc, Box<Expression>, Box<Expression>),
1211 AssignMultiply(Loc, Box<Expression>, Box<Expression>),
1213 AssignDivide(Loc, Box<Expression>, Box<Expression>),
1215 AssignModulo(Loc, Box<Expression>, Box<Expression>),
1217
1218 BoolLiteral(Loc, bool),
1220 NumberLiteral(Loc, String, String, Option<Identifier>),
1222 RationalNumberLiteral(Loc, String, String, String, Option<Identifier>),
1224 HexNumberLiteral(Loc, String, Option<Identifier>),
1226 StringLiteral(Vec<StringLiteral>),
1228 Type(Loc, Type),
1230 HexLiteral(Vec<HexLiteral>),
1232 AddressLiteral(Loc, String),
1238 Variable(Identifier),
1240 List(Loc, ParameterList),
1242 ArrayLiteral(Loc, Vec<Expression>),
1244}
1245
1246macro_rules! expr_components {
1248 ($s:ident) => {
1249 match $s {
1250 PostDecrement(_, expr) | PostIncrement(_, expr) => (Some(expr), None),
1252
1253 Not(_, expr)
1255 | BitwiseNot(_, expr)
1256 | New(_, expr)
1257 | Delete(_, expr)
1258 | UnaryPlus(_, expr)
1259 | Negate(_, expr)
1260 | PreDecrement(_, expr)
1261 | Parenthesis(_, expr)
1262 | PreIncrement(_, expr) => (None, Some(expr)),
1263
1264 Power(_, left, right)
1266 | Multiply(_, left, right)
1267 | Divide(_, left, right)
1268 | Modulo(_, left, right)
1269 | Add(_, left, right)
1270 | Subtract(_, left, right)
1271 | ShiftLeft(_, left, right)
1272 | ShiftRight(_, left, right)
1273 | BitwiseAnd(_, left, right)
1274 | BitwiseXor(_, left, right)
1275 | BitwiseOr(_, left, right)
1276 | Less(_, left, right)
1277 | More(_, left, right)
1278 | LessEqual(_, left, right)
1279 | MoreEqual(_, left, right)
1280 | Equal(_, left, right)
1281 | NotEqual(_, left, right)
1282 | And(_, left, right)
1283 | Or(_, left, right)
1284 | Assign(_, left, right)
1285 | AssignOr(_, left, right)
1286 | AssignAnd(_, left, right)
1287 | AssignXor(_, left, right)
1288 | AssignShiftLeft(_, left, right)
1289 | AssignShiftRight(_, left, right)
1290 | AssignAdd(_, left, right)
1291 | AssignSubtract(_, left, right)
1292 | AssignMultiply(_, left, right)
1293 | AssignDivide(_, left, right)
1294 | AssignModulo(_, left, right) => (Some(left), Some(right)),
1295
1296 MemberAccess(..)
1298 | ConditionalOperator(..)
1299 | ArraySubscript(..)
1300 | ArraySlice(..)
1301 | FunctionCall(..)
1302 | FunctionCallBlock(..)
1303 | NamedFunctionCall(..)
1304 | BoolLiteral(..)
1305 | NumberLiteral(..)
1306 | RationalNumberLiteral(..)
1307 | HexNumberLiteral(..)
1308 | StringLiteral(..)
1309 | Type(..)
1310 | HexLiteral(..)
1311 | AddressLiteral(..)
1312 | Variable(..)
1313 | List(..)
1314 | ArrayLiteral(..) => (None, None),
1315 }
1316 };
1317}
1318
1319impl Expression {
1320 #[inline]
1322 pub fn remove_parenthesis(&self) -> &Expression {
1323 if let Expression::Parenthesis(_, expr) = self {
1324 expr
1325 } else {
1326 self
1327 }
1328 }
1329
1330 pub fn strip_parentheses(&self) -> &Expression {
1332 match self {
1333 Expression::Parenthesis(_, expr) => expr.strip_parentheses(),
1334 _ => self,
1335 }
1336 }
1337
1338 #[inline]
1364 pub fn components(&self) -> (Option<&Self>, Option<&Self>) {
1365 use Expression::*;
1366 expr_components!(self)
1367 }
1368
1369 #[inline]
1373 pub fn components_mut(&mut self) -> (Option<&mut Self>, Option<&mut Self>) {
1374 use Expression::*;
1375 expr_components!(self)
1376 }
1377
1378 #[inline]
1380 pub const fn is_unsplittable(&self) -> bool {
1381 use Expression::*;
1382 matches!(
1383 self,
1384 BoolLiteral(..)
1385 | NumberLiteral(..)
1386 | RationalNumberLiteral(..)
1387 | HexNumberLiteral(..)
1388 | StringLiteral(..)
1389 | HexLiteral(..)
1390 | AddressLiteral(..)
1391 | Variable(..)
1392 )
1393 }
1394
1395 #[inline]
1397 pub const fn has_space_around(&self) -> bool {
1398 use Expression::*;
1399 !matches!(
1400 self,
1401 PostIncrement(..)
1402 | PreIncrement(..)
1403 | PostDecrement(..)
1404 | PreDecrement(..)
1405 | Not(..)
1406 | BitwiseNot(..)
1407 | UnaryPlus(..)
1408 | Negate(..)
1409 )
1410 }
1411
1412 pub fn is_literal(&self) -> bool {
1414 matches!(
1415 self,
1416 Expression::AddressLiteral(..)
1417 | Expression::HexLiteral(..)
1418 | Expression::BoolLiteral(..)
1419 | Expression::NumberLiteral(..)
1420 | Expression::ArrayLiteral(..)
1421 | Expression::HexNumberLiteral(..)
1422 | Expression::RationalNumberLiteral(..)
1423 | Expression::StringLiteral(..)
1424 )
1425 }
1426}
1427
1428#[derive(Debug, PartialEq, Eq, Clone)]
1432#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1433pub struct Parameter {
1434 pub loc: Loc,
1436 pub annotation: Option<Annotation>,
1438 pub ty: Expression,
1440 pub storage: Option<StorageLocation>,
1442 pub name: Option<Identifier>,
1444}
1445
1446#[derive(Debug, PartialEq, Eq, Clone)]
1448#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1449pub enum Mutability {
1450 Pure(Loc),
1452
1453 View(Loc),
1455
1456 Constant(Loc),
1458
1459 Payable(Loc),
1461}
1462
1463#[derive(Debug, PartialEq, Eq, Clone)]
1467#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1468#[repr(u8)] pub enum Visibility {
1470 External(Option<Loc>),
1472
1473 Public(Option<Loc>),
1475
1476 Internal(Option<Loc>),
1478
1479 Private(Option<Loc>),
1481}
1482
1483#[derive(Debug, PartialEq, Eq, Clone)]
1485#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1486#[repr(u8)] pub enum FunctionAttribute {
1488 Visibility(Visibility),
1490
1491 Mutability(Mutability),
1493
1494 Virtual(Loc),
1496
1497 Immutable(Loc),
1499
1500 Override(Loc, Vec<IdentifierPath>),
1502
1503 BaseOrModifier(Loc, Base),
1505
1506 Error(Loc),
1508}
1509
1510#[derive(Debug, PartialEq, Eq, Clone, Copy)]
1512#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1513pub enum FunctionTy {
1514 Constructor,
1516
1517 Function,
1519
1520 Fallback,
1522
1523 Receive,
1525
1526 Modifier,
1528}
1529
1530#[derive(Debug, PartialEq, Eq, Clone)]
1534#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1535pub struct FunctionDefinition {
1536 pub loc_prototype: Loc,
1538 pub loc: Loc,
1540 pub ty: FunctionTy,
1542 pub name: Option<Identifier>,
1546 pub name_loc: Loc,
1548 pub params: ParameterList,
1550 pub attributes: Vec<FunctionAttribute>,
1552 pub return_not_returns: Option<Loc>,
1554 pub returns: ParameterList,
1556 pub body: Option<Statement>,
1560}
1561
1562impl FunctionDefinition {
1563 #[inline]
1565 pub fn is_void(&self) -> bool {
1566 self.returns.is_empty()
1567 }
1568
1569 #[inline]
1571 pub fn is_empty(&self) -> bool {
1572 self.body.as_ref().is_none_or(Statement::is_empty)
1573 }
1574
1575 #[inline]
1577 pub fn sort_attributes(&mut self) {
1578 self.attributes.sort();
1581 }
1582}
1583
1584#[derive(Debug, PartialEq, Eq, Clone)]
1586#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1587#[allow(clippy::large_enum_variant, clippy::type_complexity)]
1588pub enum Statement {
1589 Block {
1591 loc: Loc,
1593 unchecked: bool,
1595 statements: Vec<Statement>,
1597 },
1598 Assembly {
1600 loc: Loc,
1602 dialect: Option<StringLiteral>,
1604 flags: Option<Vec<StringLiteral>>,
1606 block: YulBlock,
1608 },
1609 Args(Loc, Vec<NamedArgument>),
1611 If(Loc, Expression, Box<Statement>, Option<Box<Statement>>),
1615 While(Loc, Expression, Box<Statement>),
1619 Expression(Loc, Expression),
1621 VariableDefinition(Loc, VariableDeclaration, Option<Expression>),
1623 For(
1627 Loc,
1628 Option<Box<Statement>>,
1629 Option<Box<Expression>>,
1630 Option<Box<Expression>>,
1631 Option<Box<Statement>>,
1632 ),
1633 DoWhile(Loc, Box<Statement>, Expression),
1637 Continue(Loc),
1639 Break(Loc),
1641 Return(Loc, Option<Expression>),
1643 Revert(Loc, Option<IdentifierPath>, Vec<Expression>),
1645 RevertNamedArgs(Loc, Option<IdentifierPath>, Vec<NamedArgument>),
1647 Emit(Loc, Expression),
1651 Try(
1655 Loc,
1656 Expression,
1657 Option<(ParameterList, Box<Statement>)>,
1658 Vec<CatchClause>,
1659 ),
1660 Error(Loc),
1662}
1663
1664impl Statement {
1665 #[inline]
1667 pub fn is_empty(&self) -> bool {
1668 match self {
1669 Self::Block { statements, .. } => statements.is_empty(),
1670 Self::Assembly { block, .. } => block.is_empty(),
1671 Self::Args(_, args) => args.is_empty(),
1672 _ => false,
1673 }
1674 }
1675}
1676
1677#[derive(Debug, PartialEq, Eq, Clone)]
1679#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1680pub enum CatchClause {
1681 Simple(Loc, Option<Parameter>, Statement),
1683
1684 Named(Loc, Identifier, Parameter, Statement),
1686}
1687
1688#[derive(Debug, PartialEq, Eq, Clone)]
1690#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1691pub enum YulStatement {
1692 Assign(Loc, Vec<YulExpression>, YulExpression),
1694 VariableDeclaration(Loc, Vec<YulTypedIdentifier>, Option<YulExpression>),
1696 If(Loc, YulExpression, YulBlock),
1698 For(YulFor),
1700 Switch(YulSwitch),
1702 Leave(Loc),
1704 Break(Loc),
1706 Continue(Loc),
1708 Block(YulBlock),
1710 FunctionDefinition(Box<YulFunctionDefinition>),
1712 FunctionCall(Box<YulFunctionCall>),
1714 Error(Loc),
1716}
1717
1718#[derive(Debug, PartialEq, Eq, Clone)]
1728#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1729pub struct YulSwitch {
1730 pub loc: Loc,
1732 pub condition: YulExpression,
1734 pub cases: Vec<YulSwitchOptions>,
1736 pub default: Option<YulSwitchOptions>,
1738}
1739
1740#[derive(Debug, PartialEq, Eq, Clone)]
1744#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1745pub struct YulFor {
1746 pub loc: Loc,
1748 pub init_block: YulBlock,
1750 pub condition: YulExpression,
1752 pub post_block: YulBlock,
1754 pub execution_block: YulBlock,
1756}
1757
1758#[derive(Debug, PartialEq, Eq, Clone)]
1762#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1763pub struct YulBlock {
1764 pub loc: Loc,
1766 pub statements: Vec<YulStatement>,
1768}
1769
1770impl YulBlock {
1771 #[inline]
1773 pub fn is_empty(&self) -> bool {
1774 self.statements.is_empty()
1775 }
1776}
1777
1778#[derive(Debug, PartialEq, Eq, Clone)]
1780#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1781pub enum YulExpression {
1782 BoolLiteral(Loc, bool, Option<Identifier>),
1784 NumberLiteral(Loc, String, String, Option<Identifier>),
1786 HexNumberLiteral(Loc, String, Option<Identifier>),
1788 HexStringLiteral(HexLiteral, Option<Identifier>),
1790 StringLiteral(StringLiteral, Option<Identifier>),
1792 Variable(Identifier),
1794 FunctionCall(Box<YulFunctionCall>),
1796 SuffixAccess(Loc, Box<YulExpression>, Identifier),
1798}
1799
1800#[derive(Debug, PartialEq, Eq, Clone)]
1804#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1805pub struct YulTypedIdentifier {
1806 pub loc: Loc,
1808 pub id: Identifier,
1810 pub ty: Option<Identifier>,
1812}
1813
1814#[derive(Debug, PartialEq, Eq, Clone)]
1818#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1819pub struct YulFunctionDefinition {
1820 pub loc: Loc,
1822 pub id: Identifier,
1824 pub params: Vec<YulTypedIdentifier>,
1826 pub returns: Vec<YulTypedIdentifier>,
1828 pub body: YulBlock,
1830}
1831
1832impl YulFunctionDefinition {
1833 #[inline]
1835 pub fn is_void(&self) -> bool {
1836 self.returns.is_empty()
1837 }
1838
1839 #[inline]
1841 pub fn is_empty(&self) -> bool {
1842 self.body.is_empty()
1843 }
1844}
1845
1846#[derive(Debug, PartialEq, Eq, Clone)]
1850#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1851pub struct YulFunctionCall {
1852 pub loc: Loc,
1854 pub id: Identifier,
1856 pub arguments: Vec<YulExpression>,
1858}
1859
1860#[derive(Debug, PartialEq, Eq, Clone)]
1862#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1863pub enum YulSwitchOptions {
1864 Case(Loc, YulExpression, YulBlock),
1866 Default(Loc, YulBlock),
1868}