mirror of
https://gitee.com/openharmony/third_party_rust_cxx
synced 2025-02-17 15:09:41 +00:00
Parse function pointer types
This commit is contained in:
parent
265f6a079d
commit
c071b89c2c
@ -45,6 +45,7 @@ pub(crate) fn typecheck(apis: &[Api], types: &Types) -> Result<()> {
|
||||
errors.push(unsupported_reference_type(ty));
|
||||
}
|
||||
}
|
||||
Type::Fn(_) => errors.push(unimplemented_fn_type(ty)),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@ -213,3 +214,7 @@ fn return_by_value(ty: &Type, types: &Types) -> Error {
|
||||
let message = format!("returning {} by value is not supported", desc);
|
||||
Error::new_spanned(ty, message)
|
||||
}
|
||||
|
||||
fn unimplemented_fn_type(ty: &Type) -> Error {
|
||||
Error::new_spanned(ty, "function pointer support is not implemented yet")
|
||||
}
|
||||
|
@ -3,11 +3,11 @@ use crate::syntax::{
|
||||
Ty1, Type, Var,
|
||||
};
|
||||
use proc_macro2::Ident;
|
||||
use quote::quote;
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{
|
||||
Abi, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType, GenericArgument, Item,
|
||||
ItemForeignMod, ItemStruct, Pat, PathArguments, Result, ReturnType, Type as RustType, TypePath,
|
||||
TypeReference,
|
||||
ItemForeignMod, ItemStruct, Pat, PathArguments, Result, ReturnType, Type as RustType,
|
||||
TypeBareFn, TypePath, TypeReference,
|
||||
};
|
||||
|
||||
pub fn parse_items(items: Vec<Item>) -> Result<Vec<Api>> {
|
||||
@ -176,32 +176,7 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<ExternFn> {
|
||||
}
|
||||
|
||||
let mut throws = false;
|
||||
let ret = match &foreign_fn.sig.output {
|
||||
ReturnType::Default => None,
|
||||
ReturnType::Type(_, ret) => {
|
||||
let mut ret = ret.as_ref();
|
||||
if let RustType::Path(ty) = ret {
|
||||
let path = &ty.path;
|
||||
if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
|
||||
let segment = &path.segments[0];
|
||||
let ident = segment.ident.clone();
|
||||
if let PathArguments::AngleBracketed(generic) = &segment.arguments {
|
||||
if ident == "Result" && generic.args.len() == 1 {
|
||||
if let GenericArgument::Type(arg) = &generic.args[0] {
|
||||
ret = arg;
|
||||
throws = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
match parse_type(ret)? {
|
||||
Type::Void(_) => None,
|
||||
ty => Some(ty),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let ret = parse_return_type(&foreign_fn.sig.output, &mut throws)?;
|
||||
let doc = attrs::parse_doc(&foreign_fn.attrs)?;
|
||||
let fn_token = foreign_fn.sig.fn_token;
|
||||
let ident = foreign_fn.sig.ident.clone();
|
||||
@ -230,6 +205,7 @@ fn parse_type(ty: &RustType) -> Result<Type> {
|
||||
match ty {
|
||||
RustType::Reference(ty) => parse_type_reference(ty),
|
||||
RustType::Path(ty) => parse_type_path(ty),
|
||||
RustType::BareFn(ty) => parse_type_fn(ty),
|
||||
RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span)),
|
||||
_ => Err(Error::new_spanned(ty, "unsupported type")),
|
||||
}
|
||||
@ -290,6 +266,71 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
|
||||
Err(Error::new_spanned(ty, "unsupported type"))
|
||||
}
|
||||
|
||||
fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
|
||||
if ty.lifetimes.is_some() {
|
||||
return Err(Error::new_spanned(
|
||||
ty,
|
||||
"function pointer with lifetime parameters is not supported yet",
|
||||
));
|
||||
}
|
||||
if ty.variadic.is_some() {
|
||||
return Err(Error::new_spanned(
|
||||
ty,
|
||||
"variadic function pointer is not supported yet",
|
||||
));
|
||||
}
|
||||
let args = ty
|
||||
.inputs
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, arg)| {
|
||||
let ty = parse_type(&arg.ty)?;
|
||||
let ident = match &arg.name {
|
||||
Some(ident) => ident.0.clone(),
|
||||
None => format_ident!("_{}", i),
|
||||
};
|
||||
Ok(Var { ident, ty })
|
||||
})
|
||||
.collect::<Result<_>>()?;
|
||||
let mut throws = false;
|
||||
let ret = parse_return_type(&ty.output, &mut throws)?;
|
||||
let tokens = quote!(#ty);
|
||||
Ok(Type::Fn(Box::new(Signature {
|
||||
fn_token: ty.fn_token,
|
||||
receiver: None,
|
||||
args,
|
||||
ret,
|
||||
throws,
|
||||
tokens,
|
||||
})))
|
||||
}
|
||||
|
||||
fn parse_return_type(ty: &ReturnType, throws: &mut bool) -> Result<Option<Type>> {
|
||||
let mut ret = match ty {
|
||||
ReturnType::Default => return Ok(None),
|
||||
ReturnType::Type(_, ret) => ret.as_ref(),
|
||||
};
|
||||
if let RustType::Path(ty) = ret {
|
||||
let path = &ty.path;
|
||||
if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
|
||||
let segment = &path.segments[0];
|
||||
let ident = segment.ident.clone();
|
||||
if let PathArguments::AngleBracketed(generic) = &segment.arguments {
|
||||
if ident == "Result" && generic.args.len() == 1 {
|
||||
if let GenericArgument::Type(arg) = &generic.args[0] {
|
||||
ret = arg;
|
||||
*throws = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
match parse_type(ret)? {
|
||||
Type::Void(_) => Ok(None),
|
||||
ty => Ok(Some(ty)),
|
||||
}
|
||||
}
|
||||
|
||||
fn check_reserved_name(ident: &Ident) -> Result<()> {
|
||||
if ident == "Box" || ident == "UniquePtr" || Atom::from(ident).is_some() {
|
||||
Err(Error::new(ident.span(), "reserved name"))
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::syntax::atom::Atom::*;
|
||||
use crate::syntax::{Derive, ExternFn, Ref, Ty1, Type, Var};
|
||||
use crate::syntax::{Derive, ExternFn, Ref, Signature, Ty1, Type, Var};
|
||||
use proc_macro2::{Ident, Span, TokenStream};
|
||||
use quote::{quote, quote_spanned, ToTokens};
|
||||
use quote::{quote_spanned, ToTokens};
|
||||
use syn::Token;
|
||||
|
||||
impl ToTokens for Type {
|
||||
@ -16,21 +16,7 @@ impl ToTokens for Type {
|
||||
}
|
||||
Type::RustBox(ty) | Type::UniquePtr(ty) => ty.to_tokens(tokens),
|
||||
Type::Ref(r) | Type::Str(r) => r.to_tokens(tokens),
|
||||
Type::Fn(f) => {
|
||||
let fn_token = f.fn_token;
|
||||
let args = &f.args;
|
||||
tokens.extend(quote!(#fn_token(#(#args),*)));
|
||||
let mut ret = match &f.ret {
|
||||
Some(ret) => quote!(#ret),
|
||||
None => quote!(()),
|
||||
};
|
||||
if f.throws {
|
||||
ret = quote!(::std::result::Result<#ret, _>);
|
||||
}
|
||||
if f.ret.is_some() || f.throws {
|
||||
tokens.extend(quote!(-> #ret));
|
||||
}
|
||||
}
|
||||
Type::Fn(f) => f.to_tokens(tokens),
|
||||
Type::Void(span) => tokens.extend(quote_spanned!(*span=> ())),
|
||||
}
|
||||
}
|
||||
@ -80,3 +66,9 @@ impl ToTokens for ExternFn {
|
||||
self.sig.tokens.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for Signature {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
self.tokens.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user