1mod macros;
15mod misc;
16pub use misc::*;
17pub mod util;
18pub mod visitor;
19
20pub(crate) mod lowfidelity;
22pub use lowfidelity::{Ast, Node, NodeType, SourceLocation as LowFidelitySourceLocation};
23
24pub mod yul;
28
29use crate::artifacts::serde_helpers;
30use macros::{ast_node, expr_node, node_group, stmt_node};
31use serde::{Deserialize, Serialize};
32use std::collections::BTreeMap;
33use yul::YulBlock;
34
35ast_node!(
36 struct SourceUnit {
38 #[serde(rename = "absolutePath")]
39 absolute_path: String,
40 #[serde(default, rename = "exportedSymbols")]
41 exported_symbols: BTreeMap<String, Vec<usize>>,
42 #[serde(default)]
43 license: Option<String>,
44 #[serde(default, skip_serializing_if = "Vec::is_empty")]
45 nodes: Vec<SourceUnitPart>,
46 }
47);
48
49node_group! {
50 SourceUnitPart;
51
52 PragmaDirective,
53 ImportDirective,
54 UsingForDirective,
55 VariableDeclaration,
56 EnumDefinition,
57 ErrorDefinition,
58 FunctionDefinition,
59 StructDefinition,
60 UserDefinedValueTypeDefinition,
61 ContractDefinition,
62}
63
64node_group! {
65 Expression;
66
67 Assignment,
68 BinaryOperation,
69 Conditional,
70 ElementaryTypeNameExpression,
71 FunctionCall,
72 FunctionCallOptions,
73 Identifier,
74 IndexAccess,
75 IndexRangeAccess,
76 Literal,
77 MemberAccess,
78 NewExpression,
79 TupleExpression,
80 UnaryOperation,
81}
82
83node_group! {
84 Statement;
85
86 Block,
87 Break,
88 Continue,
89 DoWhileStatement,
90 EmitStatement,
91 ExpressionStatement,
92 ForStatement,
93 IfStatement,
94 InlineAssembly,
95 PlaceholderStatement,
96 Return,
97 RevertStatement,
98 TryStatement,
99 UncheckedBlock,
100 VariableDeclarationStatement,
101 WhileStatement,
102
103}
104
105node_group! {
106 ContractDefinitionPart;
107
108 EnumDefinition,
109 ErrorDefinition,
110 EventDefinition,
111 FunctionDefinition,
112 ModifierDefinition,
113 StructDefinition,
114 UserDefinedValueTypeDefinition,
115 UsingForDirective,
116 VariableDeclaration,
117}
118
119node_group! {
120 TypeName;
121
122 ArrayTypeName,
123 ElementaryTypeName,
124 FunctionTypeName,
125 Mapping,
126 UserDefinedTypeName,
127}
128
129node_group! {
131 UserDefinedTypeNameOrIdentifierPath;
132
133 UserDefinedTypeName,
134 IdentifierPath,
135}
136
137#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
139#[serde(untagged)]
140pub enum BlockOrStatement {
141 Statement(Statement),
142 Block(Block),
143}
144
145node_group! {
147 ExpressionOrVariableDeclarationStatement;
148
149 ExpressionStatement,
150 VariableDeclarationStatement
151}
152
153node_group! {
155 IdentifierOrIdentifierPath;
156
157 Identifier,
158 IdentifierPath
159}
160
161ast_node!(
162 struct ContractDefinition {
164 name: String,
165 #[serde(default, with = "serde_helpers::display_from_str_opt")]
166 name_location: Option<SourceLocation>,
167 #[serde(default, rename = "abstract")]
168 is_abstract: bool,
169 base_contracts: Vec<InheritanceSpecifier>,
170 canonical_name: Option<String>,
171 contract_dependencies: Vec<usize>,
172 #[serde(rename = "contractKind")]
173 kind: ContractKind,
174 documentation: Option<StructuredDocumentation>,
175 fully_implemented: bool,
176 linearized_base_contracts: Vec<usize>,
177 nodes: Vec<ContractDefinitionPart>,
178 scope: usize,
179 #[serde(default, deserialize_with = "serde_helpers::default_for_null")]
180 used_errors: Vec<usize>,
181 #[serde(default, deserialize_with = "serde_helpers::default_for_null")]
182 used_events: Vec<usize>,
183 #[serde(default, rename = "internalFunctionIDs")]
184 internal_function_ids: BTreeMap<usize, usize>,
185 }
186);
187
188#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
190#[serde(rename_all = "camelCase")]
191pub enum ContractKind {
192 Contract,
194 Interface,
196 Library,
198}
199
200ast_node!(
201 struct InheritanceSpecifier {
203 #[serde(default, deserialize_with = "serde_helpers::default_for_null")]
204 arguments: Vec<Expression>,
205 base_name: UserDefinedTypeNameOrIdentifierPath,
206 }
207);
208
209expr_node!(
210 struct Assignment {
212 #[serde(rename = "leftHandSide")]
213 lhs: Expression,
214 operator: AssignmentOperator,
215 #[serde(rename = "rightHandSide")]
216 rhs: Expression,
217 }
218);
219
220#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
222pub enum AssignmentOperator {
223 #[serde(rename = "=")]
225 Assign,
226 #[serde(rename = "+=")]
228 AddAssign,
229 #[serde(rename = "-=")]
231 SubAssign,
232 #[serde(rename = "*=")]
234 MulAssign,
235 #[serde(rename = "/=")]
237 DivAssign,
238 #[serde(rename = "%=")]
240 ModAssign,
241 #[serde(rename = "|=")]
243 OrAssign,
244 #[serde(rename = "&=")]
246 AndAssign,
247 #[serde(rename = "^=")]
249 XorAssign,
250 #[serde(rename = ">>=")]
252 ShrAssign,
253 #[serde(rename = "<<=")]
255 ShlAssign,
256}
257
258ast_node!(
259 struct BinaryOperation {
261 common_type: TypeDescriptions,
262 #[serde(rename = "leftExpression")]
263 lhs: Expression,
264 operator: BinaryOperator,
265 #[serde(rename = "rightExpression")]
266 rhs: Expression,
267 }
268);
269
270#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
272pub enum BinaryOperator {
273 #[serde(rename = "+")]
275 Add,
276 #[serde(rename = "-")]
278 Sub,
279 #[serde(rename = "*")]
281 Mul,
282 #[serde(rename = "/")]
284 Div,
285 #[serde(rename = "%")]
287 Mod,
288 #[serde(rename = "**")]
290 Pow,
291 #[serde(rename = "&&")]
293 And,
294 #[serde(rename = "||")]
296 Or,
297 #[serde(rename = "!=")]
299 NotEqual,
300 #[serde(rename = "==")]
302 Equal,
303 #[serde(rename = "<")]
305 LessThan,
306 #[serde(rename = "<=")]
308 LessThanOrEqual,
309 #[serde(rename = ">")]
311 GreaterThan,
312 #[serde(rename = ">=")]
314 GreaterThanOrEqual,
315 #[serde(rename = "^")]
317 Xor,
318 #[serde(rename = "~")]
320 BitNot,
321 #[serde(rename = "&")]
323 BitAnd,
324 #[serde(rename = "|")]
326 BitOr,
327 #[serde(rename = "<<")]
329 Shl,
330 #[serde(rename = ">>")]
332 Shr,
333}
334
335expr_node!(
336 struct Conditional {
338 condition: Expression,
340 false_expression: Expression,
342 true_expression: Expression,
344 }
345);
346
347expr_node!(
348 struct ElementaryTypeNameExpression {
349 type_name: ElementaryOrRawTypeName,
350 }
351);
352
353#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
355#[serde(untagged)]
356pub enum ElementaryOrRawTypeName {
357 ElementaryTypeName(ElementaryTypeName),
361 Raw(String),
365}
366
367ast_node!(
368 struct ElementaryTypeName {
369 type_descriptions: TypeDescriptions,
370 name: String,
371 state_mutability: Option<StateMutability>,
372 }
373);
374
375expr_node!(
376 struct FunctionCall {
378 arguments: Vec<Expression>,
379 expression: Expression,
380 kind: FunctionCallKind,
381 names: Vec<String>,
382 #[serde(default)]
383 try_call: bool,
384 }
385);
386
387#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
389#[serde(rename_all = "camelCase")]
390pub enum FunctionCallKind {
391 FunctionCall,
393 TypeConversion,
395 StructConstructorCall,
397}
398
399expr_node!(
400 struct FunctionCallOptions {
402 expression: Expression,
403 names: Vec<String>,
404 options: Vec<Expression>,
405 }
406);
407
408ast_node!(
409 struct Identifier {
411 #[serde(default, deserialize_with = "serde_helpers::default_for_null")]
412 argument_types: Vec<TypeDescriptions>,
413 name: String,
414 overloaded_declarations: Vec<isize>,
415 referenced_declaration: Option<isize>,
416 type_descriptions: TypeDescriptions,
417 }
418);
419
420expr_node!(
421 struct IndexAccess {
423 base_expression: Expression,
424 index_expression: Option<Expression>,
425 }
426);
427
428expr_node!(
429 struct IndexRangeAccess {
431 base_expression: Expression,
432 start_expression: Option<Expression>,
433 end_expression: Option<Expression>,
434 }
435);
436
437expr_node!(
438 struct Literal {
440 hex_value: String,
442 kind: LiteralKind,
443 subdenomination: Option<String>, value: Option<String>, }
446);
447
448#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
450#[serde(rename_all = "camelCase")]
451pub enum LiteralKind {
452 Bool,
454 Number,
456 String,
458 HexString,
460 UnicodeString,
462}
463
464expr_node!(
465 struct MemberAccess {
467 expression: Expression,
468 member_name: String,
469 referenced_declaration: Option<isize>,
470 }
471);
472
473expr_node!(
474 struct NewExpression {
476 type_name: TypeName,
477 }
478);
479
480ast_node!(
481 struct ArrayTypeName {
483 type_descriptions: TypeDescriptions,
484 base_type: TypeName,
485 length: Option<Expression>,
486 }
487);
488
489ast_node!(
490 struct FunctionTypeName {
492 type_descriptions: TypeDescriptions,
493 parameter_types: ParameterList,
494 return_parameter_types: ParameterList,
495 state_mutability: StateMutability,
496 visibility: Visibility,
497 }
498);
499
500ast_node!(
501 struct ParameterList {
503 parameters: Vec<VariableDeclaration>,
504 }
505);
506
507ast_node!(
508 struct VariableDeclaration {
510 name: String,
511 #[serde(default, with = "serde_helpers::display_from_str_opt")]
512 name_location: Option<SourceLocation>,
513 #[serde(default, deserialize_with = "serde_helpers::default_for_null")]
514 base_functions: Vec<usize>,
515 #[serde(default)]
520 constant: bool,
521 #[serde(default)]
526 state_variable: bool,
527 documentation: Option<StructuredDocumentation>,
528 function_selector: Option<String>, #[serde(default)]
530 indexed: bool,
531 #[serde(default)]
534 mutability: Option<Mutability>,
535 overrides: Option<OverrideSpecifier>,
536 scope: usize,
537 storage_location: StorageLocation,
538 type_descriptions: TypeDescriptions,
539 type_name: Option<TypeName>,
540 value: Option<Expression>,
541 visibility: Visibility,
542 }
543);
544
545impl VariableDeclaration {
546 pub fn mutability(&self) -> &Mutability {
550 if let Some(mutability) = &self.mutability {
551 mutability
552 } else if self.constant {
553 &Mutability::Constant
554 } else if self.state_variable {
555 &Mutability::Mutable
556 } else {
557 unreachable!()
558 }
559 }
560}
561
562#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
564#[serde(untagged)]
565pub enum StructuredDocumentation {
566 Parsed { text: String },
568 Text(String),
570}
571
572ast_node!(
573 struct OverrideSpecifier {
575 overrides: Vec<UserDefinedTypeNameOrIdentifierPath>,
576 }
577);
578
579ast_node!(
580 struct UserDefinedTypeName {
582 type_descriptions: TypeDescriptions,
583 contract_scope: Option<String>, name: Option<String>,
585 path_node: Option<IdentifierPath>,
586 referenced_declaration: isize,
587 }
588);
589
590ast_node!(
591 struct IdentifierPath {
593 name: String,
594 referenced_declaration: isize,
595 }
596);
597
598ast_node!(
599 struct Mapping {
601 type_descriptions: TypeDescriptions,
602 key_type: TypeName,
603 value_type: TypeName,
604 }
605);
606
607expr_node!(
608 struct TupleExpression {
610 components: Vec<Option<Expression>>,
611 is_inline_array: bool,
612 }
613);
614
615expr_node!(
616 struct UnaryOperation {
618 operator: UnaryOperator,
619 prefix: bool,
621 sub_expression: Expression,
622 }
623);
624
625#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
627pub enum UnaryOperator {
628 #[serde(rename = "++")]
630 Increment,
631 #[serde(rename = "--")]
633 Decrement,
634 #[serde(rename = "-")]
636 Negate,
637 #[serde(rename = "!")]
639 Not,
640 #[serde(rename = "~")]
642 BitNot,
643 #[serde(rename = "delete")]
645 Delete,
646}
647
648ast_node!(
649 struct EnumDefinition {
651 name: String,
652 #[serde(default, with = "serde_helpers::display_from_str_opt")]
653 name_location: Option<SourceLocation>,
654 canonical_name: String,
655 members: Vec<EnumValue>,
656 }
657);
658
659ast_node!(
660 struct EnumValue {
662 name: String,
663 #[serde(default, with = "serde_helpers::display_from_str_opt")]
664 name_location: Option<SourceLocation>,
665 }
666);
667
668ast_node!(
669 struct ErrorDefinition {
671 name: String,
672 #[serde(default, with = "serde_helpers::display_from_str_opt")]
673 name_location: Option<SourceLocation>,
674 documentation: Option<StructuredDocumentation>,
675 error_selector: Option<String>, parameters: ParameterList,
677 }
678);
679
680ast_node!(
681 struct EventDefinition {
683 name: String,
684 #[serde(default, with = "serde_helpers::display_from_str_opt")]
685 name_location: Option<SourceLocation>,
686 anonymous: bool,
687 event_selector: Option<String>, documentation: Option<StructuredDocumentation>,
689 parameters: ParameterList,
690 }
691);
692
693ast_node!(
694 struct FunctionDefinition {
696 name: String,
697 #[serde(default, with = "serde_helpers::display_from_str_opt")]
698 name_location: Option<SourceLocation>,
699 #[serde(default, deserialize_with = "serde_helpers::default_for_null")]
700 base_functions: Vec<usize>,
701 body: Option<Block>,
702 documentation: Option<StructuredDocumentation>,
703 function_selector: Option<String>, implemented: bool,
705 modifiers: Vec<ModifierInvocation>,
706 overrides: Option<OverrideSpecifier>,
707 parameters: ParameterList,
708 return_parameters: ParameterList,
709 scope: usize,
710 visibility: Visibility,
711 kind: Option<FunctionKind>,
716 #[serde(default)]
721 state_mutability: Option<StateMutability>,
722 #[serde(default, rename = "virtual")]
723 is_virtual: bool,
724 #[serde(default)]
730 is_constructor: bool,
731 #[serde(default)]
737 is_declared_const: bool,
738 #[serde(default)]
744 is_payable: bool,
745 }
746);
747
748impl FunctionDefinition {
749 pub fn kind(&self) -> &FunctionKind {
751 if let Some(kind) = &self.kind {
752 kind
753 } else if self.is_constructor {
754 &FunctionKind::Constructor
755 } else {
756 &FunctionKind::Function
757 }
758 }
759
760 pub fn state_mutability(&self) -> &StateMutability {
765 if let Some(state_mutability) = &self.state_mutability {
766 state_mutability
767 } else if self.is_declared_const {
768 &StateMutability::View
769 } else if self.is_payable {
770 &StateMutability::Payable
771 } else {
772 &StateMutability::Nonpayable
773 }
774 }
775}
776
777#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
779#[serde(rename_all = "camelCase")]
780pub enum FunctionKind {
781 Function,
783 Receive,
785 Constructor,
787 Fallback,
789 FreeFunction,
791}
792
793ast_node!(
794 struct Block {
796 documentation: Option<String>,
797 #[serde(default, deserialize_with = "serde_helpers::default_for_null")]
798 statements: Vec<Statement>,
799 }
800);
801
802stmt_node!(
803 struct Break {}
805);
806
807stmt_node!(
808 struct Continue {}
810);
811
812stmt_node!(
813 struct DoWhileStatement {
815 block: Block,
816 condition: Expression,
817 }
818);
819
820stmt_node!(
821 struct EmitStatement {
823 event_call: FunctionCall,
824 }
825);
826
827stmt_node!(
828 struct ExpressionStatement {
830 expression: Expression,
831 }
832);
833
834stmt_node!(
835 struct ForStatement {
837 body: BlockOrStatement,
838 condition: Option<Expression>,
839 initialization_expression: Option<ExpressionOrVariableDeclarationStatement>,
840 loop_expression: Option<ExpressionStatement>,
841 }
842);
843
844stmt_node!(
845 struct VariableDeclarationStatement {
847 assignments: Vec<Option<usize>>,
848 declarations: Vec<Option<VariableDeclaration>>,
849 initial_value: Option<Expression>,
850 }
851);
852
853stmt_node!(
854 struct IfStatement {
856 condition: Expression,
857 false_body: Option<BlockOrStatement>,
858 true_body: BlockOrStatement,
859 }
860);
861
862ast_node!(
863 struct InlineAssembly {
867 documentation: Option<String>,
868 #[serde(rename = "AST")]
869 ast: YulBlock,
870 external_references: Vec<ExternalInlineAssemblyReference>,
873 #[serde(default, deserialize_with = "serde_helpers::default_for_null")]
874 flags: Vec<InlineAssemblyFlag>,
875 }
876);
877
878#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
880#[serde(rename_all = "camelCase")]
881pub struct ExternalInlineAssemblyReference {
882 #[serde(with = "serde_helpers::display_from_str")]
883 pub src: SourceLocation,
884 pub declaration: usize,
885 #[serde(default)]
886 pub offset: bool,
887 #[serde(default)]
888 pub slot: bool,
889 #[serde(default)]
890 pub length: bool,
891 pub value_size: usize,
892 pub suffix: Option<AssemblyReferenceSuffix>,
893}
894
895#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
897#[serde(rename_all = "camelCase")]
898pub enum AssemblyReferenceSuffix {
899 Slot,
901 Offset,
903 Length,
905}
906
907#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
909pub enum InlineAssemblyFlag {
910 MemorySafe,
911}
912
913stmt_node!(
914 struct PlaceholderStatement {}
916);
917
918stmt_node!(
919 struct Return {
921 expression: Option<Expression>,
922 function_return_parameters: usize,
923 }
924);
925
926stmt_node!(
927 struct RevertStatement {
929 error_call: FunctionCall,
930 }
931);
932
933stmt_node!(
934 struct TryStatement {
936 clauses: Vec<TryCatchClause>,
937 external_call: FunctionCall,
938 }
939);
940
941ast_node!(
942 struct TryCatchClause {
944 block: Block,
945 error_name: String,
946 #[serde(default, deserialize_with = "serde_helpers::default_for_null")]
947 parameters: Vec<ParameterList>,
948 }
949);
950
951stmt_node!(
952 struct UncheckedBlock {
954 statements: Vec<Statement>,
955 }
956);
957
958stmt_node!(
959 struct WhileStatement {
961 body: BlockOrStatement,
962 condition: Expression,
963 }
964);
965
966ast_node!(
967 struct ModifierInvocation {
969 #[serde(default, deserialize_with = "serde_helpers::default_for_null")]
970 arguments: Vec<Expression>,
971 kind: Option<ModifierInvocationKind>,
972 modifier_name: IdentifierOrIdentifierPath,
973 }
974);
975
976#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
978#[serde(rename_all = "camelCase")]
979pub enum ModifierInvocationKind {
980 ModifierInvocation,
982 BaseConstructorSpecifier,
984}
985
986ast_node!(
987 struct ModifierDefinition {
989 name: String,
990 #[serde(default, with = "serde_helpers::display_from_str_opt")]
991 name_location: Option<SourceLocation>,
992 #[serde(default, deserialize_with = "serde_helpers::default_for_null")]
993 base_modifiers: Vec<usize>,
994 body: Block,
995 documentation: Option<StructuredDocumentation>,
996 overrides: Option<OverrideSpecifier>,
997 parameters: ParameterList,
998 #[serde(default, rename = "virtual")]
999 is_virtual: bool,
1000 visibility: Visibility,
1001 }
1002);
1003
1004ast_node!(
1005 struct StructDefinition {
1007 name: String,
1008 #[serde(default, with = "serde_helpers::display_from_str_opt")]
1009 name_location: Option<SourceLocation>,
1010 canonical_name: String,
1011 members: Vec<VariableDeclaration>,
1012 scope: usize,
1013 visibility: Visibility,
1014 }
1015);
1016
1017ast_node!(
1018 struct UserDefinedValueTypeDefinition {
1020 name: String,
1021 #[serde(default, with = "serde_helpers::display_from_str_opt")]
1022 name_location: Option<SourceLocation>,
1023 canonical_name: Option<String>,
1024 underlying_type: TypeName,
1025 }
1026);
1027
1028ast_node!(
1029 struct UsingForDirective {
1031 #[serde(default, deserialize_with = "serde_helpers::default_for_null")]
1032 function_list: Vec<FunctionIdentifierPath>,
1033 #[serde(default)]
1034 global: bool,
1035 library_name: Option<UserDefinedTypeNameOrIdentifierPath>,
1036 type_name: Option<TypeName>,
1037 }
1038);
1039
1040#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1042pub struct FunctionIdentifierPath {
1043 pub function: IdentifierPath,
1044}
1045
1046ast_node!(
1047 struct ImportDirective {
1049 absolute_path: String,
1050 file: String,
1051 #[serde(default, with = "serde_helpers::display_from_str_opt")]
1052 name_location: Option<SourceLocation>,
1053 scope: usize,
1054 source_unit: usize,
1055 symbol_aliases: Vec<SymbolAlias>,
1056 unit_alias: String,
1057 }
1058);
1059
1060#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1064pub struct SymbolAlias {
1065 pub foreign: Identifier,
1066 pub local: Option<String>,
1067 #[serde(default, with = "serde_helpers::display_from_str_opt")]
1068 pub name_location: Option<SourceLocation>,
1069}
1070
1071ast_node!(
1072 struct PragmaDirective {
1074 literals: Vec<String>,
1075 }
1076);
1077
1078#[cfg(test)]
1079mod tests {
1080 use super::*;
1081 use std::{fs, path::PathBuf};
1082
1083 #[test]
1084 fn can_parse_ast() {
1085 fs::read_dir(PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("test-data").join("ast"))
1086 .unwrap()
1087 .for_each(|path| {
1088 let path = path.unwrap().path();
1089 let path_str = path.to_string_lossy();
1090
1091 let input = fs::read_to_string(&path).unwrap();
1092 let deserializer = &mut serde_json::Deserializer::from_str(&input);
1093 let result: Result<SourceUnit, _> = serde_path_to_error::deserialize(deserializer);
1094 match result {
1095 Err(e) => {
1096 println!("... {path_str} fail: {e}");
1097 panic!();
1098 }
1099 Ok(_) => {
1100 println!("... {path_str} ok");
1101 }
1102 }
1103 })
1104 }
1105}