//! Hub for integration tests. use std::fmt; use arithmetic_parser::grammars::NumGrammar; use arithmetic_typing::{ arith::{Constraint, Num, ObjectSafeConstraint, Substitutions}, error::{Error, ErrorKind, Errors, OpErrors}, visit::Visit, Annotated, DynConstraints, Function, PrimitiveType, Type, UnknownLen, }; mod annotations; mod basics; mod errors; mod examples; mod length_eqs; mod object; type F32Grammar = Annotated>; trait ErrorsExt { fn single(self) -> Error; } impl ErrorsExt for Errors { fn single(self) -> Error { if self.len() == 1 { self.into_iter().next().unwrap() } else { panic!("Expected 1 error, got {self:?}"); } } } /// Constraint for types that can be hashed. #[derive(Debug, Clone, Copy)] struct Hashed; impl fmt::Display for Hashed { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str("Hash") } } impl Constraint for Hashed { fn visitor<'r>( &self, substitutions: &'r mut Substitutions, errors: OpErrors<'r, Prim>, ) -> Box + 'r> { use arithmetic_typing::arith::StructConstraint; StructConstraint::new(*self, |_| true).visitor(substitutions, errors) } fn clone_boxed(&self) -> Box> { Box::new(*self) } } impl ObjectSafeConstraint for Hashed {} fn assert_incompatible_types( err: &ErrorKind, first: &Type, second: &Type, ) { let ErrorKind::TypeMismatch(x, y) = err else { panic!("Unexpected error type: {err:?}"); }; assert!( (x == first && y == second) || (x == second && y == first), "Unexpected incompatible types: {:?}, expected: {:?}", (x, y), (first, second) ); } fn hash_fn_type() -> Function { Function::builder() .with_varargs(DynConstraints::just(Hashed), UnknownLen::param(0)) .returning(Type::NUM) } #[test] fn hash_fn_type_display() { assert_eq!(hash_fn_type().to_string(), "(...[dyn Hash; N]) -> Num"); } /// `zip` function signature. fn zip_fn_type() -> Function { Function::builder() .with_arg(Type::param(0).repeat(UnknownLen::param(0))) .with_arg(Type::param(1).repeat(UnknownLen::param(0))) .returning(Type::slice( (Type::param(0), Type::param(1)), UnknownLen::param(0), )) .with_static_lengths(&[0]) .into() } #[test] fn zip_fn_type_display() { let zip_fn_string = zip_fn_type().to_string(); assert_eq!( zip_fn_string, "for (['T; N], ['U; N]) -> [('T, 'U); N]" ); }