summaryrefslogtreecommitdiff
path: root/dhall/src/semantics/resolve
diff options
context:
space:
mode:
authorNadrieril2020-12-06 23:55:21 +0000
committerNadrieril2020-12-07 19:34:38 +0000
commitc785b7c0c6cd8b3b1cc15eb79caf982a757020ba (patch)
tree6d38e68385814073b8b22ee8a8956435546892dc /dhall/src/semantics/resolve
parent6287b7a7f9e421877ee13fefa586395fec844c99 (diff)
Thread cx through normalization
Diffstat (limited to 'dhall/src/semantics/resolve')
-rw-r--r--dhall/src/semantics/resolve/cache.rs24
-rw-r--r--dhall/src/semantics/resolve/env.rs13
-rw-r--r--dhall/src/semantics/resolve/hir.rs42
-rw-r--r--dhall/src/semantics/resolve/resolve.rs32
4 files changed, 69 insertions, 42 deletions
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<Typed, Error> {
+ pub fn get<'cx>(
+ &self,
+ cx: Ctxt<'cx>,
+ hash: &Hash,
+ ) -> Result<Typed<'cx>, 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<Typed, Error> {
+fn read_cache_file<'cx>(
+ cx: Ctxt<'cx>,
+ path: &Path,
+ hash: &Hash,
+) -> Result<Typed<'cx>, Error> {
let data = crate::utils::read_binary_file(path)?;
match hash {
@@ -81,7 +93,7 @@ fn read_cache_file(path: &Path, hash: &Hash) -> Result<Typed, Error> {
}
}
- 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<Hash>) -> Option<Typed> {
+ pub fn get_from_disk_cache(
+ &self,
+ hash: &Option<Hash>,
+ ) -> Option<Typed<'cx>> {
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<Hash>, expr: &Typed) {
+ pub fn write_to_disk_cache(&self, hash: &Option<Hash>, 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<Typed, Error>,
- ) -> Result<Typed, Error> {
+ do_resolve: impl FnOnce(&mut Self) -> Result<Typed<'cx>, Error>,
+ ) -> Result<Typed<'cx>, 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<Hir>),
+ Expr(ExprKind<Hir<'cx>>),
}
// An expression with resolved variables and imports.
#[derive(Debug, Clone)]
-pub struct Hir {
- kind: Box<HirKind>,
+pub struct Hir<'cx> {
+ kind: Box<HirKind<'cx>>,
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<Tir<'hir>, TypeError> {
+ env: &TyEnv<'cx>,
+ ) -> Result<Tir<'cx, 'hir>, TypeError> {
type_with(env, self, None)
}
pub fn typecheck_noenv<'hir>(
&'hir self,
- cx: Ctxt<'_>,
- ) -> Result<Tir<'hir>, TypeError> {
+ cx: Ctxt<'cx>,
+ ) -> Result<Tir<'cx, 'hir>, 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<NzEnv>) -> Nir {
+ pub fn eval(&self, env: impl Into<NzEnv<'cx>>) -> 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<Typed, Error> {
+ ) -> Result<Typed<'cx>, 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<Typed, Error>,
-) -> Result<Hir, Error> {
+ f: &mut impl FnMut(Import, Span) -> Result<Typed<'cx>, Error>,
+) -> Result<Hir<'cx>, 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<Resolved, Error> {
+) -> Result<Resolved<'cx>, 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<Resolved, Error> {
+pub fn resolve<'cx>(
+ cx: Ctxt<'cx>,
+ parsed: Parsed,
+) -> Result<Resolved<'cx>, Error> {
resolve_with_env(&mut ImportEnv::new(cx), parsed)
}
-pub fn skip_resolve_expr(expr: &Expr) -> Result<Hir, Error> {
+pub fn skip_resolve_expr<'cx>(expr: &Expr) -> Result<Hir<'cx>, Error> {
traverse_resolve_expr(&mut NameEnv::new(), expr, &mut |import, _span| {
Err(ImportError::UnexpectedImport(import).into())
})
}
-pub fn skip_resolve(parsed: Parsed) -> Result<Resolved, Error> {
+pub fn skip_resolve<'cx>(parsed: Parsed) -> Result<Resolved<'cx>, Error> {
let Parsed(expr, _) = parsed;
let resolved = skip_resolve_expr(&expr)?;
Ok(Resolved(resolved))