cmacro/ast/
function_decl.rs1use std::{
2 fmt::Debug,
3 ops::{RangeFrom, RangeTo},
4};
5
6use nom::{
7 branch::permutation,
8 combinator::opt,
9 multi::separated_list0,
10 sequence::{pair, tuple},
11 AsChar, Compare, FindSubstring, FindToken, IResult, InputIter, InputLength, InputTake, InputTakeAtPosition, Offset,
12 ParseTo, Slice,
13};
14use proc_macro2::TokenStream;
15use quote::{quote, TokenStreamExt};
16
17use super::{tokens::parenthesized, *};
18use crate::{CodegenContext, LocalContext, MacroArgType, ParseContext};
19
20#[derive(Debug, Clone, PartialEq, Eq)]
26pub struct FunctionDecl {
27 ret_ty: Type,
28 name: Identifier,
29 args: Vec<(Type, Identifier)>,
30}
31
32impl FunctionDecl {
33 pub(crate) fn parse<'i, 'p, I, C>(tokens: &'i [I], ctx: &'p ParseContext<'_>) -> IResult<&'i [I], Self>
35 where
36 I: Debug
37 + InputTake
38 + InputLength
39 + InputIter<Item = C>
40 + InputTakeAtPosition<Item = C>
41 + Slice<RangeFrom<usize>>
42 + Slice<RangeTo<usize>>
43 + Compare<&'static str>
44 + FindSubstring<&'static str>
45 + ParseTo<f64>
46 + ParseTo<f32>
47 + Offset
48 + Clone,
49 C: AsChar + Copy,
50 &'static str: FindToken<<I as InputIter>::Item>,
51 {
52 let (tokens, ((_, ret_ty), name, args)) = tuple((
53 permutation((opt(token("static")), |tokens| Type::parse(tokens, ctx))),
54 |tokens| Identifier::parse(tokens, ctx),
55 parenthesized(separated_list0(
56 pair(meta, token(",")),
57 pair(|tokens| Type::parse(tokens, ctx), |tokens| Identifier::parse(tokens, ctx)),
58 )),
59 ))(tokens)?;
60
61 Ok((tokens, Self { ret_ty, name, args }))
62 }
63
64 pub(crate) fn finish<C>(&mut self, ctx: &mut LocalContext<'_, C>) -> Result<Option<Type>, crate::Error>
65 where
66 C: CodegenContext,
67 {
68 self.ret_ty.finish(ctx)?;
69 self.name.finish(ctx)?;
70
71 if let Identifier::Literal(id) = &self.name {
72 if id.macro_arg {
73 if let Some(arg_type) = ctx.arg_type_mut(id.as_str()) {
74 *arg_type = MacroArgType::Ident;
75 }
76 }
77 }
78
79 for (ty, arg) in self.args.iter_mut() {
80 ty.finish(ctx)?;
81 arg.finish(ctx)?;
82 }
83
84 Ok(Some(Type::BuiltIn(BuiltInType::Void)))
86 }
87
88 pub(crate) fn to_tokens<C: CodegenContext>(&self, ctx: &mut LocalContext<'_, C>, tokens: &mut TokenStream) {
89 let name = self.name.to_token_stream(ctx);
90 let args = self
91 .args
92 .iter()
93 .map(|(ty, arg)| {
94 let ty = ty.to_token_stream(ctx);
95 let arg = arg.to_token_stream(ctx);
96 quote! { #arg: #ty }
97 })
98 .collect::<Vec<_>>();
99 let ret_ty = self.ret_ty.to_token_stream(ctx);
100
101 tokens.append_all(quote! {
102 extern "C" {
103 pub fn #name(#(#args),*) -> #ret_ty;
104 }
105 })
106 }
107}