syn_solidity/yul/expr/
fn_call.rs

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