#![feature(step_trait)] #![feature(type_alias_impl_trait)] #![feature(impl_trait_in_assoc_type)] #![feature(const_precise_live_drops)] #![feature(type_changing_struct_update)] #![feature(anonymous_lifetime_in_impl_trait)] #![feature(const_option_ops)] #![feature(const_trait_impl)] #![feature(const_default)] #![feature(trait_alias)] //#![feature(non_lifetime_binders)] pub(crate) use self::Direction::*; pub(crate) use std::fmt::{Debug, Display}; pub(crate) use std::ops::{Add, Sub, Mul, Div}; pub(crate) use std::sync::{Arc, RwLock, atomic::{AtomicUsize, Ordering::Relaxed}}; pub(crate) use std::marker::PhantomData; pub(crate) use dizzle::*; mod out_macros; // Must be defined first mod out_traits; pub use self::out_traits::*; mod out_structs; pub use self::out_structs::*; mod out_impls; pub use self::out_impls::*; mod widget; pub use self::widget::*; mod layout; pub use self::layout::*; #[cfg(test)] mod out_tests; #[cfg(feature = "dsl")] pub fn evaluate_output_expression <'a, O: Out + 'a, S> ( state: &S, output: &mut O, expr: &'a impl Expression ) -> Usually where S: View + for<'b>Namespace<'b, bool> + for<'b>Namespace<'b, O::Unit> { // First element of expression is used for dispatch. // Dispatch is proto-namespaced using separator character let head = expr.head()?; let mut frags = head.src()?.unwrap_or_default().split("/"); // The rest of the tokens in the expr are arguments. // Their meanings depend on the dispatched operation let args = expr.tail(); let arg0 = args.head(); let tail0 = args.tail(); let arg1 = tail0.head(); let tail1 = tail0.tail(); let arg2 = tail1.head(); // And we also have to do the above binding dance // so that the Perhapss remain in scope. match frags.next() { Some("when") => output.place(&When::new( state.resolve(arg0?)?.unwrap(), Thunk::new(move|output: &mut O|state.view(output, &arg1).unwrap()) )), Some("either") => output.place(&Either::new( state.resolve(arg0?)?.unwrap(), Thunk::new(move|output: &mut O|state.view(output, &arg1).unwrap()), Thunk::new(move|output: &mut O|state.view(output, &arg2).unwrap()) )), Some("bsp") => output.place(&{ let a = Thunk::new(move|output: &mut O|state.view(output, &arg0).unwrap()); let b = Thunk::new(move|output: &mut O|state.view(output, &arg1).unwrap()); match frags.next() { Some("n") => Bsp::n(a, b), Some("s") => Bsp::s(a, b), Some("e") => Bsp::e(a, b), Some("w") => Bsp::w(a, b), Some("a") => Bsp::a(a, b), Some("b") => Bsp::b(a, b), frag => unimplemented!("bsp/{frag:?}") } }), Some("align") => output.place(&{ let a = Thunk::new(move|output: &mut O|state.view(output, &arg0).unwrap()); match frags.next() { Some("n") => Align::n(a), Some("s") => Align::s(a), Some("e") => Align::e(a), Some("w") => Align::w(a), Some("x") => Align::x(a), Some("y") => Align::y(a), Some("c") => Align::c(a), frag => unimplemented!("align/{frag:?}") } }), Some("fill") => output.place(&{ let a = Thunk::new(move|output: &mut O|state.view(output, &arg0).unwrap()); match frags.next() { Some("xy") | None => Fill::XY(a), Some("x") => Fill::X(a), Some("y") => Fill::Y(a), frag => unimplemented!("fill/{frag:?}") } }), Some("fixed") => output.place(&{ let axis = frags.next(); let arg = match axis { Some("x") | Some("y") => arg1, Some("xy") | None => arg2, _ => panic!("fixed: unsupported axis {axis:?}") }; let cb = Thunk::new(move|output: &mut O|state.view(output, &arg).unwrap()); match axis { Some("xy") | None => Fixed::XY(state.resolve(arg0?)?.unwrap(), state.resolve(arg1?)?.unwrap(), cb), Some("x") => Fixed::X(state.resolve(arg0?)?.unwrap(), cb), Some("y") => Fixed::Y(state.resolve(arg0?)?.unwrap(), cb), frag => unimplemented!("fixed/{frag:?} ({expr:?}) ({head:?}) ({:?})", head.src()?.unwrap_or_default().split("/").next()) } }), Some("min") => output.place(&{ let axis = frags.next(); let arg = match axis { Some("x") | Some("y") => arg1, Some("xy") | None => arg2, _ => panic!("fixed: unsupported axis {axis:?}") }; let cb = Thunk::new(move|output: &mut O|state.view(output, &arg).unwrap()); match axis { Some("xy") | None => Min::XY(state.resolve(arg0?)?.unwrap(), state.resolve(arg1?)?.unwrap(), cb), Some("x") => Min::X(state.resolve(arg0?)?.unwrap(), cb), Some("y") => Min::Y(state.resolve(arg0?)?.unwrap(), cb), frag => unimplemented!("min/{frag:?}") } }), Some("max") => output.place(&{ let axis = frags.next(); let arg = match axis { Some("x") | Some("y") => arg1, Some("xy") | None => arg2, _ => panic!("fixed: unsupported axis {axis:?}") }; let cb = Thunk::new(move|output: &mut O|state.view(output, &arg).unwrap()); match axis { Some("xy") | None => Max::XY(state.resolve(arg0?)?.unwrap(), state.resolve(arg1?)?.unwrap(), cb), Some("x") => Max::X(state.resolve(arg0?)?.unwrap(), cb), Some("y") => Max::Y(state.resolve(arg0?)?.unwrap(), cb), frag => unimplemented!("max/{frag:?}") } }), Some("push") => output.place(&{ let axis = frags.next(); let arg = match axis { Some("x") | Some("y") => arg1, Some("xy") | None => arg2, _ => panic!("fixed: unsupported axis {axis:?}") }; let cb = Thunk::new(move|output: &mut O|state.view(output, &arg).unwrap()); match axis { Some("xy") | None => Push::XY(state.resolve(arg0?)?.unwrap(), state.resolve(arg1?)?.unwrap(), cb), Some("x") => Push::X(state.resolve(arg0?)?.unwrap(), cb), Some("y") => Push::Y(state.resolve(arg0?)?.unwrap(), cb), frag => unimplemented!("push/{frag:?}") } }), _ => return Ok(false) }; Ok(true) }