fn reparse_pi_type_hack<L, T>(
    span: ByteSpan,
    binder: concrete::Term,
    body: concrete::Term,
) -> Result<concrete::Term, LalrpopError<L, T, ParseError>> {
    use crate::syntax::concrete::Term;

    fn pi_binder<L, T>(
        binder: &Term,
    ) -> Result<Option<concrete::PiParamGroup>, LalrpopError<L, T, ParseError>> {
        match *binder {
            Term::Parens(_, ref term) => match **term {
                Term::Ann(ref params, ref ann) => {
                    let mut names = Vec::new();
                    param_names(&**params, &mut names)?;
                    Ok(Some((names, (**ann).clone())))
                },
                _ => Ok(None),
            },
            _ => Ok(None),
        }
    }

    fn param_names<L, T>(
        term: &Term,
        names: &mut Vec<(ByteIndex, String)>,
    ) -> Result<(), LalrpopError<L, T, ParseError>> {
        match *term {
            Term::Name(start, ref name) => names.push((start, name.clone())),
            Term::App(ref head, ref args) => {
                param_names(head, names)?;
                for arg in args {
                    param_names(arg, names)?;
                }
            },
            _ => {
                return Err(LalrpopError::User {
                    error: ParseError::IdentifierExpectedInPiType { span: term.span() },
                });
            },
        }
        Ok(())
    }

    match binder {
        Term::App(ref head, ref args) => {
            use std::iter;

            let mut binders = Vec::with_capacity(args.len() + 1);

            for next in iter::once(&**head).chain(args).map(pi_binder) {
                match next? {
                    Some((names, ann)) => binders.push((names, ann)),
                    None => return Ok(Term::Arrow(Box::new(binder.clone()), Box::new(body))),
                }
            }

            Ok(Term::Pi(span.start(), binders, Box::new(body)))
        },
        binder => match pi_binder(&binder)? {
            Some(binder) => Ok(Term::Pi(span.start(), vec![binder], Box::new(body))),
            None => Ok(Term::Arrow(binder.into(), Box::new(body))),
        },
    }
}
/// This is an ugly hack that cobbles together a pi type from a binder term and
/// a body. See the comments on the `PiTerm` rule in the `grammar.lalrpop` for
/// more information.
This is an ugly hack that cobbles together a pi type from a binder term and
a body. See the comments on the `PiTerm` rule in the `grammar.lalrpop` for
more information.
This is an ugly hack that cobbles together a pi type from a binder term and a body . See the comments on the ` PiTerm ` rule in the ` grammar . lalrpop ` for more information .
fn reparse_pi_type_hack<L, T>(
    span: ByteSpan,
    binder: concrete::Term,
    body: concrete::Term,
) -> Result<concrete::Term, LalrpopError<L, T, ParseError>> {
    use crate::syntax::concrete::Term;
    fn pi_binder<L, T>(
        binder: &Term,
    ) -> Result<Option<concrete::PiParamGroup>, LalrpopError<L, T, ParseError>> {
        match *binder {
            Term::Parens(_, ref term) => match **term {
                Term::Ann(ref params, ref ann) => {
                    let mut names = Vec::new();
                    param_names(&**params, &mut names)?;
                    Ok(Some((names, (**ann).clone())))
                },
                _ => Ok(None),
            },
            _ => Ok(None),
        }
    }
    fn param_names<L, T>(
        term: &Term,
        names: &mut Vec<(ByteIndex, String)>,
    ) -> Result<(), LalrpopError<L, T, ParseError>> {
        match *term {
            Term::Name(start, ref name) => names.push((start, name.clone())),
            Term::App(ref head, ref args) => {
                param_names(head, names)?;
                for arg in args {
                    param_names(arg, names)?;
                }
            },
            _ => {
                return Err(LalrpopError::User {
                    error: ParseError::IdentifierExpectedInPiType { span: term.span() },
                });
            },
        }
        Ok(())
    }
    match binder {
        Term::App(ref head, ref args) => {
            use std::iter;
            let mut binders = Vec::with_capacity(args.len() + 1);
            for next in iter::once(&**head).chain(args).map(pi_binder) {
                match next? {
                    Some((names, ann)) => binders.push((names, ann)),
                    None => return Ok(Term::Arrow(Box::new(binder.clone()), Box::new(body))),
                }
            }
            Ok(Term::Pi(span.start(), binders, Box::new(body)))
        },
        binder => match pi_binder(&binder)? {
            Some(binder) => Ok(Term::Pi(span.start(), vec![binder], Box::new(body))),
            None => Ok(Term::Arrow(binder.into(), Box::new(body))),
        },
    }
}
fn reparse_pi_type_hack < L , T > ( span : ByteSpan , binder : concrete :: Term , body : concrete :: Term , ) -> Result < concrete :: Term , LalrpopError < L , T , ParseError > > { use crate :: syntax :: concrete :: Term ; fn pi_binder < L , T > ( binder : & Term , ) -> Result < Option < concrete :: PiParamGroup > , LalrpopError < L , T , ParseError > > { match * binder { Term :: Parens ( _ , ref term ) => match * * term { Term :: Ann ( ref params , ref ann ) => { let mut names = Vec :: new ( ) ; param_names ( & * * params , & mut names ) ? ; Ok ( Some ( ( names , ( * * ann ) . clone ( ) ) ) ) } , _ => Ok ( None ) , } , _ => Ok ( None ) , } } fn param_names < L , T > ( term : & Term , names : & mut Vec < ( ByteIndex , String ) > , ) -> Result < ( ) , LalrpopError < L , T , ParseError > > { match * term { Term :: Name ( start , ref name ) => names . push ( ( start , name . clone ( ) ) ) , Term :: App ( ref head , ref args ) => { param_names ( head , names ) ? ; for arg in args { param_names ( arg , names ) ? ; } } , _ => { return Err ( LalrpopError :: User { error : ParseError :: IdentifierExpectedInPiType { span : term . span ( ) } , } ) ; } , } Ok ( ( ) ) } match binder { Term :: App ( ref head , ref args ) => { use std :: iter ; let mut binders = Vec :: with_capacity ( args . len ( ) + 1 ) ; for next in iter :: once ( & * * head ) . chain ( args ) . map ( pi_binder ) { match next ? { Some ( ( names , ann ) ) => binders . push ( ( names , ann ) ) , None => return Ok ( Term :: Arrow ( Box :: new ( binder . clone ( ) ) , Box :: new ( body ) ) ) , } } Ok ( Term :: Pi ( span . start ( ) , binders , Box :: new ( body ) ) ) } , binder => match pi_binder ( & binder ) ? { Some ( binder ) => Ok ( Term :: Pi ( span . start ( ) , vec ! [ binder ] , Box :: new ( body ) ) ) , None => Ok ( Term :: Arrow ( binder . into ( ) , Box :: new ( body ) ) ) , } , } }
This is an ugly hack that cobbles together a pi type from a binder term and
a body.
This is an ugly hack that cobbles together a pi type from a binder term and a body .
span
ByteSpan
binder
concrete::Term
body
concrete::Term
span
ByteSpan
binder
concrete::Term
body
concrete::Term