syn_solidity/yul/type/
function.rs

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