Skip to content

Commit

Permalink
Merge pull request #58 from metaborg/remove-hashmaps
Browse files Browse the repository at this point in the history
remove the main sg hashmap for labels
  • Loading branch information
jdonszelmann authored Jun 12, 2024
2 parents 43bddf1 + 8cb7b63 commit 169d9d9
Show file tree
Hide file tree
Showing 14 changed files with 157 additions and 67 deletions.
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

0 comments on commit 169d9d9

Please sign in to comment.