// 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