// Macros have types!
// ...but they're not higher-order (i.e., you can't do anything with a macro other than invoke it).
// This means that we can just generate a type for them at the location of invocation.
Macros have types.
but they're not higher-order .
This means that we can just generate a type for them at the location of invocation.
Macros have types . but they ' re not higher - order . This means that we can just generate a type for them at the location of invocation .
fn macro_type(forall_ty_vars: &[Name], arguments: Vec<(Name, Ty)>, output: Ty) -> Ty {
    let mut components = vec![];
    for (k, v) in arguments.iter() {
        // The fields in a struct type are not renamed like normal during freshening,
        //  so roll back any freshening that happened during evaluation, hence `unhygienic_orig`.
        // TODO: this can go wrong if a macro-defining macro collides two term names.
        // Fixing this probably requires rethinking how "component_name" works.
        // Perhaps not using structs at all might also work.
        components.push(mbe!("component_name" => (, Atom(k.unhygienic_orig())),
                             "component" => (, v.to_ast())));
    }
    let argument_struct = Node(
        crate::core_forms::find_core_form("Type", "struct"),
        crate::util::mbe::EnvMBE::new_from_anon_repeat(components),
        ExportBeta::Nothing,
    );
    let mac_fn = u!({Type fn : [(, argument_struct)] (, output.to_ast())});
    if forall_ty_vars.is_empty() {
        Ty(mac_fn)
    } else {
        ty!({"Type" "forall_type" :
            "body" => (import [* [forall "param"]] (, mac_fn)),
            "param" => (,seq forall_ty_vars.iter().map(|n| { Atom(*n) }).collect::<Vec<_>>())
        })
    }
}
fn macro_type ( forall_ty_vars : & [ Name ] , arguments : Vec < ( Name , Ty ) > , output : Ty ) -> Ty { let mut components = vec ! [ ] ; for ( k , v ) in arguments . iter ( ) { // The fields in a struct type are not renamed like normal during freshening, //  so roll back any freshening that happened during evaluation, hence `unhygienic_orig`. // TODO: this can go wrong if a macro-defining macro collides two term names. // Fixing this probably requires rethinking how "component_name" works. // Perhaps not using structs at all might also work. components . push ( mbe ! ( " " ( Atom ( k unhygienic_orig ( ) ) ) " " ( v to_ast ( ) ) ) ) ; } let argument_struct = Node ( crate :: core_forms :: find_core_form ( " " , " " ) , crate :: util :: mbe :: EnvMBE :: new_from_anon_repeat ( components ) , ExportBeta :: Nothing , ) ; let mac_fn = u ! ( { Type fn [ ( argument_struct ) ] ( output to_ast ( ) ) } ) ; if forall_ty_vars . is_empty ( ) { Ty ( mac_fn ) } else { ty ! ( { " " " " " " ( import [ [ forall " " ] ] ( mac_fn ) ) " " ( seq forall_ty_vars iter ( ) map ( n { Atom ( n ) } ) collect Vec ( ) ) } ) } }
Macros have types!
Macros have types!
forall_ty_vars
&[Name]
arguments
Vec<(Name, Ty)>
output
Ty