use voile_util::loc::Ident;
use voile_util::meta::MI;
use voile_util::tags::PiSig;
use voile_util::uid::{DBI, GI};
use crate::check::monad::TCE;
use crate::syntax::abs::{trans_expr, Abs};
use crate::syntax::surf::parse_str_err_printed;
use super::{trans_decls, AbsDecl};
#[test]
fn many_decls() {
let surf = parse_str_err_printed(
"val a : Type1;\n\
let a = Type;\n\
val b : Type1;\n\
let b = Type;",
)
.unwrap();
let mut ctx = trans_decls(surf).unwrap();
assert_eq!(4, ctx.len());
let decl = ctx.pop().unwrap();
println!("{:?}", decl);
match decl {
AbsDecl::Impl(abs, ty_dbi) => {
println!("val {};", ty_dbi);
println!("let {};", abs);
}
_ => panic!(),
};
ctx.pop().unwrap();
let decl = ctx.pop().unwrap();
println!("{:?}", decl);
match decl {
AbsDecl::Impl(abs, ty_dbi) => {
println!("val {};", ty_dbi);
println!("let {};", abs);
}
_ => panic!(),
};
ctx.pop().unwrap();
assert!(ctx.is_empty());
}
fn must_be_app(abs: Abs) -> Abs {
match abs {
Abs::App(_, _, _, abs) => *abs,
e => panic!("`{:?}` is not an `Abs::App`.", e),
}
}
fn must_be_pi(abs: Abs) -> (Abs, Abs) {
match abs {
Abs::Dt(_, PiSig::Pi, _, _, param, abs) => (*param, *abs),
e => panic!("`{:?}` is not an `Abs::Dt(_, Pi, _, _)`.", e),
}
}
fn must_be_lam(abs: Abs) -> Abs {
match abs {
Abs::Lam(_, _, _, abs) => *abs,
e => panic!("`{:?}` is not an `Abs::Lam(_, _, _)`.", e),
}
}
fn must_be_local(abs: Abs) -> DBI {
match abs {
Abs::Var(_, _, dbi) => dbi,
e => panic!("`{:?}` is not an `Abs::Local(_, _, _)`.", e),
}
}
#[test]
fn trans_pi_env() {
let pi_expr = parse_str_err_printed("val t : ((a : Type) -> (b : Type(a)) -> Type(b));")
.unwrap()
.remove(0)
.body;
let pi_expr = trans_expr(pi_expr, &[], &mut Default::default(), &Default::default())
.expect("Parse failed.");
println!("{}", pi_expr);
let (_, bc) = must_be_pi(pi_expr);
let (b, c) = must_be_pi(bc);
let b = must_be_app(b);
let c = must_be_app(c);
assert_eq!(DBI(0), must_be_local(b));
assert_eq!(DBI(0), must_be_local(c));
}
#[test]
fn trans_pi_shadowing() {
let code = "val t : ((a : Type) -> (b : Type(a)) -> (b: Type(b)) -> Type(a));";
let pi_expr = parse_str_err_printed(code).unwrap().remove(0).body;
let pi_abs = trans_expr(pi_expr, &[], &mut Default::default(), &Default::default()).unwrap();
println!("{}", pi_abs);
let (_, bc) = must_be_pi(pi_abs);
let (b1, bc) = must_be_pi(bc);
let (b2, c) = must_be_pi(bc);
let b1 = must_be_app(b1);
let b2 = must_be_app(b2);
let c = must_be_app(c);
assert_eq!(DBI(0), must_be_local(b1));
assert_eq!(DBI(0), must_be_local(b2));
assert_eq!(DBI(2), must_be_local(c));
}
#[test]
fn trans_lam() {
let code = r"let l = \a . \b . \a . b a;";
let lam_expr = parse_str_err_printed(code).unwrap().remove(0).body;
let lam_abs = trans_expr(lam_expr, &[], &mut Default::default(), &Default::default()).unwrap();
println!("{}", lam_abs);
let abs_lam_ba = must_be_lam(lam_abs);
let abs_lam_a = must_be_lam(abs_lam_ba);
match must_be_lam(abs_lam_a) {
Abs::App(_, b, _, a) => {
assert_eq!(DBI(1), must_be_local(*b));
assert_eq!(DBI(0), must_be_local(*a));
}
_ => panic!(),
}
}
#[test]
fn trans_multi_param_lam() {
let code = r"let l = \a b a . b a;";
let lam_expr = parse_str_err_printed(code).unwrap().remove(0).body;
let lam_abs = trans_expr(lam_expr, &[], &mut Default::default(), &Default::default()).unwrap();
println!("{}", lam_abs);
let abs_lam_ba = must_be_lam(lam_abs);
let abs_lam_a = must_be_lam(abs_lam_ba);
match must_be_lam(abs_lam_a) {
Abs::App(_, b, _, a) => {
assert_eq!(DBI(1), must_be_local(*b));
assert_eq!(DBI(0), must_be_local(*a));
}
_ => panic!(),
}
}
#[test]
fn trans_lam_lookup_failed() {
let code = r"let l = \a . b;";
let lam_expr = parse_str_err_printed(code).unwrap().remove(0).body;
let tce = trans_expr(lam_expr, &[], &mut Default::default(), &Default::default()).unwrap_err();
match tce {
TCE::LookUpFailed(ident) => assert_eq!(ident.text, "b"),
_ => panic!(),
}
}
#[test]
fn trans_lam_global() {
let code = r"let l = \a . b;";
let lam_expr = parse_str_err_printed(code).unwrap().remove(0).body;
let ident = Ident {
text: "".to_owned(),
loc: Default::default(),
};
let lam_abs = trans_expr(
lam_expr,
&[AbsDecl::Decl(Abs::Meta(ident, MI(0)))],
&mut MI(1),
&[("b".to_string(), GI(0))].iter().cloned().collect(),
)
.unwrap();
println!("{}", lam_abs);
match lam_abs {
Abs::Lam(_, _, _, global_b) => match *global_b {
Abs::Ref(_, b_index) => assert_eq!(b_index, GI(0)),
_ => panic!(),
},
_ => panic!(),
}
}