Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remove the main sg hashmap for labels #58

Merged
merged 2 commits into from
Jun 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions scopegraphs-macros/src/label.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,41 @@ pub fn impl_label(input: DeriveInput) -> TokenStream {
}

let mut variant_names = Vec::new();
let mut variant_numbers = Vec::new();

for variant in variants {
for (num, variant) in variants.into_iter().enumerate() {
if !variant.fields.is_empty() {
return quote_spanned!(
variant.span() => compile_error!("cannot derive Label for an enum with fields on variants");
)
.into();
}

if variant.discriminant.is_some() {
return quote_spanned!(
variant.span() => compile_error!("cannot derive Label for an enum with custom discriminated variants. Use `Label::to_usize()`");
)
.into();
}

variant_names.push(variant.ident);
variant_numbers.push(num);
}
let num_variants = variant_numbers.len();

let name = input.ident;
quote! {
impl scopegraphs::Label for #name {
unsafe impl scopegraphs::Label for #name {
type Array<T> = [T; #num_variants];

fn to_usize(&self) -> usize {
match *self {
#(
Self::#variant_names => #variant_numbers
),*
}
}

fn iter() -> impl Iterator<Item = Self> {
[
#(
Expand Down
8 changes: 4 additions & 4 deletions scopegraphs/src/completeness/critical_edge.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::completeness::Completeness;
use crate::{Scope, ScopeGraph};
use crate::{Label, Scope, ScopeGraph};
use std::cell::RefCell;
use std::{collections::HashSet, hash::Hash};

Expand Down Expand Up @@ -38,7 +38,7 @@ impl<LABEL: Hash + Eq> CriticalEdgeSet<LABEL> {
/// Provides utility function to create scopes with particular open edges.
///
/// Should not be called externally, but only from utility function on [`crate::ScopeGraph`].
pub trait CriticalEdgeBasedCompleteness<LABEL, DATA>: Completeness<LABEL, DATA> {
pub trait CriticalEdgeBasedCompleteness<LABEL: Label, DATA>: Completeness<LABEL, DATA> {
/// Initializes a new scope with a certain set of edges that are still considered "open".
fn init_scope_with(&self, open_edges: HashSet<LABEL>);
}
Expand Down Expand Up @@ -68,7 +68,7 @@ pub struct Delay<LABEL> {
/// Convenience alias for the type of `Result` returned from queries using [critical edge based completion](CriticalEdgeBasedCompleteness)
pub type EdgesOrDelay<EDGES, LABEL> = Result<EDGES, Delay<LABEL>>;

impl<'sg, LABEL: Hash + Eq, DATA, CMPL> ScopeGraph<'sg, LABEL, DATA, CMPL>
impl<'sg, LABEL: Hash + Eq + Label, DATA, CMPL> ScopeGraph<'sg, LABEL, DATA, CMPL>
where
CMPL: CriticalEdgeBasedCompleteness<LABEL, DATA>,
{
Expand All @@ -91,7 +91,7 @@ where
}
}

impl<'sg, LABEL: Hash + Eq, DATA, CMPL> ScopeGraph<'sg, LABEL, DATA, CMPL>
impl<'sg, LABEL: Hash + Eq + Label, DATA, CMPL> ScopeGraph<'sg, LABEL, DATA, CMPL>
where
DATA: Default,
CMPL: CriticalEdgeBasedCompleteness<LABEL, DATA>,
Expand Down
16 changes: 8 additions & 8 deletions scopegraphs/src/completeness/explicit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,19 @@ use std::{collections::HashSet, hash::Hash};
/// Returns [`Delay`] when edges are retrieved (e.g. during query resolution) for an edge that is
/// not yet closed.
#[derive(Debug)]
pub struct ExplicitClose<LABEL> {
pub struct ExplicitClose<LABEL: Label> {
critical_edges: CriticalEdgeSet<LABEL>,
}

impl<LABEL> Default for ExplicitClose<LABEL> {
impl<LABEL: Label> Default for ExplicitClose<LABEL> {
fn default() -> Self {
ExplicitClose {
critical_edges: CriticalEdgeSet::default(),
}
}
}

impl<LABEL> Sealed for ExplicitClose<LABEL> {}
impl<LABEL: Label> Sealed for ExplicitClose<LABEL> {}

impl<LABEL: Hash + Eq + Label, DATA> Completeness<LABEL, DATA> for ExplicitClose<LABEL> {
fn cmpl_new_scope(&self, _: &InnerScopeGraph<LABEL, DATA>, _: Scope) {
Expand Down Expand Up @@ -101,15 +101,15 @@ impl<LABEL: Hash + Eq + Label, DATA> CriticalEdgeBasedCompleteness<LABEL, DATA>
}
}

impl<LABEL: Hash + Eq> ExplicitClose<LABEL> {
impl<LABEL: Label + Hash> ExplicitClose<LABEL> {
/// Close a scope for a certain label
/// // TODO: link to "closing" in concepts
pub fn close(&self, scope: Scope, label: &LABEL) {
self.critical_edges.close(scope, label);
}
}

impl<'sg, LABEL: Hash + Eq, DATA> ScopeGraph<'sg, LABEL, DATA, ExplicitClose<LABEL>> {
impl<'sg, LABEL: Label + Hash, DATA> ScopeGraph<'sg, LABEL, DATA, ExplicitClose<LABEL>> {
// TODO: fix this sentence
/// Closes an edge, (i.e., prohibit future new
///
Expand All @@ -120,7 +120,7 @@ impl<'sg, LABEL: Hash + Eq, DATA> ScopeGraph<'sg, LABEL, DATA, ExplicitClose<LAB
/// # use scopegraphs::Storage;
/// # use scopegraphs::ScopeGraph;
///
/// # #[derive(Eq, Hash, PartialEq, Label)] enum Lbl { Def }
/// # #[derive(Eq, Hash, PartialEq, Label, Copy, Clone)] enum Lbl { Def }
/// # use Lbl::*;
/// let storage = Storage::new();
/// let mut sg = ScopeGraph::<Lbl, usize, _>::new(&storage, ExplicitClose::default());
Expand Down Expand Up @@ -199,7 +199,7 @@ impl<'sg, LABEL: Hash + Eq, DATA> ScopeGraph<'sg, LABEL, DATA, ExplicitClose<LAB
}
}

impl<'sg, LABEL: Hash + Eq + Copy, DATA> ScopeGraph<'sg, LABEL, DATA, FutureCompleteness<LABEL>> {
impl<'sg, LABEL: Label + Hash, DATA> ScopeGraph<'sg, LABEL, DATA, FutureCompleteness<LABEL>> {
// TODO: update this example to use futures
// TODO: fix this sentence
/// Closes an edge, (i.e., prohibit future new
Expand All @@ -210,7 +210,7 @@ impl<'sg, LABEL: Hash + Eq + Copy, DATA> ScopeGraph<'sg, LABEL, DATA, FutureComp
/// # use scopegraphs::ScopeGraph;
/// # use scopegraphs_macros::Label;
/// # use scopegraphs::Storage;
/// # #[derive(Eq, Hash, PartialEq, Label)] enum Lbl { Def }
/// # #[derive(Eq, Hash, PartialEq, Label, Copy, Clone)] enum Lbl { Def }
/// # use Lbl::*;
/// let storage = Storage::new();
/// let mut sg = ScopeGraph::<Lbl, usize, _>::new(&storage, ExplicitClose::default());
Expand Down
8 changes: 4 additions & 4 deletions scopegraphs/src/completeness/future.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ use std::task::{Poll, Waker};
///
/// Extends, and contains an instance of, [`ExplicitClose`].
#[derive(Debug)]
pub struct FutureCompleteness<LABEL> {
pub struct FutureCompleteness<LABEL: Label> {
explicit_close: ExplicitClose<LABEL>,
wakers: RefCell<HashMap<Delay<LABEL>, Vec<Waker>>>,
}

impl<LABEL> Default for FutureCompleteness<LABEL> {
impl<LABEL: Label> Default for FutureCompleteness<LABEL> {
fn default() -> Self {
Self {
explicit_close: ExplicitClose::<LABEL>::default(),
Expand All @@ -34,7 +34,7 @@ impl<LABEL> Default for FutureCompleteness<LABEL> {
}
}

impl<LABEL> Sealed for FutureCompleteness<LABEL> {}
impl<LABEL: Label> Sealed for FutureCompleteness<LABEL> {}

impl<LABEL: Hash + Eq + Label + Copy, DATA> Completeness<LABEL, DATA>
for FutureCompleteness<LABEL>
Expand Down Expand Up @@ -94,7 +94,7 @@ impl<LABEL: Hash + Eq + Label + Copy, DATA> Completeness<LABEL, DATA>
}
}

impl<LABEL: Hash + Eq + Copy> FutureCompleteness<LABEL> {
impl<LABEL: Label + Hash> FutureCompleteness<LABEL> {
pub(crate) fn close(&self, scope: Scope, label: &LABEL) {
self.explicit_close.close(scope, label);
for waker in self
Expand Down
3 changes: 2 additions & 1 deletion scopegraphs/src/completeness/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ mod private {
}

use crate::scopegraph::{InnerScopeGraph, Scope};
use crate::Label;
use private::Sealed;

/*** Completeness trait ***/
Expand Down Expand Up @@ -61,7 +62,7 @@ use private::Sealed;
/// You cannot define your own completeness strategies to ensure that only verified implementations are available.
// TODO: @Aron could you document this?
#[allow(missing_docs)]
pub trait Completeness<LABEL, DATA>: Sealed {
pub trait Completeness<LABEL: Label, DATA>: Sealed {
fn cmpl_new_scope(&self, inner_scope_graph: &InnerScopeGraph<LABEL, DATA>, scope: Scope);

/// Should initialize a scope without possibility to extend it with edges
Expand Down
4 changes: 2 additions & 2 deletions scopegraphs/src/completeness/unchecked.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::completeness::private::Sealed;
use crate::completeness::Completeness;
use crate::scopegraph::{InnerScopeGraph, Scope};
use std::hash::Hash;
use crate::Label;

/// No-Op implementation of [`Completeness`].
#[derive(Debug)]
Expand All @@ -23,7 +23,7 @@ impl UncheckedCompleteness {
}
}

impl<LABEL: Hash + Eq, DATA> Completeness<LABEL, DATA> for UncheckedCompleteness {
impl<LABEL: Label, DATA> Completeness<LABEL, DATA> for UncheckedCompleteness {
fn cmpl_new_scope(&self, _: &InnerScopeGraph<LABEL, DATA>, _: Scope) {}

fn cmpl_new_complete_scope(
Expand Down
51 changes: 49 additions & 2 deletions scopegraphs/src/label.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,54 @@
use std::array;

pub(crate) trait ArrayInit<T> {
fn init_from_fn(init: impl FnMut() -> T) -> Self;
}

impl<T, const N: usize> ArrayInit<T> for [T; N] {
fn init_from_fn(mut init: impl FnMut() -> T) -> Self {
array::from_fn(|_| init())
}
}

unsafe impl Label for () {
type Array<T> = [T; 1];

fn to_usize(&self) -> usize {
0
}

fn iter() -> impl Iterator<Item = Self>
where
Self: Sized,
{
[()].into_iter()
}

fn iter_ref() -> impl Iterator<Item = &'static Self>
where
Self: Sized + 'static,
{
[&()].into_iter()
}
}

/// Represents types that can be used as labels on [`scopegraph edges`](crate::concepts::edges).
///
/// Can be derived.
pub trait Label {
/// Can, and should, be derived using the [`Label`](scopegraphs_macros::Label) derive macro.
///
/// # Safety
///
/// This trait is unsafe to implement by yourself, as code in this library depends on the fact
/// that [`to_usize`](Label::to_usize) returns a list of consecutive indices from 0 to [`NUM_LABELS`](Label::NUM_LABELS) - 1
pub unsafe trait Label: Eq + Copy {
/// The type of an array of these labels, with one slot for each label type.
/// NOTE: using an associated const doesn't work without full const generics
#[allow(private_bounds)]
type Array<T>: AsRef<[T]> + AsMut<[T]> + ArrayInit<T>;

/// Convert any label to a unique usize, which m
fn to_usize(&self) -> usize;

/// Iterate over all possible labels that this label type could be.
fn iter() -> impl Iterator<Item = Self>
where
Expand Down
2 changes: 1 addition & 1 deletion scopegraphs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub use storage::Storage;
/// use scopegraphs::*;
/// use scopegraphs::Label;
///
/// #[derive(Label, Debug, PartialEq, Eq)]
/// #[derive(Label, Debug, PartialEq, Eq, Copy, Clone)]
/// pub enum Alphabet {
/// A,
/// B,
Expand Down
6 changes: 3 additions & 3 deletions scopegraphs/src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! Generally, use `sg.render_to(filename, Settings::default()` for the most basic rendering.

use crate::completeness::Completeness;
use crate::{Scope, ScopeGraph};
use crate::{Label, Scope, ScopeGraph};
use std::fs::File;
use std::io;
use std::io::Write;
Expand Down Expand Up @@ -75,7 +75,7 @@ pub struct EdgeTo {
}

/// Modifies how an edge label is rendered.
pub trait RenderScopeLabel {
pub trait RenderScopeLabel: Label {
/// Render a single label
fn render(&self) -> String;
}
Expand Down Expand Up @@ -128,7 +128,7 @@ fn escape_text_mermaid(inp: &str) -> String {
}

impl<
LABEL: Clone + RenderScopeLabel,
LABEL: Clone + RenderScopeLabel + Label,
DATA: RenderScopeData + Clone,
CMPL: Completeness<LABEL, DATA>,
> ScopeGraph<'_, LABEL, DATA, CMPL>
Expand Down
4 changes: 3 additions & 1 deletion scopegraphs/src/render/traverse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ pub fn traverse<'sg, LABEL: RenderScopeLabel, DATA, CMPL: Completeness<LABEL, DA
.flat_map(|(scope, edges)| {
(*edges)
.borrow()
.as_ref()
.iter()
.flat_map(|(lbl, edges_with_lbl)| {
.zip(LABEL::iter())
.flat_map(|(edges_with_lbl, lbl)| {
edges_with_lbl
.iter()
.map(|edge| Edge {
Expand Down
4 changes: 2 additions & 2 deletions scopegraphs/src/resolve/lookup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ where
}
}

struct ResolutionContext<'storage, 'sg: 'rslv, 'rslv, LABEL, DATA, CMPL, DWF, LO, DEq> {
struct ResolutionContext<'storage, 'sg: 'rslv, 'rslv, LABEL: Label, DATA, CMPL, DWF, LO, DEq> {
all_edges: Vec<EdgeOrData<LABEL>>,
sg: &'sg ScopeGraph<'storage, LABEL, DATA, CMPL>,
data_wellformedness: &'rslv DWF,
Expand All @@ -106,7 +106,7 @@ type EnvCache<LABEL, ENVC> = RefCell<HashMap<EdgeOrData<LABEL>, Rc<ENVC>>>;
impl<'storage, 'sg: 'rslv, 'rslv, LABEL, DATA, CMPL, DWF, LO, DEq>
ResolutionContext<'storage, 'sg, 'rslv, LABEL, DATA, CMPL, DWF, LO, DEq>
where
LABEL: Copy + Debug + Hash + Eq,
LABEL: Label + Debug + Hash,
DATA: Debug,
ResolvedPath<'sg, LABEL, DATA>: Hash + Eq,
CMPL: Completeness<LABEL, DATA>,
Expand Down
12 changes: 6 additions & 6 deletions scopegraphs/src/resolve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::marker::PhantomData;
use std::rc::Rc;

mod params;
use crate::{Scope, ScopeGraph};
use crate::{Label, Scope, ScopeGraph};
pub use params::*;
use scopegraphs_regular_expressions::RegexMatcher;

Expand Down Expand Up @@ -412,7 +412,7 @@ pub trait Resolve<'sg, 'rslv> {
}

/// A query over a scope graph. Read more [here](crate::concepts)
pub struct Query<'storage, 'sg, 'rslv, LABEL, DATA, CMPL, PWF, DWF, LO, DEq> {
pub struct Query<'storage, 'sg, 'rslv, LABEL: Label, DATA, CMPL, PWF, DWF, LO, DEq> {
_phantom: PhantomData<&'rslv ()>,
scope_graph: &'sg ScopeGraph<'storage, LABEL, DATA, CMPL>,
path_wellformedness: PWF,
Expand All @@ -421,7 +421,7 @@ pub struct Query<'storage, 'sg, 'rslv, LABEL, DATA, CMPL, PWF, DWF, LO, DEq> {
data_equivalence: DEq,
}

impl<'sg, 'storage, 'rslv, LABEL, DATA, CMPL, PWF, DWF, LO, DEq>
impl<'sg, 'storage, 'rslv, LABEL: Label, DATA, CMPL, PWF, DWF, LO, DEq>
Query<'sg, 'storage, 'rslv, LABEL, DATA, CMPL, PWF, DWF, LO, DEq>
{
/// Add a [path well-formedness](crate::concepts::path_wellformedness) to this query.
Expand All @@ -436,7 +436,7 @@ impl<'sg, 'storage, 'rslv, LABEL, DATA, CMPL, PWF, DWF, LO, DEq>
/// # let storage = Storage::new();
/// # let scopegraph = ScopeGraph::<Lbl, (), _>::new(&storage, unsafe{UncheckedCompleteness::new()});
///
/// #[derive(Label)]
/// #[derive(Label, Eq, PartialEq, Copy, Clone)]
/// pub enum Lbl {
/// Lexical,
/// Definition
Expand Down Expand Up @@ -547,7 +547,7 @@ impl<'sg, 'storage, 'rslv, LABEL, DATA, CMPL, PWF, DWF, LO, DEq>
/// # let scopegraph = ScopeGraph::<Lbl, (), _>::new(&storage, unsafe{UncheckedCompleteness::new()});
/// use scopegraphs_macros::label_order;
///
/// #[derive(Label, Copy, Clone)]
/// #[derive(Label, Copy, Clone, PartialEq, Eq)]
/// pub enum Lbl {
/// Lexical,
/// Definition
Expand Down Expand Up @@ -596,7 +596,7 @@ impl<'sg, 'storage, 'rslv, LABEL, DATA, CMPL, PWF, DWF, LO, DEq>
}
}

impl<'storage, LABEL, DATA, CMPL> ScopeGraph<'storage, LABEL, DATA, CMPL> {
impl<'storage, LABEL: Label, DATA, CMPL> ScopeGraph<'storage, LABEL, DATA, CMPL> {
/// Build a query over the scope graph.
pub fn query<'sg>(
&'sg self,
Expand Down
Loading
Loading