ast.rs 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036
  1. // SPDX-License-Identifier: Apache-2.0
  2. use super::symtable::Symtable;
  3. use crate::abi::anchor::function_discriminator;
  4. use crate::codegen::cfg::{ControlFlowGraph, Instr};
  5. use crate::diagnostics::Diagnostics;
  6. use crate::sema::ast::ExternalCallAccounts::{AbsentArgument, NoAccount};
  7. use crate::sema::yul::ast::{InlineAssembly, YulFunction};
  8. use crate::sema::Recurse;
  9. use crate::{codegen, Target};
  10. use indexmap::IndexMap;
  11. use num_bigint::BigInt;
  12. use num_rational::BigRational;
  13. use once_cell::unsync::OnceCell;
  14. pub use solang_parser::diagnostics::*;
  15. use solang_parser::pt;
  16. use solang_parser::pt::{CodeLocation, FunctionTy, OptionalCodeLocation};
  17. use std::cell::RefCell;
  18. use std::fmt::Write;
  19. use std::{
  20. collections::HashSet,
  21. collections::{BTreeMap, HashMap},
  22. fmt, hash,
  23. path::PathBuf,
  24. sync::Arc,
  25. };
  26. use tiny_keccak::{Hasher, Keccak};
  27. #[derive(PartialEq, Eq, Clone, Hash, Debug)]
  28. pub enum Type {
  29. Address(bool),
  30. Bool,
  31. Int(u16),
  32. Uint(u16),
  33. Rational,
  34. Bytes(u8),
  35. DynamicBytes,
  36. String,
  37. Array(Box<Type>, Vec<ArrayLength>),
  38. /// The usize is an index into enums in the namespace
  39. Enum(usize),
  40. /// The usize is an index into contracts in the namespace
  41. Struct(StructType),
  42. Mapping(Mapping),
  43. /// The usize is an index into contracts in the namespace
  44. Contract(usize),
  45. Ref(Box<Type>),
  46. /// Reference to storage, first bool is true for immutables
  47. StorageRef(bool, Box<Type>),
  48. InternalFunction {
  49. mutability: Mutability,
  50. params: Vec<Type>,
  51. returns: Vec<Type>,
  52. },
  53. ExternalFunction {
  54. mutability: Mutability,
  55. params: Vec<Type>,
  56. returns: Vec<Type>,
  57. },
  58. /// User type definitions, e.g. `type Foo is int128;`. The usize
  59. /// is an index into user_types in the namespace.
  60. UserType(usize),
  61. /// There is no way to declare value in Solidity (should there be?)
  62. Value,
  63. Void,
  64. Unreachable,
  65. /// DynamicBytes and String are lowered to a vector.
  66. Slice(Box<Type>),
  67. /// We could not resolve this type
  68. Unresolved,
  69. /// When we advance a pointer, it cannot be any of the previous types.
  70. /// e.g. Type::Bytes is a pointer to struct.vector. When we advance it, it is a pointer
  71. /// to latter's data region.
  72. BufferPointer,
  73. /// The function selector (or discriminator) type is 4 bytes on Polkadot and 8 bytes on Solana
  74. FunctionSelector,
  75. }
  76. #[derive(Eq, Clone, Debug)]
  77. pub struct Mapping {
  78. pub key: Box<Type>,
  79. pub key_name: Option<pt::Identifier>,
  80. pub value: Box<Type>,
  81. pub value_name: Option<pt::Identifier>,
  82. }
  83. // Ensure the key_name and value_name is not used for comparison or hashing
  84. impl PartialEq for Mapping {
  85. fn eq(&self, other: &Mapping) -> bool {
  86. self.key == other.key && self.value == other.value
  87. }
  88. }
  89. impl hash::Hash for Mapping {
  90. fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
  91. self.key.hash(hasher);
  92. self.value.hash(hasher);
  93. }
  94. }
  95. #[derive(PartialEq, Eq, Clone, Hash, Debug)]
  96. pub enum ArrayLength {
  97. Fixed(BigInt),
  98. Dynamic,
  99. /// Fixed length arrays, any length permitted. This is useful for when we
  100. /// do not want dynamic length, but want to permit any length. For example
  101. /// the create_program_address() call takes any number of seeds as its
  102. /// first argument, and we don't want to allocate a dynamic array for
  103. /// this parameter as this would be wasteful to allocate a vector for
  104. /// this argument.
  105. AnyFixed,
  106. }
  107. impl ArrayLength {
  108. /// Get the length, if fixed
  109. pub fn array_length(&self) -> Option<&BigInt> {
  110. match self {
  111. ArrayLength::Fixed(len) => Some(len),
  112. _ => None,
  113. }
  114. }
  115. }
  116. pub trait RetrieveType {
  117. /// Return the type for this expression. This assumes the expression has a single value,
  118. /// panics will occur otherwise
  119. fn ty(&self) -> Type;
  120. }
  121. impl Type {
  122. pub fn get_type_size(&self) -> u16 {
  123. match self {
  124. Type::Int(n) | Type::Uint(n) => *n,
  125. Type::Bool => 1,
  126. _ => unimplemented!("size of type not known"),
  127. }
  128. }
  129. pub fn unwrap_user_type(self, ns: &Namespace) -> Type {
  130. if let Type::UserType(type_no) = self {
  131. ns.user_types[type_no].ty.clone()
  132. } else {
  133. self
  134. }
  135. }
  136. /// Round integer width to Soroban-compatible size and emit warning if needed
  137. pub fn round_soroban_width(&self, ns: &mut Namespace, loc: pt::Loc) -> Type {
  138. match self {
  139. Type::Int(width) => {
  140. let rounded_width = Self::get_soroban_int_width(*width);
  141. if rounded_width != *width {
  142. let message = format!(
  143. "int{width} is not supported by the Soroban runtime and will be rounded up to int{rounded_width}"
  144. );
  145. if ns.strict_soroban_types {
  146. ns.diagnostics.push(Diagnostic::error(loc, message));
  147. } else {
  148. ns.diagnostics.push(Diagnostic::warning(loc, message));
  149. }
  150. Type::Int(rounded_width)
  151. } else {
  152. Type::Int(*width)
  153. }
  154. }
  155. Type::Uint(width) => {
  156. let rounded_width = Self::get_soroban_int_width(*width);
  157. if rounded_width != *width {
  158. let message = format!(
  159. "uint{width} is not supported by the Soroban runtime and will be rounded up to uint{rounded_width}"
  160. );
  161. if ns.strict_soroban_types {
  162. ns.diagnostics.push(Diagnostic::error(loc, message));
  163. } else {
  164. ns.diagnostics.push(Diagnostic::warning(loc, message));
  165. }
  166. Type::Uint(rounded_width)
  167. } else {
  168. Type::Uint(*width)
  169. }
  170. }
  171. _ => self.clone(),
  172. }
  173. }
  174. /// Get the Soroban-compatible integer width by rounding up to the next supported size
  175. pub fn get_soroban_int_width(width: u16) -> u16 {
  176. match width {
  177. 1..=32 => 32,
  178. 33..=64 => 64,
  179. 65..=128 => 128,
  180. 129..=256 => 256,
  181. _ => width, // Keep as-is if already 256+ or invalid
  182. }
  183. }
  184. /// Check if an integer width is Soroban-compatible
  185. pub fn is_soroban_compatible_width(width: u16) -> bool {
  186. matches!(width, 32 | 64 | 128 | 256)
  187. }
  188. }
  189. #[derive(PartialEq, Eq, Clone, Debug, Copy, Hash)]
  190. pub enum StructType {
  191. UserDefined(usize),
  192. AccountInfo,
  193. AccountMeta,
  194. ExternalFunction,
  195. SolParameters,
  196. }
  197. #[derive(PartialEq, Eq, Clone, Debug)]
  198. pub struct StructDecl {
  199. pub tags: Vec<Tag>,
  200. pub id: pt::Identifier,
  201. pub loc: pt::Loc,
  202. pub contract: Option<String>,
  203. pub fields: Vec<Parameter<Type>>,
  204. // List of offsets of the fields, last entry is the offset for the struct overall size
  205. pub offsets: Vec<BigInt>,
  206. // Same, but now in storage
  207. pub storage_offsets: Vec<BigInt>,
  208. }
  209. #[derive(PartialEq, Eq, Clone, Debug)]
  210. pub struct EventDecl {
  211. pub tags: Vec<Tag>,
  212. pub id: pt::Identifier,
  213. pub loc: pt::Loc,
  214. pub contract: Option<usize>,
  215. pub fields: Vec<Parameter<Type>>,
  216. pub signature: String,
  217. pub anonymous: bool,
  218. pub used: bool,
  219. }
  220. impl EventDecl {
  221. pub fn symbol_name(&self, ns: &Namespace) -> String {
  222. match &self.contract {
  223. Some(c) => format!("{}.{}", ns.contracts[*c].id, self.id),
  224. None => self.id.to_string(),
  225. }
  226. }
  227. }
  228. #[derive(Default, PartialEq, Eq, Clone, Debug)]
  229. pub struct ErrorDecl {
  230. pub tags: Vec<Tag>,
  231. pub name: String,
  232. pub loc: pt::Loc,
  233. pub contract: Option<usize>,
  234. pub fields: Vec<Parameter<Type>>,
  235. pub used: bool,
  236. }
  237. impl ErrorDecl {
  238. pub fn symbol_name(&self, ns: &Namespace) -> String {
  239. match &self.contract {
  240. Some(c) => format!("{}.{}", ns.contracts[*c].id, self.name),
  241. None => self.name.to_string(),
  242. }
  243. }
  244. }
  245. impl fmt::Display for StructDecl {
  246. /// Make the struct name into a string for printing. The struct can be declared either
  247. /// inside or outside a contract.
  248. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  249. match &self.contract {
  250. Some(c) => write!(f, "{}.{}", c, self.id),
  251. None => write!(f, "{}", self.id),
  252. }
  253. }
  254. }
  255. #[derive(Debug)]
  256. pub struct EnumDecl {
  257. pub tags: Vec<Tag>,
  258. pub id: pt::Identifier,
  259. pub contract: Option<String>,
  260. pub loc: pt::Loc,
  261. pub ty: Type,
  262. pub values: IndexMap<String, pt::Loc>,
  263. }
  264. impl fmt::Display for EnumDecl {
  265. /// Make the enum name into a string for printing. The enum can be declared either
  266. /// inside or outside a contract.
  267. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  268. match &self.contract {
  269. Some(c) => write!(f, "{}.{}", c, self.id),
  270. None => write!(f, "{}", self.id),
  271. }
  272. }
  273. }
  274. #[derive(PartialEq, Eq, Clone, Debug)]
  275. pub struct Parameter<Type> {
  276. pub loc: pt::Loc,
  277. /// The name can empty (e.g. in an event field or unnamed parameter/return)
  278. pub id: Option<pt::Identifier>,
  279. pub ty: Type,
  280. /// Yul function parameters may not have a type identifier
  281. pub ty_loc: Option<pt::Loc>,
  282. /// Event fields may indexed, which means they are sent to the log
  283. pub indexed: bool,
  284. /// Some builtin structs have readonly fields
  285. pub readonly: bool,
  286. /// A recursive struct may contain itself which make the struct infinite size in memory.
  287. pub infinite_size: bool,
  288. /// Is this struct field recursive. Recursive does not mean infinite size in all cases:
  289. /// `struct S { S[] s }` is recursive but not of infinite size.
  290. pub recursive: bool,
  291. pub annotation: Option<ParameterAnnotation>,
  292. }
  293. #[derive(Debug, Eq, Clone, PartialEq)]
  294. pub struct ParameterAnnotation {
  295. pub loc: pt::Loc,
  296. pub id: pt::Identifier,
  297. }
  298. impl Parameter<Type> {
  299. /// Create a new instance of the given `Type`, with all other values set to their default.
  300. pub fn new_default(ty: Type) -> Self {
  301. Self {
  302. ty,
  303. loc: Default::default(),
  304. id: Default::default(),
  305. ty_loc: Default::default(),
  306. indexed: Default::default(),
  307. readonly: Default::default(),
  308. infinite_size: Default::default(),
  309. recursive: Default::default(),
  310. annotation: Default::default(),
  311. }
  312. }
  313. pub fn name_as_str(&self) -> &str {
  314. if let Some(name) = &self.id {
  315. name.name.as_str()
  316. } else {
  317. ""
  318. }
  319. }
  320. }
  321. #[derive(PartialEq, Eq, Clone, Hash, Debug)]
  322. pub enum Mutability {
  323. Payable(pt::Loc),
  324. Nonpayable(pt::Loc),
  325. View(pt::Loc),
  326. Pure(pt::Loc),
  327. }
  328. impl Mutability {
  329. pub fn is_default(&self) -> bool {
  330. matches!(self, Mutability::Nonpayable(_))
  331. }
  332. }
  333. impl fmt::Display for Mutability {
  334. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  335. match self {
  336. Mutability::Pure(_) => write!(f, "pure"),
  337. Mutability::View(_) => write!(f, "view"),
  338. Mutability::Nonpayable(_) => write!(f, "nonpayable"),
  339. Mutability::Payable(_) => write!(f, "payable"),
  340. }
  341. }
  342. }
  343. #[derive(Debug)]
  344. pub struct Function {
  345. pub tags: Vec<Tag>,
  346. /// The location of the prototype (not body)
  347. pub loc_prototype: pt::Loc,
  348. pub loc: pt::Loc,
  349. pub id: pt::Identifier,
  350. pub contract_no: Option<usize>,
  351. pub ty: pt::FunctionTy,
  352. pub signature: String,
  353. pub mutability: Mutability,
  354. pub visibility: pt::Visibility,
  355. pub params: Arc<Vec<Parameter<Type>>>,
  356. pub returns: Arc<Vec<Parameter<Type>>>,
  357. /// Constructor arguments for base contracts, only present on constructors
  358. pub bases: BTreeMap<usize, (pt::Loc, usize, Vec<Expression>)>,
  359. /// Modifiers for functions
  360. pub modifiers: Vec<Expression>,
  361. pub is_virtual: bool,
  362. /// Is this function an acccesor function created by a public variable
  363. pub is_accessor: bool,
  364. pub is_override: Option<(pt::Loc, Vec<usize>)>,
  365. /// The selector (known as discriminator on Solana/Anchor)
  366. pub selector: Option<(pt::Loc, Vec<u8>)>,
  367. /// Was the function declared with a body
  368. pub has_body: bool,
  369. /// The resolved body (if any)
  370. pub body: Vec<Statement>,
  371. pub symtable: Symtable,
  372. /// What events are emitted by the body of this function
  373. pub emits_events: Vec<usize>,
  374. /// For overloaded functions this is the mangled (unique) name.
  375. pub mangled_name: String,
  376. /// Solana constructors may have seeds specified using @seed tags
  377. pub annotations: ConstructorAnnotations,
  378. /// Which contracts should we use the mangled name in?
  379. pub mangled_name_contracts: HashSet<usize>,
  380. /// This indexmap stores the accounts this functions needs to be called on Solana
  381. /// The string is the account's name
  382. pub solana_accounts: RefCell<IndexMap<String, SolanaAccount>>,
  383. /// List of contracts this function creates
  384. pub creates: Vec<(pt::Loc, usize)>,
  385. }
  386. /// This struct represents a Solana account. There is no name field, because
  387. /// it is stored in a IndexMap<String, SolanaAccount> (see above)
  388. #[derive(Clone, Copy, Debug, PartialEq, Eq)]
  389. pub struct SolanaAccount {
  390. pub loc: pt::Loc,
  391. pub is_signer: bool,
  392. pub is_writer: bool,
  393. /// Has the compiler automatically generated this account entry?
  394. pub generated: bool,
  395. }
  396. #[derive(Debug, Default)]
  397. pub struct ConstructorAnnotations {
  398. // (annotation location, annotation expression)
  399. pub seeds: Vec<(pt::Loc, Expression)>,
  400. pub space: Option<(pt::Loc, Expression)>,
  401. pub bump: Option<(pt::Loc, Expression)>,
  402. // (annotation location, account name)
  403. pub payer: Option<(pt::Loc, String)>,
  404. }
  405. /// This trait provides a single interface for fetching parameters, returns and the symbol table
  406. /// for both yul and solidity functions
  407. pub trait FunctionAttributes {
  408. fn get_symbol_table(&self) -> &Symtable;
  409. fn get_parameters(&self) -> &Vec<Parameter<Type>>;
  410. fn get_returns(&self) -> &Vec<Parameter<Type>>;
  411. }
  412. impl FunctionAttributes for Function {
  413. fn get_symbol_table(&self) -> &Symtable {
  414. &self.symtable
  415. }
  416. fn get_parameters(&self) -> &Vec<Parameter<Type>> {
  417. &self.params
  418. }
  419. fn get_returns(&self) -> &Vec<Parameter<Type>> {
  420. &self.returns
  421. }
  422. }
  423. impl Function {
  424. pub fn new(
  425. loc_prototype: pt::Loc,
  426. loc: pt::Loc,
  427. id: pt::Identifier,
  428. contract_no: Option<usize>,
  429. tags: Vec<Tag>,
  430. ty: pt::FunctionTy,
  431. mutability: Option<pt::Mutability>,
  432. visibility: pt::Visibility,
  433. params: Vec<Parameter<Type>>,
  434. returns: Vec<Parameter<Type>>,
  435. ns: &Namespace,
  436. ) -> Self {
  437. let signature = match ty {
  438. pt::FunctionTy::Fallback => String::from("@fallback"),
  439. pt::FunctionTy::Receive => String::from("@receive"),
  440. _ => ns.signature(&id.name, &params),
  441. };
  442. let mutability = match mutability {
  443. None => Mutability::Nonpayable(loc_prototype),
  444. Some(pt::Mutability::Payable(loc)) => Mutability::Payable(loc),
  445. Some(pt::Mutability::Pure(loc)) => Mutability::Pure(loc),
  446. Some(pt::Mutability::View(loc)) => Mutability::View(loc),
  447. Some(pt::Mutability::Constant(loc)) => Mutability::View(loc),
  448. };
  449. let mangled_name = signature
  450. .replace('(', "_")
  451. .replace(')', "")
  452. .replace(',', "_")
  453. .replace("[]", "Array")
  454. .replace('[', "Array")
  455. .replace(']', "");
  456. Function {
  457. tags,
  458. loc_prototype,
  459. loc,
  460. id,
  461. contract_no,
  462. ty,
  463. signature,
  464. mutability,
  465. visibility,
  466. params: Arc::new(params),
  467. returns: Arc::new(returns),
  468. bases: BTreeMap::new(),
  469. modifiers: Vec::new(),
  470. selector: None,
  471. is_virtual: false,
  472. is_accessor: false,
  473. has_body: false,
  474. is_override: None,
  475. body: Vec::new(),
  476. symtable: Symtable::default(),
  477. emits_events: Vec::new(),
  478. mangled_name,
  479. annotations: ConstructorAnnotations::default(),
  480. mangled_name_contracts: HashSet::new(),
  481. solana_accounts: IndexMap::new().into(),
  482. creates: Vec::new(),
  483. }
  484. }
  485. /// Generate selector for this function
  486. pub fn selector(&self, ns: &Namespace, contract_no: &usize) -> Vec<u8> {
  487. if let Some((_, selector)) = &self.selector {
  488. selector.clone()
  489. } else if ns.target == Target::Solana {
  490. match self.ty {
  491. FunctionTy::Constructor => function_discriminator("new"),
  492. _ => {
  493. let discriminator_image = if self.mangled_name_contracts.contains(contract_no) {
  494. &self.mangled_name
  495. } else {
  496. &self.id.name
  497. };
  498. function_discriminator(discriminator_image.as_str())
  499. }
  500. }
  501. } else {
  502. let mut res = [0u8; 32];
  503. let mut hasher = Keccak::v256();
  504. hasher.update(self.signature.as_bytes());
  505. hasher.finalize(&mut res);
  506. res[..4].to_vec()
  507. }
  508. }
  509. /// Is this a constructor
  510. pub fn is_constructor(&self) -> bool {
  511. self.ty == pt::FunctionTy::Constructor
  512. }
  513. /// Does this function have the payable state
  514. pub fn is_payable(&self) -> bool {
  515. matches!(self.mutability, Mutability::Payable(_))
  516. }
  517. /// Does this function have an @payer annotation?
  518. pub fn has_payer_annotation(&self) -> bool {
  519. self.annotations.payer.is_some()
  520. }
  521. /// Does this function have an @seed annotation?
  522. pub fn has_seed_annotation(&self) -> bool {
  523. !self.annotations.seeds.is_empty()
  524. }
  525. /// Does this function have the pure state
  526. pub fn is_pure(&self) -> bool {
  527. matches!(self.mutability, Mutability::Pure(_))
  528. }
  529. /// Is this function visible externally, based on it's visibilty modifiers.
  530. ///
  531. /// Due to inheritance, this alone does not determine whether a function is
  532. /// externally callable in the final contract artifact; for that, use
  533. /// `Namespace::function_externally_callable()` instead.
  534. pub fn is_public(&self) -> bool {
  535. matches!(
  536. self.visibility,
  537. pt::Visibility::Public(_) | pt::Visibility::External(_)
  538. )
  539. }
  540. /// Is this function accessable only from same contract
  541. pub fn is_private(&self) -> bool {
  542. matches!(self.visibility, pt::Visibility::Private(_))
  543. }
  544. }
  545. impl From<&pt::Type> for Type {
  546. fn from(p: &pt::Type) -> Type {
  547. match p {
  548. pt::Type::Bool => Type::Bool,
  549. pt::Type::Address => Type::Address(false),
  550. pt::Type::AddressPayable => Type::Address(true),
  551. pt::Type::Payable => Type::Address(true),
  552. pt::Type::Int(n) => Type::Int(*n),
  553. pt::Type::Uint(n) => Type::Uint(*n),
  554. pt::Type::Bytes(n) => Type::Bytes(*n),
  555. pt::Type::String => Type::String,
  556. pt::Type::Rational => Type::Rational,
  557. pt::Type::DynamicBytes => Type::DynamicBytes,
  558. // needs special casing
  559. pt::Type::Function { .. } | pt::Type::Mapping { .. } => unimplemented!(),
  560. }
  561. }
  562. }
  563. #[derive(PartialEq, Eq, Clone, Debug)]
  564. pub struct UserTypeDecl {
  565. pub tags: Vec<Tag>,
  566. pub loc: pt::Loc,
  567. pub name: String,
  568. pub ty: Type,
  569. pub contract: Option<String>,
  570. }
  571. impl fmt::Display for UserTypeDecl {
  572. /// Make the user type name into a string for printing. The user type can
  573. /// be declared either inside or outside a contract.
  574. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  575. match &self.contract {
  576. Some(c) => write!(f, "{}.{}", c, self.name),
  577. None => write!(f, "{}", self.name),
  578. }
  579. }
  580. }
  581. #[derive(Debug)]
  582. pub struct Variable {
  583. pub tags: Vec<Tag>,
  584. pub name: String,
  585. pub loc: pt::Loc,
  586. pub ty: Type,
  587. pub visibility: pt::Visibility,
  588. pub constant: bool,
  589. pub immutable: bool,
  590. pub initializer: Option<Expression>,
  591. pub assigned: bool,
  592. pub read: bool,
  593. pub storage_type: Option<pt::StorageType>,
  594. }
  595. #[derive(Debug, Clone, PartialEq, Eq)]
  596. pub enum Symbol {
  597. Enum(pt::Loc, usize),
  598. Function(Vec<(pt::Loc, usize)>),
  599. Variable(pt::Loc, Option<usize>, usize),
  600. Struct(pt::Loc, StructType),
  601. Event(Vec<(pt::Loc, usize)>),
  602. Error(pt::Loc, usize),
  603. Contract(pt::Loc, usize),
  604. Import(pt::Loc, usize),
  605. UserType(pt::Loc, usize),
  606. }
  607. impl CodeLocation for Symbol {
  608. fn loc(&self) -> pt::Loc {
  609. match self {
  610. Symbol::Enum(loc, _)
  611. | Symbol::Variable(loc, ..)
  612. | Symbol::Struct(loc, _)
  613. | Symbol::Contract(loc, _)
  614. | Symbol::Import(loc, _)
  615. | Symbol::Error(loc, _)
  616. | Symbol::UserType(loc, _) => *loc,
  617. Symbol::Event(items) | Symbol::Function(items) => items[0].0,
  618. }
  619. }
  620. }
  621. impl Symbol {
  622. /// Is this symbol for an event
  623. pub fn is_event(&self) -> bool {
  624. matches!(self, Symbol::Event(_))
  625. }
  626. /// Does this symbol have an accessor function
  627. pub fn has_accessor(&self, ns: &Namespace) -> bool {
  628. if let Symbol::Variable(_, Some(contract_no), var_no) = self {
  629. matches!(
  630. ns.contracts[*contract_no].variables[*var_no].visibility,
  631. pt::Visibility::Public(_)
  632. )
  633. } else {
  634. false
  635. }
  636. }
  637. /// Is this a private symbol
  638. pub fn is_private_variable(&self, ns: &Namespace) -> bool {
  639. match self {
  640. Symbol::Variable(_, Some(contract_no), var_no) => {
  641. let visibility = &ns.contracts[*contract_no].variables[*var_no].visibility;
  642. matches!(visibility, pt::Visibility::Private(_))
  643. }
  644. _ => false,
  645. }
  646. }
  647. }
  648. /// Any Solidity file, either the main file or anything that was imported
  649. #[derive(Clone, Debug)]
  650. pub struct File {
  651. /// The on-disk filename
  652. pub path: PathBuf,
  653. /// Used for offset to line-column conversions
  654. pub line_starts: Vec<usize>,
  655. /// Indicates the file number in FileResolver.files
  656. pub cache_no: Option<usize>,
  657. /// Index into FileResolver.import_paths. This is `None` when this File was
  658. /// created not during `parse_and_resolve` (e.g., builtins)
  659. pub import_no: Option<usize>,
  660. }
  661. /// When resolving a Solidity file, this holds all the resolved items
  662. #[derive(Debug)]
  663. pub struct Namespace {
  664. pub target: Target,
  665. pub pragmas: Vec<Pragma>,
  666. pub files: Vec<File>,
  667. pub enums: Vec<EnumDecl>,
  668. pub structs: Vec<StructDecl>,
  669. pub events: Vec<EventDecl>,
  670. pub errors: Vec<ErrorDecl>,
  671. pub contracts: Vec<Contract>,
  672. /// Global using declarations
  673. pub using: Vec<Using>,
  674. /// All type declarations
  675. pub user_types: Vec<UserTypeDecl>,
  676. /// All functions
  677. pub functions: Vec<Function>,
  678. /// Yul functions
  679. pub yul_functions: Vec<YulFunction>,
  680. /// Global constants
  681. pub constants: Vec<Variable>,
  682. /// address length in bytes
  683. pub address_length: usize,
  684. /// value length in bytes
  685. pub value_length: usize,
  686. pub diagnostics: Diagnostics,
  687. /// There is a separate namespace for functions and non-functions
  688. pub function_symbols: HashMap<(usize, Option<usize>, String), Symbol>,
  689. /// Symbol key is file_no, contract, identifier
  690. pub variable_symbols: HashMap<(usize, Option<usize>, String), Symbol>,
  691. // each variable in the symbol table should have a unique number
  692. pub next_id: usize,
  693. /// For a variable reference at a location, give the constant value
  694. /// This for use by the language server to show the value of a variable at a location
  695. pub var_constants: HashMap<pt::Loc, codegen::Expression>,
  696. /// Overrides for hover in the language server
  697. pub hover_overrides: HashMap<pt::Loc, String>,
  698. /// Strict mode for Soroban integer width checking
  699. pub strict_soroban_types: bool,
  700. }
  701. #[derive(Debug)]
  702. pub enum Pragma {
  703. Identifier {
  704. loc: pt::Loc,
  705. name: pt::Identifier,
  706. value: pt::Identifier,
  707. },
  708. StringLiteral {
  709. loc: pt::Loc,
  710. name: pt::Identifier,
  711. value: pt::StringLiteral,
  712. },
  713. SolidityVersion {
  714. loc: pt::Loc,
  715. versions: Vec<VersionReq>,
  716. },
  717. }
  718. #[derive(Debug)]
  719. pub enum VersionReq {
  720. Plain {
  721. loc: pt::Loc,
  722. version: Version,
  723. },
  724. Operator {
  725. loc: pt::Loc,
  726. op: pt::VersionOp,
  727. version: Version,
  728. },
  729. Range {
  730. loc: pt::Loc,
  731. from: Version,
  732. to: Version,
  733. },
  734. Or {
  735. loc: pt::Loc,
  736. left: Box<VersionReq>,
  737. right: Box<VersionReq>,
  738. },
  739. }
  740. #[derive(Debug, Clone, PartialEq)]
  741. pub struct Version {
  742. pub major: u32,
  743. pub minor: Option<u32>,
  744. pub patch: Option<u32>,
  745. }
  746. impl fmt::Display for Version {
  747. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  748. self.major.fmt(f)?;
  749. if let Some(minor) = self.minor {
  750. f.write_char('.')?;
  751. minor.fmt(f)?
  752. }
  753. if let Some(patch) = self.patch {
  754. f.write_char('.')?;
  755. patch.fmt(f)?;
  756. }
  757. Ok(())
  758. }
  759. }
  760. #[derive(Debug)]
  761. pub struct Layout {
  762. pub slot: BigInt,
  763. pub contract_no: usize,
  764. pub var_no: usize,
  765. pub ty: Type,
  766. }
  767. #[derive(Debug)]
  768. pub struct Base {
  769. pub loc: pt::Loc,
  770. pub contract_no: usize,
  771. pub constructor: Option<(usize, Vec<Expression>)>,
  772. }
  773. #[derive(Debug)]
  774. pub struct Using {
  775. pub list: UsingList,
  776. pub ty: Option<Type>,
  777. pub file_no: Option<usize>,
  778. }
  779. #[derive(Debug)]
  780. pub enum UsingList {
  781. Library(usize),
  782. Functions(Vec<UsingFunction>),
  783. }
  784. /// Using binding for a function, optionally for an operator
  785. #[derive(Debug)]
  786. pub struct UsingFunction {
  787. pub loc: pt::Loc,
  788. pub function_no: usize,
  789. pub oper: Option<pt::UserDefinedOperator>,
  790. }
  791. #[derive(Debug)]
  792. pub struct Contract {
  793. pub tags: Vec<Tag>,
  794. pub loc: pt::Loc,
  795. pub ty: pt::ContractTy,
  796. pub id: pt::Identifier,
  797. pub bases: Vec<Base>,
  798. pub using: Vec<Using>,
  799. pub layout: Vec<Layout>,
  800. pub fixed_layout_size: BigInt,
  801. pub functions: Vec<usize>,
  802. pub all_functions: BTreeMap<usize, usize>,
  803. /// maps the name of virtual functions to a vector of overriden functions.
  804. /// Each time a virtual function is overriden, there will be an entry pushed to the vector. The last
  805. /// element represents the current overriding function - there will be at least one entry in this vector.
  806. pub virtual_functions: HashMap<String, Vec<usize>>,
  807. pub yul_functions: Vec<usize>,
  808. pub variables: Vec<Variable>,
  809. /// List of contracts this contract instantiates
  810. pub creates: Vec<usize>,
  811. /// List of events this contract may emit
  812. pub emits_events: Vec<usize>,
  813. pub initializer: Option<usize>,
  814. pub default_constructor: Option<(Function, usize)>,
  815. pub cfg: Vec<ControlFlowGraph>,
  816. /// Compiled program. Only available after emit.
  817. pub code: OnceCell<Vec<u8>>,
  818. /// Can the contract be instantiated, i.e. not abstract, no errors, etc.
  819. pub instantiable: bool,
  820. /// Account of deployed program code on Solana
  821. pub program_id: Option<Vec<u8>>,
  822. }
  823. impl Contract {
  824. // Is this a concrete contract, which can be instantiated
  825. pub fn is_concrete(&self) -> bool {
  826. matches!(self.ty, pt::ContractTy::Contract(_))
  827. }
  828. // Is this an interface
  829. pub fn is_interface(&self) -> bool {
  830. matches!(self.ty, pt::ContractTy::Interface(_))
  831. }
  832. // Is this an library
  833. pub fn is_library(&self) -> bool {
  834. matches!(self.ty, pt::ContractTy::Library(_))
  835. }
  836. /// Does the constructor require arguments. Should be false is there is no constructor
  837. pub fn constructor_needs_arguments(&self, ns: &Namespace) -> bool {
  838. !self.constructors(ns).is_empty() && self.no_args_constructor(ns).is_none()
  839. }
  840. /// Does the contract have a constructor defined?
  841. /// Returns all the constructor function numbers if any
  842. pub fn constructors(&self, ns: &Namespace) -> Vec<usize> {
  843. self.functions
  844. .iter()
  845. .copied()
  846. .filter(|func_no| ns.functions[*func_no].is_constructor())
  847. .collect::<Vec<usize>>()
  848. }
  849. /// Return the constructor with no arguments
  850. pub fn no_args_constructor(&self, ns: &Namespace) -> Option<usize> {
  851. self.functions
  852. .iter()
  853. .find(|func_no| {
  854. let func = &ns.functions[**func_no];
  855. func.is_constructor() && func.params.is_empty()
  856. })
  857. .cloned()
  858. }
  859. }
  860. #[derive(PartialEq, Eq, Clone, Debug)]
  861. pub enum Expression {
  862. BoolLiteral {
  863. loc: pt::Loc,
  864. value: bool,
  865. },
  866. BytesLiteral {
  867. loc: pt::Loc,
  868. ty: Type,
  869. value: Vec<u8>,
  870. },
  871. NumberLiteral {
  872. loc: pt::Loc,
  873. ty: Type,
  874. value: BigInt,
  875. },
  876. RationalNumberLiteral {
  877. loc: pt::Loc,
  878. ty: Type,
  879. value: BigRational,
  880. },
  881. StructLiteral {
  882. loc: pt::Loc,
  883. id: pt::IdentifierPath,
  884. ty: Type,
  885. /// pt::Identifier represents the field name
  886. values: Vec<(Option<pt::Identifier>, Expression)>,
  887. },
  888. ArrayLiteral {
  889. loc: pt::Loc,
  890. ty: Type,
  891. dimensions: Vec<u32>,
  892. values: Vec<Expression>,
  893. },
  894. ConstArrayLiteral {
  895. loc: pt::Loc,
  896. ty: Type,
  897. dimensions: Vec<u32>,
  898. values: Vec<Expression>,
  899. },
  900. Add {
  901. loc: pt::Loc,
  902. ty: Type,
  903. /// Do not check for overflow, i.e. in `unchecked {}` block
  904. unchecked: bool,
  905. left: Box<Expression>,
  906. right: Box<Expression>,
  907. },
  908. Subtract {
  909. loc: pt::Loc,
  910. ty: Type,
  911. /// Do not check for overflow, i.e. in `unchecked {}` block
  912. unchecked: bool,
  913. left: Box<Expression>,
  914. right: Box<Expression>,
  915. },
  916. Multiply {
  917. loc: pt::Loc,
  918. ty: Type,
  919. /// Do not check for overflow, i.e. in `unchecked {}` block
  920. unchecked: bool,
  921. left: Box<Expression>,
  922. right: Box<Expression>,
  923. },
  924. Divide {
  925. loc: pt::Loc,
  926. ty: Type,
  927. left: Box<Expression>,
  928. right: Box<Expression>,
  929. },
  930. Modulo {
  931. loc: pt::Loc,
  932. ty: Type,
  933. left: Box<Expression>,
  934. right: Box<Expression>,
  935. },
  936. Power {
  937. loc: pt::Loc,
  938. ty: Type,
  939. /// Do not check for overflow, i.e. in `unchecked {}` block
  940. unchecked: bool,
  941. base: Box<Expression>,
  942. exp: Box<Expression>,
  943. },
  944. BitwiseOr {
  945. loc: pt::Loc,
  946. ty: Type,
  947. left: Box<Expression>,
  948. right: Box<Expression>,
  949. },
  950. BitwiseAnd {
  951. loc: pt::Loc,
  952. ty: Type,
  953. left: Box<Expression>,
  954. right: Box<Expression>,
  955. },
  956. BitwiseXor {
  957. loc: pt::Loc,
  958. ty: Type,
  959. left: Box<Expression>,
  960. right: Box<Expression>,
  961. },
  962. ShiftLeft {
  963. loc: pt::Loc,
  964. ty: Type,
  965. left: Box<Expression>,
  966. right: Box<Expression>,
  967. },
  968. ShiftRight {
  969. loc: pt::Loc,
  970. ty: Type,
  971. left: Box<Expression>,
  972. right: Box<Expression>,
  973. sign: bool,
  974. },
  975. Variable {
  976. loc: pt::Loc,
  977. ty: Type,
  978. var_no: usize,
  979. },
  980. ConstantVariable {
  981. loc: pt::Loc,
  982. ty: Type,
  983. contract_no: Option<usize>,
  984. var_no: usize,
  985. },
  986. StorageVariable {
  987. loc: pt::Loc,
  988. ty: Type,
  989. contract_no: usize,
  990. var_no: usize,
  991. },
  992. Load {
  993. loc: pt::Loc,
  994. ty: Type,
  995. expr: Box<Expression>,
  996. },
  997. GetRef {
  998. loc: pt::Loc,
  999. ty: Type,
  1000. expr: Box<Expression>,
  1001. },
  1002. StorageLoad {
  1003. loc: pt::Loc,
  1004. ty: Type,
  1005. expr: Box<Expression>,
  1006. },
  1007. ZeroExt {
  1008. loc: pt::Loc,
  1009. to: Type,
  1010. expr: Box<Expression>,
  1011. },
  1012. SignExt {
  1013. loc: pt::Loc,
  1014. to: Type,
  1015. expr: Box<Expression>,
  1016. },
  1017. Trunc {
  1018. loc: pt::Loc,
  1019. to: Type,
  1020. expr: Box<Expression>,
  1021. },
  1022. CheckingTrunc {
  1023. loc: pt::Loc,
  1024. to: Type,
  1025. expr: Box<Expression>,
  1026. },
  1027. Cast {
  1028. loc: pt::Loc,
  1029. to: Type,
  1030. expr: Box<Expression>,
  1031. },
  1032. BytesCast {
  1033. loc: pt::Loc,
  1034. from: Type,
  1035. to: Type,
  1036. expr: Box<Expression>,
  1037. },
  1038. PreIncrement {
  1039. loc: pt::Loc,
  1040. ty: Type,
  1041. /// Do not check for overflow, i.e. in `unchecked {}` block
  1042. unchecked: bool,
  1043. expr: Box<Expression>,
  1044. },
  1045. PreDecrement {
  1046. loc: pt::Loc,
  1047. ty: Type,
  1048. /// Do not check for overflow, i.e. in `unchecked {}` block
  1049. unchecked: bool,
  1050. expr: Box<Expression>,
  1051. },
  1052. PostIncrement {
  1053. loc: pt::Loc,
  1054. ty: Type,
  1055. /// Do not check for overflow, i.e. in `unchecked {}` block
  1056. unchecked: bool,
  1057. expr: Box<Expression>,
  1058. },
  1059. PostDecrement {
  1060. loc: pt::Loc,
  1061. ty: Type,
  1062. /// Do not check for overflow, i.e. in `unchecked {}` block
  1063. unchecked: bool,
  1064. expr: Box<Expression>,
  1065. },
  1066. Assign {
  1067. loc: pt::Loc,
  1068. ty: Type,
  1069. left: Box<Expression>,
  1070. right: Box<Expression>,
  1071. },
  1072. More {
  1073. loc: pt::Loc,
  1074. left: Box<Expression>,
  1075. right: Box<Expression>,
  1076. },
  1077. Less {
  1078. loc: pt::Loc,
  1079. left: Box<Expression>,
  1080. right: Box<Expression>,
  1081. },
  1082. MoreEqual {
  1083. loc: pt::Loc,
  1084. left: Box<Expression>,
  1085. right: Box<Expression>,
  1086. },
  1087. LessEqual {
  1088. loc: pt::Loc,
  1089. left: Box<Expression>,
  1090. right: Box<Expression>,
  1091. },
  1092. Equal {
  1093. loc: pt::Loc,
  1094. left: Box<Expression>,
  1095. right: Box<Expression>,
  1096. },
  1097. NotEqual {
  1098. loc: pt::Loc,
  1099. left: Box<Expression>,
  1100. right: Box<Expression>,
  1101. },
  1102. Not {
  1103. loc: pt::Loc,
  1104. expr: Box<Expression>,
  1105. },
  1106. BitwiseNot {
  1107. loc: pt::Loc,
  1108. ty: Type,
  1109. expr: Box<Expression>,
  1110. },
  1111. Negate {
  1112. loc: pt::Loc,
  1113. ty: Type,
  1114. /// Do not check for overflow, i.e. in `unchecked {}` block
  1115. unchecked: bool,
  1116. expr: Box<Expression>,
  1117. },
  1118. ConditionalOperator {
  1119. loc: pt::Loc,
  1120. ty: Type,
  1121. cond: Box<Expression>,
  1122. true_option: Box<Expression>,
  1123. false_option: Box<Expression>,
  1124. },
  1125. Subscript {
  1126. loc: pt::Loc,
  1127. ty: Type,
  1128. array_ty: Type,
  1129. array: Box<Expression>,
  1130. index: Box<Expression>,
  1131. },
  1132. NamedMember {
  1133. loc: pt::Loc,
  1134. ty: Type,
  1135. array: Box<Expression>,
  1136. name: String,
  1137. },
  1138. StructMember {
  1139. loc: pt::Loc,
  1140. ty: Type,
  1141. expr: Box<Expression>,
  1142. field: usize,
  1143. },
  1144. AllocDynamicBytes {
  1145. loc: pt::Loc,
  1146. ty: Type,
  1147. length: Box<Expression>,
  1148. init: Option<Vec<u8>>,
  1149. },
  1150. StorageArrayLength {
  1151. loc: pt::Loc,
  1152. ty: Type,
  1153. array: Box<Expression>,
  1154. elem_ty: Type,
  1155. },
  1156. StringCompare {
  1157. loc: pt::Loc,
  1158. left: StringLocation<Expression>,
  1159. right: StringLocation<Expression>,
  1160. },
  1161. Or {
  1162. loc: pt::Loc,
  1163. left: Box<Expression>,
  1164. right: Box<Expression>,
  1165. },
  1166. And {
  1167. loc: pt::Loc,
  1168. left: Box<Expression>,
  1169. right: Box<Expression>,
  1170. },
  1171. InternalFunction {
  1172. loc: pt::Loc,
  1173. id: pt::IdentifierPath,
  1174. ty: Type,
  1175. function_no: usize,
  1176. signature: Option<String>,
  1177. },
  1178. ExternalFunction {
  1179. loc: pt::Loc,
  1180. ty: Type,
  1181. address: Box<Expression>,
  1182. function_no: usize,
  1183. },
  1184. InternalFunctionCall {
  1185. loc: pt::Loc,
  1186. returns: Vec<Type>,
  1187. function: Box<Expression>,
  1188. args: Vec<Expression>,
  1189. },
  1190. ExternalFunctionCall {
  1191. loc: pt::Loc,
  1192. returns: Vec<Type>,
  1193. function: Box<Expression>,
  1194. args: Vec<Expression>,
  1195. call_args: CallArgs,
  1196. },
  1197. ExternalFunctionCallRaw {
  1198. loc: pt::Loc,
  1199. ty: CallTy,
  1200. address: Box<Expression>,
  1201. args: Box<Expression>,
  1202. call_args: CallArgs,
  1203. },
  1204. Constructor {
  1205. loc: pt::Loc,
  1206. contract_no: usize,
  1207. constructor_no: Option<usize>,
  1208. args: Vec<Expression>,
  1209. call_args: CallArgs,
  1210. },
  1211. FormatString {
  1212. loc: pt::Loc,
  1213. format: Vec<(FormatArg, Expression)>,
  1214. },
  1215. Builtin {
  1216. loc: pt::Loc,
  1217. tys: Vec<Type>,
  1218. kind: Builtin,
  1219. args: Vec<Expression>,
  1220. },
  1221. List {
  1222. loc: pt::Loc,
  1223. list: Vec<Expression>,
  1224. },
  1225. UserDefinedOperator {
  1226. loc: pt::Loc,
  1227. ty: Type,
  1228. oper: pt::UserDefinedOperator,
  1229. function_no: usize,
  1230. args: Vec<Expression>,
  1231. },
  1232. EventSelector {
  1233. loc: pt::Loc,
  1234. ty: Type,
  1235. event_no: usize,
  1236. },
  1237. TypeOperator {
  1238. loc: pt::Loc,
  1239. ty: Type,
  1240. },
  1241. }
  1242. #[derive(PartialEq, Eq, Clone, Default, Debug)]
  1243. pub struct CallArgs {
  1244. pub gas: Option<Box<Expression>>,
  1245. pub salt: Option<Box<Expression>>,
  1246. pub value: Option<Box<Expression>>,
  1247. pub accounts: ExternalCallAccounts<Box<Expression>>,
  1248. pub seeds: Option<Box<Expression>>,
  1249. pub flags: Option<Box<Expression>>,
  1250. pub program_id: Option<Box<Expression>>,
  1251. }
  1252. /// This enum manages the accounts in an external call on Solana. There can be three options:
  1253. /// 1. The developer explicitly specifies there are not accounts for the call (`NoAccount`).
  1254. /// 2. The accounts call argument is absent, in which case we attempt to generate the AccountMetas
  1255. /// vector automatically (`AbsentArgumet`).
  1256. /// 3. There are accounts specified in the accounts call argument (Present).
  1257. #[derive(PartialEq, Eq, Clone, Debug, Default)]
  1258. pub enum ExternalCallAccounts<T> {
  1259. NoAccount,
  1260. #[default]
  1261. AbsentArgument,
  1262. Present(T),
  1263. }
  1264. impl<T> ExternalCallAccounts<T> {
  1265. /// Is the accounts call argument missing?
  1266. pub fn is_absent(&self) -> bool {
  1267. matches!(self, ExternalCallAccounts::AbsentArgument)
  1268. }
  1269. /// Returns if the accounts call argument was present in the call
  1270. pub fn argument_provided(&self) -> bool {
  1271. matches!(
  1272. self,
  1273. ExternalCallAccounts::Present(_) | ExternalCallAccounts::NoAccount
  1274. )
  1275. }
  1276. /// Applies a function on the nested objects
  1277. pub fn map<P, F>(&self, func: F) -> ExternalCallAccounts<P>
  1278. where
  1279. F: FnOnce(&T) -> P,
  1280. {
  1281. match self {
  1282. NoAccount => NoAccount,
  1283. AbsentArgument => AbsentArgument,
  1284. ExternalCallAccounts::Present(value) => ExternalCallAccounts::Present(func(value)),
  1285. }
  1286. }
  1287. /// Transform the nested object into a reference
  1288. pub const fn as_ref(&self) -> ExternalCallAccounts<&T> {
  1289. match self {
  1290. ExternalCallAccounts::Present(value) => ExternalCallAccounts::Present(value),
  1291. NoAccount => NoAccount,
  1292. AbsentArgument => AbsentArgument,
  1293. }
  1294. }
  1295. /// Return a reference to the nested object
  1296. pub fn unwrap(&self) -> &T {
  1297. match self {
  1298. ExternalCallAccounts::Present(value) => value,
  1299. _ => panic!("unwrap called at variant without a nested object"),
  1300. }
  1301. }
  1302. }
  1303. impl Recurse for CallArgs {
  1304. type ArgType = Expression;
  1305. fn recurse<T>(&self, cx: &mut T, f: fn(expr: &Expression, ctx: &mut T) -> bool) {
  1306. if let Some(gas) = &self.gas {
  1307. gas.recurse(cx, f);
  1308. }
  1309. if let Some(salt) = &self.salt {
  1310. salt.recurse(cx, f);
  1311. }
  1312. if let Some(value) = &self.value {
  1313. value.recurse(cx, f);
  1314. }
  1315. if let ExternalCallAccounts::Present(accounts) = &self.accounts {
  1316. accounts.recurse(cx, f);
  1317. }
  1318. if let Some(flags) = &self.flags {
  1319. flags.recurse(cx, f);
  1320. }
  1321. }
  1322. }
  1323. impl Recurse for Expression {
  1324. type ArgType = Expression;
  1325. fn recurse<T>(&self, cx: &mut T, f: fn(expr: &Expression, ctx: &mut T) -> bool) {
  1326. if f(self, cx) {
  1327. match self {
  1328. Expression::StructLiteral { values, .. } => {
  1329. for (_, e) in values {
  1330. e.recurse(cx, f);
  1331. }
  1332. }
  1333. Expression::ArrayLiteral { values, .. }
  1334. | Expression::ConstArrayLiteral { values, .. } => {
  1335. for e in values {
  1336. e.recurse(cx, f);
  1337. }
  1338. }
  1339. Expression::Load { expr, .. }
  1340. | Expression::StorageLoad { expr, .. }
  1341. | Expression::ZeroExt { expr, .. }
  1342. | Expression::SignExt { expr, .. }
  1343. | Expression::Trunc { expr, .. }
  1344. | Expression::CheckingTrunc { expr, .. }
  1345. | Expression::Cast { expr, .. }
  1346. | Expression::BytesCast { expr, .. }
  1347. | Expression::PreIncrement { expr, .. }
  1348. | Expression::PreDecrement { expr, .. }
  1349. | Expression::PostIncrement { expr, .. }
  1350. | Expression::PostDecrement { expr, .. }
  1351. | Expression::Not { expr, .. }
  1352. | Expression::BitwiseNot { expr, .. }
  1353. | Expression::Negate { expr, .. }
  1354. | Expression::GetRef { expr, .. }
  1355. | Expression::NamedMember { array: expr, .. }
  1356. | Expression::StructMember { expr, .. } => expr.recurse(cx, f),
  1357. Expression::Add { left, right, .. }
  1358. | Expression::Subtract { left, right, .. }
  1359. | Expression::Multiply { left, right, .. }
  1360. | Expression::Divide { left, right, .. }
  1361. | Expression::Modulo { left, right, .. }
  1362. | Expression::Power {
  1363. base: left,
  1364. exp: right,
  1365. ..
  1366. }
  1367. | Expression::BitwiseOr { left, right, .. }
  1368. | Expression::BitwiseAnd { left, right, .. }
  1369. | Expression::BitwiseXor { left, right, .. }
  1370. | Expression::ShiftLeft { left, right, .. }
  1371. | Expression::ShiftRight { left, right, .. }
  1372. | Expression::Assign { left, right, .. }
  1373. | Expression::More { left, right, .. }
  1374. | Expression::Less { left, right, .. }
  1375. | Expression::MoreEqual { left, right, .. }
  1376. | Expression::LessEqual { left, right, .. }
  1377. | Expression::Equal { left, right, .. }
  1378. | Expression::NotEqual { left, right, .. }
  1379. | Expression::Or { left, right, .. }
  1380. | Expression::And { left, right, .. } => {
  1381. left.recurse(cx, f);
  1382. right.recurse(cx, f);
  1383. }
  1384. Expression::ConditionalOperator {
  1385. cond,
  1386. true_option: left,
  1387. false_option: right,
  1388. ..
  1389. } => {
  1390. cond.recurse(cx, f);
  1391. left.recurse(cx, f);
  1392. right.recurse(cx, f);
  1393. }
  1394. Expression::Subscript {
  1395. array: left,
  1396. index: right,
  1397. ..
  1398. } => {
  1399. left.recurse(cx, f);
  1400. right.recurse(cx, f);
  1401. }
  1402. Expression::AllocDynamicBytes { length, .. } => length.recurse(cx, f),
  1403. Expression::StorageArrayLength { array, .. } => array.recurse(cx, f),
  1404. Expression::StringCompare { left, right, .. } => {
  1405. if let StringLocation::RunTime(expr) = left {
  1406. expr.recurse(cx, f);
  1407. }
  1408. if let StringLocation::RunTime(expr) = right {
  1409. expr.recurse(cx, f);
  1410. }
  1411. }
  1412. Expression::InternalFunctionCall { function, args, .. } => {
  1413. function.recurse(cx, f);
  1414. for e in args {
  1415. e.recurse(cx, f);
  1416. }
  1417. }
  1418. Expression::ExternalFunction { address, .. } => {
  1419. address.recurse(cx, f);
  1420. }
  1421. Expression::ExternalFunctionCall {
  1422. function,
  1423. args,
  1424. call_args,
  1425. ..
  1426. } => {
  1427. for e in args {
  1428. e.recurse(cx, f);
  1429. }
  1430. function.recurse(cx, f);
  1431. call_args.recurse(cx, f);
  1432. }
  1433. Expression::ExternalFunctionCallRaw {
  1434. address,
  1435. args,
  1436. call_args,
  1437. ..
  1438. } => {
  1439. args.recurse(cx, f);
  1440. address.recurse(cx, f);
  1441. call_args.recurse(cx, f);
  1442. }
  1443. Expression::Constructor {
  1444. args, call_args, ..
  1445. } => {
  1446. for e in args {
  1447. e.recurse(cx, f);
  1448. }
  1449. call_args.recurse(cx, f);
  1450. }
  1451. Expression::UserDefinedOperator { args: exprs, .. }
  1452. | Expression::Builtin { args: exprs, .. }
  1453. | Expression::List { list: exprs, .. } => {
  1454. for e in exprs {
  1455. e.recurse(cx, f);
  1456. }
  1457. }
  1458. Expression::FormatString { format, .. } => {
  1459. for (_, arg) in format {
  1460. arg.recurse(cx, f);
  1461. }
  1462. }
  1463. Expression::NumberLiteral { .. }
  1464. | Expression::InternalFunction { .. }
  1465. | Expression::ConstantVariable { .. }
  1466. | Expression::StorageVariable { .. }
  1467. | Expression::Variable { .. }
  1468. | Expression::RationalNumberLiteral { .. }
  1469. | Expression::BytesLiteral { .. }
  1470. | Expression::BoolLiteral { .. }
  1471. | Expression::EventSelector { .. }
  1472. | Expression::TypeOperator { .. } => (),
  1473. }
  1474. }
  1475. }
  1476. }
  1477. impl CodeLocation for Expression {
  1478. fn loc(&self) -> pt::Loc {
  1479. match self {
  1480. Expression::BoolLiteral { loc, .. }
  1481. | Expression::BytesLiteral { loc, .. }
  1482. | Expression::NumberLiteral { loc, .. }
  1483. | Expression::RationalNumberLiteral { loc, .. }
  1484. | Expression::StructLiteral { loc, .. }
  1485. | Expression::ArrayLiteral { loc, .. }
  1486. | Expression::ConstArrayLiteral { loc, .. }
  1487. | Expression::Add { loc, .. }
  1488. | Expression::Subtract { loc, .. }
  1489. | Expression::Multiply { loc, .. }
  1490. | Expression::Divide { loc, .. }
  1491. | Expression::Modulo { loc, .. }
  1492. | Expression::Power { loc, .. }
  1493. | Expression::BitwiseOr { loc, .. }
  1494. | Expression::BitwiseAnd { loc, .. }
  1495. | Expression::BitwiseXor { loc, .. }
  1496. | Expression::ShiftLeft { loc, .. }
  1497. | Expression::ShiftRight { loc, .. }
  1498. | Expression::Variable { loc, .. }
  1499. | Expression::ConstantVariable { loc, .. }
  1500. | Expression::StorageVariable { loc, .. }
  1501. | Expression::Load { loc, .. }
  1502. | Expression::GetRef { loc, .. }
  1503. | Expression::StorageLoad { loc, .. }
  1504. | Expression::ZeroExt { loc, .. }
  1505. | Expression::SignExt { loc, .. }
  1506. | Expression::Trunc { loc, .. }
  1507. | Expression::CheckingTrunc { loc, .. }
  1508. | Expression::Cast { loc, .. }
  1509. | Expression::BytesCast { loc, .. }
  1510. | Expression::More { loc, .. }
  1511. | Expression::Less { loc, .. }
  1512. | Expression::MoreEqual { loc, .. }
  1513. | Expression::LessEqual { loc, .. }
  1514. | Expression::Equal { loc, .. }
  1515. | Expression::NotEqual { loc, .. }
  1516. | Expression::Not { loc, expr: _ }
  1517. | Expression::BitwiseNot { loc, .. }
  1518. | Expression::Negate { loc, .. }
  1519. | Expression::ConditionalOperator { loc, .. }
  1520. | Expression::Subscript { loc, .. }
  1521. | Expression::StructMember { loc, .. }
  1522. | Expression::Or { loc, .. }
  1523. | Expression::AllocDynamicBytes { loc, .. }
  1524. | Expression::StorageArrayLength { loc, .. }
  1525. | Expression::StringCompare { loc, .. }
  1526. | Expression::InternalFunction { loc, .. }
  1527. | Expression::ExternalFunction { loc, .. }
  1528. | Expression::InternalFunctionCall { loc, .. }
  1529. | Expression::ExternalFunctionCall { loc, .. }
  1530. | Expression::ExternalFunctionCallRaw { loc, .. }
  1531. | Expression::Constructor { loc, .. }
  1532. | Expression::PreIncrement { loc, .. }
  1533. | Expression::PreDecrement { loc, .. }
  1534. | Expression::PostIncrement { loc, .. }
  1535. | Expression::PostDecrement { loc, .. }
  1536. | Expression::Builtin { loc, .. }
  1537. | Expression::Assign { loc, .. }
  1538. | Expression::List { loc, list: _ }
  1539. | Expression::FormatString { loc, format: _ }
  1540. | Expression::And { loc, .. }
  1541. | Expression::NamedMember { loc, .. }
  1542. | Expression::UserDefinedOperator { loc, .. }
  1543. | Expression::EventSelector { loc, .. }
  1544. | Expression::TypeOperator { loc, .. } => *loc,
  1545. }
  1546. }
  1547. }
  1548. impl CodeLocation for Statement {
  1549. fn loc(&self) -> pt::Loc {
  1550. match self {
  1551. Statement::Block { loc, .. }
  1552. | Statement::VariableDecl(loc, ..)
  1553. | Statement::If(loc, ..)
  1554. | Statement::While(loc, ..)
  1555. | Statement::For { loc, .. }
  1556. | Statement::DoWhile(loc, ..)
  1557. | Statement::Expression(loc, ..)
  1558. | Statement::Delete(loc, ..)
  1559. | Statement::Destructure(loc, ..)
  1560. | Statement::Continue(loc, ..)
  1561. | Statement::Break(loc, ..)
  1562. | Statement::Revert { loc, .. }
  1563. | Statement::Return(loc, ..)
  1564. | Statement::Emit { loc, .. }
  1565. | Statement::TryCatch(loc, ..)
  1566. | Statement::Underscore(loc, ..) => *loc,
  1567. Statement::Assembly(ia, _) => ia.loc,
  1568. }
  1569. }
  1570. }
  1571. impl CodeLocation for Instr {
  1572. fn loc(&self) -> pt::Loc {
  1573. match self {
  1574. Instr::Set { loc, expr, .. } => match loc {
  1575. pt::Loc::File(_, _, _) => *loc,
  1576. _ => expr.loc(),
  1577. },
  1578. Instr::Call { args, .. } if args.is_empty() => pt::Loc::Codegen,
  1579. Instr::Return { value } if value.is_empty() => pt::Loc::Codegen,
  1580. Instr::Call { args: arr, .. } | Instr::Return { value: arr } => arr[0].loc(),
  1581. Instr::EmitEvent { data: expr, .. }
  1582. | Instr::BranchCond { cond: expr, .. }
  1583. | Instr::Store { dest: expr, .. }
  1584. | Instr::SetStorageBytes { storage: expr, .. }
  1585. | Instr::PushStorage { storage: expr, .. }
  1586. | Instr::PopStorage { storage: expr, .. }
  1587. | Instr::LoadStorage { storage: expr, .. }
  1588. | Instr::ClearStorage { storage: expr, .. }
  1589. | Instr::ExternalCall { value: expr, .. }
  1590. | Instr::SetStorage { value: expr, .. }
  1591. | Instr::Constructor { gas: expr, .. }
  1592. | Instr::ValueTransfer { address: expr, .. }
  1593. | Instr::SelfDestruct { recipient: expr }
  1594. | Instr::WriteBuffer { buf: expr, .. }
  1595. | Instr::Switch { cond: expr, .. }
  1596. | Instr::ReturnData { data: expr, .. }
  1597. | Instr::Print { expr } => expr.loc(),
  1598. Instr::PushMemory { value: expr, .. } => expr.loc(),
  1599. Instr::MemCopy {
  1600. source,
  1601. destination,
  1602. ..
  1603. } => match source.loc() {
  1604. pt::Loc::File(_, _, _) => source.loc(),
  1605. _ => destination.loc(),
  1606. },
  1607. Instr::Branch { .. }
  1608. | Instr::ReturnCode { .. }
  1609. | Instr::Nop
  1610. | Instr::AssertFailure { .. }
  1611. | Instr::PopMemory { .. }
  1612. | Instr::Unimplemented { .. } => pt::Loc::Codegen,
  1613. Instr::AccountAccess { loc, .. } => *loc,
  1614. }
  1615. }
  1616. }
  1617. #[derive(PartialEq, Clone, Copy, Debug, Eq)]
  1618. pub enum FormatArg {
  1619. StringLiteral,
  1620. Default,
  1621. Binary,
  1622. Hex,
  1623. }
  1624. impl fmt::Display for FormatArg {
  1625. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  1626. match self {
  1627. FormatArg::StringLiteral => write!(f, ""),
  1628. FormatArg::Default => write!(f, ""),
  1629. FormatArg::Binary => write!(f, ":b"),
  1630. FormatArg::Hex => write!(f, ":x"),
  1631. }
  1632. }
  1633. }
  1634. #[derive(PartialEq, Eq, Clone, Debug)]
  1635. pub enum StringLocation<T> {
  1636. CompileTime(Vec<u8>),
  1637. RunTime(Box<T>),
  1638. }
  1639. #[derive(PartialEq, Eq, Clone, Copy, Debug)]
  1640. pub enum Builtin {
  1641. ContractCode,
  1642. GetAddress,
  1643. Balance,
  1644. PayableSend,
  1645. PayableTransfer,
  1646. ArrayPush,
  1647. ArrayPop,
  1648. ArrayLength,
  1649. Assert,
  1650. Print,
  1651. Require,
  1652. SelfDestruct,
  1653. Keccak256,
  1654. Ripemd160,
  1655. Sha256,
  1656. Blake2_128,
  1657. Blake2_256,
  1658. BaseFee,
  1659. PrevRandao,
  1660. Gasleft,
  1661. BlockCoinbase,
  1662. BlockDifficulty,
  1663. GasLimit,
  1664. BlockNumber,
  1665. Slot,
  1666. Timestamp,
  1667. Calldata,
  1668. Sender,
  1669. Signature,
  1670. Value,
  1671. Gasprice,
  1672. Origin,
  1673. BlockHash,
  1674. MinimumBalance,
  1675. AbiDecode,
  1676. AbiEncode,
  1677. AbiEncodePacked,
  1678. AbiEncodeWithSelector,
  1679. AbiEncodeWithSignature,
  1680. AbiEncodeCall,
  1681. MulMod,
  1682. AddMod,
  1683. ChainId,
  1684. ExternalFunctionAddress,
  1685. FunctionSelector,
  1686. SignatureVerify,
  1687. ReadInt8,
  1688. ReadInt16LE,
  1689. ReadInt32LE,
  1690. ReadInt64LE,
  1691. ReadInt128LE,
  1692. ReadInt256LE,
  1693. ReadUint8,
  1694. ReadUint16LE,
  1695. ReadUint32LE,
  1696. ReadUint64LE,
  1697. ReadUint128LE,
  1698. ReadUint256LE,
  1699. ReadAddress,
  1700. WriteInt8,
  1701. WriteInt16LE,
  1702. WriteInt32LE,
  1703. WriteInt64LE,
  1704. WriteInt128LE,
  1705. WriteInt256LE,
  1706. WriteUint8,
  1707. WriteUint16LE,
  1708. WriteUint32LE,
  1709. WriteUint64LE,
  1710. WriteUint128LE,
  1711. WriteUint256LE,
  1712. WriteAddress,
  1713. WriteString,
  1714. WriteBytes,
  1715. Accounts,
  1716. UserTypeWrap,
  1717. UserTypeUnwrap,
  1718. ECRecover,
  1719. StringConcat,
  1720. BytesConcat,
  1721. TypeMin,
  1722. TypeMax,
  1723. TypeName,
  1724. TypeInterfaceId,
  1725. TypeRuntimeCode,
  1726. TypeCreatorCode,
  1727. RequireAuth,
  1728. AuthAsCurrContract,
  1729. ExtendTtl,
  1730. ExtendInstanceTtl,
  1731. }
  1732. #[derive(PartialEq, Eq, Clone, Debug)]
  1733. pub enum CallTy {
  1734. Regular,
  1735. Delegate,
  1736. Static,
  1737. }
  1738. impl fmt::Display for CallTy {
  1739. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  1740. match self {
  1741. CallTy::Regular => write!(f, "regular"),
  1742. CallTy::Static => write!(f, "static"),
  1743. CallTy::Delegate => write!(f, "delegate"),
  1744. }
  1745. }
  1746. }
  1747. #[derive(Clone, Debug)]
  1748. #[allow(clippy::large_enum_variant)]
  1749. pub enum Statement {
  1750. Block {
  1751. loc: pt::Loc,
  1752. unchecked: bool,
  1753. statements: Vec<Statement>,
  1754. },
  1755. VariableDecl(pt::Loc, usize, Parameter<Type>, Option<Arc<Expression>>),
  1756. If(pt::Loc, bool, Expression, Vec<Statement>, Vec<Statement>),
  1757. While(pt::Loc, bool, Expression, Vec<Statement>),
  1758. For {
  1759. loc: pt::Loc,
  1760. reachable: bool,
  1761. init: Vec<Statement>,
  1762. cond: Option<Expression>,
  1763. next: Option<Expression>,
  1764. body: Vec<Statement>,
  1765. },
  1766. DoWhile(pt::Loc, bool, Vec<Statement>, Expression),
  1767. Expression(pt::Loc, bool, Expression),
  1768. Delete(pt::Loc, Type, Expression),
  1769. Destructure(pt::Loc, Vec<DestructureField>, Expression),
  1770. Continue(pt::Loc),
  1771. Break(pt::Loc),
  1772. Return(pt::Loc, Option<Expression>),
  1773. Revert {
  1774. loc: pt::Loc,
  1775. error_no: Option<usize>,
  1776. args: Vec<Expression>,
  1777. },
  1778. Emit {
  1779. loc: pt::Loc,
  1780. event_no: usize,
  1781. event_loc: pt::Loc,
  1782. args: Vec<Expression>,
  1783. },
  1784. TryCatch(pt::Loc, bool, TryCatch),
  1785. Underscore(pt::Loc),
  1786. Assembly(InlineAssembly, bool),
  1787. }
  1788. #[derive(Clone, Debug)]
  1789. pub struct TryCatch {
  1790. pub expr: Expression,
  1791. pub returns: Vec<(Option<usize>, Parameter<Type>)>,
  1792. pub ok_stmt: Vec<Statement>,
  1793. pub errors: Vec<CatchClause>,
  1794. pub catch_all: Option<CatchClause>,
  1795. }
  1796. #[derive(Clone, Debug)]
  1797. pub struct CatchClause {
  1798. pub param: Option<Parameter<Type>>,
  1799. pub param_pos: Option<usize>,
  1800. pub stmt: Vec<Statement>,
  1801. }
  1802. #[derive(Clone, Debug)]
  1803. #[allow(clippy::large_enum_variant)]
  1804. pub enum DestructureField {
  1805. None,
  1806. Expression(Expression),
  1807. VariableDecl(usize, Parameter<Type>),
  1808. }
  1809. impl OptionalCodeLocation for DestructureField {
  1810. fn loc_opt(&self) -> Option<pt::Loc> {
  1811. match self {
  1812. DestructureField::None => None,
  1813. DestructureField::Expression(e) => Some(e.loc()),
  1814. DestructureField::VariableDecl(_, p) => Some(p.loc),
  1815. }
  1816. }
  1817. }
  1818. impl Recurse for Statement {
  1819. type ArgType = Statement;
  1820. fn recurse<T>(&self, cx: &mut T, f: fn(stmt: &Statement, ctx: &mut T) -> bool) {
  1821. if f(self, cx) {
  1822. match self {
  1823. Statement::Block { statements, .. } => {
  1824. for stmt in statements {
  1825. stmt.recurse(cx, f);
  1826. }
  1827. }
  1828. Statement::If(_, _, _, then_stmt, else_stmt) => {
  1829. for stmt in then_stmt {
  1830. stmt.recurse(cx, f);
  1831. }
  1832. for stmt in else_stmt {
  1833. stmt.recurse(cx, f);
  1834. }
  1835. }
  1836. Statement::For { init, body, .. } => {
  1837. for stmt in init {
  1838. stmt.recurse(cx, f);
  1839. }
  1840. for stmt in body {
  1841. stmt.recurse(cx, f);
  1842. }
  1843. }
  1844. Statement::While(_, _, _, body) => {
  1845. for stmt in body {
  1846. stmt.recurse(cx, f);
  1847. }
  1848. }
  1849. Statement::DoWhile(_, _, body, _) => {
  1850. for stmt in body {
  1851. stmt.recurse(cx, f);
  1852. }
  1853. }
  1854. Statement::TryCatch(_, _, try_catch) => {
  1855. for stmt in &try_catch.ok_stmt {
  1856. stmt.recurse(cx, f);
  1857. }
  1858. for clause in &try_catch.errors {
  1859. for stmt in &clause.stmt {
  1860. stmt.recurse(cx, f);
  1861. }
  1862. }
  1863. if let Some(clause) = try_catch.catch_all.as_ref() {
  1864. for stmt in &clause.stmt {
  1865. stmt.recurse(cx, f);
  1866. }
  1867. }
  1868. }
  1869. _ => (),
  1870. }
  1871. }
  1872. }
  1873. }
  1874. impl Statement {
  1875. /// Shorthand for checking underscore
  1876. pub fn is_underscore(&self) -> bool {
  1877. matches!(&self, Statement::Underscore(_))
  1878. }
  1879. pub fn reachable(&self) -> bool {
  1880. match self {
  1881. Statement::Block { statements, .. } => statements.iter().all(|s| s.reachable()),
  1882. Statement::Underscore(_)
  1883. | Statement::Destructure(..)
  1884. | Statement::VariableDecl(..)
  1885. | Statement::Emit { .. }
  1886. | Statement::Delete(..) => true,
  1887. Statement::Continue(_)
  1888. | Statement::Break(_)
  1889. | Statement::Return(..)
  1890. | Statement::Revert { .. } => false,
  1891. Statement::If(_, reachable, ..)
  1892. | Statement::While(_, reachable, ..)
  1893. | Statement::DoWhile(_, reachable, ..)
  1894. | Statement::Expression(_, reachable, _)
  1895. | Statement::For { reachable, .. }
  1896. | Statement::TryCatch(_, reachable, _)
  1897. | Statement::Assembly(_, reachable) => *reachable,
  1898. }
  1899. }
  1900. }
  1901. #[derive(PartialEq, Eq, Clone, Debug)]
  1902. pub struct Tag {
  1903. pub loc: pt::Loc,
  1904. pub tag: String,
  1905. pub no: usize,
  1906. pub value: String,
  1907. }