metaborg / rust-scopegraphs

Scope Graph Implementation in Rust
https://github.com/metaborg/rust-scopegraphs
MIT License
20 stars 0 forks source link

Leverage Rusts `Drop` to close scopes automatically and implicitly #44

Open AZWN opened 2 months ago

AZWN commented 2 months ago

The regular 'scope ownership'/permission-to-extend is rather similar to Rust's scoping/lifetime rules.

Perhaps, we can leverage the Rust type system to close scopes automatically.

This could look as follows:

struct ScopeRef(u64)
struct ScopeExt<LABEL> { ref: &ScopeRef, lbl: &LABEL, _sg: &ScopeGraph<...> }

where ScopeRef can be used for querying, but a ScopeExt is required for extension:

struct NewScope<...> {
  ref: ScopeRef,
  ext: Vec<ScopeExt>
}

impl ScopeGraph<...> {
  pub fn add_scope(&self, data: &DATA, open_edges: &[LABEL]) -> NewScope {
    ...
  }

  pub fn get_edges(&self, scope: &ScopeRef, lbl: &LABEL) -> impl Iterator<Item = &ScopeRef> { ... }

  pub fn add_edge(&self, ext: &ScopeExt, tgt: &ScopeRef) { ... }
}

The NewScope type carries all information of the new scope:

The trick now is the following. We can implement a custom Drop for ScopeExt:

impl Drop for ScopeExt<...> {
  fn drop(&mut self) {
    self._sg.close(&self.ref, &self.lbl);
  }
}

This ensures that a scope is closed when the ScopeExt is deallocated.

Macro

Perhaps, it would be better to wrap the API in a macro that unpacks the ScopeExt instances:

let (scope, ext_lex, ext_def) = new_scope!(sg, data, Lbl::Lexical, Lbl::Definition);