fn nominalize(env: &mut TypeEnv, path: &mut Vec<TypePath>, t: Type) -> Type {
    match t {
        Type::Opt(ty) => {
            path.push(TypePath::Opt);
            let ty = nominalize(env, path, *ty);
            path.pop();
            Type::Opt(Box::new(ty))
        }
        Type::Vec(ty) => {
            path.push(TypePath::Opt);
            let ty = nominalize(env, path, *ty);
            path.pop();
            Type::Vec(Box::new(ty))
        }
        Type::Record(fs) => {
            if matches!(
                path.last(),
                None | Some(TypePath::VariantField(_)) | Some(TypePath::Id(_))
            ) || is_tuple(&fs)
            {
                let fs: Vec<_> = fs
                    .into_iter()
                    .map(|Field { id, ty }| {
                        path.push(TypePath::RecordField(id.to_string()));
                        let ty = nominalize(env, path, ty);
                        path.pop();
                        Field { id, ty }
                    })
                    .collect();
                Type::Record(fs)
            } else {
                let new_var = path_to_var(path);
                let ty = nominalize(
                    env,
                    &mut vec![TypePath::Id(new_var.clone())],
                    Type::Record(fs),
                );
                env.0.insert(new_var.clone(), ty);
                Type::Var(new_var)
            }
        }
        Type::Variant(fs) => match path.last() {
            None | Some(TypePath::Id(_)) => {
                let fs: Vec<_> = fs
                    .into_iter()
                    .map(|Field { id, ty }| {
                        path.push(TypePath::VariantField(id.to_string()));
                        let ty = nominalize(env, path, ty);
                        path.pop();
                        Field { id, ty }
                    })
                    .collect();
                Type::Variant(fs)
            }
            Some(_) => {
                let new_var = path_to_var(path);
                let ty = nominalize(
                    env,
                    &mut vec![TypePath::Id(new_var.clone())],
                    Type::Variant(fs),
                );
                env.0.insert(new_var.clone(), ty);
                Type::Var(new_var)
            }
        },
        Type::Func(func) => Type::Func(Function {
            modes: func.modes,
            args: func
                .args
                .into_iter()
                .enumerate()
                .map(|(i, ty)| {
                    path.push(TypePath::Func(format!("arg{}", i)));
                    let ty = nominalize(env, path, ty);
                    path.pop();
                    ty
                })
                .collect(),
            rets: func
                .rets
                .into_iter()
                .enumerate()
                .map(|(i, ty)| {
                    path.push(TypePath::Func(format!("ret{}", i)));
                    let ty = nominalize(env, path, ty);
                    path.pop();
                    ty
                })
                .collect(),
        }),
        Type::Service(serv) => Type::Service(
            serv.into_iter()
                .map(|(meth, ty)| {
                    path.push(TypePath::Id(meth.to_string()));
                    let ty = nominalize(env, path, ty);
                    path.pop();
                    (meth, ty)
                })
                .collect(),
        ),
        Type::Class(args, ty) => Type::Class(
            args.into_iter()
                .map(|ty| {
                    path.push(TypePath::Init);
                    let ty = nominalize(env, path, ty);
                    path.pop();
                    ty
                })
                .collect(),
            Box::new(nominalize(env, path, *ty)),
        ),
        _ => t,
    }
}
// Convert structural typing to nominal typing to fit Rust's type system
Convert structural typing to nominal typing to fit Rust's type system
Convert structural typing to nominal typing to fit Rust ' s type system
fn nominalize(env: &mut TypeEnv, path: &mut Vec<TypePath>, t: Type) -> Type {
    match t {
        Type::Opt(ty) => {
            path.push(TypePath::Opt);
            let ty = nominalize(env, path, *ty);
            path.pop();
            Type::Opt(Box::new(ty))
        }
        Type::Vec(ty) => {
            path.push(TypePath::Opt);
            let ty = nominalize(env, path, *ty);
            path.pop();
            Type::Vec(Box::new(ty))
        }
        Type::Record(fs) => {
            if matches!(
                path.last(),
                None | Some(TypePath::VariantField(_)) | Some(TypePath::Id(_))
            ) || is_tuple(&fs)
            {
                let fs: Vec<_> = fs
                    .into_iter()
                    .map(|Field { id, ty }| {
                        path.push(TypePath::RecordField(id.to_string()));
                        let ty = nominalize(env, path, ty);
                        path.pop();
                        Field { id, ty }
                    })
                    .collect();
                Type::Record(fs)
            } else {
                let new_var = path_to_var(path);
                let ty = nominalize(
                    env,
                    &mut vec![TypePath::Id(new_var.clone())],
                    Type::Record(fs),
                );
                env.0.insert(new_var.clone(), ty);
                Type::Var(new_var)
            }
        }
        Type::Variant(fs) => match path.last() {
            None | Some(TypePath::Id(_)) => {
                let fs: Vec<_> = fs
                    .into_iter()
                    .map(|Field { id, ty }| {
                        path.push(TypePath::VariantField(id.to_string()));
                        let ty = nominalize(env, path, ty);
                        path.pop();
                        Field { id, ty }
                    })
                    .collect();
                Type::Variant(fs)
            }
            Some(_) => {
                let new_var = path_to_var(path);
                let ty = nominalize(
                    env,
                    &mut vec![TypePath::Id(new_var.clone())],
                    Type::Variant(fs),
                );
                env.0.insert(new_var.clone(), ty);
                Type::Var(new_var)
            }
        },
        Type::Func(func) => Type::Func(Function {
            modes: func.modes,
            args: func
                .args
                .into_iter()
                .enumerate()
                .map(|(i, ty)| {
                    path.push(TypePath::Func(format!("arg{}", i)));
                    let ty = nominalize(env, path, ty);
                    path.pop();
                    ty
                })
                .collect(),
            rets: func
                .rets
                .into_iter()
                .enumerate()
                .map(|(i, ty)| {
                    path.push(TypePath::Func(format!("ret{}", i)));
                    let ty = nominalize(env, path, ty);
                    path.pop();
                    ty
                })
                .collect(),
        }),
        Type::Service(serv) => Type::Service(
            serv.into_iter()
                .map(|(meth, ty)| {
                    path.push(TypePath::Id(meth.to_string()));
                    let ty = nominalize(env, path, ty);
                    path.pop();
                    (meth, ty)
                })
                .collect(),
        ),
        Type::Class(args, ty) => Type::Class(
            args.into_iter()
                .map(|ty| {
                    path.push(TypePath::Init);
                    let ty = nominalize(env, path, ty);
                    path.pop();
                    ty
                })
                .collect(),
            Box::new(nominalize(env, path, *ty)),
        ),
        _ => t,
    }
}
fn nominalize ( env : & mut TypeEnv , path : & mut Vec < TypePath > , t : Type ) -> Type { match t { Type :: Opt ( ty ) => { path . push ( TypePath :: Opt ) ; let ty = nominalize ( env , path , * ty ) ; path . pop ( ) ; Type :: Opt ( Box :: new ( ty ) ) } Type :: Vec ( ty ) => { path . push ( TypePath :: Opt ) ; let ty = nominalize ( env , path , * ty ) ; path . pop ( ) ; Type :: Vec ( Box :: new ( ty ) ) } Type :: Record ( fs ) => { if matches ! ( path last ( ) None Some ( TypePath VariantField ( ) ) Some ( TypePath Id ( ) ) ) || is_tuple ( & fs ) { let fs : Vec < _ > = fs . into_iter ( ) . map ( | Field { id , ty } | { path . push ( TypePath :: RecordField ( id . to_string ( ) ) ) ; let ty = nominalize ( env , path , ty ) ; path . pop ( ) ; Field { id , ty } } ) . collect ( ) ; Type :: Record ( fs ) } else { let new_var = path_to_var ( path ) ; let ty = nominalize ( env , & mut vec ! [ TypePath Id ( new_var clone ( ) ) ] , Type :: Record ( fs ) , ) ; env . 0 . insert ( new_var . clone ( ) , ty ) ; Type :: Var ( new_var ) } } Type :: Variant ( fs ) => match path . last ( ) { None | Some ( TypePath :: Id ( _ ) ) => { let fs : Vec < _ > = fs . into_iter ( ) . map ( | Field { id , ty } | { path . push ( TypePath :: VariantField ( id . to_string ( ) ) ) ; let ty = nominalize ( env , path , ty ) ; path . pop ( ) ; Field { id , ty } } ) . collect ( ) ; Type :: Variant ( fs ) } Some ( _ ) => { let new_var = path_to_var ( path ) ; let ty = nominalize ( env , & mut vec ! [ TypePath Id ( new_var clone ( ) ) ] , Type :: Variant ( fs ) , ) ; env . 0 . insert ( new_var . clone ( ) , ty ) ; Type :: Var ( new_var ) } } , Type :: Func ( func ) => Type :: Func ( Function { modes : func . modes , args : func . args . into_iter ( ) . enumerate ( ) . map ( | ( i , ty ) | { path . push ( TypePath :: Func ( format ! ( " " i ) ) ) ; let ty = nominalize ( env , path , ty ) ; path . pop ( ) ; ty } ) . collect ( ) , rets : func . rets . into_iter ( ) . enumerate ( ) . map ( | ( i , ty ) | { path . push ( TypePath :: Func ( format ! ( " " i ) ) ) ; let ty = nominalize ( env , path , ty ) ; path . pop ( ) ; ty } ) . collect ( ) , } ) , Type :: Service ( serv ) => Type :: Service ( serv . into_iter ( ) . map ( | ( meth , ty ) | { path . push ( TypePath :: Id ( meth . to_string ( ) ) ) ; let ty = nominalize ( env , path , ty ) ; path . pop ( ) ; ( meth , ty ) } ) . collect ( ) , ) , Type :: Class ( args , ty ) => Type :: Class ( args . into_iter ( ) . map ( | ty | { path . push ( TypePath :: Init ) ; let ty = nominalize ( env , path , ty ) ; path . pop ( ) ; ty } ) . collect ( ) , Box :: new ( nominalize ( env , path , * ty ) ) , ) , _ => t , } }
Convert structural typing to nominal typing to fit Rust's type system
Convert structural typing to nominal typing to fit Rust ' s type system
env
&mut TypeEnv
path
&mut Vec<TypePath>
t
Type
env
&mut TypeEnv
path
&mut Vec<TypePath>
t
Type