syn_solidity/yul/type/
function.rs

1use crate::{kw, utils::DebugPunctuated, Spanned, YulBlock, YulIdent};
2use proc_macro2::Span;
3use std::fmt;
4use syn::{
5    parenthesized,
6    parse::{Parse, ParseStream},
7    punctuated::Punctuated,
8    token::Paren,
9    Result, Token,
10};
11
12/// Yul function definition: `function f() -> a, b { ... }`.
13///
14/// Solitify Reference:
15/// <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.yulFunctionDefinition>
16#[derive(Clone)]
17pub struct YulFunctionDef {
18    pub function_token: kw::function,
19    pub ident: YulIdent,
20    pub paren_token: Paren,
21    pub arguments: Punctuated<YulIdent, Token![,]>,
22    pub returns: Option<YulReturns>,
23    pub body: YulBlock,
24}
25
26impl Parse for YulFunctionDef {
27    fn parse(input: ParseStream<'_>) -> Result<Self> {
28        let content;
29        Ok(Self {
30            function_token: input.parse()?,
31            ident: input.parse()?,
32            paren_token: parenthesized!(content in input),
33            arguments: Punctuated::parse_terminated(&content)?,
34            returns: input.call(YulReturns::parse_opt)?,
35            body: input.parse()?,
36        })
37    }
38}
39
40impl Spanned for YulFunctionDef {
41    fn span(&self) -> Span {
42        let span = self.function_token.span();
43        span.join(self.body.span()).unwrap_or(span)
44    }
45
46    fn set_span(&mut self, span: Span) {
47        self.function_token.set_span(span);
48        self.ident.set_span(span);
49        self.paren_token = Paren(span);
50        self.arguments.set_span(span);
51        self.returns.set_span(span);
52        self.body.set_span(span);
53    }
54}
55
56impl fmt::Debug for YulFunctionDef {
57    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58        f.debug_struct("YulFunctionDef")
59            .field("ident", &self.ident)
60            .field("arguments", DebugPunctuated::new(&self.arguments))
61            .field("returns", &self.returns)
62            .field("body", &self.body)
63            .finish()
64    }
65}
66
67/// The return attribute of a Yul function definition.
68#[derive(Clone)]
69pub struct YulReturns {
70    pub arrow_token: Token![->],
71    pub returns: Punctuated<YulIdent, Token![,]>,
72}
73
74impl YulReturns {
75    pub fn parse_opt(input: ParseStream<'_>) -> Result<Option<Self>> {
76        if input.peek(Token![->]) {
77            Ok(Some(Self {
78                arrow_token: input.parse()?,
79                returns: Punctuated::parse_separated_nonempty(input)?,
80            }))
81        } else {
82            Ok(None)
83        }
84    }
85}
86
87impl Parse for YulReturns {
88    fn parse(input: ParseStream<'_>) -> Result<Self> {
89        Ok(Self {
90            arrow_token: input.parse()?,
91            returns: Punctuated::parse_separated_nonempty(input)?,
92        })
93    }
94}
95
96impl Spanned for YulReturns {
97    fn span(&self) -> Span {
98        let span = self.arrow_token.span();
99        span.join(self.returns.span()).unwrap_or(span)
100    }
101
102    fn set_span(&mut self, span: Span) {
103        self.arrow_token.set_span(span);
104        self.returns.set_span(span);
105    }
106}
107
108impl fmt::Debug for YulReturns {
109    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110        f.debug_struct("YulReturns").field("returns", DebugPunctuated::new(&self.returns)).finish()
111    }
112}