summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNadrieril2020-11-02 01:03:59 +0000
committerNadrieril2020-11-03 23:18:58 +0000
commit055e70f52bb0d8740ce6ac00b98ae856c29642b2 (patch)
treef2cd4fdb15cd519ff1da2a32ff5aa0cbfad54d7a
parent71c8e889610b8b9bb6155c20ca91bac4ebc9daee (diff)
Try to keep ownership of `Nir`s when convenient
The goal is that we might avoid cloning internals in the common case where a value is not shared
-rw-r--r--dhall/src/operations/normalization.rs105
-rw-r--r--dhall/src/semantics/nze/normalize.rs2
2 files changed, 52 insertions, 55 deletions
diff --git a/dhall/src/operations/normalization.rs b/dhall/src/operations/normalization.rs
index dbd58f9..e9ae825 100644
--- a/dhall/src/operations/normalization.rs
+++ b/dhall/src/operations/normalization.rs
@@ -8,52 +8,52 @@ use crate::semantics::{
};
use crate::syntax::{ExprKind, Label, NumKind};
-fn normalize_binop(o: BinOp, x: &Nir, y: &Nir) -> Ret {
+fn normalize_binop(o: BinOp, x: Nir, y: Nir) -> Ret {
use BinOp::*;
use NirKind::{EmptyListLit, NEListLit, Num, RecordLit, RecordType};
use NumKind::{Bool, Natural};
match (o, x.kind(), y.kind()) {
- (BoolAnd, Num(Bool(true)), _) => ret_ref(y),
- (BoolAnd, _, Num(Bool(true))) => ret_ref(x),
+ (BoolAnd, Num(Bool(true)), _) => ret_nir(y),
+ (BoolAnd, _, Num(Bool(true))) => ret_nir(x),
(BoolAnd, Num(Bool(false)), _) => ret_kind(Num(Bool(false))),
(BoolAnd, _, Num(Bool(false))) => ret_kind(Num(Bool(false))),
- (BoolAnd, _, _) if x == y => ret_ref(x),
+ (BoolAnd, _, _) if x == y => ret_nir(x),
(BoolOr, Num(Bool(true)), _) => ret_kind(Num(Bool(true))),
(BoolOr, _, Num(Bool(true))) => ret_kind(Num(Bool(true))),
- (BoolOr, Num(Bool(false)), _) => ret_ref(y),
- (BoolOr, _, Num(Bool(false))) => ret_ref(x),
- (BoolOr, _, _) if x == y => ret_ref(x),
- (BoolEQ, Num(Bool(true)), _) => ret_ref(y),
- (BoolEQ, _, Num(Bool(true))) => ret_ref(x),
+ (BoolOr, Num(Bool(false)), _) => ret_nir(y),
+ (BoolOr, _, Num(Bool(false))) => ret_nir(x),
+ (BoolOr, _, _) if x == y => ret_nir(x),
+ (BoolEQ, Num(Bool(true)), _) => ret_nir(y),
+ (BoolEQ, _, Num(Bool(true))) => ret_nir(x),
(BoolEQ, Num(Bool(x)), Num(Bool(y))) => ret_kind(Num(Bool(x == y))),
(BoolEQ, _, _) if x == y => ret_kind(Num(Bool(true))),
- (BoolNE, Num(Bool(false)), _) => ret_ref(y),
- (BoolNE, _, Num(Bool(false))) => ret_ref(x),
+ (BoolNE, Num(Bool(false)), _) => ret_nir(y),
+ (BoolNE, _, Num(Bool(false))) => ret_nir(x),
(BoolNE, Num(Bool(x)), Num(Bool(y))) => ret_kind(Num(Bool(x != y))),
(BoolNE, _, _) if x == y => ret_kind(Num(Bool(false))),
- (NaturalPlus, Num(Natural(0)), _) => ret_ref(y),
- (NaturalPlus, _, Num(Natural(0))) => ret_ref(x),
+ (NaturalPlus, Num(Natural(0)), _) => ret_nir(y),
+ (NaturalPlus, _, Num(Natural(0))) => ret_nir(x),
(NaturalPlus, Num(Natural(x)), Num(Natural(y))) => {
ret_kind(Num(Natural(x + y)))
}
(NaturalTimes, Num(Natural(0)), _) => ret_kind(Num(Natural(0))),
(NaturalTimes, _, Num(Natural(0))) => ret_kind(Num(Natural(0))),
- (NaturalTimes, Num(Natural(1)), _) => ret_ref(y),
- (NaturalTimes, _, Num(Natural(1))) => ret_ref(x),
+ (NaturalTimes, Num(Natural(1)), _) => ret_nir(y),
+ (NaturalTimes, _, Num(Natural(1))) => ret_nir(x),
(NaturalTimes, Num(Natural(x)), Num(Natural(y))) => {
ret_kind(Num(Natural(x * y)))
}
- (ListAppend, EmptyListLit(_), _) => ret_ref(y),
- (ListAppend, _, EmptyListLit(_)) => ret_ref(x),
+ (ListAppend, EmptyListLit(_), _) => ret_nir(y),
+ (ListAppend, _, EmptyListLit(_)) => ret_nir(x),
(ListAppend, NEListLit(xs), NEListLit(ys)) => {
ret_kind(NEListLit(xs.iter().chain(ys.iter()).cloned().collect()))
}
- (TextAppend, NirKind::TextLit(x), _) if x.is_empty() => ret_ref(y),
- (TextAppend, _, NirKind::TextLit(y)) if y.is_empty() => ret_ref(x),
+ (TextAppend, NirKind::TextLit(x), _) if x.is_empty() => ret_nir(y),
+ (TextAppend, _, NirKind::TextLit(y)) if y.is_empty() => ret_nir(x),
(TextAppend, NirKind::TextLit(x), NirKind::TextLit(y)) => {
ret_kind(NirKind::TextLit(x.concat(y)))
}
@@ -65,10 +65,10 @@ fn normalize_binop(o: BinOp, x: &Nir, y: &Nir) -> Ret {
)),
(RightBiasedRecordMerge, _, RecordLit(kvs)) if kvs.is_empty() => {
- ret_ref(x)
+ ret_nir(x)
}
(RightBiasedRecordMerge, RecordLit(kvs), _) if kvs.is_empty() => {
- ret_ref(y)
+ ret_nir(y)
}
(RightBiasedRecordMerge, RecordLit(kvs1), RecordLit(kvs2)) => {
let mut kvs = kvs2.clone();
@@ -78,13 +78,13 @@ fn normalize_binop(o: BinOp, x: &Nir, y: &Nir) -> Ret {
}
ret_kind(RecordLit(kvs))
}
- (RightBiasedRecordMerge, _, _) if x == y => ret_ref(y),
+ (RightBiasedRecordMerge, _, _) if x == y => ret_nir(y),
(RecursiveRecordMerge, _, RecordLit(kvs)) if kvs.is_empty() => {
- ret_ref(x)
+ ret_nir(x)
}
(RecursiveRecordMerge, RecordLit(kvs), _) if kvs.is_empty() => {
- ret_ref(y)
+ ret_nir(y)
}
(RecursiveRecordMerge, RecordLit(kvs1), RecordLit(kvs2)) => {
let kvs = merge_maps(kvs1, kvs2, |_, v1, v2| {
@@ -113,11 +113,9 @@ fn normalize_binop(o: BinOp, x: &Nir, y: &Nir) -> Ret {
ret_kind(RecordType(kts))
}
- (Equivalence, _, _) => {
- ret_kind(NirKind::Equivalence(x.clone(), y.clone()))
- }
+ (Equivalence, _, _) => ret_kind(NirKind::Equivalence(x, y)),
- _ => ret_op(OpKind::BinOp(o, x.clone(), y.clone())),
+ _ => ret_op(OpKind::BinOp(o, x, y)),
}
}
@@ -189,7 +187,7 @@ fn normalize_field(v: &Nir, field: &Label) -> Ret {
}
}
-pub fn normalize_operation(opkind: &OpKind<Nir>) -> Ret {
+pub fn normalize_operation(opkind: OpKind<Nir>) -> Ret {
use self::BinOp::RightBiasedRecordMerge;
use NirKind::{
EmptyListLit, EmptyOptionalLit, NEListLit, NEOptionalLit, Num, Op,
@@ -197,46 +195,45 @@ pub fn normalize_operation(opkind: &OpKind<Nir>) -> Ret {
};
use NumKind::Bool;
use OpKind::*;
- let nothing_to_do = || ret_op(opkind.clone());
match opkind {
- App(v, a) => ret_kind(v.app_to_kind(a.clone())),
- BinOp(o, x, y) => normalize_binop(*o, x, y),
+ App(v, a) => ret_kind(v.app_to_kind(a)),
+ BinOp(o, x, y) => normalize_binop(o, x, y),
BoolIf(b, e1, e2) => {
match b.kind() {
- Num(Bool(true)) => ret_ref(e1),
- Num(Bool(false)) => ret_ref(e2),
+ Num(Bool(true)) => ret_nir(e1),
+ Num(Bool(false)) => ret_nir(e2),
_ => {
match (e1.kind(), e2.kind()) {
// Simplify `if b then True else False`
- (Num(Bool(true)), Num(Bool(false))) => ret_ref(b),
- _ if e1 == e2 => ret_ref(e1),
- _ => nothing_to_do(),
+ (Num(Bool(true)), Num(Bool(false))) => ret_nir(b),
+ _ if e1 == e2 => ret_nir(e1),
+ _ => ret_op(BoolIf(b, e1, e2)),
}
}
}
}
- Merge(handlers, variant, _) => match handlers.kind() {
+ Merge(handlers, variant, ty) => match handlers.kind() {
RecordLit(kvs) => match variant.kind() {
UnionConstructor(l, _) => match kvs.get(l) {
Some(h) => ret_ref(h),
- None => nothing_to_do(),
+ None => ret_op(Merge(handlers, variant, ty)),
},
UnionLit(l, v, _) => match kvs.get(l) {
Some(h) => ret_kind(h.app_to_kind(v.clone())),
- None => nothing_to_do(),
+ None => ret_op(Merge(handlers, variant, ty)),
},
EmptyOptionalLit(_) => match kvs.get("None") {
Some(h) => ret_ref(h),
- None => nothing_to_do(),
+ None => ret_op(Merge(handlers, variant, ty)),
},
NEOptionalLit(v) => match kvs.get("Some") {
Some(h) => ret_kind(h.app_to_kind(v.clone())),
- None => nothing_to_do(),
+ None => ret_op(Merge(handlers, variant, ty)),
},
- _ => nothing_to_do(),
+ _ => ret_op(Merge(handlers, variant, ty)),
},
- _ => nothing_to_do(),
+ _ => ret_op(Merge(handlers, variant, ty)),
},
ToMap(v, annot) => match v.kind() {
RecordLit(kvs) if kvs.is_empty() => {
@@ -244,7 +241,7 @@ pub fn normalize_operation(opkind: &OpKind<Nir>) -> Ret {
Some(NirKind::ListType(t)) => {
ret_kind(EmptyListLit(t.clone()))
}
- _ => nothing_to_do(),
+ _ => ret_op(ToMap(v, annot)),
}
}
RecordLit(kvs) => ret_kind(NEListLit(
@@ -258,9 +255,9 @@ pub fn normalize_operation(opkind: &OpKind<Nir>) -> Ret {
})
.collect(),
)),
- _ => nothing_to_do(),
+ _ => ret_op(ToMap(v, annot)),
},
- Field(v, field) => normalize_field(v, field),
+ Field(v, field) => normalize_field(&v, &field),
Projection(_, ls) if ls.is_empty() => {
ret_kind(RecordLit(HashMap::new()))
}
@@ -271,12 +268,12 @@ pub fn normalize_operation(opkind: &OpKind<Nir>) -> Ret {
.collect(),
)),
Op(Projection(v2, _)) => {
- normalize_operation(&Projection(v2.clone(), ls.clone()))
+ normalize_operation(Projection(v2.clone(), ls))
}
Op(BinOp(RightBiasedRecordMerge, l, r)) => match r.kind() {
RecordLit(kvs) => {
let r_keys = kvs.keys().cloned().collect();
- normalize_operation(&BinOp(
+ normalize_operation(BinOp(
RightBiasedRecordMerge,
Nir::from_partial_expr(ExprKind::Op(Projection(
l.clone(),
@@ -288,16 +285,16 @@ pub fn normalize_operation(opkind: &OpKind<Nir>) -> Ret {
))),
))
}
- _ => nothing_to_do(),
+ _ => ret_op(Projection(v, ls)),
},
- _ => nothing_to_do(),
+ _ => ret_op(Projection(v, ls)),
},
ProjectionByExpr(v, t) => match t.kind() {
- RecordType(kts) => normalize_operation(&Projection(
- v.clone(),
+ RecordType(kts) => normalize_operation(Projection(
+ v,
kts.keys().cloned().collect(),
)),
- _ => nothing_to_do(),
+ _ => ret_op(ProjectionByExpr(v, t)),
},
With(record, labels, expr) => {
let mut current_nir: Option<Nir> = Some(record.clone());
diff --git a/dhall/src/semantics/nze/normalize.rs b/dhall/src/semantics/nze/normalize.rs
index d042f3f..3b40fac 100644
--- a/dhall/src/semantics/nze/normalize.rs
+++ b/dhall/src/semantics/nze/normalize.rs
@@ -144,7 +144,7 @@ pub fn normalize_one_layer(expr: ExprKind<Nir>, env: &NzEnv) -> NirKind {
ExprKind::UnionType(kvs) => {
ret_kind(UnionType(kvs.into_iter().collect()))
}
- ExprKind::Op(ref op) => normalize_operation(op),
+ ExprKind::Op(op) => normalize_operation(op),
ExprKind::Annot(x, _) => ret_nir(x),
ExprKind::Assert(x) => ret_kind(Assert(x)),
ExprKind::Import(..) => {