fn lower_ty(module: &mut Module, path: &Path, ty: &core::RcType) -> RcType {
    use semantics::Repr;

    // Mirroring `core::Type::repr`
    match *ty.inner {
        core::Type::Var(_, ref var) => lower_ty_var(var),
        core::Type::Const(ty_const) => Type::Const(ty_const.repr()).into(),
        core::Type::Lam(_, _, _) => {
            // Due to the way our surface syntax is defined, the only type
            // abstractions we should encounter are those that are defined on
            // top-level definitions. Thes should have already been handled in
            // the `From<&'a core::Module>` impl for `Module`.
            panic!("ICE: encountered unexpected type abstraction: {:?}", ty)
        }
        core::Type::App(_, ref ty, ref param_tys) => {
            let lowered_ty = lower_ty(module, path, ty);

            // Replace empty parameter lists on paths with the supplied parameters
            // TODO: This feels rather hacky! I'm sure it will break in non-trivial cases.
            // surely there is a better way to handle this?
            if let Type::Path(ref path, ref params) = *lowered_ty.inner {
                assert!(params.is_empty(), "ICE: Params not empty: {:?}", params);

                let lowered_params = param_tys
                    .iter()
                    .enumerate()
                    .map(|(i, ty)| lower_ty(module, &path.append_child(format!("Arg{}", i)), ty))
                    .collect::<Vec<_>>();

                return Type::Path(path.clone(), lowered_params).into();
            }

            lowered_ty
        }

        core::Type::Array(_, ref elem_ty, _) => {
            let elem_path = path.append_child("Elem");
            let elem_ty = lower_ty(module, &elem_path, elem_ty);

            Type::Array(elem_ty).into()
        }
        core::Type::Assert(_, ref ty, _) => lower_ty(module, path, ty),
        core::Type::Interp(_, _, _, ref repr_ty) => lower_repr_ty(path, repr_ty),
        core::Type::Cond(_, ref options) => {
            let definition = Definition {
                doc: "".into(),
                path: path.clone(),
                params: vec![],
                item: Item::Union(
                    lower_row(path, options, |option_path, &(_, ref ty)| {
                        lower_ty(module, &option_path, ty)
                    }),
                    None,
                ),
            };

            module.define(definition);
            Type::Path(path.clone(), vec![]).into()
        }
        core::Type::Struct(_, ref fields) => {
            let definition = Definition {
                doc: "".into(),
                path: path.clone(),
                params: vec![],
                item: Item::Struct(
                    lower_row(path, fields, |field_path, ty| {
                        lower_ty(module, &field_path, ty)
                    }),
                    None,
                ),
            };

            module.define(definition);
            Type::Path(path.clone(), vec![]).into()
        }

        _ => unimplemented!(),
    }
}
/// Lower binary types to the nominal format
///
/// # Arguments
///
/// * `module` - the current module. Sub-structs and unions will mutate the
///   module, creating corresponding top-level definitions
/// * `path` - path to the parent struct or union
/// * `ty` - the type to be lowered
Lower binary types to the nominal format
Lower binary types to the nominal format
fn lower_ty(module: &mut Module, path: &Path, ty: &core::RcType) -> RcType {
    use semantics::Repr;
    // Mirroring `core::Type::repr`
    match *ty.inner {
        core::Type::Var(_, ref var) => lower_ty_var(var),
        core::Type::Const(ty_const) => Type::Const(ty_const.repr()).into(),
        core::Type::Lam(_, _, _) => {
            // Due to the way our surface syntax is defined, the only type
            // abstractions we should encounter are those that are defined on
            // top-level definitions. Thes should have already been handled in
            // the `From<&'a core::Module>` impl for `Module`.
            panic!("ICE: encountered unexpected type abstraction: {:?}", ty)
        }
        core::Type::App(_, ref ty, ref param_tys) => {
            let lowered_ty = lower_ty(module, path, ty);
            // Replace empty parameter lists on paths with the supplied parameters
            // TODO: This feels rather hacky! I'm sure it will break in non-trivial cases.
            // surely there is a better way to handle this?
            if let Type::Path(ref path, ref params) = *lowered_ty.inner {
                assert!(params.is_empty(), "ICE: Params not empty: {:?}", params);
                let lowered_params = param_tys
                    .iter()
                    .enumerate()
                    .map(|(i, ty)| lower_ty(module, &path.append_child(format!("Arg{}", i)), ty))
                    .collect::<Vec<_>>();
                return Type::Path(path.clone(), lowered_params).into();
            }
            lowered_ty
        }
        core::Type::Array(_, ref elem_ty, _) => {
            let elem_path = path.append_child("Elem");
            let elem_ty = lower_ty(module, &elem_path, elem_ty);
            Type::Array(elem_ty).into()
        }
        core::Type::Assert(_, ref ty, _) => lower_ty(module, path, ty),
        core::Type::Interp(_, _, _, ref repr_ty) => lower_repr_ty(path, repr_ty),
        core::Type::Cond(_, ref options) => {
            let definition = Definition {
                doc: "".into(),
                path: path.clone(),
                params: vec![],
                item: Item::Union(
                    lower_row(path, options, |option_path, &(_, ref ty)| {
                        lower_ty(module, &option_path, ty)
                    }),
                    None,
                ),
            };
            module.define(definition);
            Type::Path(path.clone(), vec![]).into()
        }
        core::Type::Struct(_, ref fields) => {
            let definition = Definition {
                doc: "".into(),
                path: path.clone(),
                params: vec![],
                item: Item::Struct(
                    lower_row(path, fields, |field_path, ty| {
                        lower_ty(module, &field_path, ty)
                    }),
                    None,
                ),
            };
            module.define(definition);
            Type::Path(path.clone(), vec![]).into()
        }
        _ => unimplemented!(),
    }
}
fn lower_ty ( module : & mut Module , path : & Path , ty : & core :: RcType ) -> RcType { use semantics :: Repr ; // Mirroring `core::Type::repr` match * ty . inner { core :: Type :: Var ( _ , ref var ) => lower_ty_var ( var ) , core :: Type :: Const ( ty_const ) => Type :: Const ( ty_const . repr ( ) ) . into ( ) , core :: Type :: Lam ( _ , _ , _ ) => { // Due to the way our surface syntax is defined, the only type // abstractions we should encounter are those that are defined on // top-level definitions. Thes should have already been handled in // the `From<&'a core::Module>` impl for `Module`. panic ! ( " " ty ) } core :: Type :: App ( _ , ref ty , ref param_tys ) => { let lowered_ty = lower_ty ( module , path , ty ) ; // Replace empty parameter lists on paths with the supplied parameters // TODO: This feels rather hacky! I'm sure it will break in non-trivial cases. // surely there is a better way to handle this? if let Type :: Path ( ref path , ref params ) = * lowered_ty . inner { assert ! ( params is_empty ( ) " " params ) ; let lowered_params = param_tys . iter ( ) . enumerate ( ) . map ( | ( i , ty ) | lower_ty ( module , & path . append_child ( format ! ( " " i ) ) , ty ) ) . collect :: < Vec < _ > > ( ) ; return Type :: Path ( path . clone ( ) , lowered_params ) . into ( ) ; } lowered_ty } core :: Type :: Array ( _ , ref elem_ty , _ ) => { let elem_path = path . append_child ( " " ) ; let elem_ty = lower_ty ( module , & elem_path , elem_ty ) ; Type :: Array ( elem_ty ) . into ( ) } core :: Type :: Assert ( _ , ref ty , _ ) => lower_ty ( module , path , ty ) , core :: Type :: Interp ( _ , _ , _ , ref repr_ty ) => lower_repr_ty ( path , repr_ty ) , core :: Type :: Cond ( _ , ref options ) => { let definition = Definition { doc : " " . into ( ) , path : path . clone ( ) , params : vec ! [ ] , item : Item :: Union ( lower_row ( path , options , | option_path , & ( _ , ref ty ) | { lower_ty ( module , & option_path , ty ) } ) , None , ) , } ; module . define ( definition ) ; Type :: Path ( path . clone ( ) , vec ! [ ] ) . into ( ) } core :: Type :: Struct ( _ , ref fields ) => { let definition = Definition { doc : " " . into ( ) , path : path . clone ( ) , params : vec ! [ ] , item : Item :: Struct ( lower_row ( path , fields , | field_path , ty | { lower_ty ( module , & field_path , ty ) } ) , None , ) , } ; module . define ( definition ) ; Type :: Path ( path . clone ( ) , vec ! [ ] ) . into ( ) } _ => unimplemented ! ( ) , } }
Lower binary types to the nominal format
Lower binary types to the nominal format
module
&mut Module
path
&Path
ty
&core::RcType
module
&mut Module
path
&Path
ty
&core::RcType