From 4473f3549f331c51a7df0e307d356a06c00d7288 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 7 Dec 2020 19:02:07 +0000 Subject: Resolve imports and alternatives outside of the ast traversal --- dhall/src/ctxt.rs | 203 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 139 insertions(+), 64 deletions(-) (limited to 'dhall/src/ctxt.rs') diff --git a/dhall/src/ctxt.rs b/dhall/src/ctxt.rs index 3809bc9..aad1a1b 100644 --- a/dhall/src/ctxt.rs +++ b/dhall/src/ctxt.rs @@ -3,29 +3,19 @@ use once_cell::sync::OnceCell; use std::marker::PhantomData; use std::ops::{Deref, Index}; -use crate::semantics::{Import, ImportLocation}; +use crate::semantics::{Import, ImportLocation, ImportNode}; use crate::syntax::Span; use crate::Typed; -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct ImportId<'cx>(usize, PhantomData<&'cx ()>); -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct ImportResultId<'cx>(usize, PhantomData<&'cx ()>); - -/// What's stored for each `ImportId`. Allows getting and setting a result for this import. -pub struct StoredImport<'cx> { - cx: Ctxt<'cx>, - pub base_location: ImportLocation, - pub import: Import, - pub span: Span, - result: OnceCell>, -} +///////////////////////////////////////////////////////////////////////////////////////////////////// +// Ctxt /// Implementation detail. Made public for the `Index` instances. #[derive(Default)] pub struct CtxtS<'cx> { imports: FrozenVec>>, - import_results: FrozenVec>>, + import_alternatives: FrozenVec>>, + import_results: FrozenVec>>, } /// Context for the dhall compiler. Stores various global maps. @@ -40,33 +30,46 @@ impl Ctxt<'_> { f(cx) } } -impl<'cx> Ctxt<'cx> { - /// Store an import and the location relative to which it must be resolved. - pub fn push_import( - self, - base_location: ImportLocation, - import: Import, - span: Span, - ) -> ImportId<'cx> { - let stored = StoredImport { - cx: self, - base_location, - import, - span, - result: OnceCell::new(), - }; - let id = self.0.imports.len(); - self.0.imports.push(Box::new(stored)); - ImportId(id, PhantomData) +impl<'cx> Deref for Ctxt<'cx> { + type Target = &'cx CtxtS<'cx>; + fn deref(&self) -> &&'cx CtxtS<'cx> { + &self.0 } - /// Store the result of fetching an import. - pub fn push_import_result(self, res: Typed<'cx>) -> ImportResultId<'cx> { - let id = self.0.import_results.len(); - self.0.import_results.push(Box::new(res)); - ImportResultId(id, PhantomData) +} +impl<'a, 'cx, T> Index<&'a T> for CtxtS<'cx> +where + Self: Index, + T: Copy, +{ + type Output = >::Output; + fn index(&self, id: &'a T) -> &Self::Output { + &self[*id] + } +} + +/// Empty impl, because `FrozenVec` does not implement `Debug` and I can't be bothered to do it +/// myself. +impl<'cx> std::fmt::Debug for Ctxt<'cx> { + fn fmt(&self, _: &mut std::fmt::Formatter) -> std::fmt::Result { + Ok(()) } } +///////////////////////////////////////////////////////////////////////////////////////////////////// +// Imports + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct ImportId<'cx>(usize, PhantomData<&'cx ()>); + +/// What's stored for each `ImportId`. Allows getting and setting a result for this import. +pub struct StoredImport<'cx> { + cx: Ctxt<'cx>, + pub base_location: ImportLocation, + pub import: Import, + pub span: Span, + result: OnceCell>, +} + impl<'cx> StoredImport<'cx> { /// Get the id of the result of fetching this import. Returns `None` if the result has not yet /// been fetched. @@ -79,58 +82,130 @@ impl<'cx> StoredImport<'cx> { } /// Get the result of fetching this import. Returns `None` if the result has not yet been /// fetched. - pub fn get_result(&self) -> Option<&'cx Typed<'cx>> { + pub fn get_result(&self) -> Option<&'cx StoredImportResult<'cx>> { let res = self.get_resultid()?; Some(&self.cx[res]) } /// Get the result of fetching this import. Panicx if the result has not yet been /// fetched. - pub fn unwrap_result(&self) -> &'cx Typed<'cx> { + pub fn unwrap_result(&self) -> &'cx StoredImportResult<'cx> { self.get_result() .expect("imports should all have been resolved at this stage") } /// Store the result of fetching this import. - pub fn set_result(&self, res: Typed<'cx>) -> ImportResultId<'cx> { + pub fn set_result( + &self, + res: StoredImportResult<'cx>, + ) -> ImportResultId<'cx> { let res = self.cx.push_import_result(res); self.set_resultid(res); res } } - -impl<'cx> Deref for Ctxt<'cx> { - type Target = &'cx CtxtS<'cx>; - fn deref(&self) -> &&'cx CtxtS<'cx> { - &self.0 +impl<'cx> Ctxt<'cx> { + /// Store an import and the location relative to which it must be resolved. + pub fn push_import( + self, + base_location: ImportLocation, + import: Import, + span: Span, + ) -> ImportId<'cx> { + let stored = StoredImport { + cx: self, + base_location, + import, + span, + result: OnceCell::new(), + }; + let id = self.0.imports.len(); + self.0.imports.push(Box::new(stored)); + ImportId(id, PhantomData) } } - impl<'cx> Index> for CtxtS<'cx> { type Output = StoredImport<'cx>; fn index(&self, id: ImportId<'cx>) -> &StoredImport<'cx> { &self.imports[id.0] } } -impl<'cx> Index> for CtxtS<'cx> { - type Output = Typed<'cx>; - fn index(&self, id: ImportResultId<'cx>) -> &Typed<'cx> { - &self.import_results[id.0] + +///////////////////////////////////////////////////////////////////////////////////////////////////// +// Import alternatives + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct ImportAlternativeId<'cx>(usize, PhantomData<&'cx ()>); + +/// What's stored for each `ImportAlternativeId`. +pub struct StoredImportAlternative<'cx> { + pub left_imports: Box<[ImportNode<'cx>]>, + pub right_imports: Box<[ImportNode<'cx>]>, + /// `true` for left, `false` for right. + selected: OnceCell, +} + +impl<'cx> StoredImportAlternative<'cx> { + /// Get which alternative got selected. `true` for left, `false` for right. + pub fn get_selected(&self) -> Option { + self.selected.get().copied() + } + /// Get which alternative got selected. `true` for left, `false` for right. + pub fn unwrap_selected(&self) -> bool { + self.get_selected() + .expect("imports should all have been resolved at this stage") + } + /// Set which alternative got selected. `true` for left, `false` for right. + pub fn set_selected(&self, selected: bool) { + let _ = self.selected.set(selected); } } -impl<'a, 'cx, T> Index<&'a T> for CtxtS<'cx> -where - Self: Index, - T: Copy, -{ - type Output = >::Output; - fn index(&self, id: &'a T) -> &Self::Output { - &self[*id] +impl<'cx> Ctxt<'cx> { + pub fn push_import_alternative( + self, + left_imports: Box<[ImportNode<'cx>]>, + right_imports: Box<[ImportNode<'cx>]>, + ) -> ImportAlternativeId<'cx> { + let stored = StoredImportAlternative { + left_imports, + right_imports, + selected: OnceCell::new(), + }; + let id = self.0.import_alternatives.len(); + self.0.import_alternatives.push(Box::new(stored)); + ImportAlternativeId(id, PhantomData) + } +} +impl<'cx> Index> for CtxtS<'cx> { + type Output = StoredImportAlternative<'cx>; + fn index( + &self, + id: ImportAlternativeId<'cx>, + ) -> &StoredImportAlternative<'cx> { + &self.import_alternatives[id.0] } } -/// Empty impl, because `FrozenVec` does not implement `Debug` and I can't be bothered to do it -/// myself. -impl<'cx> std::fmt::Debug for Ctxt<'cx> { - fn fmt(&self, _: &mut std::fmt::Formatter) -> std::fmt::Result { - Ok(()) +///////////////////////////////////////////////////////////////////////////////////////////////////// +// Import results + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct ImportResultId<'cx>(usize, PhantomData<&'cx ()>); + +type StoredImportResult<'cx> = Typed<'cx>; + +impl<'cx> Ctxt<'cx> { + /// Store the result of fetching an import. + pub fn push_import_result( + self, + res: StoredImportResult<'cx>, + ) -> ImportResultId<'cx> { + let id = self.0.import_results.len(); + self.0.import_results.push(Box::new(res)); + ImportResultId(id, PhantomData) + } +} +impl<'cx> Index> for CtxtS<'cx> { + type Output = StoredImportResult<'cx>; + fn index(&self, id: ImportResultId<'cx>) -> &StoredImportResult<'cx> { + &self.import_results[id.0] } } -- cgit v1.2.3