From 28c36acc8af1e3ece9512c98aa9fd70fedf1b252 Mon Sep 17 00:00:00 2001
From: Nadrieril
Date: Mon, 6 Apr 2020 18:47:17 +0100
Subject: Avoid a few allocations

---
 dhall/src/semantics/nze/nir.rs       |  8 +++++---
 dhall/src/semantics/nze/normalize.rs | 28 +++++++++++++++-------------
 2 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/dhall/src/semantics/nze/nir.rs b/dhall/src/semantics/nze/nir.rs
index 2b7a819..0dff105 100644
--- a/dhall/src/semantics/nze/nir.rs
+++ b/dhall/src/semantics/nze/nir.rs
@@ -111,8 +111,7 @@ impl Nir {
         NirInternal::from_whnf(v).into_nir()
     }
     pub fn from_const(c: Const) -> Self {
-        let v = NirKind::Const(c);
-        NirInternal::from_whnf(v).into_nir()
+        Self::from_kind(NirKind::Const(c))
     }
     pub fn from_builtin(b: Builtin) -> Self {
         Self::from_builtin_env(b, &NzEnv::new())
@@ -148,7 +147,10 @@ impl Nir {
     }
 
     pub fn app(&self, v: Nir) -> Nir {
-        Nir::from_kind(apply_any(self.clone(), v))
+        Nir::from_kind(self.app_to_kind(v))
+    }
+    pub fn app_to_kind(&self, v: Nir) -> NirKind {
+        apply_any(self, v)
     }
 
     pub fn to_hir(&self, venv: VarEnv) -> Hir {
diff --git a/dhall/src/semantics/nze/normalize.rs b/dhall/src/semantics/nze/normalize.rs
index bf37a3c..f6782af 100644
--- a/dhall/src/semantics/nze/normalize.rs
+++ b/dhall/src/semantics/nze/normalize.rs
@@ -7,14 +7,14 @@ use crate::syntax::{
     BinOp, ExprKind, InterpolatedTextContents, Label, NumKind, OpKind,
 };
 
-pub fn apply_any(f: Nir, a: Nir) -> NirKind {
+pub fn apply_any(f: &Nir, a: Nir) -> NirKind {
     match f.kind() {
         NirKind::LamClosure { closure, .. } => closure.apply(a).kind().clone(),
         NirKind::AppliedBuiltin(closure) => closure.apply(a),
         NirKind::UnionConstructor(l, kts) => {
             NirKind::UnionLit(l.clone(), a, kts.clone())
         }
-        _ => NirKind::PartialExpr(ExprKind::Op(OpKind::App(f, a))),
+        _ => NirKind::PartialExpr(ExprKind::Op(OpKind::App(f.clone(), a))),
     }
 }
 
@@ -219,7 +219,7 @@ fn normalize_field(v: &Nir, field: &Label) -> Option<Ret> {
 
     Some(match v.kind() {
         RecordLit(kvs) => match kvs.get(field) {
-            Some(r) => ret_nir(r.clone()),
+            Some(r) => ret_ref(r),
             None => return None,
         },
         UnionType(kts) => {
@@ -229,7 +229,7 @@ fn normalize_field(v: &Nir, field: &Label) -> Option<Ret> {
         PartialExpr(Op(BinOp(RightBiasedRecordMerge, x, y))) => {
             match (x.kind(), y.kind()) {
                 (_, RecordLit(kvs)) => match kvs.get(field) {
-                    Some(r) => ret_nir(r.clone()),
+                    Some(r) => ret_ref(r),
                     None => return normalize_field(x, field),
                 },
                 (RecordLit(kvs), _) => match kvs.get(field) {
@@ -299,7 +299,7 @@ fn normalize_operation(opkind: &OpKind<Nir>) -> Option<Ret> {
     use OpKind::*;
 
     Some(match opkind {
-        App(v, a) => ret_nir(v.app(a.clone())),
+        App(v, a) => ret_kind(v.app_to_kind(a.clone())),
         BinOp(o, x, y) => return normalize_binop(*o, x, y),
         BoolIf(b, e1, e2) => {
             match b.kind() {
@@ -318,19 +318,19 @@ fn normalize_operation(opkind: &OpKind<Nir>) -> Option<Ret> {
         Merge(handlers, variant, _) => match handlers.kind() {
             RecordLit(kvs) => match variant.kind() {
                 UnionConstructor(l, _) => match kvs.get(l) {
-                    Some(h) => ret_nir(h.clone()),
+                    Some(h) => ret_ref(h),
                     None => return None,
                 },
                 UnionLit(l, v, _) => match kvs.get(l) {
-                    Some(h) => ret_nir(h.app(v.clone())),
+                    Some(h) => ret_kind(h.app_to_kind(v.clone())),
                     None => return None,
                 },
                 EmptyOptionalLit(_) => match kvs.get(&"None".into()) {
-                    Some(h) => ret_nir(h.clone()),
+                    Some(h) => ret_ref(h),
                     None => return None,
                 },
                 NEOptionalLit(v) => match kvs.get(&"Some".into()) {
-                    Some(h) => ret_nir(h.app(v.clone())),
+                    Some(h) => ret_kind(h.app_to_kind(v.clone())),
                     None => return None,
                 },
                 _ => return None,
@@ -391,7 +391,7 @@ fn normalize_operation(opkind: &OpKind<Nir>) -> Option<Ret> {
 
 pub fn normalize_one_layer(expr: ExprKind<Nir>, env: &NzEnv) -> NirKind {
     use NirKind::{
-        NEListLit, NEOptionalLit, Num, RecordLit, RecordType, UnionType,
+        Const, NEListLit, NEOptionalLit, Num, RecordLit, RecordType, UnionType,
     };
 
     match expr {
@@ -402,14 +402,16 @@ pub fn normalize_one_layer(expr: ExprKind<Nir>, env: &NzEnv) -> NirKind {
             unreachable!("This case should have been handled in normalize_hir")
         }
 
-        ExprKind::Const(c) => ret_nir(Nir::from_const(c)),
+        ExprKind::Const(c) => ret_kind(Const(c)),
         ExprKind::Num(l) => ret_kind(Num(l)),
-        ExprKind::Builtin(b) => ret_nir(Nir::from_builtin_env(b, env)),
+        ExprKind::Builtin(b) => {
+            ret_kind(NirKind::from_builtin_env(b, env.clone()))
+        }
         ExprKind::TextLit(elts) => {
             let tlit = TextLit::new(elts.into_iter());
             // Simplify bare interpolation
             if let Some(v) = tlit.as_single_expr() {
-                ret_nir(v.clone())
+                ret_ref(v)
             } else {
                 ret_kind(NirKind::TextLit(tlit))
             }
-- 
cgit v1.2.3