use crate::{DynConstraints, Function, Object, PrimitiveType, Tuple, TupleLen, Type, TypeVar};
#[allow(unused_variables)]
pub trait Visit<Prim: PrimitiveType> {
fn visit_type(&mut self, ty: &Type<Prim>) {
visit_type(self, ty)
}
fn visit_var(&mut self, var: TypeVar) {
}
fn visit_primitive(&mut self, primitive: &Prim) {
}
fn visit_tuple(&mut self, tuple: &Tuple<Prim>) {
visit_tuple(self, tuple);
}
fn visit_object(&mut self, object: &Object<Prim>) {
visit_object(self, object);
}
fn visit_dyn_constraints(&mut self, constraints: &DynConstraints<Prim>) {
if let Some(object) = &constraints.inner.object {
self.visit_object(object);
}
}
fn visit_function(&mut self, function: &Function<Prim>) {
visit_function(self, function);
}
}
pub fn visit_type<Prim, V>(visitor: &mut V, ty: &Type<Prim>)
where
Prim: PrimitiveType,
V: Visit<Prim> + ?Sized,
{
match ty {
Type::Any => { }
Type::Dyn(constraints) => visitor.visit_dyn_constraints(constraints),
Type::Var(var) => visitor.visit_var(*var),
Type::Prim(primitive) => visitor.visit_primitive(primitive),
Type::Tuple(tuple) => visitor.visit_tuple(tuple),
Type::Object(obj) => visitor.visit_object(obj),
Type::Function(function) => visitor.visit_function(function.as_ref()),
}
}
pub fn visit_tuple<Prim, V>(visitor: &mut V, tuple: &Tuple<Prim>)
where
Prim: PrimitiveType,
V: Visit<Prim> + ?Sized,
{
for (_, ty) in tuple.element_types() {
visitor.visit_type(ty);
}
}
pub fn visit_object<Prim, V>(visitor: &mut V, object: &Object<Prim>)
where
Prim: PrimitiveType,
V: Visit<Prim> + ?Sized,
{
for (_, ty) in object.iter() {
visitor.visit_type(ty);
}
}
pub fn visit_function<Prim, V>(visitor: &mut V, function: &Function<Prim>)
where
Prim: PrimitiveType,
V: Visit<Prim> + ?Sized,
{
visitor.visit_tuple(&function.args);
visitor.visit_type(&function.return_type);
}
#[allow(unused_variables)]
pub trait VisitMut<Prim: PrimitiveType> {
fn visit_type_mut(&mut self, ty: &mut Type<Prim>) {
visit_type_mut(self, ty)
}
fn visit_tuple_mut(&mut self, tuple: &mut Tuple<Prim>) {
visit_tuple_mut(self, tuple);
}
fn visit_object_mut(&mut self, object: &mut Object<Prim>) {
visit_object_mut(self, object);
}
fn visit_dyn_constraints_mut(&mut self, constraints: &mut DynConstraints<Prim>) {
if let Some(object) = &mut constraints.inner.object {
self.visit_object_mut(object);
}
}
fn visit_middle_len_mut(&mut self, len: &mut TupleLen) {
}
fn visit_function_mut(&mut self, function: &mut Function<Prim>) {
visit_function_mut(self, function);
}
}
pub fn visit_type_mut<Prim, V>(visitor: &mut V, ty: &mut Type<Prim>)
where
Prim: PrimitiveType,
V: VisitMut<Prim> + ?Sized,
{
match ty {
Type::Any | Type::Var(_) | Type::Prim(_) => {}
Type::Dyn(constraints) => visitor.visit_dyn_constraints_mut(constraints),
Type::Tuple(tuple) => visitor.visit_tuple_mut(tuple),
Type::Object(obj) => visitor.visit_object_mut(obj),
Type::Function(function) => visitor.visit_function_mut(function.as_mut()),
}
}
pub fn visit_tuple_mut<Prim, V>(visitor: &mut V, tuple: &mut Tuple<Prim>)
where
Prim: PrimitiveType,
V: VisitMut<Prim> + ?Sized,
{
if let Some(middle) = tuple.parts_mut().1 {
visitor.visit_middle_len_mut(middle.len_mut());
}
for ty in tuple.element_types_mut() {
visitor.visit_type_mut(ty);
}
}
pub fn visit_object_mut<Prim, V>(visitor: &mut V, object: &mut Object<Prim>)
where
Prim: PrimitiveType,
V: VisitMut<Prim> + ?Sized,
{
for (_, ty) in object.iter_mut() {
visitor.visit_type_mut(ty);
}
}
pub fn visit_function_mut<Prim, V>(visitor: &mut V, function: &mut Function<Prim>)
where
Prim: PrimitiveType,
V: VisitMut<Prim> + ?Sized,
{
visitor.visit_tuple_mut(&mut function.args);
visitor.visit_type_mut(&mut function.return_type);
}