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 StorageLocation(StorageLocation),
1001}
1002
1003#[derive(Debug, PartialEq, Eq, Clone)]
1005#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1006#[repr(u8)] pub enum StorageType {
1008 Temporary(Option<Loc>),
1010
1011 Persistent(Option<Loc>),
1013
1014 Instance(Option<Loc>),
1016}
1017
1018#[derive(Debug, PartialEq, Eq, Clone)]
1022#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1023pub struct VariableDefinition {
1024 pub loc: Loc,
1026 pub ty: Expression,
1028 pub attrs: Vec<VariableAttribute>,
1030 pub name: Option<Identifier>,
1034 pub initializer: Option<Expression>,
1036}
1037
1038#[derive(Debug, PartialEq, Eq, Clone)]
1042#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1043pub struct TypeDefinition {
1044 pub loc: Loc,
1046 pub name: Identifier,
1048 pub ty: Expression,
1050}
1051
1052#[derive(Debug, PartialEq, Eq, Clone)]
1056#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1057pub struct Annotation {
1058 pub loc: Loc,
1060 pub id: Identifier,
1062 pub value: Option<Expression>,
1064}
1065
1066#[derive(Debug, PartialEq, Eq, Clone)]
1070#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1071pub struct StringLiteral {
1072 pub loc: Loc,
1074 pub unicode: bool,
1076 pub string: String,
1080}
1081
1082#[derive(Debug, PartialEq, Eq, Clone)]
1086#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1087pub struct HexLiteral {
1088 pub loc: Loc,
1090 pub hex: String,
1094}
1095
1096#[derive(Debug, PartialEq, Eq, Clone)]
1100#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1101pub struct NamedArgument {
1102 pub loc: Loc,
1104 pub name: Identifier,
1106 pub expr: Expression,
1108}
1109
1110#[derive(Debug, PartialEq, Eq, Clone)]
1112#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1113pub enum Expression {
1114 PostIncrement(Loc, Box<Expression>),
1116 PostDecrement(Loc, Box<Expression>),
1118 New(Loc, Box<Expression>),
1120 ArraySubscript(Loc, Box<Expression>, Option<Box<Expression>>),
1122 ArraySlice(
1124 Loc,
1125 Box<Expression>,
1126 Option<Box<Expression>>,
1127 Option<Box<Expression>>,
1128 ),
1129 Parenthesis(Loc, Box<Expression>),
1131 MemberAccess(Loc, Box<Expression>, Identifier),
1133 FunctionCall(Loc, Box<Expression>, Vec<Expression>),
1135 FunctionCallBlock(Loc, Box<Expression>, Box<Statement>),
1137 NamedFunctionCall(Loc, Box<Expression>, Vec<NamedArgument>),
1139 Not(Loc, Box<Expression>),
1141 BitwiseNot(Loc, Box<Expression>),
1143 Delete(Loc, Box<Expression>),
1145 PreIncrement(Loc, Box<Expression>),
1147 PreDecrement(Loc, Box<Expression>),
1149 UnaryPlus(Loc, Box<Expression>),
1153 Negate(Loc, Box<Expression>),
1155
1156 Power(Loc, Box<Expression>, Box<Expression>),
1158 Multiply(Loc, Box<Expression>, Box<Expression>),
1160 Divide(Loc, Box<Expression>, Box<Expression>),
1162 Modulo(Loc, Box<Expression>, Box<Expression>),
1164 Add(Loc, Box<Expression>, Box<Expression>),
1166 Subtract(Loc, Box<Expression>, Box<Expression>),
1168 ShiftLeft(Loc, Box<Expression>, Box<Expression>),
1170 ShiftRight(Loc, Box<Expression>, Box<Expression>),
1172 BitwiseAnd(Loc, Box<Expression>, Box<Expression>),
1174 BitwiseXor(Loc, Box<Expression>, Box<Expression>),
1176 BitwiseOr(Loc, Box<Expression>, Box<Expression>),
1178 Less(Loc, Box<Expression>, Box<Expression>),
1180 More(Loc, Box<Expression>, Box<Expression>),
1182 LessEqual(Loc, Box<Expression>, Box<Expression>),
1184 MoreEqual(Loc, Box<Expression>, Box<Expression>),
1186 Equal(Loc, Box<Expression>, Box<Expression>),
1188 NotEqual(Loc, Box<Expression>, Box<Expression>),
1190 And(Loc, Box<Expression>, Box<Expression>),
1192 Or(Loc, Box<Expression>, Box<Expression>),
1194 ConditionalOperator(Loc, Box<Expression>, Box<Expression>, Box<Expression>),
1198 Assign(Loc, Box<Expression>, Box<Expression>),
1200 AssignOr(Loc, Box<Expression>, Box<Expression>),
1202 AssignAnd(Loc, Box<Expression>, Box<Expression>),
1204 AssignXor(Loc, Box<Expression>, Box<Expression>),
1206 AssignShiftLeft(Loc, Box<Expression>, Box<Expression>),
1208 AssignShiftRight(Loc, Box<Expression>, Box<Expression>),
1210 AssignAdd(Loc, Box<Expression>, Box<Expression>),
1212 AssignSubtract(Loc, Box<Expression>, Box<Expression>),
1214 AssignMultiply(Loc, Box<Expression>, Box<Expression>),
1216 AssignDivide(Loc, Box<Expression>, Box<Expression>),
1218 AssignModulo(Loc, Box<Expression>, Box<Expression>),
1220
1221 BoolLiteral(Loc, bool),
1223 NumberLiteral(Loc, String, String, Option<Identifier>),
1225 RationalNumberLiteral(Loc, String, String, String, Option<Identifier>),
1227 HexNumberLiteral(Loc, String, Option<Identifier>),
1229 StringLiteral(Vec<StringLiteral>),
1231 Type(Loc, Type),
1233 HexLiteral(Vec<HexLiteral>),
1235 AddressLiteral(Loc, String),
1241 Variable(Identifier),
1243 List(Loc, ParameterList),
1245 ArrayLiteral(Loc, Vec<Expression>),
1247}
1248
1249macro_rules! expr_components {
1251 ($s:ident) => {
1252 match $s {
1253 PostDecrement(_, expr) | PostIncrement(_, expr) => (Some(expr), None),
1255
1256 Not(_, expr)
1258 | BitwiseNot(_, expr)
1259 | New(_, expr)
1260 | Delete(_, expr)
1261 | UnaryPlus(_, expr)
1262 | Negate(_, expr)
1263 | PreDecrement(_, expr)
1264 | Parenthesis(_, expr)
1265 | PreIncrement(_, expr) => (None, Some(expr)),
1266
1267 Power(_, left, right)
1269 | Multiply(_, left, right)
1270 | Divide(_, left, right)
1271 | Modulo(_, left, right)
1272 | Add(_, left, right)
1273 | Subtract(_, left, right)
1274 | ShiftLeft(_, left, right)
1275 | ShiftRight(_, left, right)
1276 | BitwiseAnd(_, left, right)
1277 | BitwiseXor(_, left, right)
1278 | BitwiseOr(_, left, right)
1279 | Less(_, left, right)
1280 | More(_, left, right)
1281 | LessEqual(_, left, right)
1282 | MoreEqual(_, left, right)
1283 | Equal(_, left, right)
1284 | NotEqual(_, left, right)
1285 | And(_, left, right)
1286 | Or(_, left, right)
1287 | Assign(_, left, right)
1288 | AssignOr(_, left, right)
1289 | AssignAnd(_, left, right)
1290 | AssignXor(_, left, right)
1291 | AssignShiftLeft(_, left, right)
1292 | AssignShiftRight(_, left, right)
1293 | AssignAdd(_, left, right)
1294 | AssignSubtract(_, left, right)
1295 | AssignMultiply(_, left, right)
1296 | AssignDivide(_, left, right)
1297 | AssignModulo(_, left, right) => (Some(left), Some(right)),
1298
1299 MemberAccess(..)
1301 | ConditionalOperator(..)
1302 | ArraySubscript(..)
1303 | ArraySlice(..)
1304 | FunctionCall(..)
1305 | FunctionCallBlock(..)
1306 | NamedFunctionCall(..)
1307 | BoolLiteral(..)
1308 | NumberLiteral(..)
1309 | RationalNumberLiteral(..)
1310 | HexNumberLiteral(..)
1311 | StringLiteral(..)
1312 | Type(..)
1313 | HexLiteral(..)
1314 | AddressLiteral(..)
1315 | Variable(..)
1316 | List(..)
1317 | ArrayLiteral(..) => (None, None),
1318 }
1319 };
1320}
1321
1322impl Expression {
1323 #[inline]
1325 pub fn remove_parenthesis(&self) -> &Expression {
1326 if let Expression::Parenthesis(_, expr) = self {
1327 expr
1328 } else {
1329 self
1330 }
1331 }
1332
1333 pub fn strip_parentheses(&self) -> &Expression {
1335 match self {
1336 Expression::Parenthesis(_, expr) => expr.strip_parentheses(),
1337 _ => self,
1338 }
1339 }
1340
1341 #[inline]
1367 pub fn components(&self) -> (Option<&Self>, Option<&Self>) {
1368 use Expression::*;
1369 expr_components!(self)
1370 }
1371
1372 #[inline]
1376 pub fn components_mut(&mut self) -> (Option<&mut Self>, Option<&mut Self>) {
1377 use Expression::*;
1378 expr_components!(self)
1379 }
1380
1381 #[inline]
1383 pub const fn is_unsplittable(&self) -> bool {
1384 use Expression::*;
1385 matches!(
1386 self,
1387 BoolLiteral(..)
1388 | NumberLiteral(..)
1389 | RationalNumberLiteral(..)
1390 | HexNumberLiteral(..)
1391 | StringLiteral(..)
1392 | HexLiteral(..)
1393 | AddressLiteral(..)
1394 | Variable(..)
1395 )
1396 }
1397
1398 #[inline]
1400 pub const fn has_space_around(&self) -> bool {
1401 use Expression::*;
1402 !matches!(
1403 self,
1404 PostIncrement(..)
1405 | PreIncrement(..)
1406 | PostDecrement(..)
1407 | PreDecrement(..)
1408 | Not(..)
1409 | BitwiseNot(..)
1410 | UnaryPlus(..)
1411 | Negate(..)
1412 )
1413 }
1414
1415 pub fn is_literal(&self) -> bool {
1417 matches!(
1418 self,
1419 Expression::AddressLiteral(..)
1420 | Expression::HexLiteral(..)
1421 | Expression::BoolLiteral(..)
1422 | Expression::NumberLiteral(..)
1423 | Expression::ArrayLiteral(..)
1424 | Expression::HexNumberLiteral(..)
1425 | Expression::RationalNumberLiteral(..)
1426 | Expression::StringLiteral(..)
1427 )
1428 }
1429}
1430
1431#[derive(Debug, PartialEq, Eq, Clone)]
1435#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1436pub struct Parameter {
1437 pub loc: Loc,
1439 pub annotation: Option<Annotation>,
1441 pub ty: Expression,
1443 pub storage: Option<StorageLocation>,
1445 pub name: Option<Identifier>,
1447}
1448
1449#[derive(Debug, PartialEq, Eq, Clone)]
1451#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1452pub enum Mutability {
1453 Pure(Loc),
1455
1456 View(Loc),
1458
1459 Constant(Loc),
1461
1462 Payable(Loc),
1464}
1465
1466#[derive(Debug, PartialEq, Eq, Clone)]
1470#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1471#[repr(u8)] pub enum Visibility {
1473 External(Option<Loc>),
1475
1476 Public(Option<Loc>),
1478
1479 Internal(Option<Loc>),
1481
1482 Private(Option<Loc>),
1484}
1485
1486#[derive(Debug, PartialEq, Eq, Clone)]
1488#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1489#[repr(u8)] pub enum FunctionAttribute {
1491 Visibility(Visibility),
1493
1494 Mutability(Mutability),
1496
1497 Virtual(Loc),
1499
1500 Immutable(Loc),
1502
1503 Override(Loc, Vec<IdentifierPath>),
1505
1506 BaseOrModifier(Loc, Base),
1508
1509 Error(Loc),
1511}
1512
1513#[derive(Debug, PartialEq, Eq, Clone, Copy)]
1515#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1516pub enum FunctionTy {
1517 Constructor,
1519
1520 Function,
1522
1523 Fallback,
1525
1526 Receive,
1528
1529 Modifier,
1531}
1532
1533#[derive(Debug, PartialEq, Eq, Clone)]
1537#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1538pub struct FunctionDefinition {
1539 pub loc_prototype: Loc,
1541 pub loc: Loc,
1543 pub ty: FunctionTy,
1545 pub name: Option<Identifier>,
1549 pub name_loc: Loc,
1551 pub params: ParameterList,
1553 pub attributes: Vec<FunctionAttribute>,
1555 pub return_not_returns: Option<Loc>,
1557 pub returns: ParameterList,
1559 pub body: Option<Statement>,
1563}
1564
1565impl FunctionDefinition {
1566 #[inline]
1568 pub fn is_void(&self) -> bool {
1569 self.returns.is_empty()
1570 }
1571
1572 #[inline]
1574 pub fn is_empty(&self) -> bool {
1575 self.body.as_ref().is_none_or(Statement::is_empty)
1576 }
1577
1578 #[inline]
1580 pub fn sort_attributes(&mut self) {
1581 self.attributes.sort();
1584 }
1585}
1586
1587#[derive(Debug, PartialEq, Eq, Clone)]
1589#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1590#[allow(clippy::large_enum_variant, clippy::type_complexity)]
1591pub enum Statement {
1592 Block {
1594 loc: Loc,
1596 unchecked: bool,
1598 statements: Vec<Statement>,
1600 },
1601 Assembly {
1603 loc: Loc,
1605 dialect: Option<StringLiteral>,
1607 flags: Option<Vec<StringLiteral>>,
1609 block: YulBlock,
1611 },
1612 Args(Loc, Vec<NamedArgument>),
1614 If(Loc, Expression, Box<Statement>, Option<Box<Statement>>),
1618 While(Loc, Expression, Box<Statement>),
1622 Expression(Loc, Expression),
1624 VariableDefinition(Loc, VariableDeclaration, Option<Expression>),
1626 For(
1630 Loc,
1631 Option<Box<Statement>>,
1632 Option<Box<Expression>>,
1633 Option<Box<Expression>>,
1634 Option<Box<Statement>>,
1635 ),
1636 DoWhile(Loc, Box<Statement>, Expression),
1640 Continue(Loc),
1642 Break(Loc),
1644 Return(Loc, Option<Expression>),
1646 Revert(Loc, Option<IdentifierPath>, Vec<Expression>),
1648 RevertNamedArgs(Loc, Option<IdentifierPath>, Vec<NamedArgument>),
1650 Emit(Loc, Expression),
1654 Try(
1658 Loc,
1659 Expression,
1660 Option<(ParameterList, Box<Statement>)>,
1661 Vec<CatchClause>,
1662 ),
1663 Error(Loc),
1665}
1666
1667impl Statement {
1668 #[inline]
1670 pub fn is_empty(&self) -> bool {
1671 match self {
1672 Self::Block { statements, .. } => statements.is_empty(),
1673 Self::Assembly { block, .. } => block.is_empty(),
1674 Self::Args(_, args) => args.is_empty(),
1675 _ => false,
1676 }
1677 }
1678}
1679
1680#[derive(Debug, PartialEq, Eq, Clone)]
1682#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1683pub enum CatchClause {
1684 Simple(Loc, Option<Parameter>, Statement),
1686
1687 Named(Loc, Identifier, Parameter, Statement),
1689}
1690
1691#[derive(Debug, PartialEq, Eq, Clone)]
1693#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1694pub enum YulStatement {
1695 Assign(Loc, Vec<YulExpression>, YulExpression),
1697 VariableDeclaration(Loc, Vec<YulTypedIdentifier>, Option<YulExpression>),
1699 If(Loc, YulExpression, YulBlock),
1701 For(YulFor),
1703 Switch(YulSwitch),
1705 Leave(Loc),
1707 Break(Loc),
1709 Continue(Loc),
1711 Block(YulBlock),
1713 FunctionDefinition(Box<YulFunctionDefinition>),
1715 FunctionCall(Box<YulFunctionCall>),
1717 Error(Loc),
1719}
1720
1721#[derive(Debug, PartialEq, Eq, Clone)]
1731#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1732pub struct YulSwitch {
1733 pub loc: Loc,
1735 pub condition: YulExpression,
1737 pub cases: Vec<YulSwitchOptions>,
1739 pub default: Option<YulSwitchOptions>,
1741}
1742
1743#[derive(Debug, PartialEq, Eq, Clone)]
1747#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1748pub struct YulFor {
1749 pub loc: Loc,
1751 pub init_block: YulBlock,
1753 pub condition: YulExpression,
1755 pub post_block: YulBlock,
1757 pub execution_block: YulBlock,
1759}
1760
1761#[derive(Debug, PartialEq, Eq, Clone)]
1765#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1766pub struct YulBlock {
1767 pub loc: Loc,
1769 pub statements: Vec<YulStatement>,
1771}
1772
1773impl YulBlock {
1774 #[inline]
1776 pub fn is_empty(&self) -> bool {
1777 self.statements.is_empty()
1778 }
1779}
1780
1781#[derive(Debug, PartialEq, Eq, Clone)]
1783#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1784pub enum YulExpression {
1785 BoolLiteral(Loc, bool, Option<Identifier>),
1787 NumberLiteral(Loc, String, String, Option<Identifier>),
1789 HexNumberLiteral(Loc, String, Option<Identifier>),
1791 HexStringLiteral(HexLiteral, Option<Identifier>),
1793 StringLiteral(StringLiteral, Option<Identifier>),
1795 Variable(Identifier),
1797 FunctionCall(Box<YulFunctionCall>),
1799 SuffixAccess(Loc, Box<YulExpression>, Identifier),
1801}
1802
1803#[derive(Debug, PartialEq, Eq, Clone)]
1807#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1808pub struct YulTypedIdentifier {
1809 pub loc: Loc,
1811 pub id: Identifier,
1813 pub ty: Option<Identifier>,
1815}
1816
1817#[derive(Debug, PartialEq, Eq, Clone)]
1821#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1822pub struct YulFunctionDefinition {
1823 pub loc: Loc,
1825 pub id: Identifier,
1827 pub params: Vec<YulTypedIdentifier>,
1829 pub returns: Vec<YulTypedIdentifier>,
1831 pub body: YulBlock,
1833}
1834
1835impl YulFunctionDefinition {
1836 #[inline]
1838 pub fn is_void(&self) -> bool {
1839 self.returns.is_empty()
1840 }
1841
1842 #[inline]
1844 pub fn is_empty(&self) -> bool {
1845 self.body.is_empty()
1846 }
1847}
1848
1849#[derive(Debug, PartialEq, Eq, Clone)]
1853#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1854pub struct YulFunctionCall {
1855 pub loc: Loc,
1857 pub id: Identifier,
1859 pub arguments: Vec<YulExpression>,
1861}
1862
1863#[derive(Debug, PartialEq, Eq, Clone)]
1865#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1866pub enum YulSwitchOptions {
1867 Case(Loc, YulExpression, YulBlock),
1869 Default(Loc, YulBlock),
1871}