diff options
author | NanoTech | 2016-12-11 23:04:11 +0000 |
---|---|---|
committer | NanoTech | 2017-03-10 23:48:29 -0600 |
commit | 93def475f7c9b241b62cd29cfe9ac8410a19cb07 (patch) | |
tree | 3fa4b4048bc425c8ccef9f51798b868d1b1a432f | |
parent | 2893c14936a3c5f03ad520347e3c2b281b65555e (diff) |
Implement all subst cases
-rw-r--r-- | src/core.rs | 59 |
1 files changed, 51 insertions, 8 deletions
diff --git a/src/core.rs b/src/core.rs index 71b6b14..c5a475e 100644 --- a/src/core.rs +++ b/src/core.rs @@ -513,6 +513,13 @@ fn map_record_value<'a, I, K, V, U, F>(it: I, f: F) -> BTreeMap<K, U> it.into_iter().map(|(&k, v)| (k, f(v))).collect() } +fn map_op2<T, U, V, F, G>(f: F, g: G, a: T, b: T) -> V + where F: FnOnce(U, U) -> V, + G: Fn(T) -> U, +{ + f(g(a), g(b)) +} + /// `shift` is used by both normalization and type-checking to avoid variable /// capture by shifting variable indices /// @@ -668,7 +675,7 @@ fn shift_op2<'i, S, T, A, F>(f: F, where F: FnOnce(Box<Expr<'i, T, A>>, Box<Expr<'i, T, A>>) -> Expr<'i, T, A>, A: Clone { - f(bx(shift(d, v, a)), bx(shift(d, v, b))) + map_op2(f, |x| bx(shift(d, v, x)), a, b) } /// Substitute all occurrences of a variable with an expression @@ -678,9 +685,8 @@ fn shift_op2<'i, S, T, A, F>(f: F, /// ``` /// pub fn subst<'i, S, T, A>(v: V<'i>, e: &Expr<'i, S, A>, b: &Expr<'i, T, A>) -> Expr<'i, S, A> - where S: Clone + fmt::Debug, - T: Clone + fmt::Debug, - A: Clone + fmt::Debug + where S: Clone, + A: Clone { use Expr::*; let V(x, n) = v; @@ -711,28 +717,65 @@ pub fn subst<'i, S, T, A>(v: V<'i>, e: &Expr<'i, S, A>, b: &Expr<'i, T, A>) -> E let r2 = subst(V(x, n), e, r); Let(f, mt2, bx(r2), bx(b2)) } + &Annot(ref a, ref b) => subst_op2(Annot, v, e, a, b), &BuiltinType(t) => BuiltinType(t), &BuiltinValue(v) => BuiltinValue(v), &BoolLit(a) => BoolLit(a), + &BoolAnd(ref a, ref b) => subst_op2(BoolAnd, v, e, a, b), + &BoolOr(ref a, ref b) => subst_op2(BoolOr, v, e, a, b), + &BoolEQ(ref a, ref b) => subst_op2(BoolEQ, v, e, a, b), + &BoolNE(ref a, ref b) => subst_op2(BoolNE, v, e, a, b), + &BoolIf(ref a, ref b, ref c) => { + BoolIf(bx(subst(v, e, a)), bx(subst(v, e, b)), bx(subst(v, e, c))) + } &NaturalLit(a) => NaturalLit(a), - &NaturalPlus(ref a, ref b) => NaturalPlus(bx(subst(v, e, a)), bx(subst(v, e, b))), - &NaturalTimes(ref a, ref b) => NaturalTimes(bx(subst(v, e, a)), bx(subst(v, e, b))), + &NaturalPlus(ref a, ref b) => subst_op2(NaturalPlus, v, e, a, b), + &NaturalTimes(ref a, ref b) => subst_op2(NaturalTimes, v, e, a, b), &IntegerLit(a) => IntegerLit(a), &DoubleLit(a) => DoubleLit(a), &TextLit(ref a) => TextLit(a.clone()), + &TextAppend(ref a, ref b) => subst_op2(TextAppend, v, e, a, b), &ListLit(ref a, ref b) => { let a2 = subst(v, e, a); let b2 = b.iter().map(|be| subst(v, e, be)).collect(); ListLit(bx(a2), b2) } + &OptionalLit(ref a, ref b) => { + let a2 = subst(v, e, a); + let b2 = b.iter().map(|be| subst(v, e, be)).collect(); + OptionalLit(bx(a2), b2) + } &Record(ref kts) => Record(map_record_value(kts, |t| subst(v, e, t))), - &RecordLit(ref kvs) => Record(map_record_value(kvs, |val| subst(v, e, val))), + &RecordLit(ref kvs) => RecordLit(map_record_value(kvs, |val| subst(v, e, val))), + &Union(ref kts) => Union(map_record_value(kts, |t| subst(v, e, t))), + &UnionLit(k, ref uv, ref kvs) => { + UnionLit(k, + bx(subst(v, e, uv)), + map_record_value(kvs, |val| subst(v, e, val))) + } + &Combine(ref a, ref b) => subst_op2(Combine, v, e, a, b), + &Merge(ref a, ref b, ref c) => { + Merge(bx(subst(v, e, a)), bx(subst(v, e, b)), bx(subst(v, e, c))) + } &Field(ref a, b) => Field(bx(subst(v, e, a)), b), &Note(_, ref b) => subst(v, e, b), - b => panic!("Unimplemented subst case: {:?}", b), + &Embed(ref p) => Embed(p.clone()), } } +fn subst_op2<'i, S, T, A, F>(f: F, + v: V<'i>, + e: &Expr<'i, S, A>, + a: &Expr<'i, T, A>, + b: &Expr<'i, T, A>) + -> Expr<'i, S, A> + where F: FnOnce(Box<Expr<'i, S, A>>, Box<Expr<'i, S, A>>) -> Expr<'i, S, A>, + S: Clone, + A: Clone +{ + map_op2(f, |x| bx(subst(v, e, x)), a, b) +} + /// Reduce an expression to its normal form, performing beta reduction /// /// `normalize` does not type-check the expression. You may want to type-check |