-
-
Save rust-play/eca8908d9bbc474f5a2682fa05db3f31 to your computer and use it in GitHub Desktop.
Code shared from the Rust Playground
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 characters
| #![feature(tuple_trait)] | |
| #![feature(fn_traits)] | |
| #![feature(type_alias_impl_trait)] | |
| #![feature(unboxed_closures)] | |
| #![feature(associated_type_defaults)] | |
| trait Spec { | |
| type SpecOwn; | |
| type SpecOut<'a> | |
| where | |
| Self::SpecOwn: 'a; | |
| type SpecArgs<'a>: std::marker::Tuple = (Self::SpecOut<'a>,) where Self::SpecOwn: 'a; | |
| } | |
| struct Own<A>(std::marker::PhantomData<A>); | |
| impl<A> Spec for Own<A> { | |
| type SpecOwn = A; | |
| type SpecOut<'a> = A where A: 'a; | |
| } | |
| struct Ref<A>(std::marker::PhantomData<A>); | |
| impl<A> Spec for Ref<A> { | |
| type SpecOwn = A; | |
| type SpecOut<'a> = &'a A where A: 'a; | |
| } | |
| /// Spec FnOnce. | |
| trait Sfno<Args: Spec> { | |
| type SfnoOut; | |
| extern "rust-call" fn sfno(self, args: Args::SpecArgs<'_>) -> Self::SfnoOut; | |
| } | |
| struct SfnoWrap<F>(F); | |
| impl<A, B, Imp: FnOnce<(A,), Output = B>> Sfno<Own<A>> for SfnoWrap<Imp> { | |
| type SfnoOut = B; | |
| extern "rust-call" fn sfno(self, args: (A,)) -> B { | |
| self.0.call_once(args) | |
| } | |
| } | |
| impl<A, B, Imp: for<'a> FnOnce<(&'a A,), Output = B>> Sfno<Ref<A>> for SfnoWrap<Imp> { | |
| type SfnoOut = B; | |
| extern "rust-call" fn sfno(self, args: (&A,)) -> B { | |
| self.0.call_once(args) | |
| } | |
| } | |
| struct DummySfno<A, B>(std::marker::PhantomData<(A, B)>); | |
| impl<A: Spec, B> Sfno<A> for DummySfno<A, B> { | |
| type SfnoOut = B; | |
| extern "rust-call" fn sfno(self, _args: A::SpecArgs<'_>) -> B { | |
| unreachable!() | |
| } | |
| } | |
| /// Spec Cont FnOnce Morphism. | |
| trait Scfnom<ScfnomDom: Spec>: Sized { | |
| type ScfnomCod: Spec; | |
| type ScfnomOut<R, F: Sfno<Self::ScfnomCod, SfnoOut = R>>: Sfno<ScfnomDom, SfnoOut = R>; | |
| fn scfnom<R, F: Sfno<Self::ScfnomCod, SfnoOut = R>>(self, f: F) -> Self::ScfnomOut<R, F>; | |
| } | |
| struct DummyScfnom<A, B>(std::marker::PhantomData<(A, B)>); | |
| impl<A: Spec, B: Spec> Scfnom<A> for DummyScfnom<A, B> { | |
| type ScfnomCod = B; | |
| type ScfnomOut<R, F: Sfno<Self::ScfnomCod, SfnoOut = R>> = DummySfno<A, R>; | |
| fn scfnom<R, F: Sfno<Self::ScfnomCod, SfnoOut = R>>(self, _f: F) -> Self::ScfnomOut<R, F> { | |
| unreachable!() | |
| } | |
| } | |
| struct DummyAttic<Dom, Cod>(std::marker::PhantomData<(Dom, Cod)>); | |
| impl<Dom: Spec, Cod: Spec> Attic for DummyAttic<Dom, Cod> { | |
| type Domain = Dom; | |
| type Codomain = Cod; | |
| } | |
| trait Attic: Sized { | |
| type Domain: Spec = Own<()>; | |
| type Codomain: Spec = Own<()>; | |
| type SfnoSol: Sfno<Self::Domain, SfnoOut = <Self::Codomain as Spec>::SpecOwn> = | |
| DummySfno<Self::Domain, <Self::Codomain as Spec>::SpecOwn>; | |
| type ScfnomSol: Scfnom<Self::Domain, ScfnomCod = Self::Codomain> = | |
| DummyScfnom<Self::Domain, Self::Codomain>; | |
| type Clause: Clause = (); | |
| type Scrap: Attic< | |
| Domain = <Self::Clause as Clause>::Dom<Self>, | |
| Codomain = <Self::Clause as Clause>::Cod<Self>, | |
| > = DummyAttic<<Self::Clause as Clause>::Dom<Self>, <Self::Clause as Clause>::Cod<Self>>; | |
| } | |
| trait Clause: Sized { | |
| type Dom<Att: Attic>: Spec = Att::Domain; | |
| type Cod<Att: Attic>: Spec = Att::Codomain; | |
| } | |
| impl Clause for () {} | |
| trait Cursor: Sized { | |
| type BlockSol<Att: Attic<Clause = Self::Clause>>; | |
| type ReturnSol<Att: Attic<Clause = Self::Clause>>; | |
| type Clause: Clause = (); | |
| } | |
| type BlockSolOf<Cur, Att> = <Cur as Cursor>::BlockSol<Att>; | |
| type ReturnSolOf<Cur, Att> = <Cur as Cursor>::ReturnSol<Att>; | |
| trait IdOp: Cursor { | |
| type IdOpAtt<A: Spec>: Attic<Clause = Self::Clause, Domain = A, Codomain = A>; | |
| fn id_op<A: Spec>(self) -> (Self, BlockSolOf<Self, Self::IdOpAtt<A>>); | |
| } | |
| trait CatOp: Cursor { | |
| type CatOpAtt<_1, _2>: Attic< | |
| Clause = Self::Clause, | |
| Domain = _1::Domain, | |
| Codomain = _2::Codomain, | |
| > | |
| where | |
| _1: Attic<Clause = Self::Clause>, | |
| _2: Attic<Clause = Self::Clause, Domain = _1::Codomain>; | |
| fn cat_op<_1, _2>( | |
| self, | |
| lhs: BlockSolOf<Self, _1>, | |
| rhs: BlockSolOf<Self, _2>, | |
| ) -> (Self, BlockSolOf<Self, Self::CatOpAtt<_1, _2>>) | |
| where | |
| _1: Attic<Clause = Self::Clause>, | |
| _2: Attic<Clause = Self::Clause, Domain = _1::Codomain>; | |
| } | |
| trait ArrOp: Cursor { | |
| type ArrOpAtt<A: Spec, B: Spec, F: Scfnom<A, ScfnomCod = B>>: Attic< | |
| Clause = Self::Clause, | |
| Domain = A, | |
| Codomain = B, | |
| >; | |
| #[allow(clippy::type_complexity)] | |
| fn arr_op<A: Spec, B: Spec, F: Scfnom<A, ScfnomCod = B>>( | |
| self, | |
| f: F, | |
| ) -> (Self, BlockSolOf<Self, Self::ArrOpAtt<A, B, F>>); | |
| } | |
| trait AsRefOp: Cursor { | |
| type AsRefOpAtt<A, _1>: Attic<Clause = Self::Clause, Domain = Own<A>, Codomain = _1::Codomain> | |
| where | |
| _1: Attic<Clause = Self::Clause, Domain = Ref<A>>; | |
| #[allow(clippy::wrong_self_convention)] | |
| fn as_ref_op<A, _1>( | |
| self, | |
| arg: BlockSolOf<Self, _1>, | |
| ) -> (Self, BlockSolOf<Self, Self::AsRefOpAtt<A, _1>>) | |
| where | |
| _1: Attic<Clause = Self::Clause, Domain = Ref<A>>; | |
| } | |
| trait ReturnOp: Cursor { | |
| type ReturnOpAtt<A, _1: Attic<Clause = Self::Clause, Codomain = Own<A>>>: Attic< | |
| Clause = Self::Clause, | |
| Domain = _1::Domain, | |
| Codomain = Own<A>, | |
| >; | |
| fn return_op<A, _1: Attic<Clause = Self::Clause, Codomain = Own<A>>>( | |
| self, | |
| blk: BlockSolOf<Self, _1>, | |
| ) -> (Self, ReturnSolOf<Self, Self::ReturnOpAtt<A, _1>>); | |
| } | |
| macro_rules! decl_cfnom { | |
| ($Name:ident $self:ident $f:ident [$($q:tt)*] [$($A:tt)*] [$($B:tt)*] [$($code:tt)*]) => { | |
| struct $Name; | |
| const _: () = { | |
| impl $($q)* Scfnom<$($A)*> for $Name { | |
| type ScfnomCod = $($B)*; | |
| type ScfnomOut<R, F: Sfno<Self::ScfnomCod, SfnoOut = R>> = impl Sfno<$($A)*, SfnoOut = R>; | |
| fn scfnom<R, F: Sfno<Self::ScfnomCod, SfnoOut = R>>(self, $f: F) -> Self::ScfnomOut<R, F> { | |
| $($code)* | |
| } | |
| } | |
| }; | |
| } | |
| } | |
| fn main() { | |
| use rand::Rng; | |
| let mut rng = rand::thread_rng(); | |
| let x: u32 = rng.gen(); | |
| println!("{}", program_asm(x >> 2)); | |
| } | |
| #[inline(never)] | |
| pub extern "C" fn program_asm(a: u32) -> u64 { | |
| let (_, b) = program(MyCursor); | |
| b.sfno((a,)) | |
| } | |
| fn program<Cur>( | |
| cur: Cur, | |
| ) -> ( | |
| Cur, | |
| ReturnSolOf<Cur, impl Attic<Clause = Cur::Clause, Domain = Own<u32>, Codomain = Own<u64>>>, | |
| ) | |
| where | |
| Cur: IdOp + CatOp + ArrOp + AsRefOp + ReturnOp, | |
| { | |
| decl_cfnom! { Cfn01 self f [] [Own<u32>] [Own<(u32,u64,u128)>] [ | |
| SfnoWrap(|dom: u32| f.sfno((((dom + 11) * 22, ((dom + 33) as u64) * 44, ((dom + 55) as u128) * 66),))) | |
| ]} | |
| let (cur, cratic_a) = cur.arr_op(Cfn01); | |
| decl_cfnom! { Cfn02 self f [] [Ref<(u32,u64,u128)>] [Own<u64>] [ | |
| SfnoWrap(|dom: &(u32,u64,u128)| f.sfno((dom.0 as u64 + dom.1 + dom.2 as u64 + 77_u64,))) | |
| ]} | |
| let (cur, cratic_b) = cur.arr_op(Cfn02); | |
| let (cur, cratic_c) = cur.as_ref_op(cratic_b); | |
| let (cur, cratic_d) = cur.id_op(); | |
| let (cur, cratic_e) = cur.cat_op(cratic_a, cratic_c); | |
| let (cur, cratic_f) = cur.cat_op(cratic_e, cratic_d); | |
| let (cur, cratic) = cur.return_op(cratic_f); | |
| (cur, cratic) | |
| } | |
| struct MyCursor; | |
| impl Cursor for MyCursor { | |
| type BlockSol<Att: Attic<Clause = Self::Clause>> = Att::ScfnomSol; | |
| type ReturnSol<Att: Attic<Clause = Self::Clause>> = Att::SfnoSol; | |
| } | |
| const _: () = { | |
| struct Scfn; | |
| impl<A: Spec> Scfnom<A> for Scfn { | |
| type ScfnomCod = A; | |
| type ScfnomOut<R, F: Sfno<Self::ScfnomCod, SfnoOut = R>> = impl Sfno<A, SfnoOut = R>; | |
| fn scfnom<R, F: Sfno<Self::ScfnomCod, SfnoOut = R>>(self, f: F) -> Self::ScfnomOut<R, F> { | |
| f | |
| } | |
| } | |
| struct Att<A>(std::marker::PhantomData<A>); | |
| impl<A: Spec> Attic for Att<A> { | |
| type Domain = A; | |
| type Codomain = A; | |
| type ScfnomSol = Scfn; | |
| } | |
| impl IdOp for MyCursor { | |
| type IdOpAtt<A: Spec> = Att<A>; | |
| fn id_op<A: Spec>(self) -> (Self, Scfn) { | |
| (self, Scfn) | |
| } | |
| } | |
| }; | |
| const _: () = { | |
| struct Scfn<_1, _2>(BlockSolOf<MyCursor, _1>, BlockSolOf<MyCursor, _2>) | |
| where | |
| _1: Attic<Clause = ()>, | |
| _2: Attic<Clause = (), Domain = _1::Codomain>; | |
| impl<_1, _2> Scfnom<_1::Domain> for Scfn<_1, _2> | |
| where | |
| _1: Attic<Clause = ()>, | |
| _2: Attic<Clause = (), Domain = _1::Codomain>, | |
| { | |
| type ScfnomCod = _2::Codomain; | |
| type ScfnomOut<R, F: Sfno<Self::ScfnomCod, SfnoOut = R>> = | |
| impl Sfno<_1::Domain, SfnoOut = R>; | |
| fn scfnom<R, F: Sfno<Self::ScfnomCod, SfnoOut = R>>(self, f: F) -> Self::ScfnomOut<R, F> { | |
| self.0.scfnom(self.1.scfnom(f)) | |
| } | |
| } | |
| struct Att<_1, _2>(std::marker::PhantomData<(_1, _2)>); | |
| impl<_1, _2> Attic for Att<_1, _2> | |
| where | |
| _1: Attic<Clause = ()>, | |
| _2: Attic<Clause = (), Domain = _1::Codomain>, | |
| { | |
| type Domain = _1::Domain; | |
| type Codomain = _2::Codomain; | |
| type ScfnomSol = Scfn<_1, _2>; | |
| } | |
| impl CatOp for MyCursor { | |
| type CatOpAtt<_1, _2> = Att<_1, _2> | |
| where | |
| _1: Attic<Clause = Self::Clause>, | |
| _2: Attic<Clause = Self::Clause, Domain = _1::Codomain>; | |
| fn cat_op<_1, _2>( | |
| self, | |
| lhs: BlockSolOf<Self, _1>, | |
| rhs: BlockSolOf<Self, _2>, | |
| ) -> (Self, BlockSolOf<Self, Self::CatOpAtt<_1, _2>>) | |
| where | |
| _1: Attic<Clause = Self::Clause>, | |
| _2: Attic<Clause = Self::Clause, Domain = _1::Codomain>, | |
| { | |
| (Self, Scfn::<_1, _2>(lhs, rhs)) | |
| } | |
| } | |
| }; | |
| const _: () = { | |
| struct Att<A, B, F>(std::marker::PhantomData<(A, B, F)>); | |
| impl<A: Spec, B: Spec, F: Scfnom<A, ScfnomCod = B>> Attic for Att<A, B, F> { | |
| type Domain = A; | |
| type Codomain = B; | |
| type ScfnomSol = F; | |
| } | |
| impl ArrOp for MyCursor { | |
| type ArrOpAtt<A: Spec, B: Spec, F: Scfnom<A, ScfnomCod = B>> = Att<A, B, F>; | |
| fn arr_op<A: Spec, B: Spec, F: Scfnom<A, ScfnomCod = B>>(self, f: F) -> (Self, F) { | |
| (self, f) | |
| } | |
| } | |
| }; | |
| const _: () = { | |
| struct Scfn<_1: Attic<Clause = ()>>(BlockSolOf<MyCursor, _1>); | |
| impl<A, _1> Scfnom<Own<A>> for Scfn<_1> | |
| where | |
| _1: Attic<Clause = (), Domain = Ref<A>>, | |
| { | |
| type ScfnomCod = _1::Codomain; | |
| type ScfnomOut<R, F: Sfno<Self::ScfnomCod, SfnoOut = R>> = impl Sfno<Own<A>, SfnoOut = R>; | |
| fn scfnom<R, F: Sfno<Self::ScfnomCod, SfnoOut = R>>(self, f: F) -> Self::ScfnomOut<R, F> { | |
| SfnoWrap(|dom| self.0.scfnom(f).sfno((&dom,))) | |
| } | |
| } | |
| struct Att<A, _1>(std::marker::PhantomData<(A, _1)>); | |
| impl<A, _1> Attic for Att<A, _1> | |
| where | |
| _1: Attic<Clause = (), Domain = Ref<A>>, | |
| { | |
| type Domain = Own<A>; | |
| type Codomain = _1::Codomain; | |
| type ScfnomSol = Scfn<_1>; | |
| } | |
| impl AsRefOp for MyCursor { | |
| type AsRefOpAtt<A, _1> = Att<A, _1> | |
| where | |
| _1: Attic<Clause = Self::Clause, Domain = Ref<A>>; | |
| fn as_ref_op<A, _1>( | |
| self, | |
| arg: BlockSolOf<Self, _1>, | |
| ) -> (Self, BlockSolOf<Self, Self::AsRefOpAtt<A, _1>>) | |
| where | |
| _1: Attic<Clause = Self::Clause, Domain = Ref<A>>, | |
| { | |
| (self, Scfn::<_1>(arg)) | |
| } | |
| } | |
| }; | |
| const _: () = { | |
| struct Att<A, _1, F>(std::marker::PhantomData<(A, _1, F)>); | |
| impl<A, _1, F> Attic for Att<A, _1, F> | |
| where | |
| _1: Attic<Clause = (), Codomain = Own<A>>, | |
| F: Sfno<_1::Domain, SfnoOut = A>, | |
| { | |
| type Domain = _1::Domain; | |
| type Codomain = Own<A>; | |
| type SfnoSol = F; | |
| } | |
| impl ReturnOp for MyCursor { | |
| type ReturnOpAtt<A, _1: Attic<Clause = Self::Clause, Codomain = Own<A>>> = | |
| Att<A, _1, impl Sfno<_1::Domain, SfnoOut = A>>; | |
| fn return_op<A, _1: Attic<Clause = Self::Clause, Codomain = Own<A>>>( | |
| self, | |
| blk: BlockSolOf<Self, _1>, | |
| ) -> (Self, ReturnSolOf<Self, Self::ReturnOpAtt<A, _1>>) { | |
| (self, blk.scfnom(SfnoWrap(|a: A| a))) | |
| } | |
| } | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment