use std::rc::Rc;
use crate::{ast::*, bitype, bitype::{Ctx,Term}, subst};
macro_rules! fgi_db_normal {
( $fmt_string:expr ) => {{
}};
( $fmt_string:expr, $( $arg:expr ),* ) => {{
}}
}
#[derive(Clone,Debug,Eq,PartialEq,Hash,Serialize,PartialOrd,Ord)]
pub enum NmSetTm {
Single(NameTm),
Subset(IdxTm),
}
pub type NmSetTms = Vec<NmSetTm>;
#[derive(Clone,Debug,Eq,PartialEq,Hash,Serialize,PartialOrd,Ord)]
pub enum NmSetCons {
Union,
Apart,
}
#[derive(Clone,Debug,Eq,PartialEq,Hash,Serialize,PartialOrd,Ord)]
pub struct NmSet {
pub cons: Option<NmSetCons>,
pub terms: Vec<NmSetTm>
}
pub fn nmset_cons_join(c1:Option<NmSetCons>,
c2:Option<NmSetCons>) -> Option<NmSetCons> {
match (c1, c2) {
(None, None) => None,
(Some(c), None) => Some(c),
(None, Some(c)) => Some(c),
(Some(NmSetCons::Union),_) => Some(NmSetCons::Union),
(_,Some(NmSetCons::Union)) => Some(NmSetCons::Union),
(Some(NmSetCons::Apart),
Some(NmSetCons::Apart)) => Some(NmSetCons::Apart),
}
}
fn nmset_terms_add(cons:Option<NmSetCons>, terms:&mut Vec<NmSetTm>, tm:NmSetTm) {
match tm {
NmSetTm::Subset(i) => {
match i {
IdxTm::NmSet(mut ns) => {
assert_eq!(cons, ns.cons);
terms.append(&mut ns.terms)
}
i => {
terms.push(NmSetTm::Subset(i))
}
}
}
tm => {
terms.push(tm)
}
}
}
pub fn is_normal_nmtm(_ctx:&Ctx, n:&NameTm) -> bool {
match *n {
NameTm::Var(_) |
NameTm::ValVar(_) |
NameTm::Name(_) |
NameTm::Lam(_,_,_) => true,
NameTm::WriteScope => true,
NameTm::Bin(_,_) |
NameTm::App(_,_) => false,
NameTm::Ident(_) => false,
NameTm::NoParse(_) => false,
}
}
pub fn is_normal_idxtm(ctx:&Ctx, i:&IdxTm) -> bool {
match *i {
IdxTm::Unknown => true,
IdxTm::Ident(_) => false,
IdxTm::NmTm(ref n) => is_normal_nmtm(ctx, n),
IdxTm::NmSet(_) => false,
IdxTm::Var(ref x) => {
None == bitype::find_defs_for_idxtm_var(&ctx, &x)
}
IdxTm::Unit => true,
IdxTm::WriteScope => true,
IdxTm::Lam(_,_,_) => true,
IdxTm::Pair(ref i, ref j) => { is_normal_idxtm(ctx, i) && is_normal_idxtm(ctx, j) }
IdxTm::Proj1(_) => false,
IdxTm::Proj2(_) => false,
IdxTm::Empty |
IdxTm::Sing(_) |
IdxTm::Apart(_, _) |
IdxTm::App(_, _) |
IdxTm::Union(_, _) |
IdxTm::Bin(_, _) |
IdxTm::Map(_, _) |
IdxTm::MapStar(_, _) |
IdxTm::FlatMap(_, _) |
IdxTm::FlatMapStar(_, _) |
IdxTm::NoParse(_) => false
}
}
pub fn normal_idxtm_rec(ctx:&Ctx, i:Rc<IdxTm>) -> Rc<IdxTm> {
let r = Rc::new(normal_idxtm(ctx, (*i).clone()));
r
}
pub fn normal_idxtm(ctx:&Ctx, i:IdxTm) -> IdxTm {
if is_normal_idxtm(ctx, &i) {
return i
} else {
match i {
IdxTm::Empty => {
IdxTm::NmSet(NmSet{cons:None, terms:vec![]})
}
IdxTm::Var(ref x) => {
let xdef = bitype::find_defs_for_idxtm_var(&ctx, x);
normal_idxtm(ctx, xdef.unwrap())
}
IdxTm::Sing(n) => {
let n = normal_nmtm(ctx, n);
IdxTm::NmSet(NmSet{cons:None, terms:vec![
NmSetTm::Single( n )
]})
}
IdxTm::NmTm(n) => {
IdxTm::NmTm(normal_nmtm(ctx, n))
}
IdxTm::Ident(ref ident) => {
match ctx.lookup_idxtm_def(ident) {
Some(i) => normal_idxtm(ctx, i),
_ => {
fgi_db!("undefined idxtm: {} in\n{}", ident, ctx);
i.clone()
}
}
}
IdxTm::NmSet(ns) => {
let mut terms = vec![];
let mut cons = ns.cons.clone();
for t in ns.terms.iter() {
match t {
&NmSetTm::Single(ref n) => {
let tm = normal_nmtm(ctx, n.clone());
nmset_terms_add(cons.clone(), &mut terms, NmSetTm::Single(tm))
}
&NmSetTm::Subset(ref i) => {
let i2 = normal_idxtm(ctx, i.clone());
match i2 {
IdxTm::NmSet(ns2) => {
cons = nmset_cons_join(cons.clone(), ns2.cons.clone());
for tm2 in ns2.terms {
nmset_terms_add(cons.clone(),
&mut terms,
tm2.clone())
}
},
i => {
nmset_terms_add(cons.clone(),
&mut terms,
NmSetTm::Subset(i));
}
}
}
}
}
IdxTm::NmSet(NmSet{
cons:ns.cons.clone(),
terms:terms,
})
}
IdxTm::Apart(i1, i2) => {
let i1 = normal_idxtm_rec(ctx, i1);
let i2 = normal_idxtm_rec(ctx, i2);
match ((*i1).clone(), (*i2).clone()) {
(IdxTm::NmSet(ns1),
IdxTm::NmSet(ns2)) => {
match (ns1.cons, ns2.cons) {
(None, None) |
(None, Some(NmSetCons::Apart)) |
(Some(NmSetCons::Apart), None) |
(Some(NmSetCons::Apart), Some(NmSetCons::Apart)) => {
let mut terms1 = ns1.terms;
let mut terms2 = ns2.terms;
terms1.append(&mut terms2);
IdxTm::NmSet(NmSet{
cons:Some(NmSetCons::Apart),
terms:terms1
})
},
_ => IdxTm::Apart(i1, i2)
}}
(i, IdxTm::NmSet(mut ns)) |
(IdxTm::NmSet(mut ns), i) => {
nmset_terms_add(ns.cons.clone(), &mut ns.terms, NmSetTm::Subset(i));
IdxTm::NmSet(ns)
}
_ => {
IdxTm::NmSet(NmSet{
cons:Some(NmSetCons::Apart),
terms:vec![NmSetTm::Subset((*i1).clone()),
NmSetTm::Subset((*i2).clone())],
})
}
}
}
IdxTm::Union(i1, i2) => {
let i1 = normal_idxtm_rec(ctx, i1);
let i2 = normal_idxtm_rec(ctx, i2);
match ((*i1).clone(), (*i2).clone()) {
(IdxTm::NmSet(ns1),
IdxTm::NmSet(ns2)) => {
let mut terms1 = ns1.terms;
let mut terms2 = ns2.terms;
terms1.append(&mut terms2);
IdxTm::NmSet(NmSet{
cons:Some(NmSetCons::Union),
terms:terms1
})
}
(i, IdxTm::NmSet(mut ns)) |
(IdxTm::NmSet(mut ns), i) => {
nmset_terms_add(ns.cons.clone(), &mut ns.terms, NmSetTm::Subset(i));
IdxTm::NmSet(ns)
}
_ => {
IdxTm::NmSet(NmSet{
cons:Some(NmSetCons::Union),
terms:vec![NmSetTm::Subset((*i1).clone()),
NmSetTm::Subset((*i2).clone())],
})
}
}
}
IdxTm::Bin(i1, i2) => {
use self::NmSetTm::*;
let i1 = normal_idxtm_rec(ctx, i1);
let i2 = normal_idxtm_rec(ctx, i2);
fn bin_tm (ctx:&Ctx, tm1:NmSetTm, tm2:NmSetTm) -> NmSetTm { match (tm1, tm2) {
(Single(n), Single(m)) => {
Single(normal_nmtm(
ctx, NameTm::Bin(Rc::new(n), Rc::new(m))
))
},
(Subset(i), Single(m)) => {
Subset( normal_idxtm(
ctx, fgi_index!{
[ #x:Nm. x * (^m) ] ^i
}
))
},
(Single(n), Subset(j)) => {
Subset(normal_idxtm(
ctx, fgi_index!{
[ #x:Nm. (^n) * x ] ^j
}
))
},
(Subset(IdxTm::Var(ref x_w_def)), Subset(ref j))
if None != bitype::find_defs_for_idxtm_var(&ctx, x_w_def)
=>
{ let xdef = bitype::find_defs_for_idxtm_var(&ctx, x_w_def);
match normal_idxtm(ctx, xdef.unwrap()) {
IdxTm::NmSet(ns) => {
let mut terms = vec![];
for t in ns.terms.iter() {
match t {
&NmSetTm::Single(ref n) => {
fgi_db_normal!("Here? 1");
let tm = normal_idxtm(ctx, IdxTm::Bin(Rc::new(IdxTm::Sing(n.clone())), Rc::new(j.clone())));
nmset_terms_add(ns.cons.clone(), &mut terms, NmSetTm::Subset(tm))
}
&NmSetTm::Subset(ref i) => {
fgi_db_normal!("Here? 2");
let tm = normal_idxtm(ctx, IdxTm::Bin(Rc::new(i.clone()), Rc::new(j.clone())));
nmset_terms_add(ns.cons.clone(), &mut terms, NmSetTm::Subset(tm));
}
}
};
Subset(IdxTm::NmSet(NmSet{
cons:ns.cons.clone(),
terms:terms,
}))
},
_ => {
Subset(normal_idxtm(
ctx, IdxTm::Bin(Rc::new(IdxTm::Var(x_w_def.clone())),Rc::new(j.clone()))
))
}
}
}
(Subset(i), Subset(j)) => {
Subset(IdxTm::Bin(
Rc::new(i),
Rc::new(j)
))
},
}};
match ((*i1).clone(), (*i2).clone()) {
(IdxTm::Var(x),
IdxTm::NmSet(ns2)) =>
{
let mut terms = vec![];
for tm2 in ns2.terms.iter() {
nmset_terms_add(
ns2.cons.clone(), &mut terms,
bin_tm(ctx, NmSetTm::Subset(IdxTm::Var(x.clone())),tm2.clone()));
}
IdxTm::NmSet(NmSet{
cons:ns2.cons,
terms:terms
})
},
(IdxTm::NmSet(ns1),
IdxTm::Var(y)) =>
{
let mut terms = vec![];
for tm1 in ns1.terms.iter() {
nmset_terms_add(
ns1.cons.clone(), &mut terms,
bin_tm(ctx, tm1.clone(), NmSetTm::Subset(IdxTm::Var(y.clone()))));
}
IdxTm::NmSet(NmSet{
cons:ns1.cons,
terms:terms
})
},
(IdxTm::NmSet(ns1),
IdxTm::NmSet(ns2)) =>
{
let cons3 = nmset_cons_join(ns1.cons, ns2.cons);
let mut terms = vec![];
for tm1 in ns1.terms.iter() {
for tm2 in ns2.terms.iter() {
nmset_terms_add(
cons3.clone(), &mut terms,
bin_tm(ctx, tm1.clone(), tm2.clone()));
}
}
IdxTm::NmSet(NmSet{
cons:cons3,
terms:terms
})
},
(i, j) => {
IdxTm::Bin(Rc::new(i), Rc::new(j))
}
}
}
IdxTm::App(i1, i2) => {
let i1 = normal_idxtm_rec(ctx, i1);
let i2 = normal_idxtm_rec(ctx, i2);
match (*i1).clone() {
IdxTm::WriteScope => {
match (*i2).clone() {
IdxTm::NmSet(mut ns) => {
let mut terms = vec![];
for t in ns.terms.iter() {
match *t {
NmSetTm::Single(ref n) => {
terms.push( NmSetTm::Single(
normal_nmtm(
ctx, NameTm::App( Rc::new(NameTm::WriteScope), Rc::new(n.clone())
) ) ) )
},
NmSetTm::Subset(ref i) => {
let i =
if false {
normal_idxtm(
ctx, IdxTm::App(
Rc::new( IdxTm::WriteScope ),
Rc::new(i.clone())))
} else {
IdxTm::App(
Rc::new( IdxTm::WriteScope ),
Rc::new(i.clone()))
};
nmset_terms_add(
ns.cons.clone(),
&mut terms,
NmSetTm::Subset( i )
);
}
}
}
ns.terms = terms;
let r = normal_idxtm(ctx, IdxTm::NmSet(ns));
r
},
i2 => {
fgi_db_normal!("Here? 3");
normal_idxtm(ctx, IdxTm::Map(Rc::new(NameTm::WriteScope), Rc::new(i2)))
}
}
},
IdxTm::Lam(x,_gx,i11) => {
fgi_db_normal!("Here? 4");
let i11 = subst::subst_term_idxtm(Term::IdxTm((*i2).clone()), &x, (*i11).clone());
normal_idxtm(ctx, i11)
}
_ => IdxTm::App(i1, i2)
}
}
IdxTm::Map(n1, i2) => {
let n1 = normal_nmtm_rec(ctx, n1);
let i2 = normal_idxtm_rec(ctx, i2);
match ((*n1).clone(), (*i2).clone()) {
(NameTm::Lam(_,_,_), IdxTm::Var(ref x))
if None != bitype::find_defs_for_idxtm_var(&ctx, &x) =>
{
let xdef = bitype::find_defs_for_idxtm_var(&ctx, &x).unwrap();
match normal_idxtm(ctx, xdef) {
IdxTm::NmSet(ns) => {
let mut terms = vec![];
for t in ns.terms.iter() {
match t {
&NmSetTm::Single(ref n) => {
fgi_db_normal!("Here? 5");
let tm = normal_idxtm(ctx, IdxTm::Map(n1.clone(), Rc::new(IdxTm::Sing(n.clone()))));
nmset_terms_add(ns.cons.clone(), &mut terms, NmSetTm::Subset(tm))
}
&NmSetTm::Subset(ref i) => {
fgi_db_normal!("Here? 6");
let tm = normal_idxtm(ctx, IdxTm::Map(n1.clone(), Rc::new(i.clone())));
nmset_terms_add(ns.cons.clone(), &mut terms, NmSetTm::Subset(tm));
}
}
};
IdxTm::NmSet(NmSet{
cons:ns.cons.clone(),
terms:terms,
})
},
_ => {
IdxTm::Map(n1, i2)
}
}
}
(NameTm::Lam(_x,_gx,_n11), IdxTm::NmSet(ns2)) => {
let mut terms = vec![];
for tm2 in ns2.terms.iter() {
use self::NmSetTm::*;
let mapped_tm = match tm2.clone() {
Single(n) => {
Single(normal_nmtm(ctx, NameTm::App(n1.clone(), Rc::new(n.clone()))))
}
Subset(i) => {
Subset(IdxTm::Map(n1.clone(), Rc::new(i)))
}
};
nmset_terms_add(ns2.cons.clone(), &mut terms, mapped_tm)
};
IdxTm::NmSet(NmSet{
cons:ns2.cons,
terms:terms
})
},
(NameTm::WriteScope, IdxTm::NmSet(ns2)) => {
let mut terms = vec![];
for tm2 in ns2.terms.iter() {
use self::NmSetTm::*;
let mapped_tm = match tm2.clone() {
Single(n) => {
Single(normal_nmtm(ctx, NameTm::App(Rc::new(NameTm::WriteScope), Rc::new(n.clone()))))
}
Subset(i) => {
fgi_db_normal!("Here? 7");
Subset(IdxTm::Map(Rc::new(NameTm::WriteScope), Rc::new(i)))
}
};
nmset_terms_add(ns2.cons.clone(), &mut terms, mapped_tm)
};
IdxTm::NmSet(NmSet{
cons:ns2.cons,
terms:terms
})
},
(n1, i2) => {
IdxTm::Map(Rc::new(n1), Rc::new(i2))
}
}
}
IdxTm::MapStar(n1, i2) => {
let n1 = normal_nmtm_rec(ctx, n1);
let i2 = normal_idxtm_rec(ctx, i2);
match ((*n1).clone(), (*i2).clone()) {
(NameTm::Lam(_,_,_), IdxTm::Var(ref x))
if None != bitype::find_defs_for_idxtm_var(&ctx, &x) =>
{
let xdef = bitype::find_defs_for_idxtm_var(&ctx, &x).unwrap();
match normal_idxtm(ctx, xdef) {
IdxTm::NmSet(ns) => {
let mut terms = vec![];
for t in ns.terms.iter() {
match t {
&NmSetTm::Single(ref n) => {
fgi_db_normal!("Here? 8");
let tm = normal_idxtm(ctx, IdxTm::MapStar(n1.clone(), Rc::new(IdxTm::Sing(n.clone()))));
nmset_terms_add(ns.cons.clone(), &mut terms, NmSetTm::Subset(tm));
}
&NmSetTm::Subset(ref i) => {
fgi_db_normal!("Here? 9");
let tm = normal_idxtm(ctx, IdxTm::MapStar(n1.clone(), Rc::new(i.clone())));
nmset_terms_add(ns.cons.clone(), &mut terms, NmSetTm::Subset(tm));
}
}
};
IdxTm::NmSet(NmSet{
cons:ns.cons.clone(),
terms:terms,
})
},
_ => {
IdxTm::MapStar(n1, i2)
}
}
}
(NameTm::Lam(_,_,_), IdxTm::NmSet(ref ns2)) => {
if ns2.terms.len() == 0 {
IdxTm::NmSet(NmSet{
cons:ns2.cons.clone(),
terms:vec![]
})
} else {
let mut terms = vec![];
for tm2 in ns2.terms.iter() {
use self::NmSetTm::*;
let mapped_tm = match tm2.clone() {
Single(n) => {
Subset(IdxTm::MapStar(n1.clone(), Rc::new(IdxTm::Sing(n))))
}
Subset(i) => {
Subset(IdxTm::MapStar(n1.clone(), Rc::new(i)))
}
};
nmset_terms_add(ns2.cons.clone(), &mut terms, mapped_tm)
};
IdxTm::NmSet(NmSet{
cons:ns2.cons.clone(),
terms:terms
})
}
},
(n1, i2) => {
IdxTm::MapStar(Rc::new(n1), Rc::new(i2))
}
}
}
IdxTm::FlatMap(i1, i2) => {
let i1 = normal_idxtm_rec(ctx, i1);
let i2 = normal_idxtm_rec(ctx, i2);
match ((*i1).clone(), (*i2).clone()) {
(IdxTm::Lam(x,_gx,i11), IdxTm::NmSet(ns2)) => {
let mut terms = vec![];
for tm2 in ns2.terms.iter() {
use self::NmSetTm::*;
match tm2.clone() {
Single(n) => {
let i12 = subst::subst_term_idxtm(Term::NmTm(n.clone()), &x, (*i11).clone());
match normal_idxtm(ctx, i12) {
IdxTm::NmSet(mut ns) => {
if ns.cons == None || ns.cons == Some(NmSetCons::Apart) {
terms.append(&mut ns.terms);
ns.cons = Some(NmSetCons::Apart);
} else {
terms.push(Subset(IdxTm::NmSet(ns)))
}
}
i13 => {
nmset_terms_add(ns2.cons.clone(), &mut terms, Subset(i13))
}
}
}
Subset(i) => {
fgi_db_normal!("Here? 9");
nmset_terms_add(
ns2.cons.clone(),
&mut terms,
NmSetTm::Subset(normal_idxtm(ctx, IdxTm::FlatMap(i1.clone(), Rc::new(i))))
);
}
};
};
IdxTm::NmSet(NmSet{
cons:ns2.cons,
terms:terms
})
},
(IdxTm::Lam(_,_,_), IdxTm::Var(ref x))
if None != bitype::find_defs_for_idxtm_var(&ctx, &x) =>
{
let xdef = bitype::find_defs_for_idxtm_var(&ctx, &x).unwrap();
match normal_idxtm(ctx, xdef) {
IdxTm::NmSet(ns) => {
let mut terms = vec![];
for t in ns.terms.iter() {
match t {
&NmSetTm::Single(ref n) => {
fgi_db_normal!("Here? 10");
let tm = normal_idxtm(ctx, IdxTm::FlatMap(i1.clone(), Rc::new(IdxTm::Sing(n.clone()))));
nmset_terms_add(ns.cons.clone(), &mut terms, NmSetTm::Subset(tm))
}
&NmSetTm::Subset(ref i) => {
fgi_db_normal!("Here? 11");
let tm = normal_idxtm(ctx, IdxTm::FlatMap(i1.clone(), Rc::new(i.clone())));
nmset_terms_add(ns.cons.clone(), &mut terms, NmSetTm::Subset(tm));
}
}
};
IdxTm::NmSet(NmSet{
cons:ns.cons.clone(),
terms:terms,
})
},
_ => {
IdxTm::FlatMap(i1, i2)
}
}
}
(IdxTm::Lam(x,gx,body), j) => { match (*body).clone() {
IdxTm::Sing(body_nmtm) => {
fgi_db_normal!("Here? 11");
normal_idxtm(
ctx,
IdxTm::Map(Rc::new(NameTm::Lam(x,gx,Rc::new(body_nmtm))),
Rc::new(j))
)
},
IdxTm::Apart(body_l, body_r) => {
fgi_db_normal!("Here? 12");
normal_idxtm(
ctx,
IdxTm::Apart(
Rc::new(normal_idxtm(
ctx,
IdxTm::FlatMap(
Rc::new(IdxTm::Lam(x.clone(), gx.clone(), body_l)),
Rc::new(j.clone())
))),
Rc::new(normal_idxtm(
ctx,
IdxTm::FlatMap(
Rc::new(IdxTm::Lam(x.clone(), gx.clone(), body_r)),
Rc::new(j)
))),
))
},
_ => {
IdxTm::FlatMap(i1, i2)
}
}},
_tm => {
IdxTm::FlatMap(i1, i2)
}
}
},
IdxTm::FlatMapStar(i, j) => {
let i = normal_idxtm_rec(ctx, i);
let j = normal_idxtm_rec(ctx, j);
match ((*i).clone(), (*j).clone()) {
(IdxTm::Lam(_,_,_), IdxTm::Var(ref x))
if None != bitype::find_defs_for_idxtm_var(&ctx, &x) =>
{
let xdef = bitype::find_defs_for_idxtm_var(&ctx, &x).unwrap();
match normal_idxtm(ctx, xdef) {
IdxTm::NmSet(ns) => {
let mut terms = vec![];
for t in ns.terms.iter() {
match t {
&NmSetTm::Single(ref n) => {
fgi_db_normal!("Here? 12");
let tm = normal_idxtm(ctx, IdxTm::FlatMapStar(i.clone(), Rc::new(IdxTm::Sing(n.clone()))));
nmset_terms_add(
ns.cons.clone(),
&mut terms,
NmSetTm::Subset(tm)
);
}
&NmSetTm::Subset(ref j) => {
fgi_db_normal!("Here? 13");
let tm = normal_idxtm(ctx, IdxTm::FlatMapStar(i.clone(), Rc::new(j.clone())));
nmset_terms_add(
ns.cons.clone(),
&mut terms,
NmSetTm::Subset(tm)
);
}
}
};
IdxTm::NmSet(NmSet{
cons:ns.cons.clone(),
terms:terms,
})
},
_ => {
IdxTm::FlatMapStar(i, j)
}
}
},
(IdxTm::Lam(x,gx,body),_) => { match (*body).clone() {
IdxTm::Sing(body_nmtm) => {
fgi_db_normal!("Here? 14");
IdxTm::MapStar(Rc::new(NameTm::Lam(x,gx,Rc::new(body_nmtm))), j)
},
IdxTm::Apart(body_l, body_r) => {
fgi_db_normal!("Here? 15");
normal_idxtm(
ctx,
IdxTm::Apart(
Rc::new(normal_idxtm(
ctx,
IdxTm::FlatMapStar(
Rc::new(IdxTm::Lam(x.clone(), gx.clone(), body_l)),
j.clone()
))),
Rc::new(normal_idxtm(
ctx,
IdxTm::FlatMapStar(
Rc::new(IdxTm::Lam(x.clone(), gx.clone(), body_r)), j
))),
))
},
_ => {
IdxTm::FlatMapStar(i, j)
}
}},
(_, _) => {
IdxTm::FlatMapStar(i, j)
}
}
}
i_othercase => {
i_othercase
}
}
}
}
pub fn normal_nmtm(ctx:&Ctx, n:NameTm) -> NameTm {
if is_normal_nmtm(ctx, &n) {
return n
} else {
match n {
NameTm::Ident(x) => {
match ctx.lookup_nmtm_def(&x) {
Some(a) => {
normal_nmtm(ctx, a)
},
_ => {
fgi_db!("undefined name term: {} in\n{}", x, ctx);
NameTm::Ident(x.clone())
}
}
}
NameTm::Bin(n1,n2) => {
let n1 = normal_nmtm_rec(ctx, n1);
let n2 = normal_nmtm_rec(ctx, n2);
match ((*n1).clone(),(*n2).clone()) {
(NameTm::Name(n1),
NameTm::Name(n2)) => {
NameTm::Name(
Name::Bin(Rc::new(n1),
Rc::new(n2)))
},
_ => NameTm::Bin(n1,n2)
}
},
NameTm::App(n1,n2) => {
let n1 = normal_nmtm_rec(ctx, n1);
let n2 = normal_nmtm_rec(ctx, n2);
match ((*n1).clone(), (*n2).clone()) {
(NameTm::Lam(x, _xg, n11), n2) => {
let n12 = subst::subst_nmtm_rec(n2, &x, n11);
normal_nmtm(ctx, (*n12).clone())
},
_ => NameTm::App(n1,n2)
}
},
n_othercase => n_othercase
}
}
}
pub fn normal_nmtm_rec(ctx:&Ctx, n:Rc<NameTm>) -> Rc<NameTm> {
Rc::new(normal_nmtm(ctx, (*n).clone()))
}
pub fn idxtm_of_nmsettms(tms:&NmSetTms) -> IdxTm {
let mut i : IdxTm = IdxTm::Empty;
for t in tms.iter() {
i = IdxTm::Apart(
Rc::new({
match (*t).clone() {
NmSetTm::Single(m) => IdxTm::Sing(m),
NmSetTm::Subset(i) => i.clone()
}
}),
Rc::new(i)
);
}
return i
}
pub fn normal_type(ctx:&Ctx, typ:&Type) -> Type {
db_region_open!(false);
fgi_db!("normal({}) ~~> ?", typ);
let res = match typ {
&Type::Unit |
&Type::Var(_) |
&Type::NoParse(_)
=>
typ.clone(),
&Type::Rec(_, _) |
&Type::Nm(_) |
&Type::NmFn(_) |
&Type::TypeFn(_,_,_)|
&Type::IdxFn(_,_,_)
=>
typ.clone(),
&Type::Thk(ref i, ref ce) => {
Type::Thk(normal_idxtm(ctx,i.clone()),
Rc::new(normal_ceffect(ctx, (**ce).clone())))
}
&Type::Ref(ref i, ref a) => {
Type::Ref(normal_idxtm(ctx,i.clone()),
Rc::new(normal_type(ctx, a)))
}
&Type::Sum(ref a, ref b) => {
Type::Sum(Rc::new(normal_type(ctx, a)),
Rc::new(normal_type(ctx, b)))
}
&Type::Prod(ref a, ref b) => {
Type::Prod(Rc::new(normal_type(ctx, a)),
Rc::new(normal_type(ctx, b)))
}
&Type::Exists(ref x, ref g, ref p, ref t) => {
let t2 = normal_type(ctx, t);
Type::Exists(x.clone(), g.clone(), p.clone(), Rc::new(t2))
}
&Type::Ident(ref x) => {
crate::expand::expand_type(ctx, Type::Ident(x.clone()))
},
&Type::IdentDef(ref _ident, ref def) => {
(**def).clone()
},
&Type::Prim(ref pt) => { Type::Prim(pt.clone()) },
&Type::Abstract(ref x) => { Type::Abstract(x.clone()) },
&Type::IdentUndef(ref x) => { Type::IdentUndef(x.clone()) },
&Type::TypeApp(ref a, ref b) => {
let a = normal_type(ctx, a);
let b = normal_type(ctx, b);
match a {
Type::TypeFn(ref x, ref _k, ref body) => {
let body = subst::subst_type_type(b,x,(**body).clone());
normal_type(ctx, &body)
},
a => {
Type::TypeApp(Rc::new(a), Rc::new(b))
}
}
}
&Type::IdxApp(ref a, ref i) => {
let a = normal_type(ctx, a);
let i = normal_idxtm(ctx, i.clone());
match a {
Type::IdxFn(ref x, ref _g, ref body) => {
let body = subst::subst_idxtm_type(i.clone(),x,(**body).clone());
normal_type(ctx, &body)
},
a => {
Type::IdxApp(Rc::new(a), i.clone())
}
}
}
};
fgi_db!("normal({}) ~~> {}", typ, res);
db_region_close!();
res
}
pub fn normal_ctype(ctx:&Ctx, ct:CType) -> CType {
match ct {
CType::Lift(a) => {
CType::Lift(normal_type(ctx, &a))
}
CType::Arrow(a, ce) => {
CType::Arrow(normal_type(ctx, &a),
normal_ceffect_rec(ctx, ce))
}
CType::NoParse(s) => CType::NoParse(s)
}
}
pub fn normal_effect(ctx:&Ctx, eff:Effect) -> Effect {
match eff {
Effect::WR(i, j) => {
Effect::WR(normal_idxtm(ctx, i),
normal_idxtm(ctx, j))
},
Effect::NoParse(s) => Effect::NoParse(s)
}
}
pub fn normal_ceffect(ctx:&Ctx, ce:CEffect) -> CEffect {
db_region_open!(false);
fgi_db!("normal({}) ~~> ?", ce);
let res = match ce.clone() {
CEffect::Cons(ct, eff) => {
CEffect::Cons(normal_ctype(ctx, ct),
normal_effect(ctx, eff))
}
CEffect::ForallType(y, k, ce) => {
CEffect::ForallType(y, k, normal_ceffect_rec(ctx, ce))
}
CEffect::ForallIdx(y, g, p, ce) => {
CEffect::ForallIdx(y, g,
p.clone(),
normal_ceffect_rec(ctx, ce))
}
CEffect::NoParse(s) => CEffect::NoParse(s)
};
fgi_db!("normal({}) ~~> {}", ce, res);
db_region_close!();
res
}
pub fn normal_ceffect_rec(ctx:&Ctx, ce:Rc<CEffect>) -> Rc<CEffect> {
Rc::new(normal_ceffect(ctx, (*ce).clone()))
}
pub fn match_ceffect(ctx:&Ctx, ce:CEffect) -> CEffect {
db_region_open!(false);
fgi_db!("match_ceffect({}) ~~> ?", ce);
let res = match ce.clone() {
CEffect::Cons(ce, eff) => CEffect::Cons(match_ctype(ctx, ce), eff),
ce => ce
};
fgi_db!("match_ceffect({}) ~~> {}", ce, res);
db_region_close!();
res
}
pub fn match_ctype(ctx:&Ctx, ct:CType) -> CType {
match ct {
CType::Lift(ref a) => CType::Lift(match_type(ctx, a)),
ct => ct
}
}
pub fn match_type_rec(ctx:&Ctx, t:&TypeRec) -> TypeRec {
Rc::new(match_type(ctx, &**t))
}
pub fn match_type(ctx:&Ctx, t:&Type) -> Type {
db_region_open!(false);
fgi_db!("match_type({}) ~~> ?", t);
let res = match t.clone() {
Type::IdxApp(ref t, ref i) => {
normal_type
(&Ctx::Empty,
&Type::IdxApp(crate::expand::expand_type_rec(ctx, t.clone()), i.clone()))
},
Type::IdentDef(_, ref t) => (**t).clone(),
Type::Ident(ref x) => {
crate::expand::expand_type(ctx, Type::Ident(x.clone()))
},
t => t,
};
fgi_db!("match_type({}) ~~> {}", t, res);
db_region_close!();
res
}
pub fn unroll_type(ctx:&Ctx, typ:&Type) -> (Type, bool) {
db_region_open!(false);
fgi_db!("unroll_type({}) ~~> ?", typ);
let (res, flag) = match typ {
&Type::Rec(ref x, ref a) => {
(subst::subst_type_type(typ.clone(), x, (**a).clone()), true)
}
&Type::IdxApp(ref t, ref i) => {
let (t2, b) = unroll_type(ctx, t);
(Type::IdxApp(Rc::new(t2), i.clone()), b)
},
&Type::TypeApp(ref t1, ref t2) => {
let (t12, b) = unroll_type(ctx, t1);
(Type::TypeApp(Rc::new(t12), t2.clone()), b)
},
&Type::IdentDef(_, ref xdef) => {
unroll_type(ctx, &**xdef)
},
&Type::Ident(_) => {
unroll_type(ctx, &crate::expand::expand_type(ctx, typ.clone()))
},
_ => {
(typ.clone(), false)
}
};
if flag {
fgi_db!("unroll_type({}) ~~> {}", typ, res);
} else {
fgi_db!("unroll_type: failed to unroll: {}", typ);
}
db_region_close!();
(res, flag)
}