#[doc(hidden)]
pub use crate::helpers::{CodeLocation, OptionalCodeLocation};
#[cfg(feature = "pt-serde")]
use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub enum Loc {
Builtin,
CommandLine,
Implicit,
Codegen,
File(usize, usize, usize),
}
impl Default for Loc {
fn default() -> Self {
Self::File(0, 0, 0)
}
}
#[inline(never)]
#[cold]
#[track_caller]
fn not_a_file() -> ! {
panic!("location is not a file")
}
impl Loc {
#[inline]
pub fn begin_range(&self) -> Self {
match self {
Loc::File(file_no, start, _) => Loc::File(*file_no, *start, *start),
loc => *loc,
}
}
#[inline]
pub fn end_range(&self) -> Self {
match self {
Loc::File(file_no, _, end) => Loc::File(*file_no, *end, *end),
loc => *loc,
}
}
#[track_caller]
#[inline]
pub fn file_no(&self) -> usize {
match self {
Loc::File(file_no, _, _) => *file_no,
_ => not_a_file(),
}
}
#[inline]
pub fn try_file_no(&self) -> Option<usize> {
match self {
Loc::File(file_no, _, _) => Some(*file_no),
_ => None,
}
}
#[track_caller]
#[inline]
pub fn start(&self) -> usize {
match self {
Loc::File(_, start, _) => *start,
_ => not_a_file(),
}
}
#[track_caller]
#[inline]
pub fn end(&self) -> usize {
match self {
Loc::File(_, _, end) => *end,
_ => not_a_file(),
}
}
#[track_caller]
#[inline]
pub fn exclusive_end(&self) -> usize {
self.end() + 1
}
#[track_caller]
#[inline]
pub fn use_start_from(&mut self, other: &Loc) {
match (self, other) {
(Loc::File(_, start, _), Loc::File(_, other_start, _)) => {
*start = *other_start;
}
_ => not_a_file(),
}
}
#[track_caller]
#[inline]
pub fn use_end_from(&mut self, other: &Loc) {
match (self, other) {
(Loc::File(_, _, end), Loc::File(_, _, other_end)) => {
*end = *other_end;
}
_ => not_a_file(),
}
}
#[track_caller]
#[inline]
pub fn with_start_from(mut self, other: &Self) -> Self {
self.use_start_from(other);
self
}
#[track_caller]
#[inline]
pub fn with_end_from(mut self, other: &Self) -> Self {
self.use_end_from(other);
self
}
#[track_caller]
#[inline]
pub fn with_start(self, start: usize) -> Self {
match self {
Self::File(no, _, end) => Self::File(no, start, end),
_ => not_a_file(),
}
}
#[track_caller]
#[inline]
pub fn with_end(self, end: usize) -> Self {
match self {
Self::File(no, start, _) => Self::File(no, start, end),
_ => not_a_file(),
}
}
#[track_caller]
#[inline]
pub fn range(self) -> std::ops::Range<usize> {
match self {
Self::File(_, start, end) => start..end,
_ => not_a_file(),
}
}
pub fn union(&mut self, other: &Self) {
match (self, other) {
(Self::File(r_file, r_start, r_end), Self::File(l_file, l_start, l_end)) => {
assert_eq!(r_file, l_file, "cannot perform union in different files");
*r_start = std::cmp::min(*r_start, *l_start);
*r_end = std::cmp::max(*r_end, *l_end);
}
_ => unimplemented!("cannot perform union in non File Loc"),
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct Identifier {
pub loc: Loc,
pub name: String,
}
impl Identifier {
pub fn new(s: impl Into<String>) -> Self {
Self {
loc: Loc::default(),
name: s.into(),
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct IdentifierPath {
pub loc: Loc,
pub identifiers: Vec<Identifier>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub enum Comment {
Line(Loc, String),
Block(Loc, String),
DocLine(Loc, String),
DocBlock(Loc, String),
}
impl Comment {
#[inline]
pub const fn value(&self) -> &String {
match self {
Self::Line(_, s) | Self::Block(_, s) | Self::DocLine(_, s) | Self::DocBlock(_, s) => s,
}
}
#[inline]
pub const fn is_doc(&self) -> bool {
matches!(self, Self::DocLine(..) | Self::DocBlock(..))
}
#[inline]
pub const fn is_line(&self) -> bool {
matches!(self, Self::Line(..) | Self::DocLine(..))
}
#[inline]
pub const fn is_block(&self) -> bool {
!self.is_line()
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct SourceUnit(pub Vec<SourceUnitPart>);
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub enum SourceUnitPart {
PragmaDirective(Box<PragmaDirective>),
ImportDirective(Import),
ContractDefinition(Box<ContractDefinition>),
EnumDefinition(Box<EnumDefinition>),
StructDefinition(Box<StructDefinition>),
EventDefinition(Box<EventDefinition>),
ErrorDefinition(Box<ErrorDefinition>),
FunctionDefinition(Box<FunctionDefinition>),
VariableDefinition(Box<VariableDefinition>),
TypeDefinition(Box<TypeDefinition>),
Annotation(Box<Annotation>),
Using(Box<Using>),
StraySemicolon(Loc),
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub enum Import {
Plain(ImportPath, Loc),
GlobalSymbol(ImportPath, Identifier, Loc),
Rename(ImportPath, Vec<(Identifier, Option<Identifier>)>, Loc),
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub enum ImportPath {
Filename(StringLiteral),
Path(IdentifierPath),
}
impl Import {
#[inline]
pub const fn literal(&self) -> Option<&StringLiteral> {
match self {
Self::Plain(ImportPath::Filename(literal), _)
| Self::GlobalSymbol(ImportPath::Filename(literal), _, _)
| Self::Rename(ImportPath::Filename(literal), _, _) => Some(literal),
_ => None,
}
}
}
pub type ParameterList = Vec<(Loc, Option<Parameter>)>;
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub enum Type {
Address,
AddressPayable,
Payable,
Bool,
String,
Int(u16),
Uint(u16),
Bytes(u8),
Rational,
DynamicBytes,
Mapping {
loc: Loc,
key: Box<Expression>,
key_name: Option<Identifier>,
value: Box<Expression>,
value_name: Option<Identifier>,
},
Function {
params: ParameterList,
attributes: Vec<FunctionAttribute>,
returns: Option<(ParameterList, Vec<FunctionAttribute>)>,
},
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub enum StorageLocation {
Memory(Loc),
Storage(Loc),
Calldata(Loc),
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct VariableDeclaration {
pub loc: Loc,
pub ty: Expression,
pub storage: Option<StorageLocation>,
pub name: Option<Identifier>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct StructDefinition {
pub loc: Loc,
pub name: Option<Identifier>,
pub fields: Vec<VariableDeclaration>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub enum ContractPart {
StructDefinition(Box<StructDefinition>),
EventDefinition(Box<EventDefinition>),
EnumDefinition(Box<EnumDefinition>),
ErrorDefinition(Box<ErrorDefinition>),
VariableDefinition(Box<VariableDefinition>),
FunctionDefinition(Box<FunctionDefinition>),
TypeDefinition(Box<TypeDefinition>),
Annotation(Box<Annotation>),
Using(Box<Using>),
StraySemicolon(Loc),
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub enum PragmaDirective {
Identifier(Loc, Option<Identifier>, Option<Identifier>),
StringLiteral(Loc, Identifier, StringLiteral),
Version(Loc, Identifier, Vec<VersionComparator>),
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub enum VersionComparator {
Plain {
loc: Loc,
version: Vec<String>,
},
Operator {
loc: Loc,
op: VersionOp,
version: Vec<String>,
},
Or {
loc: Loc,
left: Box<VersionComparator>,
right: Box<VersionComparator>,
},
Range {
loc: Loc,
from: Vec<String>,
to: Vec<String>,
},
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub enum VersionOp {
Exact,
Greater,
GreaterEq,
Less,
LessEq,
Tilde,
Caret,
Wildcard,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub enum UsingList {
Library(IdentifierPath),
Functions(Vec<UsingFunction>),
Error,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct UsingFunction {
pub loc: Loc,
pub path: IdentifierPath,
pub oper: Option<UserDefinedOperator>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub enum UserDefinedOperator {
BitwiseAnd,
BitwiseNot,
Negate,
BitwiseOr,
BitwiseXor,
Add,
Divide,
Modulo,
Multiply,
Subtract,
Equal,
More,
MoreEqual,
Less,
LessEqual,
NotEqual,
}
impl UserDefinedOperator {
#[inline]
pub const fn args(&self) -> usize {
match self {
UserDefinedOperator::BitwiseNot | UserDefinedOperator::Negate => 1,
_ => 2,
}
}
#[inline]
pub const fn is_unary(&self) -> bool {
matches!(self, Self::BitwiseNot | Self::Negate)
}
#[inline]
pub const fn is_binary(&self) -> bool {
!self.is_unary()
}
#[inline]
pub const fn is_bitwise(&self) -> bool {
matches!(
self,
Self::BitwiseAnd | Self::BitwiseOr | Self::BitwiseXor | Self::BitwiseNot
)
}
#[inline]
pub const fn is_arithmetic(&self) -> bool {
matches!(
self,
Self::Add | Self::Subtract | Self::Multiply | Self::Divide | Self::Modulo
)
}
#[inline]
pub const fn is_comparison(&self) -> bool {
matches!(
self,
Self::Equal
| Self::NotEqual
| Self::Less
| Self::LessEqual
| Self::More
| Self::MoreEqual
)
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct Using {
pub loc: Loc,
pub list: UsingList,
pub ty: Option<Expression>,
pub global: Option<Identifier>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub enum ContractTy {
Abstract(Loc),
Contract(Loc),
Interface(Loc),
Library(Loc),
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct Base {
pub loc: Loc,
pub name: IdentifierPath,
pub args: Option<Vec<Expression>>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct ContractDefinition {
pub loc: Loc,
pub ty: ContractTy,
pub name: Option<Identifier>,
pub base: Vec<Base>,
pub parts: Vec<ContractPart>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct EventParameter {
pub loc: Loc,
pub ty: Expression,
pub indexed: bool,
pub name: Option<Identifier>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct EventDefinition {
pub loc: Loc,
pub name: Option<Identifier>,
pub fields: Vec<EventParameter>,
pub anonymous: bool,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct ErrorParameter {
pub loc: Loc,
pub ty: Expression,
pub name: Option<Identifier>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct ErrorDefinition {
pub loc: Loc,
pub keyword: Expression,
pub name: Option<Identifier>,
pub fields: Vec<ErrorParameter>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct EnumDefinition {
pub loc: Loc,
pub name: Option<Identifier>,
pub values: Vec<Option<Identifier>>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
#[repr(u8)] pub enum VariableAttribute {
Visibility(Visibility),
Constant(Loc),
Immutable(Loc),
Override(Loc, Vec<IdentifierPath>),
StorageType(StorageType),
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
#[repr(u8)] pub enum StorageType {
Temporary(Option<Loc>),
Persistent(Option<Loc>),
Instance(Option<Loc>),
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct VariableDefinition {
pub loc: Loc,
pub ty: Expression,
pub attrs: Vec<VariableAttribute>,
pub name: Option<Identifier>,
pub initializer: Option<Expression>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct TypeDefinition {
pub loc: Loc,
pub name: Identifier,
pub ty: Expression,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct Annotation {
pub loc: Loc,
pub id: Identifier,
pub value: Option<Expression>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct StringLiteral {
pub loc: Loc,
pub unicode: bool,
pub string: String,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct HexLiteral {
pub loc: Loc,
pub hex: String,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct NamedArgument {
pub loc: Loc,
pub name: Identifier,
pub expr: Expression,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub enum Expression {
PostIncrement(Loc, Box<Expression>),
PostDecrement(Loc, Box<Expression>),
New(Loc, Box<Expression>),
ArraySubscript(Loc, Box<Expression>, Option<Box<Expression>>),
ArraySlice(
Loc,
Box<Expression>,
Option<Box<Expression>>,
Option<Box<Expression>>,
),
Parenthesis(Loc, Box<Expression>),
MemberAccess(Loc, Box<Expression>, Identifier),
FunctionCall(Loc, Box<Expression>, Vec<Expression>),
FunctionCallBlock(Loc, Box<Expression>, Box<Statement>),
NamedFunctionCall(Loc, Box<Expression>, Vec<NamedArgument>),
Not(Loc, Box<Expression>),
BitwiseNot(Loc, Box<Expression>),
Delete(Loc, Box<Expression>),
PreIncrement(Loc, Box<Expression>),
PreDecrement(Loc, Box<Expression>),
UnaryPlus(Loc, Box<Expression>),
Negate(Loc, Box<Expression>),
Power(Loc, Box<Expression>, Box<Expression>),
Multiply(Loc, Box<Expression>, Box<Expression>),
Divide(Loc, Box<Expression>, Box<Expression>),
Modulo(Loc, Box<Expression>, Box<Expression>),
Add(Loc, Box<Expression>, Box<Expression>),
Subtract(Loc, Box<Expression>, Box<Expression>),
ShiftLeft(Loc, Box<Expression>, Box<Expression>),
ShiftRight(Loc, Box<Expression>, Box<Expression>),
BitwiseAnd(Loc, Box<Expression>, Box<Expression>),
BitwiseXor(Loc, Box<Expression>, Box<Expression>),
BitwiseOr(Loc, Box<Expression>, Box<Expression>),
Less(Loc, Box<Expression>, Box<Expression>),
More(Loc, Box<Expression>, Box<Expression>),
LessEqual(Loc, Box<Expression>, Box<Expression>),
MoreEqual(Loc, Box<Expression>, Box<Expression>),
Equal(Loc, Box<Expression>, Box<Expression>),
NotEqual(Loc, Box<Expression>, Box<Expression>),
And(Loc, Box<Expression>, Box<Expression>),
Or(Loc, Box<Expression>, Box<Expression>),
ConditionalOperator(Loc, Box<Expression>, Box<Expression>, Box<Expression>),
Assign(Loc, Box<Expression>, Box<Expression>),
AssignOr(Loc, Box<Expression>, Box<Expression>),
AssignAnd(Loc, Box<Expression>, Box<Expression>),
AssignXor(Loc, Box<Expression>, Box<Expression>),
AssignShiftLeft(Loc, Box<Expression>, Box<Expression>),
AssignShiftRight(Loc, Box<Expression>, Box<Expression>),
AssignAdd(Loc, Box<Expression>, Box<Expression>),
AssignSubtract(Loc, Box<Expression>, Box<Expression>),
AssignMultiply(Loc, Box<Expression>, Box<Expression>),
AssignDivide(Loc, Box<Expression>, Box<Expression>),
AssignModulo(Loc, Box<Expression>, Box<Expression>),
BoolLiteral(Loc, bool),
NumberLiteral(Loc, String, String, Option<Identifier>),
RationalNumberLiteral(Loc, String, String, String, Option<Identifier>),
HexNumberLiteral(Loc, String, Option<Identifier>),
StringLiteral(Vec<StringLiteral>),
Type(Loc, Type),
HexLiteral(Vec<HexLiteral>),
AddressLiteral(Loc, String),
Variable(Identifier),
List(Loc, ParameterList),
ArrayLiteral(Loc, Vec<Expression>),
}
macro_rules! expr_components {
($s:ident) => {
match $s {
PostDecrement(_, expr) | PostIncrement(_, expr) => (Some(expr), None),
Not(_, expr)
| BitwiseNot(_, expr)
| New(_, expr)
| Delete(_, expr)
| UnaryPlus(_, expr)
| Negate(_, expr)
| PreDecrement(_, expr)
| Parenthesis(_, expr)
| PreIncrement(_, expr) => (None, Some(expr)),
Power(_, left, right)
| Multiply(_, left, right)
| Divide(_, left, right)
| Modulo(_, left, right)
| Add(_, left, right)
| Subtract(_, left, right)
| ShiftLeft(_, left, right)
| ShiftRight(_, left, right)
| BitwiseAnd(_, left, right)
| BitwiseXor(_, left, right)
| BitwiseOr(_, left, right)
| Less(_, left, right)
| More(_, left, right)
| LessEqual(_, left, right)
| MoreEqual(_, left, right)
| Equal(_, left, right)
| NotEqual(_, left, right)
| And(_, left, right)
| Or(_, left, right)
| Assign(_, left, right)
| AssignOr(_, left, right)
| AssignAnd(_, left, right)
| AssignXor(_, left, right)
| AssignShiftLeft(_, left, right)
| AssignShiftRight(_, left, right)
| AssignAdd(_, left, right)
| AssignSubtract(_, left, right)
| AssignMultiply(_, left, right)
| AssignDivide(_, left, right)
| AssignModulo(_, left, right) => (Some(left), Some(right)),
MemberAccess(..)
| ConditionalOperator(..)
| ArraySubscript(..)
| ArraySlice(..)
| FunctionCall(..)
| FunctionCallBlock(..)
| NamedFunctionCall(..)
| BoolLiteral(..)
| NumberLiteral(..)
| RationalNumberLiteral(..)
| HexNumberLiteral(..)
| StringLiteral(..)
| Type(..)
| HexLiteral(..)
| AddressLiteral(..)
| Variable(..)
| List(..)
| ArrayLiteral(..) => (None, None),
}
};
}
impl Expression {
#[inline]
pub fn remove_parenthesis(&self) -> &Expression {
if let Expression::Parenthesis(_, expr) = self {
expr
} else {
self
}
}
pub fn strip_parentheses(&self) -> &Expression {
match self {
Expression::Parenthesis(_, expr) => expr.strip_parentheses(),
_ => self,
}
}
#[inline]
pub fn components(&self) -> (Option<&Self>, Option<&Self>) {
use Expression::*;
expr_components!(self)
}
#[inline]
pub fn components_mut(&mut self) -> (Option<&mut Self>, Option<&mut Self>) {
use Expression::*;
expr_components!(self)
}
#[inline]
pub const fn is_unsplittable(&self) -> bool {
use Expression::*;
matches!(
self,
BoolLiteral(..)
| NumberLiteral(..)
| RationalNumberLiteral(..)
| HexNumberLiteral(..)
| StringLiteral(..)
| HexLiteral(..)
| AddressLiteral(..)
| Variable(..)
)
}
#[inline]
pub const fn has_space_around(&self) -> bool {
use Expression::*;
!matches!(
self,
PostIncrement(..)
| PreIncrement(..)
| PostDecrement(..)
| PreDecrement(..)
| Not(..)
| BitwiseNot(..)
| UnaryPlus(..)
| Negate(..)
)
}
pub fn is_literal(&self) -> bool {
matches!(
self,
Expression::AddressLiteral(..)
| Expression::HexLiteral(..)
| Expression::BoolLiteral(..)
| Expression::NumberLiteral(..)
| Expression::ArrayLiteral(..)
| Expression::HexNumberLiteral(..)
| Expression::RationalNumberLiteral(..)
| Expression::StringLiteral(..)
)
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct Parameter {
pub loc: Loc,
pub annotation: Option<Annotation>,
pub ty: Expression,
pub storage: Option<StorageLocation>,
pub name: Option<Identifier>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub enum Mutability {
Pure(Loc),
View(Loc),
Constant(Loc),
Payable(Loc),
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
#[repr(u8)] pub enum Visibility {
External(Option<Loc>),
Public(Option<Loc>),
Internal(Option<Loc>),
Private(Option<Loc>),
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
#[repr(u8)] pub enum FunctionAttribute {
Visibility(Visibility),
Mutability(Mutability),
Virtual(Loc),
Immutable(Loc),
Override(Loc, Vec<IdentifierPath>),
BaseOrModifier(Loc, Base),
Error(Loc),
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub enum FunctionTy {
Constructor,
Function,
Fallback,
Receive,
Modifier,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct FunctionDefinition {
pub loc_prototype: Loc,
pub loc: Loc,
pub ty: FunctionTy,
pub name: Option<Identifier>,
pub name_loc: Loc,
pub params: ParameterList,
pub attributes: Vec<FunctionAttribute>,
pub return_not_returns: Option<Loc>,
pub returns: ParameterList,
pub body: Option<Statement>,
}
impl FunctionDefinition {
#[inline]
pub fn is_void(&self) -> bool {
self.returns.is_empty()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.body.as_ref().is_none_or(Statement::is_empty)
}
#[inline]
pub fn sort_attributes(&mut self) {
self.attributes.sort();
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
#[allow(clippy::large_enum_variant, clippy::type_complexity)]
pub enum Statement {
Block {
loc: Loc,
unchecked: bool,
statements: Vec<Statement>,
},
Assembly {
loc: Loc,
dialect: Option<StringLiteral>,
flags: Option<Vec<StringLiteral>>,
block: YulBlock,
},
Args(Loc, Vec<NamedArgument>),
If(Loc, Expression, Box<Statement>, Option<Box<Statement>>),
While(Loc, Expression, Box<Statement>),
Expression(Loc, Expression),
VariableDefinition(Loc, VariableDeclaration, Option<Expression>),
For(
Loc,
Option<Box<Statement>>,
Option<Box<Expression>>,
Option<Box<Expression>>,
Option<Box<Statement>>,
),
DoWhile(Loc, Box<Statement>, Expression),
Continue(Loc),
Break(Loc),
Return(Loc, Option<Expression>),
Revert(Loc, Option<IdentifierPath>, Vec<Expression>),
RevertNamedArgs(Loc, Option<IdentifierPath>, Vec<NamedArgument>),
Emit(Loc, Expression),
Try(
Loc,
Expression,
Option<(ParameterList, Box<Statement>)>,
Vec<CatchClause>,
),
Error(Loc),
}
impl Statement {
#[inline]
pub fn is_empty(&self) -> bool {
match self {
Self::Block { statements, .. } => statements.is_empty(),
Self::Assembly { block, .. } => block.is_empty(),
Self::Args(_, args) => args.is_empty(),
_ => false,
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub enum CatchClause {
Simple(Loc, Option<Parameter>, Statement),
Named(Loc, Identifier, Parameter, Statement),
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub enum YulStatement {
Assign(Loc, Vec<YulExpression>, YulExpression),
VariableDeclaration(Loc, Vec<YulTypedIdentifier>, Option<YulExpression>),
If(Loc, YulExpression, YulBlock),
For(YulFor),
Switch(YulSwitch),
Leave(Loc),
Break(Loc),
Continue(Loc),
Block(YulBlock),
FunctionDefinition(Box<YulFunctionDefinition>),
FunctionCall(Box<YulFunctionCall>),
Error(Loc),
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct YulSwitch {
pub loc: Loc,
pub condition: YulExpression,
pub cases: Vec<YulSwitchOptions>,
pub default: Option<YulSwitchOptions>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct YulFor {
pub loc: Loc,
pub init_block: YulBlock,
pub condition: YulExpression,
pub post_block: YulBlock,
pub execution_block: YulBlock,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct YulBlock {
pub loc: Loc,
pub statements: Vec<YulStatement>,
}
impl YulBlock {
#[inline]
pub fn is_empty(&self) -> bool {
self.statements.is_empty()
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub enum YulExpression {
BoolLiteral(Loc, bool, Option<Identifier>),
NumberLiteral(Loc, String, String, Option<Identifier>),
HexNumberLiteral(Loc, String, Option<Identifier>),
HexStringLiteral(HexLiteral, Option<Identifier>),
StringLiteral(StringLiteral, Option<Identifier>),
Variable(Identifier),
FunctionCall(Box<YulFunctionCall>),
SuffixAccess(Loc, Box<YulExpression>, Identifier),
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct YulTypedIdentifier {
pub loc: Loc,
pub id: Identifier,
pub ty: Option<Identifier>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct YulFunctionDefinition {
pub loc: Loc,
pub id: Identifier,
pub params: Vec<YulTypedIdentifier>,
pub returns: Vec<YulTypedIdentifier>,
pub body: YulBlock,
}
impl YulFunctionDefinition {
#[inline]
pub fn is_void(&self) -> bool {
self.returns.is_empty()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.body.is_empty()
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub struct YulFunctionCall {
pub loc: Loc,
pub id: Identifier,
pub arguments: Vec<YulExpression>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
pub enum YulSwitchOptions {
Case(Loc, YulExpression, YulBlock),
Default(Loc, YulBlock),
}