use std::{collections::HashMap, rc::Rc}; use crate::{ exec::{DeBrujinAst as DBAst, builtin_definitions::AddOp}, parse::{Ast, Constant}, types::{PrimitiveType, Type}, }; use super::builtins::Builtin; #[test] fn to_de_brujin_ast_simple() { let input = Ast::Abstraction( "x".to_string(), Some(Type::Primitive(PrimitiveType::Nat).into()), Box::new(Ast::Abstraction( "x".to_string(), Some(Type::Primitive(PrimitiveType::Nat).into()), Box::new(Ast::Variable("x".to_string())), )), ); let de_brujin: DBAst = input.into(); assert_eq!( de_brujin, DBAst::Abstraction( "x".to_string(), Some(Type::Primitive(PrimitiveType::Nat).into()), Box::new(DBAst::Abstraction( "x".to_string(), Some(Type::Primitive(PrimitiveType::Nat).into()), Box::new(DBAst::BoundVariable(1)) )) ) ) } #[test] fn de_brujin_beta_reduce() { let input = Ast::Application( Box::new(Ast::Abstraction( "x".to_string(), Some(Type::arrow(PrimitiveType::Nat, PrimitiveType::Nat).into()), Box::new(Ast::Application( Box::new(Ast::Variable("x".to_string())), Box::new(Ast::Constant(Constant::Nat(5))), )), )), Box::new(Ast::Variable("y".to_string())), ); let dbast: DBAst = input.into(); let reduced = dbast.beta_reduce(); assert_eq!( reduced, DBAst::Application( Box::new(DBAst::FreeVariable("y".to_string())), Box::new(DBAst::Constant(Constant::Nat(5))), ), ) } #[test] fn to_and_from_de_brujin_is_id() { let input = Ast::Application( Box::new(Ast::Abstraction( "x".to_string(), Some(Type::arrow(PrimitiveType::Nat, PrimitiveType::Nat).into()), Box::new(Ast::Application( Box::new(Ast::Variable("x".to_string())), Box::new(Ast::Constant(Constant::Nat(5))), )), )), Box::new(Ast::Variable("y".to_string())), ); let dbast: DBAst = input.clone().into(); let output: Ast = dbast.into(); assert_eq!(input, output); } #[test] fn reduce_add() { let input: DBAst = Ast::Application( Box::new(Ast::Application( Box::new(Ast::Variable("add".to_string())), Box::new(Ast::Constant(Constant::Nat(5))), )), Box::new(Ast::Constant(Constant::Nat(5))), ) .into(); let mut builtins: HashMap> = HashMap::new(); builtins.insert("add".to_string(), Rc::new(AddOp)); let output = input.reduce_builtins(&builtins); assert_eq!(output, DBAst::Constant(Constant::Nat(10))); }