summaryrefslogtreecommitdiff
path: root/dhall/src
diff options
context:
space:
mode:
Diffstat (limited to 'dhall/src')
-rw-r--r--dhall/src/semantics/resolve.rs87
1 files changed, 56 insertions, 31 deletions
diff --git a/dhall/src/semantics/resolve.rs b/dhall/src/semantics/resolve.rs
index 3acf114..5ec6192 100644
--- a/dhall/src/semantics/resolve.rs
+++ b/dhall/src/semantics/resolve.rs
@@ -18,11 +18,42 @@ type ImportCache = HashMap<Import, Normalized>;
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 to_import_stack(&self) -> ImportStack {
+ self.stack.clone()
+ }
+ pub fn check_cyclic_import(&self, import: &Import) -> bool {
+ self.stack.contains(import)
+ }
+ pub fn get_from_cache(&self, import: &Import) -> Option<&Normalized> {
+ self.cache.get(import)
+ }
+ pub fn push_on_stack(&mut self, import: Import) {
+ self.stack.push(import)
+ }
+ pub fn pop_from_stack(&mut self) {
+ self.stack.pop();
+ }
+ pub fn insert_cache(&mut self, import: Import, expr: Normalized) {
+ self.cache.insert(import, expr);
+ }
+}
+
fn resolve_import(
+ env: &mut ResolveEnv,
import: &Import,
root: &ImportRoot,
- import_cache: &mut ImportCache,
- import_stack: &ImportStack,
) -> Result<Normalized, ImportError> {
use self::ImportRoot::*;
use syntax::FilePrefix::*;
@@ -39,53 +70,47 @@ fn resolve_import(
Here => cwd.join(path_buf),
_ => unimplemented!("{:?}", import),
};
- Ok(load_import(&path_buf, import_cache, import_stack).map_err(
- |e| ImportError::Recursive(import.clone(), Box::new(e)),
- )?)
+ Ok(load_import(env, &path_buf).map_err(|e| {
+ ImportError::Recursive(import.clone(), Box::new(e))
+ })?)
}
_ => unimplemented!("{:?}", import),
}
}
-fn load_import(
- f: &Path,
- import_cache: &mut ImportCache,
- import_stack: &ImportStack,
-) -> Result<Normalized, Error> {
- Ok(
- do_resolve_expr(Parsed::parse_file(f)?, import_cache, import_stack)?
- .typecheck()?
- .normalize(),
- )
+fn load_import(env: &mut ResolveEnv, f: &Path) -> Result<Normalized, Error> {
+ Ok(do_resolve_expr(env, Parsed::parse_file(f)?)?
+ .typecheck()?
+ .normalize())
}
fn do_resolve_expr(
+ env: &mut ResolveEnv,
parsed: Parsed,
- import_cache: &mut ImportCache,
- import_stack: &ImportStack,
) -> Result<Resolved, ImportError> {
let Parsed(mut expr, root) = parsed;
let mut resolve = |import: Import| -> Result<Normalized, ImportError> {
- if import_stack.contains(&import) {
- return Err(ImportError::ImportCycle(import_stack.clone(), import));
+ if env.check_cyclic_import(&import) {
+ return Err(ImportError::ImportCycle(
+ env.to_import_stack(),
+ import,
+ ));
}
- match import_cache.get(&import) {
+ match env.get_from_cache(&import) {
Some(expr) => Ok(expr.clone()),
None => {
- // Copy the import stack and push the current import
- let mut import_stack = import_stack.clone();
- import_stack.push(import.clone());
+ // Push the current import on the stack
+ env.push_on_stack(import.clone());
// Resolve the import recursively
- let expr = resolve_import(
- &import,
- &root,
- import_cache,
- &import_stack,
- )?;
+ let expr = resolve_import(env, &import, &root)?;
+
+ // Remove import from the stack.
+ env.pop_from_stack();
// Add the import to the cache
- import_cache.insert(import, expr.clone());
+ env.insert_cache(import, expr.clone());
+
Ok(expr)
}
}
@@ -95,7 +120,7 @@ fn do_resolve_expr(
}
pub(crate) fn resolve(e: Parsed) -> Result<Resolved, ImportError> {
- do_resolve_expr(e, &mut HashMap::new(), &Vec::new())
+ do_resolve_expr(&mut ResolveEnv::new(), e)
}
pub(crate) fn skip_resolve_expr(