pub fn eval(term: &RcTerm, env: &Env<RcValue>) -> Result<RcValue, NbeError> {
    match term.as_ref() {
        Term::Var(index) => match env.lookup_entry(*index) {
            Some(value) => Ok(value.clone()),
            None => Err(NbeError::new("eval: variable not found")),
        },
        Term::PrimitiveAbort(_, message) => Err(NbeError::new(format!("abort: {}", message))),
        Term::Let(def, body) => {
            let def = eval(def, env)?;
            let mut env = env.clone();
            env.add_entry(def);
            eval(body, &env)
        },

        // Literals
        Term::LiteralType(literal_ty) => Ok(RcValue::from(Value::LiteralType(literal_ty.clone()))),
        Term::LiteralIntro(literal_intro) => {
            Ok(RcValue::from(Value::LiteralIntro(literal_intro.clone())))
        },
        Term::LiteralElim(scrutinee, clauses, default_body) => {
            let scrutinee = eval(scrutinee, env)?;
            let clauses = ClauseClosure::new(clauses.clone(), env.clone());
            let default_body = AppClosure::new(default_body.clone(), env.clone());

            do_literal_elim(scrutinee, clauses, default_body)
        },

        // Functions
        Term::FunType(app_mode, param_ty, body_ty) => {
            let app_mode = app_mode.clone();
            let param_ty = eval(param_ty, env)?;
            let body_ty = AppClosure::new(body_ty.clone(), env.clone());

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

            Ok(RcValue::from(Value::FunIntro(app_mode, body)))
        },
        Term::FunElim(fun, app_mode, arg) => {
            let fun = eval(fun, env)?;
            let app_mode = app_mode.clone();
            let arg = eval(arg, env)?;

            do_fun_elim(fun, app_mode, arg)
        },

        // Records
        Term::RecordType(fields) => match fields.split_first() {
            None => Ok(RcValue::from(Value::RecordTypeEmpty)),
            Some(((doc, label, ty), rest)) => {
                let doc = doc.clone();
                let label = label.clone();
                let ty = eval(ty, env)?;
                let rest_fields = rest.iter().cloned().collect(); // FIXME: Seems expensive?
                let rest =
                    AppClosure::new(RcTerm::from(Term::RecordType(rest_fields)), env.clone());

                Ok(RcValue::from(Value::RecordTypeExtend(doc, label, ty, rest)))
            },
        },
        Term::RecordIntro(fields) => {
            let fields = fields
                .iter()
                .map(|(label, term)| Ok((label.clone(), eval(term, env)?)))
                .collect::<Result<_, _>>()?;

            Ok(RcValue::from(Value::RecordIntro(fields)))
        },
        Term::RecordElim(record, label) => do_record_elim(eval(record, env)?, label),

        // Universes
        Term::Universe(level) => Ok(RcValue::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: &RcTerm, env: &Env<RcValue>) -> Result<RcValue, NbeError> {
    match term.as_ref() {
        Term::Var(index) => match env.lookup_entry(*index) {
            Some(value) => Ok(value.clone()),
            None => Err(NbeError::new("eval: variable not found")),
        },
        Term::PrimitiveAbort(_, message) => Err(NbeError::new(format!("abort: {}", message))),
        Term::Let(def, body) => {
            let def = eval(def, env)?;
            let mut env = env.clone();
            env.add_entry(def);
            eval(body, &env)
        },
        // Literals
        Term::LiteralType(literal_ty) => Ok(RcValue::from(Value::LiteralType(literal_ty.clone()))),
        Term::LiteralIntro(literal_intro) => {
            Ok(RcValue::from(Value::LiteralIntro(literal_intro.clone())))
        },
        Term::LiteralElim(scrutinee, clauses, default_body) => {
            let scrutinee = eval(scrutinee, env)?;
            let clauses = ClauseClosure::new(clauses.clone(), env.clone());
            let default_body = AppClosure::new(default_body.clone(), env.clone());
            do_literal_elim(scrutinee, clauses, default_body)
        },
        // Functions
        Term::FunType(app_mode, param_ty, body_ty) => {
            let app_mode = app_mode.clone();
            let param_ty = eval(param_ty, env)?;
            let body_ty = AppClosure::new(body_ty.clone(), env.clone());
            Ok(RcValue::from(Value::FunType(app_mode, param_ty, body_ty)))
        },
        Term::FunIntro(app_mode, body) => {
            let app_mode = app_mode.clone();
            let body = AppClosure::new(body.clone(), env.clone());
            Ok(RcValue::from(Value::FunIntro(app_mode, body)))
        },
        Term::FunElim(fun, app_mode, arg) => {
            let fun = eval(fun, env)?;
            let app_mode = app_mode.clone();
            let arg = eval(arg, env)?;
            do_fun_elim(fun, app_mode, arg)
        },
        // Records
        Term::RecordType(fields) => match fields.split_first() {
            None => Ok(RcValue::from(Value::RecordTypeEmpty)),
            Some(((doc, label, ty), rest)) => {
                let doc = doc.clone();
                let label = label.clone();
                let ty = eval(ty, env)?;
                let rest_fields = rest.iter().cloned().collect(); // FIXME: Seems expensive?
                let rest =
                    AppClosure::new(RcTerm::from(Term::RecordType(rest_fields)), env.clone());
                Ok(RcValue::from(Value::RecordTypeExtend(doc, label, ty, rest)))
            },
        },
        Term::RecordIntro(fields) => {
            let fields = fields
                .iter()
                .map(|(label, term)| Ok((label.clone(), eval(term, env)?)))
                .collect::<Result<_, _>>()?;
            Ok(RcValue::from(Value::RecordIntro(fields)))
        },
        Term::RecordElim(record, label) => do_record_elim(eval(record, env)?, label),
        // Universes
        Term::Universe(level) => Ok(RcValue::from(Value::Universe(*level))),
    }
}
pub fn eval ( term : & RcTerm , env : & Env < RcValue > ) -> Result < RcValue , NbeError > { match term . as_ref ( ) { Term :: Var ( index ) => match env . lookup_entry ( * index ) { Some ( value ) => Ok ( value . clone ( ) ) , None => Err ( NbeError :: new ( " " ) ) , } , Term :: PrimitiveAbort ( _ , message ) => Err ( NbeError :: new ( format ! ( " " message ) ) ) , Term :: Let ( def , body ) => { let def = eval ( def , env ) ? ; let mut env = env . clone ( ) ; env . add_entry ( def ) ; eval ( body , & env ) } , // Literals Term :: LiteralType ( literal_ty ) => Ok ( RcValue :: from ( Value :: LiteralType ( literal_ty . clone ( ) ) ) ) , Term :: LiteralIntro ( literal_intro ) => { Ok ( RcValue :: from ( Value :: LiteralIntro ( literal_intro . clone ( ) ) ) ) } , Term :: LiteralElim ( scrutinee , clauses , default_body ) => { let scrutinee = eval ( scrutinee , env ) ? ; let clauses = ClauseClosure :: new ( clauses . clone ( ) , env . clone ( ) ) ; let default_body = AppClosure :: new ( default_body . clone ( ) , env . clone ( ) ) ; do_literal_elim ( scrutinee , clauses , default_body ) } , // Functions Term :: FunType ( app_mode , param_ty , body_ty ) => { let app_mode = app_mode . clone ( ) ; let param_ty = eval ( param_ty , env ) ? ; let body_ty = AppClosure :: new ( body_ty . clone ( ) , env . clone ( ) ) ; Ok ( RcValue :: from ( Value :: FunType ( app_mode , param_ty , body_ty ) ) ) } , Term :: FunIntro ( app_mode , body ) => { let app_mode = app_mode . clone ( ) ; let body = AppClosure :: new ( body . clone ( ) , env . clone ( ) ) ; Ok ( RcValue :: from ( Value :: FunIntro ( app_mode , body ) ) ) } , Term :: FunElim ( fun , app_mode , arg ) => { let fun = eval ( fun , env ) ? ; let app_mode = app_mode . clone ( ) ; let arg = eval ( arg , env ) ? ; do_fun_elim ( fun , app_mode , arg ) } , // Records Term :: RecordType ( fields ) => match fields . split_first ( ) { None => Ok ( RcValue :: from ( Value :: RecordTypeEmpty ) ) , Some ( ( ( doc , label , ty ) , rest ) ) => { let doc = doc . clone ( ) ; let label = label . clone ( ) ; let ty = eval ( ty , env ) ? ; let rest_fields = rest . iter ( ) . cloned ( ) . collect ( ) ; // FIXME: Seems expensive? let rest = AppClosure :: new ( RcTerm :: from ( Term :: RecordType ( rest_fields ) ) , env . clone ( ) ) ; Ok ( RcValue :: from ( Value :: RecordTypeExtend ( doc , label , ty , rest ) ) ) } , } , Term :: RecordIntro ( fields ) => { let fields = fields . iter ( ) . map ( | ( label , term ) | Ok ( ( label . clone ( ) , eval ( term , env ) ? ) ) ) . collect :: < Result < _ , _ > > ( ) ? ; Ok ( RcValue :: from ( Value :: RecordIntro ( fields ) ) ) } , Term :: RecordElim ( record , label ) => do_record_elim ( eval ( record , env ) ? , label ) , // Universes Term :: Universe ( level ) => Ok ( RcValue :: 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 .
term
&RcTerm
env
&Env<RcValue>