Last active
October 11, 2019 13:17
-
-
Save Hywan/ce725569fd3534adee5f6f8d90f67a36 to your computer and use it in GitHub Desktop.
Revisions
-
Hywan revised this gist
Oct 11, 2019 . 1 changed file with 105 additions and 6 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,4 +1,4 @@ use std::{convert::TryFrom, fmt::Debug}; pub trait WitValue where @@ -19,16 +19,20 @@ pub trait WitCall<Func, Inputs> { macro_rules! do_it { ( $($x:ident),* ) => { // Implement `Function` for `Func` impl< Func $( , $x )* > Function<Func, ( $( $x ),* )> for Func where Func: Fn( $( $x ),* ), $( $x: WitValue ),* { fn to_callable(&self) -> &Func { println!("size of me {}", ::std::mem::size_of::<Self>()); println!("size of usize {}", ::std::mem::size_of::<usize>()); self } } // Implement `WitCall` for tuples. impl< Func $( , $x )* > WitCall<Func, ( $( $x ),* )> for ( $( $x ),* ) where Func: Fn( $( $x ),* ), @@ -42,12 +46,13 @@ macro_rules! do_it { } } // Implement `call` on `dyn Function`. impl<Func $( , $x )*> dyn Function<Func, ( $( $x ),* )> where Func: Fn( $( $x ),* ), $( $x: WitValue ),* { #[allow(dead_code, non_snake_case)] fn call(&self $( , $x: $x )*) { ( $( $x ),* ).call(self); } @@ -71,7 +76,7 @@ do_it!(A, B, C, D, E, F, G, H, I, J, K, L); #[cfg(test)] #[test] fn test_functions() { // arity 0 ().call(&|| { @@ -85,23 +90,117 @@ fn main() { // arity 1 (42).call(&|a: i32| { println!("{:?}", a); }); let f1: &dyn Function<_, _> = &|a: i32| { println!("~~~> {:?}", a); }; f1.call(42); // arity 2 (1, 2).call(&|a: i32, b: i32| { println!("{:?}, {:?}", a, b); }); let f2: &dyn Function<_, _> = &|a: i32, b: i32| { println!("~~~> {:?}, {:?}", a, b); }; f2.call(1, 2); } pub enum Ty { I32, I64, F32, F64, } #[derive(Debug)] pub enum Value { I32(i32), I64(i64), F32(f32), F64(f64), } macro_rules! impl_value { ($native_type:ty, $value_variant:ident) => { impl TryFrom<&Value> for $native_type { type Error = &'static str; fn try_from(w: &Value) -> Result<Self, Self::Error> { match w { Value::$value_variant(n) => Ok(n.clone()), _ => Err("Invalid cast."), } } } }; } impl_value!(i32, I32); impl_value!(i64, I64); impl_value!(f32, F32); impl_value!(f64, F64); #[allow(unused)] macro_rules! any_to_value { ($variable:ident, $expected_ty:expr) => {{ use std::convert::TryInto; let value: Value = { let var_ref: &dyn Any = &$variable; match $expected_ty { Ty::I32 => var_ref .downcast_ref::<i32>() .and_then(|v| Some(Value::I32(*v))), Ty::I64 => var_ref .downcast_ref::<i64>() .and_then(|v| Some(Value::I64(*v))), Ty::F32 => var_ref .downcast_ref::<f32>() .and_then(|v| Some(Value::F32(*v))), Ty::F64 => var_ref .downcast_ref::<f64>() .and_then(|v| Some(Value::F64(*v))), } } .expect(&format!( "Failed to downcast the value of `{}`.", stringify!($variable) )); (&value).try_into().expect("Failed to cast.") }}; } #[cfg(test)] #[test] fn test_dynamically_typed_functions() { use std::any::Any; // more fun with dynamically typed inputs fn f<A, B>() -> impl Fn(A, B) where A: Any + WitValue, B: Any + WitValue, { let a_expected_type = Ty::I32; let b_expected_type = Ty::I32; move |a: A, b: B| { let a: i32 = any_to_value!(a, a_expected_type); let b: i32 = any_to_value!(b, b_expected_type); println!("~~~> {:?} + {:?} = {:?}", a, b, a + b); } } let f2: &dyn Function<_, _> = &f(); f2.call(1i32, 2i32); } -
Hywan revised this gist
Oct 11, 2019 . 1 changed file with 35 additions and 23 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -2,12 +2,12 @@ use std::fmt::Debug; pub trait WitValue where Self: Sized + Debug + Copy, { } impl WitValue for i32 {} impl WitValue for f32 {} pub trait Function<Func, Inputs> { fn to_callable(&self) -> &Func; @@ -19,20 +19,20 @@ pub trait WitCall<Func, Inputs> { macro_rules! do_it { ( $($x:ident),* ) => { impl< Func $( , $x )* > Function<Func, ( $( $x ),* )> for Func where Func: Fn( $( $x ),* ), $( $x: WitValue ),* { fn to_callable(&self) -> &Func { self } } impl< Func $( , $x )* > WitCall<Func, ( $( $x ),* )> for ( $( $x ),* ) where Func: Fn( $( $x ),* ), $( $x: WitValue ),* { #[allow(non_snake_case, unused_parens)] fn call(self, function: &dyn Function<Func, ( $( $x ),* )>) { @@ -41,6 +41,17 @@ macro_rules! do_it { function( $( $x ),* ) } } impl<Func $( , $x )*> dyn Function<Func, ( $( $x ),* )> where Func: Fn( $( $x ),* ), $( $x: WitValue ),* { #[allow(non_snake_case)] fn call(&self $( , $x: $x )*) { ( $( $x ),* ).call(self); } } } } @@ -56,40 +67,41 @@ do_it!(A, B, C, D, E, F, G, H); do_it!(A, B, C, D, E, F, G, H, I); do_it!(A, B, C, D, E, F, G, H, I, J); do_it!(A, B, C, D, E, F, G, H, I, J, K); do_it!(A, B, C, D, E, F, G, H, I, J, K, L); #[cfg(test)] #[test] fn main() { // arity 0 ().call(&|| { println!("()"); }); let f0: &dyn Function<_, _> = &|| { println!("~~~> ()"); }; f0.call(); // arity 1 (42i32).call(&|a: i32| { println!("{:?}", a); }); let f1: &dyn Function<_, _> = &|a: i32| { println!("~~~> {:?}", a); }; f1.call(42i32); // arity 2 (1i32, 2i32).call(&|a: i32, b: i32| { println!("{:?}, {:?}", a, b); }); let f2: &dyn Function<_, _> = &|a: i32, b: i32| { println!("~~~> {:?}, {:?}", a, b); }; f2.call(1i32, 2i32); } -
Hywan created this gist
Oct 7, 2019 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,95 @@ use std::fmt::Debug; pub trait WitValue where Self: Debug, { } impl WitValue for i32 {} impl WitValue for u32 {} pub trait Function<Func, Inputs> { fn to_callable(&self) -> &Func; } pub trait WitCall<Func, Inputs> { fn call(self, function: &dyn Function<Func, Inputs>); } macro_rules! do_it { ( $($x:ident),* ) => { impl< Func $( ,$x )* > Function<Func, ( $( $x ),* )> for Func where Func: Fn( $( $x ),* ) $( ,$x: WitValue )* { fn to_callable(&self) -> &Func { self } } impl< Func $( ,$x )* > WitCall<Func, ( $( $x ),* )> for ( $( $x ),* ) where Func: Fn( $( $x ),* ) $( ,$x: WitValue )* { #[allow(non_snake_case, unused_parens)] fn call(self, function: &dyn Function<Func, ( $( $x ),* )>) { let function: &dyn Fn( $( $x ),* ) = function.to_callable(); let ( $( $x ),* ) = self; function( $( $x ),* ) } } } } do_it!(); do_it!(A); do_it!(A, B); do_it!(A, B, C); do_it!(A, B, C, D); do_it!(A, B, C, D, E); do_it!(A, B, C, D, E, F); do_it!(A, B, C, D, E, F, G); do_it!(A, B, C, D, E, F, G, H); do_it!(A, B, C, D, E, F, G, H, I); do_it!(A, B, C, D, E, F, G, H, I, J); do_it!(A, B, C, D, E, F, G, H, I, J, K); pub fn call<InputTypes, InputValues, Func>( inputs: InputValues, function: &dyn Function<Func, InputTypes>, ) where InputValues: WitCall<Func, InputTypes>, { inputs.call(function); } #[cfg(test)] #[test] fn main() { ().call(&|| { println!("()"); }); call((), &|| { println!("~~~> ()"); }); (42i32).call(&|a: i32| { println!("{:?}", a); }); call(42i32, &|a: i32| { println!("~~~> {:?}", a); }); (1i32, 2i32).call(&|a: i32, b: i32| { println!("{:?}, {:?}", a, b); }); call((1i32, 2i32), &|a: i32, b: i32| { println!("~~~> {:?}, {:?}", a, b); }); }