From 3a623acaf70c934ee9dbd74dfadcaa2c612160c5 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 6 Dec 2020 20:10:51 +0000 Subject: Make global store of imports and import results --- dhall/src/ctxt.rs | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 dhall/src/ctxt.rs (limited to 'dhall/src/ctxt.rs') diff --git a/dhall/src/ctxt.rs b/dhall/src/ctxt.rs new file mode 100644 index 0000000..1d97232 --- /dev/null +++ b/dhall/src/ctxt.rs @@ -0,0 +1,109 @@ +use elsa::vec::FrozenVec; +use once_cell::sync::OnceCell; + +use crate::semantics::{Import, ImportLocation}; +use crate::syntax::Span; +use crate::Typed; + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct ImportId(usize); +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct ImportResultId(usize); + +struct StoredImport { + base_location: ImportLocation, + import: Import, + span: Span, + result: OnceCell, +} + +#[derive(Default)] +struct CtxtS { + imports: FrozenVec>, + import_results: FrozenVec>, +} + +/// Context for the dhall compiler. Stores various global maps. +#[derive(Copy, Clone)] +pub struct Ctxt<'cx>(&'cx CtxtS); + +impl Ctxt<'_> { + pub fn with_new(f: impl for<'cx> FnOnce(Ctxt<'cx>) -> T) -> T { + let cx = CtxtS::default(); + let cx = Ctxt(&cx); + f(cx) + } +} +impl<'cx> Ctxt<'cx> { + fn get_stored_import(self, import: ImportId) -> &'cx StoredImport { + self.0.imports.get(import.0).unwrap() + } + pub fn get_import_result(self, id: ImportResultId) -> &'cx Typed { + &self.0.import_results.get(id.0).unwrap() + } + + /// 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 { + let stored = StoredImport { + base_location, + import, + span, + result: OnceCell::new(), + }; + let id = self.0.imports.len(); + self.0.imports.push(Box::new(stored)); + ImportId(id) + } + /// Store the result of fetching an import. + pub fn push_import_result(self, res: Typed) -> ImportResultId { + let id = self.0.import_results.len(); + self.0.import_results.push(Box::new(res)); + ImportResultId(id) + } + + pub fn get_import(self, import: ImportId) -> &'cx Import { + &self.get_stored_import(import).import + } + pub fn get_import_base_location( + self, + import: ImportId, + ) -> &'cx ImportLocation { + &self.get_stored_import(import).base_location + } + pub fn get_import_span(self, import: ImportId) -> Span { + self.get_stored_import(import).span.clone() + } + /// Get the result of fetching this import. Returns `None` if the result has not yet been + /// fetched. + pub fn get_result_of_import(self, import: ImportId) -> Option<&'cx Typed> { + let res = self.get_resultid_of_import(import)?; + Some(self.get_import_result(res)) + } + /// Get the id of the result of fetching this import. Returns `None` if the result has not yet + /// been fetched. + pub fn get_resultid_of_import( + self, + import: ImportId, + ) -> Option { + self.get_stored_import(import).result.get().copied() + } + /// Store the result of fetching this import. + pub fn set_result_of_import( + self, + import: ImportId, + res: Typed, + ) -> ImportResultId { + let res = self.push_import_result(res); + self.set_resultid_of_import(import, res); + res + } + /// Store the result of fetching this import. + pub fn set_resultid_of_import(self, import: ImportId, res: ImportResultId) { + let _ = self.get_stored_import(import).result.set(res); + } +} -- cgit v1.2.3 From 9991bd4891774c4dd598decae02ee860554d2ab7 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 6 Dec 2020 22:52:50 +0000 Subject: Improve ergonomics of `Ctxt` --- dhall/src/ctxt.rs | 91 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 46 insertions(+), 45 deletions(-) (limited to 'dhall/src/ctxt.rs') diff --git a/dhall/src/ctxt.rs b/dhall/src/ctxt.rs index 1d97232..2394d8e 100644 --- a/dhall/src/ctxt.rs +++ b/dhall/src/ctxt.rs @@ -10,22 +10,26 @@ pub struct ImportId(usize); #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct ImportResultId(usize); -struct StoredImport { - base_location: ImportLocation, - import: Import, - span: Span, +/// 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, } +/// Implementation detail. Made public for the `Index` instances. #[derive(Default)] -struct CtxtS { - imports: FrozenVec>, +pub struct CtxtS<'cx> { + imports: FrozenVec>>, import_results: FrozenVec>, } /// Context for the dhall compiler. Stores various global maps. +/// Access the relevant value using `cx[id]`. #[derive(Copy, Clone)] -pub struct Ctxt<'cx>(&'cx CtxtS); +pub struct Ctxt<'cx>(&'cx CtxtS<'cx>); impl Ctxt<'_> { pub fn with_new(f: impl for<'cx> FnOnce(Ctxt<'cx>) -> T) -> T { @@ -35,13 +39,6 @@ impl Ctxt<'_> { } } impl<'cx> Ctxt<'cx> { - fn get_stored_import(self, import: ImportId) -> &'cx StoredImport { - self.0.imports.get(import.0).unwrap() - } - pub fn get_import_result(self, id: ImportResultId) -> &'cx Typed { - &self.0.import_results.get(id.0).unwrap() - } - /// Store an import and the location relative to which it must be resolved. pub fn push_import( self, @@ -50,6 +47,7 @@ impl<'cx> Ctxt<'cx> { span: Span, ) -> ImportId { let stored = StoredImport { + cx: self, base_location, import, span, @@ -65,45 +63,48 @@ impl<'cx> Ctxt<'cx> { self.0.import_results.push(Box::new(res)); ImportResultId(id) } +} - pub fn get_import(self, import: ImportId) -> &'cx Import { - &self.get_stored_import(import).import - } - pub fn get_import_base_location( - self, - import: ImportId, - ) -> &'cx ImportLocation { - &self.get_stored_import(import).base_location +impl<'cx> StoredImport<'cx> { + /// Get the id of the result of fetching this import. Returns `None` if the result has not yet + /// been fetched. + pub fn get_resultid(&self) -> Option { + self.result.get().copied() } - pub fn get_import_span(self, import: ImportId) -> Span { - self.get_stored_import(import).span.clone() + /// Store the result of fetching this import. + pub fn set_resultid(&self, res: ImportResultId) { + let _ = self.result.set(res); } /// Get the result of fetching this import. Returns `None` if the result has not yet been /// fetched. - pub fn get_result_of_import(self, import: ImportId) -> Option<&'cx Typed> { - let res = self.get_resultid_of_import(import)?; - Some(self.get_import_result(res)) - } - /// Get the id of the result of fetching this import. Returns `None` if the result has not yet - /// been fetched. - pub fn get_resultid_of_import( - self, - import: ImportId, - ) -> Option { - self.get_stored_import(import).result.get().copied() + pub fn get_result(&self) -> Option<&'cx Typed> { + let res = self.get_resultid()?; + Some(&self.cx[res]) } /// Store the result of fetching this import. - pub fn set_result_of_import( - self, - import: ImportId, - res: Typed, - ) -> ImportResultId { - let res = self.push_import_result(res); - self.set_resultid_of_import(import, res); + pub fn set_result(&self, res: Typed) -> ImportResultId { + let res = self.cx.push_import_result(res); + self.set_resultid(res); res } - /// Store the result of fetching this import. - pub fn set_resultid_of_import(self, import: ImportId, res: ImportResultId) { - let _ = self.get_stored_import(import).result.set(res); +} + +impl<'cx> std::ops::Deref for Ctxt<'cx> { + type Target = &'cx CtxtS<'cx>; + fn deref(&self) -> &&'cx CtxtS<'cx> { + &self.0 + } +} + +impl<'cx> std::ops::Index for CtxtS<'cx> { + type Output = StoredImport<'cx>; + fn index(&self, id: ImportId) -> &StoredImport<'cx> { + &self.imports[id.0] + } +} +impl<'cx> std::ops::Index for CtxtS<'cx> { + type Output = Typed; + fn index(&self, id: ImportResultId) -> &Typed { + &self.import_results[id.0] } } -- cgit v1.2.3 From 6287b7a7f9e421877ee13fefa586395fec844c99 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 6 Dec 2020 21:41:03 +0000 Subject: Thread cx through typecheck --- dhall/src/ctxt.rs | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'dhall/src/ctxt.rs') diff --git a/dhall/src/ctxt.rs b/dhall/src/ctxt.rs index 2394d8e..37fab35 100644 --- a/dhall/src/ctxt.rs +++ b/dhall/src/ctxt.rs @@ -108,3 +108,11 @@ impl<'cx> std::ops::Index for CtxtS<'cx> { &self.import_results[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(()) + } +} -- cgit v1.2.3 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/ctxt.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'dhall/src/ctxt.rs') diff --git a/dhall/src/ctxt.rs b/dhall/src/ctxt.rs index 37fab35..a171ebe 100644 --- a/dhall/src/ctxt.rs +++ b/dhall/src/ctxt.rs @@ -23,7 +23,7 @@ pub struct StoredImport<'cx> { #[derive(Default)] pub struct CtxtS<'cx> { imports: FrozenVec>>, - import_results: FrozenVec>, + import_results: FrozenVec>>, } /// Context for the dhall compiler. Stores various global maps. @@ -58,7 +58,7 @@ impl<'cx> Ctxt<'cx> { ImportId(id) } /// Store the result of fetching an import. - pub fn push_import_result(self, res: Typed) -> ImportResultId { + pub fn push_import_result(self, res: Typed<'cx>) -> ImportResultId { let id = self.0.import_results.len(); self.0.import_results.push(Box::new(res)); ImportResultId(id) @@ -77,12 +77,12 @@ 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> { + pub fn get_result(&self) -> Option<&'cx Typed<'cx>> { let res = self.get_resultid()?; Some(&self.cx[res]) } /// Store the result of fetching this import. - pub fn set_result(&self, res: Typed) -> ImportResultId { + pub fn set_result(&self, res: Typed<'cx>) -> ImportResultId { let res = self.cx.push_import_result(res); self.set_resultid(res); res @@ -103,8 +103,8 @@ impl<'cx> std::ops::Index for CtxtS<'cx> { } } impl<'cx> std::ops::Index for CtxtS<'cx> { - type Output = Typed; - fn index(&self, id: ImportResultId) -> &Typed { + type Output = Typed<'cx>; + fn index(&self, id: ImportResultId) -> &Typed<'cx> { &self.import_results[id.0] } } -- cgit v1.2.3 From 3c522217b7445c6df9e170d830f485086ad7e062 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 7 Dec 2020 13:47:21 +0000 Subject: Tag cx ids with the cx lifetime To make sure we don't let ids escape and we don't mix scopes. --- dhall/src/ctxt.rs | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) (limited to 'dhall/src/ctxt.rs') diff --git a/dhall/src/ctxt.rs b/dhall/src/ctxt.rs index a171ebe..8bdf99d 100644 --- a/dhall/src/ctxt.rs +++ b/dhall/src/ctxt.rs @@ -1,14 +1,16 @@ use elsa::vec::FrozenVec; use once_cell::sync::OnceCell; +use std::marker::PhantomData; +use std::ops::{Deref, Index}; use crate::semantics::{Import, ImportLocation}; use crate::syntax::Span; use crate::Typed; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct ImportId(usize); +pub struct ImportId<'cx>(usize, PhantomData<&'cx ()>); #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct ImportResultId(usize); +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> { @@ -16,7 +18,7 @@ pub struct StoredImport<'cx> { pub base_location: ImportLocation, pub import: Import, pub span: Span, - result: OnceCell, + result: OnceCell>, } /// Implementation detail. Made public for the `Index` instances. @@ -45,7 +47,7 @@ impl<'cx> Ctxt<'cx> { base_location: ImportLocation, import: Import, span: Span, - ) -> ImportId { + ) -> ImportId<'cx> { let stored = StoredImport { cx: self, base_location, @@ -55,24 +57,24 @@ impl<'cx> Ctxt<'cx> { }; let id = self.0.imports.len(); self.0.imports.push(Box::new(stored)); - ImportId(id) + ImportId(id, PhantomData) } /// Store the result of fetching an import. - pub fn push_import_result(self, res: Typed<'cx>) -> ImportResultId { + 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) + ImportResultId(id, PhantomData) } } impl<'cx> StoredImport<'cx> { /// Get the id of the result of fetching this import. Returns `None` if the result has not yet /// been fetched. - pub fn get_resultid(&self) -> Option { + pub fn get_resultid(&self) -> Option> { self.result.get().copied() } /// Store the result of fetching this import. - pub fn set_resultid(&self, res: ImportResultId) { + pub fn set_resultid(&self, res: ImportResultId<'cx>) { let _ = self.result.set(res); } /// Get the result of fetching this import. Returns `None` if the result has not yet been @@ -82,32 +84,42 @@ impl<'cx> StoredImport<'cx> { Some(&self.cx[res]) } /// Store the result of fetching this import. - pub fn set_result(&self, res: Typed<'cx>) -> ImportResultId { + pub fn set_result(&self, res: Typed<'cx>) -> ImportResultId<'cx> { let res = self.cx.push_import_result(res); self.set_resultid(res); res } } -impl<'cx> std::ops::Deref for Ctxt<'cx> { +impl<'cx> Deref for Ctxt<'cx> { type Target = &'cx CtxtS<'cx>; fn deref(&self) -> &&'cx CtxtS<'cx> { &self.0 } } -impl<'cx> std::ops::Index for CtxtS<'cx> { +impl<'cx> Index> for CtxtS<'cx> { type Output = StoredImport<'cx>; - fn index(&self, id: ImportId) -> &StoredImport<'cx> { + fn index(&self, id: ImportId<'cx>) -> &StoredImport<'cx> { &self.imports[id.0] } } -impl<'cx> std::ops::Index for CtxtS<'cx> { +impl<'cx> Index> for CtxtS<'cx> { type Output = Typed<'cx>; - fn index(&self, id: ImportResultId) -> &Typed<'cx> { + fn index(&self, id: ImportResultId<'cx>) -> &Typed<'cx> { &self.import_results[id.0] } } +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. -- cgit v1.2.3 From 8c5b3ff15f2125e9d731fc199e194e1993c36b37 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 7 Dec 2020 14:15:43 +0000 Subject: Thread cx everywhere else imports are read --- dhall/src/ctxt.rs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'dhall/src/ctxt.rs') diff --git a/dhall/src/ctxt.rs b/dhall/src/ctxt.rs index 8bdf99d..3809bc9 100644 --- a/dhall/src/ctxt.rs +++ b/dhall/src/ctxt.rs @@ -83,6 +83,12 @@ impl<'cx> StoredImport<'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> { + 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> { let res = self.cx.push_import_result(res); -- cgit v1.2.3 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