From c785b7c0c6cd8b3b1cc15eb79caf982a757020ba Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 6 Dec 2020 23:55:21 +0000 Subject: Thread cx through normalization --- dhall/src/semantics/resolve/cache.rs | 24 ++++++++++++++----- dhall/src/semantics/resolve/env.rs | 13 +++++++---- dhall/src/semantics/resolve/hir.rs | 42 +++++++++++++++++++--------------- dhall/src/semantics/resolve/resolve.rs | 32 ++++++++++++++++---------- 4 files changed, 69 insertions(+), 42 deletions(-) (limited to 'dhall/src/semantics/resolve') diff --git a/dhall/src/semantics/resolve/cache.rs b/dhall/src/semantics/resolve/cache.rs index b00a2d5..59463dd 100644 --- a/dhall/src/semantics/resolve/cache.rs +++ b/dhall/src/semantics/resolve/cache.rs @@ -5,7 +5,7 @@ use std::path::{Path, PathBuf}; use crate::error::{CacheError, Error}; use crate::parse::parse_binary; use crate::syntax::{binary, Hash}; -use crate::Typed; +use crate::{Ctxt, Typed}; use std::ffi::OsStr; use std::fs::File; @@ -52,9 +52,13 @@ impl Cache { self.cache_dir.join(filename_for_hash(hash)) } - pub fn get(&self, hash: &Hash) -> Result { + pub fn get<'cx>( + &self, + cx: Ctxt<'cx>, + hash: &Hash, + ) -> Result, Error> { let path = self.entry_path(hash); - let res = read_cache_file(&path, hash); + let res = read_cache_file(cx, &path, hash); if res.is_err() && path.exists() { // Delete cache file since it's invalid. We ignore the error. let _ = std::fs::remove_file(&path); @@ -62,14 +66,22 @@ impl Cache { res } - pub fn insert(&self, hash: &Hash, expr: &Typed) -> Result<(), Error> { + pub fn insert<'cx>( + &self, + hash: &Hash, + expr: &Typed<'cx>, + ) -> Result<(), Error> { let path = self.entry_path(hash); write_cache_file(&path, expr) } } /// Read a file from the cache, also checking that its hash is valid. -fn read_cache_file(path: &Path, hash: &Hash) -> Result { +fn read_cache_file<'cx>( + cx: Ctxt<'cx>, + path: &Path, + hash: &Hash, +) -> Result, Error> { let data = crate::utils::read_binary_file(path)?; match hash { @@ -81,7 +93,7 @@ fn read_cache_file(path: &Path, hash: &Hash) -> Result { } } - Ok(parse_binary(&data)?.skip_resolve()?.typecheck()?) + Ok(parse_binary(&data)?.skip_resolve()?.typecheck(cx)?) } /// Write a file to the cache. diff --git a/dhall/src/semantics/resolve/env.rs b/dhall/src/semantics/resolve/env.rs index 82f21e8..2b998f8 100644 --- a/dhall/src/semantics/resolve/env.rs +++ b/dhall/src/semantics/resolve/env.rs @@ -86,9 +86,12 @@ impl<'cx> ImportEnv<'cx> { Some(*self.mem_cache.get(location)?) } - pub fn get_from_disk_cache(&self, hash: &Option) -> Option { + pub fn get_from_disk_cache( + &self, + hash: &Option, + ) -> Option> { let hash = hash.as_ref()?; - let expr = self.disk_cache.as_ref()?.get(hash).ok()?; + let expr = self.disk_cache.as_ref()?.get(self.cx(), hash).ok()?; Some(expr) } @@ -100,7 +103,7 @@ impl<'cx> ImportEnv<'cx> { self.mem_cache.insert(location, result); } - pub fn write_to_disk_cache(&self, hash: &Option, expr: &Typed) { + pub fn write_to_disk_cache(&self, hash: &Option, expr: &Typed<'cx>) { if let Some(disk_cache) = self.disk_cache.as_ref() { if let Some(hash) = hash { let _ = disk_cache.insert(hash, &expr); @@ -111,8 +114,8 @@ impl<'cx> ImportEnv<'cx> { pub fn with_cycle_detection( &mut self, location: ImportLocation, - do_resolve: impl FnOnce(&mut Self) -> Result, - ) -> Result { + do_resolve: impl FnOnce(&mut Self) -> Result, Error>, + ) -> Result, Error> { if self.stack.contains(&location) { return Err( ImportError::ImportCycle(self.stack.clone(), location).into() diff --git a/dhall/src/semantics/resolve/hir.rs b/dhall/src/semantics/resolve/hir.rs index c2d1883..c67ab75 100644 --- a/dhall/src/semantics/resolve/hir.rs +++ b/dhall/src/semantics/resolve/hir.rs @@ -10,19 +10,19 @@ pub struct AlphaVar { } #[derive(Debug, Clone, PartialEq, Eq)] -pub enum HirKind { +pub enum HirKind<'cx> { /// A resolved variable (i.e. a DeBruijn index) Var(AlphaVar), /// Result of resolving an import. - Import(Hir, Type), + Import(Hir<'cx>, Type<'cx>), // Forbidden ExprKind variants: Var, Import, Completion - Expr(ExprKind), + Expr(ExprKind>), } // An expression with resolved variables and imports. #[derive(Debug, Clone)] -pub struct Hir { - kind: Box, +pub struct Hir<'cx> { + kind: Box>, span: Span, } @@ -35,15 +35,15 @@ impl AlphaVar { } } -impl Hir { - pub fn new(kind: HirKind, span: Span) -> Self { +impl<'cx> Hir<'cx> { + pub fn new(kind: HirKind<'cx>, span: Span) -> Self { Hir { kind: Box::new(kind), span, } } - pub fn kind(&self) -> &HirKind { + pub fn kind(&self) -> &HirKind<'cx> { &*self.kind } pub fn span(&self) -> Span { @@ -63,7 +63,7 @@ impl Hir { let opts = ToExprOptions { alpha: true }; self.to_expr(opts) } - pub fn to_expr_tyenv(&self, env: &TyEnv) -> Expr { + pub fn to_expr_tyenv(&self, env: &TyEnv<'cx>) -> Expr { let opts = ToExprOptions { alpha: false }; let mut env = env.as_nameenv().clone(); hir_to_expr(self, opts, &mut env) @@ -72,29 +72,33 @@ impl Hir { /// Typecheck the Hir. pub fn typecheck<'hir>( &'hir self, - env: &TyEnv, - ) -> Result, TypeError> { + env: &TyEnv<'cx>, + ) -> Result, TypeError> { type_with(env, self, None) } pub fn typecheck_noenv<'hir>( &'hir self, - cx: Ctxt<'_>, - ) -> Result, TypeError> { + cx: Ctxt<'cx>, + ) -> Result, TypeError> { self.typecheck(&TyEnv::new(cx)) } /// Eval the Hir. It will actually get evaluated only as needed on demand. - pub fn eval(&self, env: impl Into) -> Nir { + pub fn eval(&self, env: impl Into>) -> Nir<'cx> { Nir::new_thunk(env.into(), self.clone()) } /// Eval a closed Hir (i.e. without free variables). It will actually get evaluated only as /// needed on demand. - pub fn eval_closed_expr(&self) -> Nir { - self.eval(NzEnv::new()) + pub fn eval_closed_expr(&self, cx: Ctxt<'cx>) -> Nir<'cx> { + self.eval(NzEnv::new(cx)) } } -fn hir_to_expr(hir: &Hir, opts: ToExprOptions, env: &mut NameEnv) -> Expr { +fn hir_to_expr<'cx>( + hir: &Hir<'cx>, + opts: ToExprOptions, + env: &mut NameEnv, +) -> Expr { let kind = match hir.kind() { HirKind::Var(v) if opts.alpha => ExprKind::Var(V("_".into(), v.idx())), HirKind::Var(v) => ExprKind::Var(env.label_var(*v)), @@ -127,9 +131,9 @@ fn hir_to_expr(hir: &Hir, opts: ToExprOptions, env: &mut NameEnv) -> Expr { Expr::new(kind, hir.span()) } -impl std::cmp::PartialEq for Hir { +impl<'cx> std::cmp::PartialEq for Hir<'cx> { fn eq(&self, other: &Self) -> bool { self.kind == other.kind } } -impl std::cmp::Eq for Hir {} +impl<'cx> std::cmp::Eq for Hir<'cx> {} diff --git a/dhall/src/semantics/resolve/resolve.rs b/dhall/src/semantics/resolve/resolve.rs index cf72f80..488c516 100644 --- a/dhall/src/semantics/resolve/resolve.rs +++ b/dhall/src/semantics/resolve/resolve.rs @@ -231,12 +231,13 @@ impl ImportLocation { &self, env: &mut ImportEnv<'cx>, span: Span, - ) -> Result { + ) -> Result, Error> { let (hir, ty) = match self.mode { ImportMode::Code => { let parsed = self.kind.fetch_dhall()?; - let typed = resolve_with_env(env, parsed)?.typecheck()?; - let hir = typed.normalize().to_hir(); + let typed = + resolve_with_env(env, parsed)?.typecheck(env.cx())?; + let hir = typed.normalize(env.cx()).to_hir(); (hir, typed.ty) } ImportMode::RawText => { @@ -245,7 +246,7 @@ impl ImportLocation { HirKind::Expr(ExprKind::TextLit(text.into())), span, ); - (hir, Type::from_builtin(Builtin::Text)) + (hir, Type::from_builtin(env.cx(), Builtin::Text)) } ImportMode::Location => { let expr = self.kind.to_location(); @@ -286,7 +287,11 @@ fn make_aslocation_uniontype() -> Expr { mkexpr(ExprKind::UnionType(union)) } -fn check_hash(import: &Import, typed: &Typed, span: Span) -> Result<(), Error> { +fn check_hash<'cx>( + import: &Import, + typed: &Typed<'cx>, + span: Span, +) -> Result<(), Error> { if let (ImportMode::Code, Some(Hash::SHA256(hash))) = (import.mode, &import.hash) { @@ -338,11 +343,11 @@ fn desugar(expr: &Expr) -> Cow<'_, Expr> { /// Traverse the expression, handling import alternatives and passing /// found imports to the provided function. Also resolving names. -fn traverse_resolve_expr( +fn traverse_resolve_expr<'cx>( name_env: &mut NameEnv, expr: &Expr, - f: &mut impl FnMut(Import, Span) -> Result, -) -> Result { + f: &mut impl FnMut(Import, Span) -> Result, Error>, +) -> Result, Error> { let expr = desugar(expr); Ok(match expr.kind() { ExprKind::Var(var) => match name_env.unlabel_var(&var) { @@ -447,7 +452,7 @@ fn fetch_import<'cx>( fn resolve_with_env<'cx>( env: &mut ImportEnv<'cx>, parsed: Parsed, -) -> Result { +) -> Result, Error> { let Parsed(expr, base_location) = parsed; let resolved = traverse_resolve_expr( &mut NameEnv::new(), @@ -463,17 +468,20 @@ fn resolve_with_env<'cx>( Ok(Resolved(resolved)) } -pub fn resolve(cx: Ctxt<'_>, parsed: Parsed) -> Result { +pub fn resolve<'cx>( + cx: Ctxt<'cx>, + parsed: Parsed, +) -> Result, Error> { resolve_with_env(&mut ImportEnv::new(cx), parsed) } -pub fn skip_resolve_expr(expr: &Expr) -> Result { +pub fn skip_resolve_expr<'cx>(expr: &Expr) -> Result, Error> { traverse_resolve_expr(&mut NameEnv::new(), expr, &mut |import, _span| { Err(ImportError::UnexpectedImport(import).into()) }) } -pub fn skip_resolve(parsed: Parsed) -> Result { +pub fn skip_resolve<'cx>(parsed: Parsed) -> Result, Error> { let Parsed(expr, _) = parsed; let resolved = skip_resolve_expr(&expr)?; Ok(Resolved(resolved)) -- cgit v1.2.3