Small optimization for ArgumentSignature from ArgList

This commit is contained in:
Gino Valente 2024-12-07 17:34:11 -07:00
parent a6121d62f9
commit f93aadd0dd
2 changed files with 78 additions and 6 deletions

View file

@ -1,4 +1,4 @@
use crate::func::signature::ArgumentSignature; use crate::func::signature::{ArgListSignature, ArgumentSignature};
use crate::func::{ArgList, FunctionError, FunctionInfo, FunctionOverloadError}; use crate::func::{ArgList, FunctionError, FunctionInfo, FunctionOverloadError};
use alloc::borrow::Cow; use alloc::borrow::Cow;
use bevy_utils::hashbrown::HashMap; use bevy_utils::hashbrown::HashMap;
@ -62,13 +62,13 @@ impl<F> DynamicFunctionInternal<F> {
return Ok(&self.functions[0]); return Ok(&self.functions[0]);
} }
let signature = ArgumentSignature::from(args); let signature = ArgListSignature::from(args);
self.arg_map self.arg_map
.get(&signature) .get(&signature)
.map(|index| &self.functions[*index]) .map(|index| &self.functions[*index])
.ok_or_else(|| FunctionError::NoOverload { .ok_or_else(|| FunctionError::NoOverload {
expected: self.arg_map.keys().cloned().collect(), expected: self.arg_map.keys().cloned().collect(),
received: signature, received: ArgumentSignature::from(args),
}) })
} }
@ -83,13 +83,13 @@ impl<F> DynamicFunctionInternal<F> {
return Ok(&mut self.functions[0]); return Ok(&mut self.functions[0]);
} }
let signature = ArgumentSignature::from(args); let signature = ArgListSignature::from(args);
self.arg_map self.arg_map
.get(&signature) .get(&signature)
.map(|index| &mut self.functions[*index]) .map(|index| &mut self.functions[*index])
.ok_or_else(|| FunctionError::NoOverload { .ok_or_else(|| FunctionError::NoOverload {
expected: self.arg_map.keys().cloned().collect(), expected: self.arg_map.keys().cloned().collect(),
received: signature, received: ArgumentSignature::from(args),
}) })
} }

View file

@ -14,8 +14,10 @@
use crate::func::args::ArgInfo; use crate::func::args::ArgInfo;
use crate::func::{ArgList, SignatureInfo}; use crate::func::{ArgList, SignatureInfo};
use crate::Type; use crate::Type;
use bevy_utils::hashbrown::Equivalent;
use core::borrow::Borrow; use core::borrow::Borrow;
use core::fmt::{Debug, Formatter}; use core::fmt::{Debug, Formatter};
use core::hash::{Hash, Hasher};
use core::ops::{Deref, DerefMut}; use core::ops::{Deref, DerefMut};
/// The signature of a function. /// The signature of a function.
@ -57,13 +59,69 @@ impl<T: Borrow<SignatureInfo>> From<T> for Signature {
} }
} }
/// A wrapper around a borrowed [`ArgList`] that can be used as an
/// [equivalent] of an [`ArgumentSignature`].
///
/// [equivalent]: Equivalent
pub(super) struct ArgListSignature<'a, 'b>(&'a ArgList<'b>);
impl Equivalent<ArgumentSignature> for ArgListSignature<'_, '_> {
fn equivalent(&self, key: &ArgumentSignature) -> bool {
self.len() == key.len() && self.iter().eq(key.iter())
}
}
impl<'a, 'b> ArgListSignature<'a, 'b> {
pub fn iter(&self) -> impl ExactSizeIterator<Item = &Type> {
self.0.iter().map(|arg| {
arg.value()
.get_represented_type_info()
.unwrap_or_else(|| {
panic!("no `TypeInfo` found for argument: {:?}", arg);
})
.ty()
})
}
pub fn len(&self) -> usize {
self.0.len()
}
}
impl Eq for ArgListSignature<'_, '_> {}
impl PartialEq for ArgListSignature<'_, '_> {
fn eq(&self, other: &Self) -> bool {
self.len() == other.len() && self.iter().eq(other.iter())
}
}
impl Hash for ArgListSignature<'_, '_> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.iter().for_each(|arg| {
arg.value()
.get_represented_type_info()
.unwrap_or_else(|| {
panic!("no `TypeInfo` found for argument: {:?}", arg);
})
.ty()
.hash(state);
});
}
}
impl<'a, 'b> From<&'a ArgList<'b>> for ArgListSignature<'a, 'b> {
fn from(args: &'a ArgList<'b>) -> Self {
Self(args)
}
}
/// The argument-portion of a function signature. /// The argument-portion of a function signature.
/// ///
/// For example, given a function signature `(a: i32, b: f32) -> u32`, /// For example, given a function signature `(a: i32, b: f32) -> u32`,
/// the argument signature would be `(i32, f32)`. /// the argument signature would be `(i32, f32)`.
/// ///
/// This can be used as a way to compare or hash functions based on their arguments. /// This can be used as a way to compare or hash functions based on their arguments.
#[derive(Clone, PartialEq, Eq, Hash)] #[derive(Clone)]
pub struct ArgumentSignature(Box<[Type]>); pub struct ArgumentSignature(Box<[Type]>);
impl Debug for ArgumentSignature { impl Debug for ArgumentSignature {
@ -90,6 +148,20 @@ impl DerefMut for ArgumentSignature {
} }
} }
impl Eq for ArgumentSignature {}
impl PartialEq for ArgumentSignature {
fn eq(&self, other: &Self) -> bool {
self.0.len() == other.0.len() && self.0.iter().eq(other.0.iter())
}
}
impl Hash for ArgumentSignature {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.iter().for_each(|ty| ty.hash(state));
}
}
impl FromIterator<Type> for ArgumentSignature { impl FromIterator<Type> for ArgumentSignature {
fn from_iter<T: IntoIterator<Item = Type>>(iter: T) -> Self { fn from_iter<T: IntoIterator<Item = Type>>(iter: T) -> Self {
Self(iter.into_iter().collect()) Self(iter.into_iter().collect())