mirror of
https://github.com/icewind1991/ivory.git
synced 2026-06-03 10:44:09 +02:00
work towards type hints in function exports
once const traits are a thing the zvaltype can be determined
This commit is contained in:
parent
9c4f3ab8a0
commit
5eb8082d86
3 changed files with 70 additions and 10 deletions
|
|
@ -7,9 +7,7 @@ mod cache;
|
||||||
use proc_macro2::{Span, TokenStream, TokenTree};
|
use proc_macro2::{Span, TokenStream, TokenTree};
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::spanned::Spanned;
|
use syn::spanned::Spanned;
|
||||||
use syn::{
|
use syn::{parse_macro_input, AttributeArgs, FnArg, Ident, Item, ItemFn, LitStr, Pat, ReturnType, Type, parse_str};
|
||||||
parse_macro_input, AttributeArgs, FnArg, Ident, Item, ItemFn, LitStr, Pat, ReturnType, Type,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// See the [crate documentation](index.html) for details
|
/// See the [crate documentation](index.html) for details
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
|
|
@ -34,6 +32,7 @@ pub fn ivory_export(
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct ArgumentDefinition {
|
pub(crate) struct ArgumentDefinition {
|
||||||
name: String,
|
name: String,
|
||||||
|
ty: String,
|
||||||
is_ref: bool,
|
is_ref: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,6 +114,7 @@ fn get_arg_info(arg: FnArg) -> (ArgumentDefinition, Type) {
|
||||||
Pat::Ident(ident_pat) => (
|
Pat::Ident(ident_pat) => (
|
||||||
ArgumentDefinition {
|
ArgumentDefinition {
|
||||||
name: ident_pat.ident.to_string(),
|
name: ident_pat.ident.to_string(),
|
||||||
|
ty: format!("{}", quote!(#arg_type)),
|
||||||
is_ref: ident_pat.by_ref.is_some(),
|
is_ref: ident_pat.by_ref.is_some(),
|
||||||
},
|
},
|
||||||
arg_type,
|
arg_type,
|
||||||
|
|
@ -164,7 +164,7 @@ pub fn ivory_module(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
entry.set_info_func(php_module_info);
|
entry.set_info_func(php_module_info);
|
||||||
|
|
||||||
|
|
||||||
entry.set_functions(&IVORY_FUCTIONS);
|
entry.set_functions(&IVORY_FUNCTIONS);
|
||||||
|
|
||||||
Box::into_raw(entry)
|
Box::into_raw(entry)
|
||||||
}
|
}
|
||||||
|
|
@ -215,7 +215,8 @@ fn get_funcs(funcs: Vec<FunctionDefinition>, span: Span) -> TokenStream {
|
||||||
let arg_defs = func.args.iter().map(|arg| {
|
let arg_defs = func.args.iter().map(|arg| {
|
||||||
let name = &arg.name;
|
let name = &arg.name;
|
||||||
let is_ref = &arg.is_ref;
|
let is_ref = &arg.is_ref;
|
||||||
quote!(::ivory::zend::ArgInfo::new(::ivory::c_str!(#name), false, false, #is_ref))
|
let ty = parse_str::<Type>(&arg.ty).unwrap();
|
||||||
|
quote!(::ivory::zend::ArgInfo::from_type::<#ty>(::ivory::c_str!(#name), #is_ref))
|
||||||
});
|
});
|
||||||
|
|
||||||
if num_args > 0 {
|
if num_args > 0 {
|
||||||
|
|
@ -223,7 +224,7 @@ fn get_funcs(funcs: Vec<FunctionDefinition>, span: Span) -> TokenStream {
|
||||||
::ivory::zend::Function::new_with_args(
|
::ivory::zend::Function::new_with_args(
|
||||||
{concat!(#name, "\0").as_ptr() as *const ::std::os::raw::c_char},
|
{concat!(#name, "\0").as_ptr() as *const ::std::os::raw::c_char},
|
||||||
#name_ident as *const ::std::os::raw::c_void,
|
#name_ident as *const ::std::os::raw::c_void,
|
||||||
&[::ivory::zend::ArgInfo::new(#num_args as *const ::std::os::raw::c_char, false, false, false),
|
&[::ivory::zend::ArgInfo::arg_count(#num_args),
|
||||||
#(#arg_defs),*
|
#(#arg_defs),*
|
||||||
],
|
],
|
||||||
#num_args as u32
|
#num_args as u32
|
||||||
|
|
@ -240,7 +241,7 @@ fn get_funcs(funcs: Vec<FunctionDefinition>, span: Span) -> TokenStream {
|
||||||
});
|
});
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
const IVORY_FUCTIONS: [::ivory::zend::Function; #func_count] = [
|
const IVORY_FUNCTIONS: [::ivory::zend::Function; #func_count] = [
|
||||||
#(#definitions),*,
|
#(#definitions),*,
|
||||||
::ivory::zend::Function::end()
|
::ivory::zend::Function::end()
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
use crate::zend::zval::GetTypeHint;
|
||||||
|
use crate::zend::ZValType;
|
||||||
use std;
|
use std;
|
||||||
use std::os::raw::{c_char, c_uchar, c_void};
|
use std::os::raw::{c_char, c_uchar, c_void};
|
||||||
|
|
||||||
|
|
@ -6,7 +8,9 @@ use std::os::raw::{c_char, c_uchar, c_void};
|
||||||
pub struct ArgInfo {
|
pub struct ArgInfo {
|
||||||
pub name: *const c_char,
|
pub name: *const c_char,
|
||||||
pub class_name: *const c_char,
|
pub class_name: *const c_char,
|
||||||
pub type_hint: c_uchar,
|
// *const c_char
|
||||||
|
pub type_hint: ZValType,
|
||||||
|
// *const c_char
|
||||||
pub pass_by_reference: c_uchar,
|
pub pass_by_reference: c_uchar,
|
||||||
pub allow_null: c_uchar,
|
pub allow_null: c_uchar,
|
||||||
pub is_variadic: c_uchar,
|
pub is_variadic: c_uchar,
|
||||||
|
|
@ -15,6 +19,7 @@ pub struct ArgInfo {
|
||||||
impl ArgInfo {
|
impl ArgInfo {
|
||||||
pub const fn new(
|
pub const fn new(
|
||||||
name: *const c_char,
|
name: *const c_char,
|
||||||
|
ty: ZValType,
|
||||||
allow_null: bool,
|
allow_null: bool,
|
||||||
is_variadic: bool,
|
is_variadic: bool,
|
||||||
by_reference: bool,
|
by_reference: bool,
|
||||||
|
|
@ -22,12 +27,36 @@ impl ArgInfo {
|
||||||
ArgInfo {
|
ArgInfo {
|
||||||
name,
|
name,
|
||||||
class_name: std::ptr::null(),
|
class_name: std::ptr::null(),
|
||||||
type_hint: 0,
|
type_hint: ty,
|
||||||
pass_by_reference: by_reference as c_uchar,
|
pass_by_reference: by_reference as c_uchar,
|
||||||
allow_null: allow_null as c_uchar,
|
allow_null: allow_null as c_uchar,
|
||||||
is_variadic: is_variadic as c_uchar,
|
is_variadic: is_variadic as c_uchar,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn arg_count(count: usize) -> Self {
|
||||||
|
ArgInfo::new(count as *const c_char, ZValType::Undef, false, false, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn from_type<T>(name: *const c_char, is_ref: bool) -> Self {
|
||||||
|
ArgInfo::new(name, ZValType::Undef, false, false, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait GetArgInfo {
|
||||||
|
fn get_arg_info(name: *const c_char, is_ref: bool) -> ArgInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: GetTypeHint> GetArgInfo for T {
|
||||||
|
fn get_arg_info(name: *const c_char, is_ref: bool) -> ArgInfo {
|
||||||
|
ArgInfo::new(name, Self::get_type_hint(), false, false, is_ref)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: GetTypeHint> GetArgInfo for Option<T> {
|
||||||
|
fn get_arg_info(name: *const c_char, is_ref: bool) -> ArgInfo {
|
||||||
|
ArgInfo::new(name, T::get_type_hint(), true, false, is_ref)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ impl ZVal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum ZValType {
|
pub enum ZValType {
|
||||||
Undef = 0,
|
Undef = 0,
|
||||||
|
|
@ -159,6 +159,36 @@ impl Display for ZValType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait GetTypeHint {
|
||||||
|
fn get_type_hint() -> ZValType;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_get_type_hint {
|
||||||
|
($type:ty, $hint:expr) => {
|
||||||
|
impl GetTypeHint for $type {
|
||||||
|
#[inline]
|
||||||
|
fn get_type_hint() -> ZValType {
|
||||||
|
$hint
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_get_type_hint!(String, ZValType::String);
|
||||||
|
impl_get_type_hint!(bool, ZValType::Bool);
|
||||||
|
impl_get_type_hint!(f64, ZValType::Double);
|
||||||
|
impl_get_type_hint!(f32, ZValType::Double);
|
||||||
|
impl_get_type_hint!(u8, ZValType::Long);
|
||||||
|
impl_get_type_hint!(u16, ZValType::Long);
|
||||||
|
impl_get_type_hint!(u32, ZValType::Long);
|
||||||
|
impl_get_type_hint!(u64, ZValType::Long);
|
||||||
|
impl_get_type_hint!(usize, ZValType::Long);
|
||||||
|
impl_get_type_hint!(i8, ZValType::Long);
|
||||||
|
impl_get_type_hint!(i16, ZValType::Long);
|
||||||
|
impl_get_type_hint!(i32, ZValType::Long);
|
||||||
|
impl_get_type_hint!(i64, ZValType::Long);
|
||||||
|
impl_get_type_hint!(isize, ZValType::Long);
|
||||||
|
|
||||||
impl From<ZValType> for u8 {
|
impl From<ZValType> for u8 {
|
||||||
fn from(val: ZValType) -> Self {
|
fn from(val: ZValType) -> Self {
|
||||||
unsafe { transmute(val) }
|
unsafe { transmute(val) }
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue