pub fn eval_term(
    prims: &prim::Env,
    metas: &meta::Env,
    values: &var::Env<Rc<Value>>,
    term: &Rc<Term>,
) -> Result<Rc<Value>, String> {
    match term.as_ref() {
        Term::Var(var_index) => match values.lookup_entry(*var_index) {
            Some(value) => Ok(value.clone()),
            None => Err("eval: variable not found".to_owned()),
        },
        Term::Meta(meta_level) => match metas.lookup_solution(*meta_level) {
            Some((_, meta::Solution::Solved(value), _)) => Ok(value.clone()),
            Some((_, meta::Solution::Unsolved, _)) => Ok(Rc::from(Value::meta(*meta_level))),
            None => Err("eval: metavariable not found".to_owned()),
        },
        Term::Prim(prim_name) => Ok(eval_prim(prims, prim_name, &[])?.0),

        Term::Ann(term, _) => eval_term(prims, metas, values, term),
        Term::Let(items, body) => {
            let mut values = values.clone();
            for item in items {
                if let Item::Definition(_, _, term) = item {
                    values.add_entry(eval_term(prims, metas, &values, term)?);
                }
            }
            eval_term(prims, metas, &values, body)
        },

        // Literals
        Term::LiteralType(ty) => Ok(Rc::from(Value::literal_ty(ty.clone()))),
        Term::LiteralIntro(intro) => Ok(Rc::from(Value::literal_intro(intro.clone()))),
        Term::LiteralElim(scrutinee, clauses, default_body) => {
            let scrutinee = eval_term(prims, metas, values, scrutinee)?;
            let closure =
                LiteralClosure::new(clauses.clone(), default_body.clone(), values.clone());

            eval_literal_elim(prims, metas, scrutinee, closure)
        },

        // Functions
        Term::FunType(app_mode, name_hint, param_ty, body_ty) => {
            let app_mode = app_mode.clone();
            let name_hint = name_hint.clone();
            let param_ty = eval_term(prims, metas, values, param_ty)?;
            let body_ty = AppClosure::new(body_ty.clone(), values.clone());

            Ok(Rc::from(Value::FunType(
                app_mode, name_hint, param_ty, body_ty,
            )))
        },
        Term::FunIntro(app_mode, name_hint, body) => {
            let app_mode = app_mode.clone();
            let name_hint = name_hint.clone();
            let body = AppClosure::new(body.clone(), values.clone());

            Ok(Rc::from(Value::FunIntro(app_mode, name_hint, body)))
        },
        Term::FunElim(fun, app_mode, arg) => {
            let fun = eval_term(prims, metas, values, fun)?;
            let arg = eval_term(prims, metas, values, arg)?;

            eval_fun_elim(prims, metas, fun, app_mode, arg)
        },

        // Records
        Term::RecordType(fields) => match fields.split_first() {
            None => Ok(Rc::from(Value::RecordTypeEmpty)),
            Some(((doc, label, name_hint, ty), rest)) => {
                let doc = doc.clone();
                let label = label.clone();
                let name_hint = name_hint.clone();
                let ty = eval_term(prims, metas, values, ty)?;
                let rest_fields = rest.iter().cloned().collect(); // FIXME: Seems expensive?
                let rest = AppClosure::new(Rc::from(Term::RecordType(rest_fields)), values.clone());

                Ok(Rc::from(Value::RecordTypeExtend(
                    doc, label, name_hint, ty, rest,
                )))
            },
        },
        Term::RecordIntro(fields) => {
            let fields = fields
                .iter()
                .map(|(label, term)| Ok((label.clone(), eval_term(prims, metas, values, term)?)))
                .collect::<Result<_, String>>()?;

            Ok(Rc::from(Value::RecordIntro(fields)))
        },
        Term::RecordElim(record, label) => {
            eval_record_elim(eval_term(prims, metas, values, record)?, label)
        },

        // Universes
        Term::Universe(level) => Ok(Rc::from(Value::universe(*level))),
    }
}
/// Evaluate a term in the environment that corresponds to the context in which
/// the term was typed.
Evaluate a term in the environment that corresponds to the context in which
the term was typed.
Evaluate a term in the environment that corresponds to the context in which the term was typed .
pub fn eval_term(
    prims: &prim::Env,
    metas: &meta::Env,
    values: &var::Env<Rc<Value>>,
    term: &Rc<Term>,
) -> Result<Rc<Value>, String> {
    match term.as_ref() {
        Term::Var(var_index) => match values.lookup_entry(*var_index) {
            Some(value) => Ok(value.clone()),
            None => Err("eval: variable not found".to_owned()),
        },
        Term::Meta(meta_level) => match metas.lookup_solution(*meta_level) {
            Some((_, meta::Solution::Solved(value), _)) => Ok(value.clone()),
            Some((_, meta::Solution::Unsolved, _)) => Ok(Rc::from(Value::meta(*meta_level))),
            None => Err("eval: metavariable not found".to_owned()),
        },
        Term::Prim(prim_name) => Ok(eval_prim(prims, prim_name, &[])?.0),
        Term::Ann(term, _) => eval_term(prims, metas, values, term),
        Term::Let(items, body) => {
            let mut values = values.clone();
            for item in items {
                if let Item::Definition(_, _, term) = item {
                    values.add_entry(eval_term(prims, metas, &values, term)?);
                }
            }
            eval_term(prims, metas, &values, body)
        },
        // Literals
        Term::LiteralType(ty) => Ok(Rc::from(Value::literal_ty(ty.clone()))),
        Term::LiteralIntro(intro) => Ok(Rc::from(Value::literal_intro(intro.clone()))),
        Term::LiteralElim(scrutinee, clauses, default_body) => {
            let scrutinee = eval_term(prims, metas, values, scrutinee)?;
            let closure =
                LiteralClosure::new(clauses.clone(), default_body.clone(), values.clone());
            eval_literal_elim(prims, metas, scrutinee, closure)
        },
        // Functions
        Term::FunType(app_mode, name_hint, param_ty, body_ty) => {
            let app_mode = app_mode.clone();
            let name_hint = name_hint.clone();
            let param_ty = eval_term(prims, metas, values, param_ty)?;
            let body_ty = AppClosure::new(body_ty.clone(), values.clone());
            Ok(Rc::from(Value::FunType(
                app_mode, name_hint, param_ty, body_ty,
            )))
        },
        Term::FunIntro(app_mode, name_hint, body) => {
            let app_mode = app_mode.clone();
            let name_hint = name_hint.clone();
            let body = AppClosure::new(body.clone(), values.clone());
            Ok(Rc::from(Value::FunIntro(app_mode, name_hint, body)))
        },
        Term::FunElim(fun, app_mode, arg) => {
            let fun = eval_term(prims, metas, values, fun)?;
            let arg = eval_term(prims, metas, values, arg)?;
            eval_fun_elim(prims, metas, fun, app_mode, arg)
        },
        // Records
        Term::RecordType(fields) => match fields.split_first() {
            None => Ok(Rc::from(Value::RecordTypeEmpty)),
            Some(((doc, label, name_hint, ty), rest)) => {
                let doc = doc.clone();
                let label = label.clone();
                let name_hint = name_hint.clone();
                let ty = eval_term(prims, metas, values, ty)?;
                let rest_fields = rest.iter().cloned().collect(); // FIXME: Seems expensive?
                let rest = AppClosure::new(Rc::from(Term::RecordType(rest_fields)), values.clone());
                Ok(Rc::from(Value::RecordTypeExtend(
                    doc, label, name_hint, ty, rest,
                )))
            },
        },
        Term::RecordIntro(fields) => {
            let fields = fields
                .iter()
                .map(|(label, term)| Ok((label.clone(), eval_term(prims, metas, values, term)?)))
                .collect::<Result<_, String>>()?;
            Ok(Rc::from(Value::RecordIntro(fields)))
        },
        Term::RecordElim(record, label) => {
            eval_record_elim(eval_term(prims, metas, values, record)?, label)
        },
        // Universes
        Term::Universe(level) => Ok(Rc::from(Value::universe(*level))),
    }
}
pub fn eval_term ( prims : & prim :: Env , metas : & meta :: Env , values : & var :: Env < Rc < Value > > , term : & Rc < Term > , ) -> Result < Rc < Value > , String > { match term . as_ref ( ) { Term :: Var ( var_index ) => match values . lookup_entry ( * var_index ) { Some ( value ) => Ok ( value . clone ( ) ) , None => Err ( " " . to_owned ( ) ) , } , Term :: Meta ( meta_level ) => match metas . lookup_solution ( * meta_level ) { Some ( ( _ , meta :: Solution :: Solved ( value ) , _ ) ) => Ok ( value . clone ( ) ) , Some ( ( _ , meta :: Solution :: Unsolved , _ ) ) => Ok ( Rc :: from ( Value :: meta ( * meta_level ) ) ) , None => Err ( " " . to_owned ( ) ) , } , Term :: Prim ( prim_name ) => Ok ( eval_prim ( prims , prim_name , & [ ] ) ? . 0 ) , Term :: Ann ( term , _ ) => eval_term ( prims , metas , values , term ) , Term :: Let ( items , body ) => { let mut values = values . clone ( ) ; for item in items { if let Item :: Definition ( _ , _ , term ) = item { values . add_entry ( eval_term ( prims , metas , & values , term ) ? ) ; } } eval_term ( prims , metas , & values , body ) } , // Literals Term :: LiteralType ( ty ) => Ok ( Rc :: from ( Value :: literal_ty ( ty . clone ( ) ) ) ) , Term :: LiteralIntro ( intro ) => Ok ( Rc :: from ( Value :: literal_intro ( intro . clone ( ) ) ) ) , Term :: LiteralElim ( scrutinee , clauses , default_body ) => { let scrutinee = eval_term ( prims , metas , values , scrutinee ) ? ; let closure = LiteralClosure :: new ( clauses . clone ( ) , default_body . clone ( ) , values . clone ( ) ) ; eval_literal_elim ( prims , metas , scrutinee , closure ) } , // Functions Term :: FunType ( app_mode , name_hint , param_ty , body_ty ) => { let app_mode = app_mode . clone ( ) ; let name_hint = name_hint . clone ( ) ; let param_ty = eval_term ( prims , metas , values , param_ty ) ? ; let body_ty = AppClosure :: new ( body_ty . clone ( ) , values . clone ( ) ) ; Ok ( Rc :: from ( Value :: FunType ( app_mode , name_hint , param_ty , body_ty , ) ) ) } , Term :: FunIntro ( app_mode , name_hint , body ) => { let app_mode = app_mode . clone ( ) ; let name_hint = name_hint . clone ( ) ; let body = AppClosure :: new ( body . clone ( ) , values . clone ( ) ) ; Ok ( Rc :: from ( Value :: FunIntro ( app_mode , name_hint , body ) ) ) } , Term :: FunElim ( fun , app_mode , arg ) => { let fun = eval_term ( prims , metas , values , fun ) ? ; let arg = eval_term ( prims , metas , values , arg ) ? ; eval_fun_elim ( prims , metas , fun , app_mode , arg ) } , // Records Term :: RecordType ( fields ) => match fields . split_first ( ) { None => Ok ( Rc :: from ( Value :: RecordTypeEmpty ) ) , Some ( ( ( doc , label , name_hint , ty ) , rest ) ) => { let doc = doc . clone ( ) ; let label = label . clone ( ) ; let name_hint = name_hint . clone ( ) ; let ty = eval_term ( prims , metas , values , ty ) ? ; let rest_fields = rest . iter ( ) . cloned ( ) . collect ( ) ; // FIXME: Seems expensive? let rest = AppClosure :: new ( Rc :: from ( Term :: RecordType ( rest_fields ) ) , values . clone ( ) ) ; Ok ( Rc :: from ( Value :: RecordTypeExtend ( doc , label , name_hint , ty , rest , ) ) ) } , } , Term :: RecordIntro ( fields ) => { let fields = fields . iter ( ) . map ( | ( label , term ) | Ok ( ( label . clone ( ) , eval_term ( prims , metas , values , term ) ? ) ) ) . collect :: < Result < _ , String > > ( ) ? ; Ok ( Rc :: from ( Value :: RecordIntro ( fields ) ) ) } , Term :: RecordElim ( record , label ) => { eval_record_elim ( eval_term ( prims , metas , values , record ) ? , label ) } , // Universes Term :: Universe ( level ) => Ok ( Rc :: from ( Value :: universe ( * level ) ) ) , } }
Evaluate a term in the environment that corresponds to the context in which
the term was typed.
Evaluate a term in the environment that corresponds to the context in which the term was typed .
prims
&prim::Env
metas
&meta::Env
values
&var::Env<Rc<Value>>
term
&Rc<Term>
prims
&prim::Env
metas
&meta::Env
values
&var::Env<Rc<Value>>
term
&Rc<Term>