From 17732b041dbd44f39ce3d04a289146db9882e865 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 30 Jan 2020 11:53:37 +0000 Subject: Encapsulate partially applied builtin in a separate struct --- dhall/src/semantics/builtins.rs | 80 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 3 deletions(-) (limited to 'dhall/src/semantics/builtins.rs') diff --git a/dhall/src/semantics/builtins.rs b/dhall/src/semantics/builtins.rs index 0b105c7..a23591e 100644 --- a/dhall/src/semantics/builtins.rs +++ b/dhall/src/semantics/builtins.rs @@ -1,5 +1,7 @@ use crate::semantics::phase::Normalized; -use crate::semantics::{typecheck, NzEnv, Value, ValueKind}; +use crate::semantics::{ + typecheck, NzEnv, TyExpr, TyExprKind, Value, ValueKind, VarEnv, +}; use crate::syntax::map::DupTreeMap; use crate::syntax::Const::Type; use crate::syntax::{ @@ -9,6 +11,66 @@ use crate::syntax::{ use std::collections::HashMap; use std::convert::TryInto; +/// A partially applied builtin. +/// Invariant: TODO +#[derive(Debug, Clone)] +pub(crate) struct BuiltinClosure { + pub env: NzEnv, + pub b: Builtin, + /// Arguments applied to the closure so far. + pub args: Vec, + /// Keeps the types of the partial applications around to be able to convert back to TyExpr. + /// If the args so far are `x_1`, ..., `x_n`, this contains the types of `b`, `b x1`, ..., + /// `b x_1 x_2 ... x_(n-1)`. + pub types: Vec, +} + +impl BuiltinClosure { + pub fn new(b: Builtin, env: NzEnv) -> Self { + BuiltinClosure { + env, + b, + args: Vec::new(), + types: Vec::new(), + } + } + + pub fn apply( + &self, + a: Value, + f_ty: Value, + ret_ty: &Value, + ) -> ValueKind { + use std::iter::once; + let args = self.args.iter().cloned().chain(once(a.clone())).collect(); + let types = self.types.iter().cloned().chain(once(f_ty)).collect(); + apply_builtin(self.b, args, ret_ty, types, self.env.clone()) + } + pub fn ensure_whnf(self, ret_ty: &Value) -> ValueKind { + apply_builtin(self.b, self.args, ret_ty, self.types, self.env) + } + pub fn normalize_mut(&mut self) { + for x in self.args.iter_mut() { + x.normalize_mut(); + } + } + pub fn to_tyexprkind(&self, venv: VarEnv) -> TyExprKind { + TyExprKind::Expr(self.args.iter().zip(self.types.iter()).fold( + ExprKind::Builtin(self.b), + |acc, (v, ty)| { + ExprKind::App( + TyExpr::new( + TyExprKind::Expr(acc), + Some(ty.clone()), + Span::Artificial, + ), + v.to_tyexpr(venv), + ) + }, + )) + } +} + pub(crate) fn rc(x: UnspannedExpr) -> Expr { Expr::new(x, Span::Artificial) } @@ -208,7 +270,7 @@ macro_rules! make_closure { } #[allow(clippy::cognitive_complexity)] -pub(crate) fn apply_builtin( +fn apply_builtin( b: Builtin, args: Vec, ty: &Value, @@ -488,6 +550,18 @@ pub(crate) fn apply_builtin( match ret { Ret::ValueKind(v) => v, Ret::Value(v) => v.to_whnf_check_type(ty), - Ret::DoneAsIs => AppliedBuiltin(b, args, types, env), + Ret::DoneAsIs => AppliedBuiltin(BuiltinClosure { + b, + args, + types, + env, + }), + } +} + +impl std::cmp::PartialEq for BuiltinClosure { + fn eq(&self, other: &Self) -> bool { + self.b == other.b && self.args == other.args } } +impl std::cmp::Eq for BuiltinClosure {} -- cgit v1.2.3