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
509#[derive(Debug, PartialEq, Eq, Clone)]
513#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
514pub struct VariableDeclaration {
515 pub loc: Loc,
517 pub ty: Expression,
519 pub storage: Option<StorageLocation>,
521 pub name: Option<Identifier>,
525}
526
527#[derive(Debug, PartialEq, Eq, Clone)]
531#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
532pub struct StructDefinition {
533 pub loc: Loc,
535 pub name: Option<Identifier>,
539 pub fields: Vec<VariableDeclaration>,
541}
542
543#[derive(Debug, PartialEq, Eq, Clone)]
545#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
546pub enum ContractPart {
547 StructDefinition(Box<StructDefinition>),
549
550 EventDefinition(Box<EventDefinition>),
552
553 EnumDefinition(Box<EnumDefinition>),
555
556 ErrorDefinition(Box<ErrorDefinition>),
558
559 VariableDefinition(Box<VariableDefinition>),
561
562 FunctionDefinition(Box<FunctionDefinition>),
564
565 TypeDefinition(Box<TypeDefinition>),
567
568 Annotation(Box<Annotation>),
570
571 Using(Box<Using>),
573
574 StraySemicolon(Loc),
576}
577
578#[derive(Debug, PartialEq, Eq, Clone)]
580#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
581pub enum PragmaDirective {
582 Identifier(Loc, Option<Identifier>, Option<Identifier>),
584 StringLiteral(Loc, Identifier, StringLiteral),
586 Version(Loc, Identifier, Vec<VersionComparator>),
588}
589
590#[derive(Debug, PartialEq, Eq, Clone)]
592#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
593pub enum VersionComparator {
594 Plain {
596 loc: Loc,
598 version: Vec<String>,
600 },
601 Operator {
603 loc: Loc,
605 op: VersionOp,
607 version: Vec<String>,
609 },
610 Or {
612 loc: Loc,
614 left: Box<VersionComparator>,
616 right: Box<VersionComparator>,
618 },
619 Range {
621 loc: Loc,
623 from: Vec<String>,
625 to: Vec<String>,
627 },
628}
629
630#[derive(Debug, PartialEq, Eq, Copy, Clone)]
632#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
633pub enum VersionOp {
634 Exact,
636 Greater,
638 GreaterEq,
640 Less,
642 LessEq,
644 Tilde,
646 Caret,
648 Wildcard,
650}
651
652#[derive(Debug, PartialEq, Eq, Clone)]
654#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
655pub enum UsingList {
656 Library(IdentifierPath),
658
659 Functions(Vec<UsingFunction>),
663
664 Error,
666}
667
668#[derive(Debug, PartialEq, Eq, Clone)]
672#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
673pub struct UsingFunction {
674 pub loc: Loc,
676 pub path: IdentifierPath,
678 pub oper: Option<UserDefinedOperator>,
680}
681
682#[derive(Clone, Copy, Debug, PartialEq, Eq)]
688#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
689pub enum UserDefinedOperator {
690 BitwiseAnd,
692 BitwiseNot,
695 Negate,
699 BitwiseOr,
701 BitwiseXor,
703 Add,
705 Divide,
707 Modulo,
709 Multiply,
711 Subtract,
713 Equal,
715 More,
717 MoreEqual,
719 Less,
721 LessEqual,
723 NotEqual,
725}
726
727impl UserDefinedOperator {
728 #[inline]
730 pub const fn args(&self) -> usize {
731 match self {
732 UserDefinedOperator::BitwiseNot | UserDefinedOperator::Negate => 1,
733 _ => 2,
734 }
735 }
736
737 #[inline]
739 pub const fn is_unary(&self) -> bool {
740 matches!(self, Self::BitwiseNot | Self::Negate)
741 }
742
743 #[inline]
745 pub const fn is_binary(&self) -> bool {
746 !self.is_unary()
747 }
748
749 #[inline]
751 pub const fn is_bitwise(&self) -> bool {
752 matches!(
753 self,
754 Self::BitwiseAnd | Self::BitwiseOr | Self::BitwiseXor | Self::BitwiseNot
755 )
756 }
757
758 #[inline]
760 pub const fn is_arithmetic(&self) -> bool {
761 matches!(
762 self,
763 Self::Add | Self::Subtract | Self::Multiply | Self::Divide | Self::Modulo
764 )
765 }
766
767 #[inline]
769 pub const fn is_comparison(&self) -> bool {
770 matches!(
771 self,
772 Self::Equal
773 | Self::NotEqual
774 | Self::Less
775 | Self::LessEqual
776 | Self::More
777 | Self::MoreEqual
778 )
779 }
780}
781
782#[derive(Debug, PartialEq, Eq, Clone)]
788#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
789pub struct Using {
790 pub loc: Loc,
792 pub list: UsingList,
794 pub ty: Option<Expression>,
798 pub global: Option<Identifier>,
800}
801
802#[derive(Debug, PartialEq, Eq, Clone)]
804#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
805pub enum ContractTy {
806 Abstract(Loc),
808
809 Contract(Loc),
811
812 Interface(Loc),
814
815 Library(Loc),
817}
818
819#[derive(Debug, PartialEq, Eq, Clone)]
826#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
827pub struct Base {
828 pub loc: Loc,
830 pub name: IdentifierPath,
832 pub args: Option<Vec<Expression>>,
834}
835
836#[derive(Debug, PartialEq, Eq, Clone)]
840#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
841pub struct ContractDefinition {
842 pub loc: Loc,
844 pub ty: ContractTy,
846 pub name: Option<Identifier>,
850 pub base: Vec<Base>,
852 pub parts: Vec<ContractPart>,
854}
855
856#[derive(Debug, PartialEq, Eq, Clone)]
860#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
861pub struct EventParameter {
862 pub loc: Loc,
864 pub ty: Expression,
866 pub indexed: bool,
868 pub name: Option<Identifier>,
870}
871
872#[derive(Debug, PartialEq, Eq, Clone)]
876#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
877pub struct EventDefinition {
878 pub loc: Loc,
880 pub name: Option<Identifier>,
884 pub fields: Vec<EventParameter>,
886 pub anonymous: bool,
888}
889
890#[derive(Debug, PartialEq, Eq, Clone)]
894#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
895pub struct ErrorParameter {
896 pub loc: Loc,
898 pub ty: Expression,
900 pub name: Option<Identifier>,
902}
903
904#[derive(Debug, PartialEq, Eq, Clone)]
908#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
909pub struct ErrorDefinition {
910 pub loc: Loc,
912 pub keyword: Expression,
914 pub name: Option<Identifier>,
918 pub fields: Vec<ErrorParameter>,
920}
921
922#[derive(Debug, PartialEq, Eq, Clone)]
926#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
927pub struct EnumDefinition {
928 pub loc: Loc,
930 pub name: Option<Identifier>,
934 pub values: Vec<Option<Identifier>>,
938}
939
940#[derive(Debug, PartialEq, Eq, Clone)]
942#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
943#[repr(u8)] pub enum VariableAttribute {
945 Visibility(Visibility),
949
950 Constant(Loc),
952
953 Immutable(Loc),
955
956 Override(Loc, Vec<IdentifierPath>),
958
959 StorageType(StorageType),
961}
962
963#[derive(Debug, PartialEq, Eq, Clone)]
965#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
966#[repr(u8)] pub enum StorageType {
968 Temporary(Option<Loc>),
970
971 Persistent(Option<Loc>),
973
974 Instance(Option<Loc>),
976}
977
978#[derive(Debug, PartialEq, Eq, Clone)]
982#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
983pub struct VariableDefinition {
984 pub loc: Loc,
986 pub ty: Expression,
988 pub attrs: Vec<VariableAttribute>,
990 pub name: Option<Identifier>,
994 pub initializer: Option<Expression>,
996}
997
998#[derive(Debug, PartialEq, Eq, Clone)]
1002#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1003pub struct TypeDefinition {
1004 pub loc: Loc,
1006 pub name: Identifier,
1008 pub ty: Expression,
1010}
1011
1012#[derive(Debug, PartialEq, Eq, Clone)]
1016#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1017pub struct Annotation {
1018 pub loc: Loc,
1020 pub id: Identifier,
1022 pub value: Option<Expression>,
1024}
1025
1026#[derive(Debug, PartialEq, Eq, Clone)]
1030#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1031pub struct StringLiteral {
1032 pub loc: Loc,
1034 pub unicode: bool,
1036 pub string: String,
1040}
1041
1042#[derive(Debug, PartialEq, Eq, Clone)]
1046#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1047pub struct HexLiteral {
1048 pub loc: Loc,
1050 pub hex: String,
1054}
1055
1056#[derive(Debug, PartialEq, Eq, Clone)]
1060#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1061pub struct NamedArgument {
1062 pub loc: Loc,
1064 pub name: Identifier,
1066 pub expr: Expression,
1068}
1069
1070#[derive(Debug, PartialEq, Eq, Clone)]
1072#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1073pub enum Expression {
1074 PostIncrement(Loc, Box<Expression>),
1076 PostDecrement(Loc, Box<Expression>),
1078 New(Loc, Box<Expression>),
1080 ArraySubscript(Loc, Box<Expression>, Option<Box<Expression>>),
1082 ArraySlice(
1084 Loc,
1085 Box<Expression>,
1086 Option<Box<Expression>>,
1087 Option<Box<Expression>>,
1088 ),
1089 Parenthesis(Loc, Box<Expression>),
1091 MemberAccess(Loc, Box<Expression>, Identifier),
1093 FunctionCall(Loc, Box<Expression>, Vec<Expression>),
1095 FunctionCallBlock(Loc, Box<Expression>, Box<Statement>),
1097 NamedFunctionCall(Loc, Box<Expression>, Vec<NamedArgument>),
1099 Not(Loc, Box<Expression>),
1101 BitwiseNot(Loc, Box<Expression>),
1103 Delete(Loc, Box<Expression>),
1105 PreIncrement(Loc, Box<Expression>),
1107 PreDecrement(Loc, Box<Expression>),
1109 UnaryPlus(Loc, Box<Expression>),
1113 Negate(Loc, Box<Expression>),
1115
1116 Power(Loc, Box<Expression>, Box<Expression>),
1118 Multiply(Loc, Box<Expression>, Box<Expression>),
1120 Divide(Loc, Box<Expression>, Box<Expression>),
1122 Modulo(Loc, Box<Expression>, Box<Expression>),
1124 Add(Loc, Box<Expression>, Box<Expression>),
1126 Subtract(Loc, Box<Expression>, Box<Expression>),
1128 ShiftLeft(Loc, Box<Expression>, Box<Expression>),
1130 ShiftRight(Loc, Box<Expression>, Box<Expression>),
1132 BitwiseAnd(Loc, Box<Expression>, Box<Expression>),
1134 BitwiseXor(Loc, Box<Expression>, Box<Expression>),
1136 BitwiseOr(Loc, Box<Expression>, Box<Expression>),
1138 Less(Loc, Box<Expression>, Box<Expression>),
1140 More(Loc, Box<Expression>, Box<Expression>),
1142 LessEqual(Loc, Box<Expression>, Box<Expression>),
1144 MoreEqual(Loc, Box<Expression>, Box<Expression>),
1146 Equal(Loc, Box<Expression>, Box<Expression>),
1148 NotEqual(Loc, Box<Expression>, Box<Expression>),
1150 And(Loc, Box<Expression>, Box<Expression>),
1152 Or(Loc, Box<Expression>, Box<Expression>),
1154 ConditionalOperator(Loc, Box<Expression>, Box<Expression>, Box<Expression>),
1158 Assign(Loc, Box<Expression>, Box<Expression>),
1160 AssignOr(Loc, Box<Expression>, Box<Expression>),
1162 AssignAnd(Loc, Box<Expression>, Box<Expression>),
1164 AssignXor(Loc, Box<Expression>, Box<Expression>),
1166 AssignShiftLeft(Loc, Box<Expression>, Box<Expression>),
1168 AssignShiftRight(Loc, Box<Expression>, Box<Expression>),
1170 AssignAdd(Loc, Box<Expression>, Box<Expression>),
1172 AssignSubtract(Loc, Box<Expression>, Box<Expression>),
1174 AssignMultiply(Loc, Box<Expression>, Box<Expression>),
1176 AssignDivide(Loc, Box<Expression>, Box<Expression>),
1178 AssignModulo(Loc, Box<Expression>, Box<Expression>),
1180
1181 BoolLiteral(Loc, bool),
1183 NumberLiteral(Loc, String, String, Option<Identifier>),
1185 RationalNumberLiteral(Loc, String, String, String, Option<Identifier>),
1187 HexNumberLiteral(Loc, String, Option<Identifier>),
1189 StringLiteral(Vec<StringLiteral>),
1191 Type(Loc, Type),
1193 HexLiteral(Vec<HexLiteral>),
1195 AddressLiteral(Loc, String),
1201 Variable(Identifier),
1203 List(Loc, ParameterList),
1205 ArrayLiteral(Loc, Vec<Expression>),
1207}
1208
1209macro_rules! expr_components {
1211 ($s:ident) => {
1212 match $s {
1213 PostDecrement(_, expr) | PostIncrement(_, expr) => (Some(expr), None),
1215
1216 Not(_, expr)
1218 | BitwiseNot(_, expr)
1219 | New(_, expr)
1220 | Delete(_, expr)
1221 | UnaryPlus(_, expr)
1222 | Negate(_, expr)
1223 | PreDecrement(_, expr)
1224 | Parenthesis(_, expr)
1225 | PreIncrement(_, expr) => (None, Some(expr)),
1226
1227 Power(_, left, right)
1229 | Multiply(_, left, right)
1230 | Divide(_, left, right)
1231 | Modulo(_, left, right)
1232 | Add(_, left, right)
1233 | Subtract(_, left, right)
1234 | ShiftLeft(_, left, right)
1235 | ShiftRight(_, left, right)
1236 | BitwiseAnd(_, left, right)
1237 | BitwiseXor(_, left, right)
1238 | BitwiseOr(_, left, right)
1239 | Less(_, left, right)
1240 | More(_, left, right)
1241 | LessEqual(_, left, right)
1242 | MoreEqual(_, left, right)
1243 | Equal(_, left, right)
1244 | NotEqual(_, left, right)
1245 | And(_, left, right)
1246 | Or(_, left, right)
1247 | Assign(_, left, right)
1248 | AssignOr(_, left, right)
1249 | AssignAnd(_, left, right)
1250 | AssignXor(_, left, right)
1251 | AssignShiftLeft(_, left, right)
1252 | AssignShiftRight(_, left, right)
1253 | AssignAdd(_, left, right)
1254 | AssignSubtract(_, left, right)
1255 | AssignMultiply(_, left, right)
1256 | AssignDivide(_, left, right)
1257 | AssignModulo(_, left, right) => (Some(left), Some(right)),
1258
1259 MemberAccess(..)
1261 | ConditionalOperator(..)
1262 | ArraySubscript(..)
1263 | ArraySlice(..)
1264 | FunctionCall(..)
1265 | FunctionCallBlock(..)
1266 | NamedFunctionCall(..)
1267 | BoolLiteral(..)
1268 | NumberLiteral(..)
1269 | RationalNumberLiteral(..)
1270 | HexNumberLiteral(..)
1271 | StringLiteral(..)
1272 | Type(..)
1273 | HexLiteral(..)
1274 | AddressLiteral(..)
1275 | Variable(..)
1276 | List(..)
1277 | ArrayLiteral(..) => (None, None),
1278 }
1279 };
1280}
1281
1282impl Expression {
1283 #[inline]
1285 pub fn remove_parenthesis(&self) -> &Expression {
1286 if let Expression::Parenthesis(_, expr) = self {
1287 expr
1288 } else {
1289 self
1290 }
1291 }
1292
1293 pub fn strip_parentheses(&self) -> &Expression {
1295 match self {
1296 Expression::Parenthesis(_, expr) => expr.strip_parentheses(),
1297 _ => self,
1298 }
1299 }
1300
1301 #[inline]
1327 pub fn components(&self) -> (Option<&Self>, Option<&Self>) {
1328 use Expression::*;
1329 expr_components!(self)
1330 }
1331
1332 #[inline]
1336 pub fn components_mut(&mut self) -> (Option<&mut Self>, Option<&mut Self>) {
1337 use Expression::*;
1338 expr_components!(self)
1339 }
1340
1341 #[inline]
1343 pub const fn is_unsplittable(&self) -> bool {
1344 use Expression::*;
1345 matches!(
1346 self,
1347 BoolLiteral(..)
1348 | NumberLiteral(..)
1349 | RationalNumberLiteral(..)
1350 | HexNumberLiteral(..)
1351 | StringLiteral(..)
1352 | HexLiteral(..)
1353 | AddressLiteral(..)
1354 | Variable(..)
1355 )
1356 }
1357
1358 #[inline]
1360 pub const fn has_space_around(&self) -> bool {
1361 use Expression::*;
1362 !matches!(
1363 self,
1364 PostIncrement(..)
1365 | PreIncrement(..)
1366 | PostDecrement(..)
1367 | PreDecrement(..)
1368 | Not(..)
1369 | BitwiseNot(..)
1370 | UnaryPlus(..)
1371 | Negate(..)
1372 )
1373 }
1374
1375 pub fn is_literal(&self) -> bool {
1377 matches!(
1378 self,
1379 Expression::AddressLiteral(..)
1380 | Expression::HexLiteral(..)
1381 | Expression::BoolLiteral(..)
1382 | Expression::NumberLiteral(..)
1383 | Expression::ArrayLiteral(..)
1384 | Expression::HexNumberLiteral(..)
1385 | Expression::RationalNumberLiteral(..)
1386 | Expression::StringLiteral(..)
1387 )
1388 }
1389}
1390
1391#[derive(Debug, PartialEq, Eq, Clone)]
1395#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1396pub struct Parameter {
1397 pub loc: Loc,
1399 pub annotation: Option<Annotation>,
1401 pub ty: Expression,
1403 pub storage: Option<StorageLocation>,
1405 pub name: Option<Identifier>,
1407}
1408
1409#[derive(Debug, PartialEq, Eq, Clone)]
1411#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1412pub enum Mutability {
1413 Pure(Loc),
1415
1416 View(Loc),
1418
1419 Constant(Loc),
1421
1422 Payable(Loc),
1424}
1425
1426#[derive(Debug, PartialEq, Eq, Clone)]
1430#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1431#[repr(u8)] pub enum Visibility {
1433 External(Option<Loc>),
1435
1436 Public(Option<Loc>),
1438
1439 Internal(Option<Loc>),
1441
1442 Private(Option<Loc>),
1444}
1445
1446#[derive(Debug, PartialEq, Eq, Clone)]
1448#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1449#[repr(u8)] pub enum FunctionAttribute {
1451 Visibility(Visibility),
1453
1454 Mutability(Mutability),
1456
1457 Virtual(Loc),
1459
1460 Immutable(Loc),
1462
1463 Override(Loc, Vec<IdentifierPath>),
1465
1466 BaseOrModifier(Loc, Base),
1468
1469 Error(Loc),
1471}
1472
1473#[derive(Debug, PartialEq, Eq, Clone, Copy)]
1475#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1476pub enum FunctionTy {
1477 Constructor,
1479
1480 Function,
1482
1483 Fallback,
1485
1486 Receive,
1488
1489 Modifier,
1491}
1492
1493#[derive(Debug, PartialEq, Eq, Clone)]
1497#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1498pub struct FunctionDefinition {
1499 pub loc_prototype: Loc,
1501 pub loc: Loc,
1503 pub ty: FunctionTy,
1505 pub name: Option<Identifier>,
1509 pub name_loc: Loc,
1511 pub params: ParameterList,
1513 pub attributes: Vec<FunctionAttribute>,
1515 pub return_not_returns: Option<Loc>,
1517 pub returns: ParameterList,
1519 pub body: Option<Statement>,
1523}
1524
1525impl FunctionDefinition {
1526 #[inline]
1528 pub fn is_void(&self) -> bool {
1529 self.returns.is_empty()
1530 }
1531
1532 #[inline]
1534 pub fn is_empty(&self) -> bool {
1535 self.body.as_ref().is_none_or(Statement::is_empty)
1536 }
1537
1538 #[inline]
1540 pub fn sort_attributes(&mut self) {
1541 self.attributes.sort();
1544 }
1545}
1546
1547#[derive(Debug, PartialEq, Eq, Clone)]
1549#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1550#[allow(clippy::large_enum_variant, clippy::type_complexity)]
1551pub enum Statement {
1552 Block {
1554 loc: Loc,
1556 unchecked: bool,
1558 statements: Vec<Statement>,
1560 },
1561 Assembly {
1563 loc: Loc,
1565 dialect: Option<StringLiteral>,
1567 flags: Option<Vec<StringLiteral>>,
1569 block: YulBlock,
1571 },
1572 Args(Loc, Vec<NamedArgument>),
1574 If(Loc, Expression, Box<Statement>, Option<Box<Statement>>),
1578 While(Loc, Expression, Box<Statement>),
1582 Expression(Loc, Expression),
1584 VariableDefinition(Loc, VariableDeclaration, Option<Expression>),
1586 For(
1590 Loc,
1591 Option<Box<Statement>>,
1592 Option<Box<Expression>>,
1593 Option<Box<Expression>>,
1594 Option<Box<Statement>>,
1595 ),
1596 DoWhile(Loc, Box<Statement>, Expression),
1600 Continue(Loc),
1602 Break(Loc),
1604 Return(Loc, Option<Expression>),
1606 Revert(Loc, Option<IdentifierPath>, Vec<Expression>),
1608 RevertNamedArgs(Loc, Option<IdentifierPath>, Vec<NamedArgument>),
1610 Emit(Loc, Expression),
1614 Try(
1618 Loc,
1619 Expression,
1620 Option<(ParameterList, Box<Statement>)>,
1621 Vec<CatchClause>,
1622 ),
1623 Error(Loc),
1625}
1626
1627impl Statement {
1628 #[inline]
1630 pub fn is_empty(&self) -> bool {
1631 match self {
1632 Self::Block { statements, .. } => statements.is_empty(),
1633 Self::Assembly { block, .. } => block.is_empty(),
1634 Self::Args(_, args) => args.is_empty(),
1635 _ => false,
1636 }
1637 }
1638}
1639
1640#[derive(Debug, PartialEq, Eq, Clone)]
1642#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1643pub enum CatchClause {
1644 Simple(Loc, Option<Parameter>, Statement),
1646
1647 Named(Loc, Identifier, Parameter, Statement),
1649}
1650
1651#[derive(Debug, PartialEq, Eq, Clone)]
1653#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1654pub enum YulStatement {
1655 Assign(Loc, Vec<YulExpression>, YulExpression),
1657 VariableDeclaration(Loc, Vec<YulTypedIdentifier>, Option<YulExpression>),
1659 If(Loc, YulExpression, YulBlock),
1661 For(YulFor),
1663 Switch(YulSwitch),
1665 Leave(Loc),
1667 Break(Loc),
1669 Continue(Loc),
1671 Block(YulBlock),
1673 FunctionDefinition(Box<YulFunctionDefinition>),
1675 FunctionCall(Box<YulFunctionCall>),
1677 Error(Loc),
1679}
1680
1681#[derive(Debug, PartialEq, Eq, Clone)]
1691#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1692pub struct YulSwitch {
1693 pub loc: Loc,
1695 pub condition: YulExpression,
1697 pub cases: Vec<YulSwitchOptions>,
1699 pub default: Option<YulSwitchOptions>,
1701}
1702
1703#[derive(Debug, PartialEq, Eq, Clone)]
1707#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1708pub struct YulFor {
1709 pub loc: Loc,
1711 pub init_block: YulBlock,
1713 pub condition: YulExpression,
1715 pub post_block: YulBlock,
1717 pub execution_block: YulBlock,
1719}
1720
1721#[derive(Debug, PartialEq, Eq, Clone)]
1725#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1726pub struct YulBlock {
1727 pub loc: Loc,
1729 pub statements: Vec<YulStatement>,
1731}
1732
1733impl YulBlock {
1734 #[inline]
1736 pub fn is_empty(&self) -> bool {
1737 self.statements.is_empty()
1738 }
1739}
1740
1741#[derive(Debug, PartialEq, Eq, Clone)]
1743#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1744pub enum YulExpression {
1745 BoolLiteral(Loc, bool, Option<Identifier>),
1747 NumberLiteral(Loc, String, String, Option<Identifier>),
1749 HexNumberLiteral(Loc, String, Option<Identifier>),
1751 HexStringLiteral(HexLiteral, Option<Identifier>),
1753 StringLiteral(StringLiteral, Option<Identifier>),
1755 Variable(Identifier),
1757 FunctionCall(Box<YulFunctionCall>),
1759 SuffixAccess(Loc, Box<YulExpression>, Identifier),
1761}
1762
1763#[derive(Debug, PartialEq, Eq, Clone)]
1767#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1768pub struct YulTypedIdentifier {
1769 pub loc: Loc,
1771 pub id: Identifier,
1773 pub ty: Option<Identifier>,
1775}
1776
1777#[derive(Debug, PartialEq, Eq, Clone)]
1781#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1782pub struct YulFunctionDefinition {
1783 pub loc: Loc,
1785 pub id: Identifier,
1787 pub params: Vec<YulTypedIdentifier>,
1789 pub returns: Vec<YulTypedIdentifier>,
1791 pub body: YulBlock,
1793}
1794
1795impl YulFunctionDefinition {
1796 #[inline]
1798 pub fn is_void(&self) -> bool {
1799 self.returns.is_empty()
1800 }
1801
1802 #[inline]
1804 pub fn is_empty(&self) -> bool {
1805 self.body.is_empty()
1806 }
1807}
1808
1809#[derive(Debug, PartialEq, Eq, Clone)]
1813#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1814pub struct YulFunctionCall {
1815 pub loc: Loc,
1817 pub id: Identifier,
1819 pub arguments: Vec<YulExpression>,
1821}
1822
1823#[derive(Debug, PartialEq, Eq, Clone)]
1825#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
1826pub enum YulSwitchOptions {
1827 Case(Loc, YulExpression, YulBlock),
1829 Default(Loc, YulBlock),
1831}