syn_solidity/yul/expr/
fn_call.rs

1use crate::{utils::DebugPunctuated, Spanned, YulEVMBuiltIn, YulExpr, YulIdent};
2use proc_macro2::Span;
3use std::fmt;
4use syn::{
5    parenthesized,
6    parse::{discouraged::Speculative, Parse, ParseStream, Result},
7    punctuated::Punctuated,
8    token::Paren,
9    Token,
10};
11
12/// Yul function call.
13///
14/// Solidity Reference:
15/// <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.yulFunctionCall>
16#[derive(Clone)]
17pub struct YulFnCall {
18    pub function_type: YulFnType,
19    pub paren_token: Paren,
20    pub arguments: Punctuated<YulExpr, Token![,]>,
21}
22
23impl Parse for YulFnCall {
24    fn parse(input: ParseStream<'_>) -> Result<Self> {
25        let content;
26        Ok(Self {
27            function_type: input.parse()?,
28            paren_token: parenthesized!(content in input),
29            arguments: content.parse_terminated(YulExpr::parse, Token![,])?,
30        })
31    }
32}
33
34impl Spanned for YulFnCall {
35    fn span(&self) -> Span {
36        let span = self.function_type.span();
37        span.join(self.arguments.span()).unwrap_or(span)
38    }
39
40    fn set_span(&mut self, span: Span) {
41        self.function_type.set_span(span);
42        self.paren_token = Paren(span);
43        self.arguments.set_span(span);
44    }
45}
46
47impl fmt::Debug for YulFnCall {
48    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49        f.debug_struct("YulFnCall")
50            .field("function_type", &self.function_type)
51            .field("arguments", DebugPunctuated::new(&self.arguments))
52            .finish()
53    }
54}
55
56/// What type of function is called.
57#[derive(Clone)]
58pub enum YulFnType {
59    /// When calling a self defined function
60    Custom(YulIdent),
61
62    /// When calling a built in evm opcode
63    EVMOpcode(YulEVMBuiltIn),
64}
65
66impl Parse for YulFnType {
67    fn parse(input: ParseStream<'_>) -> Result<Self> {
68        let speculative_parse = input.fork();
69
70        if let Ok(evm_builtin) = speculative_parse.parse::<YulEVMBuiltIn>() {
71            input.advance_to(&speculative_parse);
72            Ok(Self::EVMOpcode(evm_builtin))
73        } else {
74            Ok(Self::Custom(input.parse::<YulIdent>()?))
75        }
76    }
77}
78
79impl Spanned for YulFnType {
80    fn span(&self) -> Span {
81        match self {
82            Self::Custom(custom) => custom.span(),
83            Self::EVMOpcode(opcode) => opcode.span(),
84        }
85    }
86
87    fn set_span(&mut self, span: Span) {
88        match self {
89            Self::Custom(custom) => custom.set_span(span),
90            Self::EVMOpcode(opcode) => opcode.set_span(span),
91        }
92    }
93}
94
95impl fmt::Debug for YulFnType {
96    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97        f.write_str("FnType::")?;
98        match self {
99            Self::Custom(custom) => custom.fmt(f),
100            Self::EVMOpcode(opcode) => opcode.fmt(f),
101        }
102    }
103}