#module #nested #compiler #blocks #systems #path #root

nested-modules

Building blocks for nested module systems

2 unstable releases

0.2.0 Jun 18, 2021
0.1.0 Jul 9, 2020

#1238 in Development tools

46 downloads per month
Used in 2 crates (via kontroli)

MIT/Apache

9KB
120 lines

nested-modules

This Rust library provides building blocks for nested module systems.


lib.rs:

Nested modules.

This package enables the integration of a (nested) module system into projects such as compilers, interpreters etc. Its speciality is the way it resolves module references: In particular, we can always only reference modules by their shortest possible path relative to the current position.

For example, suppose we have the modules a/b/c, a/d/e and f. Furthermore, let us be in the module a/b/c. We can then reference a/b/c, a/b, a and the root module (ancestors of our current module) only by the empty path. Furthermore, we can reference a/d by the path d, a/d/e by the path d/e, and f by the path f.

This restriction on module references enables a very simple implementation as well as the property that we can always wrap modules around other modules and be certain that this preserves valid references of the original module.

In the following example, we create a module with root data 0 and the following submodules:

  • b: 1
  • a: 2
    • b: 3

We then search for the module "b" twice from different modules: When we are inside "a", we find two occurrences of "b", namely "a"/"b" (3) and "b" (1). When we are inside the root module, we find only one occurrence of "b", namely "b" (1).

let mut ctx = Context::new();
ctx.get_mut().data = 0;
ctx.insert("b", Module::from(1));
assert!(!ctx.close());
ctx.open_or("a", Module::from(2));
ctx.insert("b", Module::from(3));

// we are now in module "a"
assert_eq!(ctx.get().data, 2);
// searching for a module "b" yields two results
let result: Vec<_> = ctx.find(["b"].iter()).map(|m| m.data).collect();
assert_eq!(result, vec![3, 1]);
// searching for "a" yields no result, because we are inside it
let result: Vec<_> = ctx.find(["a"].iter()).map(|m| m.data).collect();
assert_eq!(result, vec![]);
assert!(ctx.close());

// we are now in the root module
assert_eq!(ctx.get().data, 0);
// searching for either module "b", "a", or "a"/"b" yields only one result now
let result: Vec<_> = ctx.find(["b"].iter()).map(|m| m.data).collect();
assert_eq!(result, vec![1]);
let result: Vec<_> = ctx.find(["a"].iter()).map(|m| m.data).collect();
assert_eq!(result, vec![2]);
let result: Vec<_> = ctx.find(["a", "b"].iter()).map(|m| m.data).collect();
assert_eq!(result, vec![3]);
assert!(!ctx.close());

No runtime deps