summaryrefslogtreecommitdiff
path: root/dhall/src/semantics/resolve
diff options
context:
space:
mode:
Diffstat (limited to 'dhall/src/semantics/resolve')
-rw-r--r--dhall/src/semantics/resolve/env.rs104
-rw-r--r--dhall/src/semantics/resolve/mod.rs4
-rw-r--r--dhall/src/semantics/resolve/resolve.rs63
3 files changed, 113 insertions, 58 deletions
diff --git a/dhall/src/semantics/resolve/env.rs b/dhall/src/semantics/resolve/env.rs
index e69de29..ff743d3 100644
--- a/dhall/src/semantics/resolve/env.rs
+++ b/dhall/src/semantics/resolve/env.rs
@@ -0,0 +1,104 @@
+use std::collections::HashMap;
+
+use crate::error::{Error, ImportError};
+use crate::semantics::{AlphaVar, Hir, Import, VarEnv};
+use crate::syntax::{Label, V};
+
+/// Environment for resolving names.
+#[derive(Debug, Clone)]
+pub(crate) struct NameEnv {
+ names: Vec<Label>,
+}
+
+pub(crate) type ImportCache = HashMap<Import, Hir>;
+pub(crate) type ImportStack = Vec<Import>;
+
+/// Environment for resolving imports
+#[derive(Debug, Clone)]
+pub(crate) struct ImportEnv {
+ cache: ImportCache,
+ stack: ImportStack,
+}
+
+impl NameEnv {
+ pub fn new() -> Self {
+ NameEnv { names: Vec::new() }
+ }
+ pub fn as_varenv(&self) -> VarEnv {
+ VarEnv::from_size(self.names.len())
+ }
+
+ pub fn insert(&self, x: &Label) -> Self {
+ let mut env = self.clone();
+ env.insert_mut(x);
+ env
+ }
+ pub fn insert_mut(&mut self, x: &Label) {
+ self.names.push(x.clone())
+ }
+ pub fn remove_mut(&mut self) {
+ self.names.pop();
+ }
+
+ pub fn unlabel_var(&self, var: &V) -> Option<AlphaVar> {
+ let V(name, idx) = var;
+ let (idx, _) = self
+ .names
+ .iter()
+ .rev()
+ .enumerate()
+ .filter(|(_, n)| *n == name)
+ .nth(*idx)?;
+ Some(AlphaVar::new(idx))
+ }
+ pub fn label_var(&self, var: &AlphaVar) -> V {
+ let name = &self.names[self.names.len() - 1 - var.idx()];
+ let idx = self
+ .names
+ .iter()
+ .rev()
+ .take(var.idx())
+ .filter(|n| *n == name)
+ .count();
+ V(name.clone(), idx)
+ }
+}
+
+impl ImportEnv {
+ pub fn new() -> Self {
+ ImportEnv {
+ cache: HashMap::new(),
+ stack: Vec::new(),
+ }
+ }
+
+ pub fn handle_import(
+ &mut self,
+ import: Import,
+ mut do_resolve: impl FnMut(&mut Self, &Import) -> Result<Hir, Error>,
+ ) -> Result<Hir, Error> {
+ if self.stack.contains(&import) {
+ return Err(
+ ImportError::ImportCycle(self.stack.clone(), import).into()
+ );
+ }
+ Ok(match self.cache.get(&import) {
+ Some(expr) => expr.clone(),
+ None => {
+ // Push the current import on the stack
+ self.stack.push(import.clone());
+
+ // Resolve the import recursively
+ let expr = do_resolve(self, &import)?;
+
+ // Remove import from the stack.
+ self.stack.pop();
+
+ // Add the import to the cache
+ self.cache.insert(import, expr.clone());
+
+ expr
+ }
+ })
+ }
+}
diff --git a/dhall/src/semantics/resolve/mod.rs b/dhall/src/semantics/resolve/mod.rs
index c0486dd..517907b 100644
--- a/dhall/src/semantics/resolve/mod.rs
+++ b/dhall/src/semantics/resolve/mod.rs
@@ -1,6 +1,6 @@
pub mod env;
-pub mod resolve;
pub mod hir;
+pub mod resolve;
pub(crate) use env::*;
-pub(crate) use resolve::*;
pub(crate) use hir::*;
+pub(crate) use resolve::*;
diff --git a/dhall/src/semantics/resolve/resolve.rs b/dhall/src/semantics/resolve/resolve.rs
index 3038597..e3db014 100644
--- a/dhall/src/semantics/resolve/resolve.rs
+++ b/dhall/src/semantics/resolve/resolve.rs
@@ -1,14 +1,13 @@
-use std::collections::HashMap;
use std::path::{Path, PathBuf};
use crate::error::ErrorBuilder;
use crate::error::{Error, ImportError};
-use crate::semantics::{mkerr, Hir, HirKind, NameEnv};
+use crate::semantics::{mkerr, Hir, HirKind, ImportEnv, NameEnv};
use crate::syntax;
use crate::syntax::{BinOp, Expr, ExprKind, FilePath, ImportLocation, URL};
use crate::{Parsed, ParsedExpr, Resolved};
-type Import = syntax::Import<Hir>;
+pub(crate) type Import = syntax::Import<Hir>;
/// A root from which to resolve relative imports.
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -16,56 +15,8 @@ pub(crate) enum ImportRoot {
LocalDir(PathBuf),
}
-type ImportCache = HashMap<Import, Hir>;
-
-pub(crate) type ImportStack = Vec<Import>;
-
-struct ResolveEnv {
- cache: ImportCache,
- stack: ImportStack,
-}
-
-impl ResolveEnv {
- pub fn new() -> Self {
- ResolveEnv {
- cache: HashMap::new(),
- stack: Vec::new(),
- }
- }
-
- pub fn handle_import(
- &mut self,
- import: Import,
- mut do_resolve: impl FnMut(&mut Self, &Import) -> Result<Hir, Error>,
- ) -> Result<Hir, Error> {
- if self.stack.contains(&import) {
- return Err(
- ImportError::ImportCycle(self.stack.clone(), import).into()
- );
- }
- Ok(match self.cache.get(&import) {
- Some(expr) => expr.clone(),
- None => {
- // Push the current import on the stack
- self.stack.push(import.clone());
-
- // Resolve the import recursively
- let expr = do_resolve(self, &import)?;
-
- // Remove import from the stack.
- self.stack.pop();
-
- // Add the import to the cache
- self.cache.insert(import, expr.clone());
-
- expr
- }
- })
- }
-}
-
fn resolve_one_import(
- env: &mut ResolveEnv,
+ env: &mut ImportEnv,
import: &Import,
root: &ImportRoot,
) -> Result<Hir, Error> {
@@ -90,7 +41,7 @@ fn resolve_one_import(
}
}
-fn load_import(env: &mut ResolveEnv, f: &Path) -> Result<Hir, Error> {
+fn load_import(env: &mut ImportEnv, f: &Path) -> Result<Hir, Error> {
let parsed = Parsed::parse_file(f)?;
Ok(resolve_with_env(env, parsed)?
.typecheck()?
@@ -99,7 +50,7 @@ fn load_import(env: &mut ResolveEnv, f: &Path) -> Result<Hir, Error> {
}
/// Traverse the expression, handling import alternatives and passing
-/// found imports to the provided function.
+/// found imports to the provided function. Also resolving names.
fn traverse_resolve_expr(
name_env: &mut NameEnv,
expr: &Expr,
@@ -169,7 +120,7 @@ fn traverse_resolve_expr(
}
fn resolve_with_env(
- env: &mut ResolveEnv,
+ env: &mut ImportEnv,
parsed: Parsed,
) -> Result<Resolved, Error> {
let Parsed(expr, root) = parsed;
@@ -183,7 +134,7 @@ fn resolve_with_env(
}
pub(crate) fn resolve(parsed: Parsed) -> Result<Resolved, Error> {
- resolve_with_env(&mut ResolveEnv::new(), parsed)
+ resolve_with_env(&mut ImportEnv::new(), parsed)
}
pub(crate) fn skip_resolve(expr: &ParsedExpr) -> Result<Hir, Error> {