fn check_items(
    context: &mut Context,
    concrete_items: &[Item<'_>],
) -> Result<Vec<core::Item>, Diagnostic<FileSpan>> {
    // Declarations that may be waiting to be defined
    let mut forward_declarations = im::HashMap::new();
    // The elaborated items
    let mut core_items = {
        let expected_defn_count = concrete_items.iter().filter(|i| i.is_definition()).count();
        Vec::with_capacity(expected_defn_count)
    };

    for concrete_item in concrete_items {
        use im::hashmap::Entry;

        match concrete_item {
            Item::Declaration(declaration) => {
                let label = declaration.label.slice;
                let concrete_body_ty = &declaration.body_ty;

                log::trace!("checking declaration:\t\t{}\t: {}", label, concrete_body_ty);

                match forward_declarations.entry(label) {
                    // No previous declaration for this name was seen, so we can
                    // go-ahead and type check, elaborate, and then add it to
                    // the context
                    Entry::Vacant(entry) => {
                        let (body_ty, _) = synth_universe(&context, &concrete_body_ty)?;
                        // Ensure that we evaluate the forward declaration in
                        // the current context - if we wait until later more
                        // definitions might have come in to scope!
                        let body_ty = context.eval(concrete_body_ty.span(), &body_ty)?;
                        entry.insert(Some((&declaration.docs, body_ty)));
                    },
                    // There's a declaration for this name already pending - we
                    // can't add a new one!
                    Entry::Occupied(_) => {
                        return Err(Diagnostic::new_error("already declared")
                            .with_label(DiagnosticLabel::new_primary(declaration.label.span())));
                    },
                }
            },
            Item::Definition(definition) => {
                let label = definition.label.slice;
                let params = &definition.params;
                let body_ty = definition.body_ty.as_ref();
                let body = &definition.body;

                log::trace!("checking definition:\t\t{}\t= {}", label, body);

                let (doc, term, term_span, ty) = match forward_declarations.entry(label) {
                    // No prior declaration was found, so we'll try synthesizing
                    // its type instead
                    Entry::Vacant(entry) => {
                        let docs = docs::concat(&definition.docs);
                        let clause = Clause::new(params, body_ty, body);
                        let (term, ty) = clause::synth_clause(&context, clause)?;

                        entry.insert(None);

                        (docs, term, body.span(), ty)
                    },
                    // Something has happened with this declaration, let's
                    // 'take' a look!
                    Entry::Occupied(mut entry) => match entry.get_mut().take() {
                        // We found a prior declaration, so we'll use it as a
                        // basis for checking the definition
                        Some((decl_docs, ty)) => {
                            let docs = docs::merge(&definition.label, decl_docs, &definition.docs)?;
                            let clause = Clause::new(params, body_ty, body);
                            let term = clause::check_clause(&context, clause, &ty)?;

                            (docs, term, body.span(), ty)
                        },
                        // This declaration was already given a definition, so
                        // this is an error!
                        //
                        // NOTE: Some languages (eg. Haskell, Agda, Idris, and
                        // Erlang) turn duplicate definitions into case matches.
                        // Languages like Elm don't. What should we do here?
                        None => {
                            return Err(Diagnostic::new_error("already defined").with_label(
                                DiagnosticLabel::new_primary(definition.label.span()),
                            ));
                        },
                    },
                };
                let value = context.eval(term_span, &term)?;
                // NOTE: Not sure how expensive this readback is here!
                let term_ty = context.read_back(None, &ty)?;

                log::trace!("elaborated declaration:\t{}\t: {}", label, term_ty);
                log::trace!("elaborated definition:\t{}\t= {}", label, term);

                context.local_define(label.to_owned(), value, ty);
                core_items.push(core::Item {
                    doc,
                    label: label.to_owned(),
                    term_ty,
                    term,
                });
            },
        }
    }

    Ok(core_items)
}
/// Check the given items and add them to the context.
///
/// Returns the elaborated items.
Check the given items and add them to the context.
Returns the elaborated items.
Check the given items and add them to the context . Returns the elaborated items .
fn check_items(
    context: &mut Context,
    concrete_items: &[Item<'_>],
) -> Result<Vec<core::Item>, Diagnostic<FileSpan>> {
    // Declarations that may be waiting to be defined
    let mut forward_declarations = im::HashMap::new();
    // The elaborated items
    let mut core_items = {
        let expected_defn_count = concrete_items.iter().filter(|i| i.is_definition()).count();
        Vec::with_capacity(expected_defn_count)
    };
    for concrete_item in concrete_items {
        use im::hashmap::Entry;
        match concrete_item {
            Item::Declaration(declaration) => {
                let label = declaration.label.slice;
                let concrete_body_ty = &declaration.body_ty;
                log::trace!("checking declaration:\t\t{}\t: {}", label, concrete_body_ty);
                match forward_declarations.entry(label) {
                    // No previous declaration for this name was seen, so we can
                    // go-ahead and type check, elaborate, and then add it to
                    // the context
                    Entry::Vacant(entry) => {
                        let (body_ty, _) = synth_universe(&context, &concrete_body_ty)?;
                        // Ensure that we evaluate the forward declaration in
                        // the current context - if we wait until later more
                        // definitions might have come in to scope!
                        let body_ty = context.eval(concrete_body_ty.span(), &body_ty)?;
                        entry.insert(Some((&declaration.docs, body_ty)));
                    },
                    // There's a declaration for this name already pending - we
                    // can't add a new one!
                    Entry::Occupied(_) => {
                        return Err(Diagnostic::new_error("already declared")
                            .with_label(DiagnosticLabel::new_primary(declaration.label.span())));
                    },
                }
            },
            Item::Definition(definition) => {
                let label = definition.label.slice;
                let params = &definition.params;
                let body_ty = definition.body_ty.as_ref();
                let body = &definition.body;
                log::trace!("checking definition:\t\t{}\t= {}", label, body);
                let (doc, term, term_span, ty) = match forward_declarations.entry(label) {
                    // No prior declaration was found, so we'll try synthesizing
                    // its type instead
                    Entry::Vacant(entry) => {
                        let docs = docs::concat(&definition.docs);
                        let clause = Clause::new(params, body_ty, body);
                        let (term, ty) = clause::synth_clause(&context, clause)?;
                        entry.insert(None);
                        (docs, term, body.span(), ty)
                    },
                    // Something has happened with this declaration, let's
                    // 'take' a look!
                    Entry::Occupied(mut entry) => match entry.get_mut().take() {
                        // We found a prior declaration, so we'll use it as a
                        // basis for checking the definition
                        Some((decl_docs, ty)) => {
                            let docs = docs::merge(&definition.label, decl_docs, &definition.docs)?;
                            let clause = Clause::new(params, body_ty, body);
                            let term = clause::check_clause(&context, clause, &ty)?;
                            (docs, term, body.span(), ty)
                        },
                        // This declaration was already given a definition, so
                        // this is an error!
                        //
                        // NOTE: Some languages (eg. Haskell, Agda, Idris, and
                        // Erlang) turn duplicate definitions into case matches.
                        // Languages like Elm don't. What should we do here?
                        None => {
                            return Err(Diagnostic::new_error("already defined").with_label(
                                DiagnosticLabel::new_primary(definition.label.span()),
                            ));
                        },
                    },
                };
                let value = context.eval(term_span, &term)?;
                // NOTE: Not sure how expensive this readback is here!
                let term_ty = context.read_back(None, &ty)?;
                log::trace!("elaborated declaration:\t{}\t: {}", label, term_ty);
                log::trace!("elaborated definition:\t{}\t= {}", label, term);
                context.local_define(label.to_owned(), value, ty);
                core_items.push(core::Item {
                    doc,
                    label: label.to_owned(),
                    term_ty,
                    term,
                });
            },
        }
    }
    Ok(core_items)
}
fn check_items ( context : & mut Context , concrete_items : & [ Item < ' _ > ] , ) -> Result < Vec < core :: Item > , Diagnostic < FileSpan > > { // Declarations that may be waiting to be defined let mut forward_declarations = im :: HashMap :: new ( ) ; // The elaborated items let mut core_items = { let expected_defn_count = concrete_items . iter ( ) . filter ( | i | i . is_definition ( ) ) . count ( ) ; Vec :: with_capacity ( expected_defn_count ) } ; for concrete_item in concrete_items { use im :: hashmap :: Entry ; match concrete_item { Item :: Declaration ( declaration ) => { let label = declaration . label . slice ; let concrete_body_ty = & declaration . body_ty ; log :: trace ! ( " \t \t \t " label concrete_body_ty ) ; match forward_declarations . entry ( label ) { // No previous declaration for this name was seen, so we can // go-ahead and type check, elaborate, and then add it to // the context Entry :: Vacant ( entry ) => { let ( body_ty , _ ) = synth_universe ( & context , & concrete_body_ty ) ? ; // Ensure that we evaluate the forward declaration in // the current context - if we wait until later more // definitions might have come in to scope! let body_ty = context . eval ( concrete_body_ty . span ( ) , & body_ty ) ? ; entry . insert ( Some ( ( & declaration . docs , body_ty ) ) ) ; } , // There's a declaration for this name already pending - we // can't add a new one! Entry :: Occupied ( _ ) => { return Err ( Diagnostic :: new_error ( " " ) . with_label ( DiagnosticLabel :: new_primary ( declaration . label . span ( ) ) ) ) ; } , } } , Item :: Definition ( definition ) => { let label = definition . label . slice ; let params = & definition . params ; let body_ty = definition . body_ty . as_ref ( ) ; let body = & definition . body ; log :: trace ! ( " \t \t \t " label body ) ; let ( doc , term , term_span , ty ) = match forward_declarations . entry ( label ) { // No prior declaration was found, so we'll try synthesizing // its type instead Entry :: Vacant ( entry ) => { let docs = docs :: concat ( & definition . docs ) ; let clause = Clause :: new ( params , body_ty , body ) ; let ( term , ty ) = clause :: synth_clause ( & context , clause ) ? ; entry . insert ( None ) ; ( docs , term , body . span ( ) , ty ) } , // Something has happened with this declaration, let's // 'take' a look! Entry :: Occupied ( mut entry ) => match entry . get_mut ( ) . take ( ) { // We found a prior declaration, so we'll use it as a // basis for checking the definition Some ( ( decl_docs , ty ) ) => { let docs = docs :: merge ( & definition . label , decl_docs , & definition . docs ) ? ; let clause = Clause :: new ( params , body_ty , body ) ; let term = clause :: check_clause ( & context , clause , & ty ) ? ; ( docs , term , body . span ( ) , ty ) } , // This declaration was already given a definition, so // this is an error! // // NOTE: Some languages (eg. Haskell, Agda, Idris, and // Erlang) turn duplicate definitions into case matches. // Languages like Elm don't. What should we do here? None => { return Err ( Diagnostic :: new_error ( " " ) . with_label ( DiagnosticLabel :: new_primary ( definition . label . span ( ) ) , ) ) ; } , } , } ; let value = context . eval ( term_span , & term ) ? ; // NOTE: Not sure how expensive this readback is here! let term_ty = context . read_back ( None , & ty ) ? ; log :: trace ! ( " \t \t " label term_ty ) ; log :: trace ! ( " \t \t " label term ) ; context . local_define ( label . to_owned ( ) , value , ty ) ; core_items . push ( core :: Item { doc , label : label . to_owned ( ) , term_ty , term , } ) ; } , } } Ok ( core_items ) }
Check the given items and add them to the context.
Check the given items and add them to the context .
context
&mut Context
concrete_items
&[Item<'_>]