Skip to main content

knave_expand/scope/
binding_table.rs

1use std::collections::hash_map;
2use std::ops::Range;
3use std::rc::Rc;
4
5use rustc_hash::FxHashMap;
6
7use super::saved_names::{NameTables, SavedNames};
8use super::{Scope, ScopeSet};
9use crate::core::{BindingId, Namespace};
10use crate::reader::Symbol;
11
12#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
13pub enum Phase {
14    Runtime,
15    CompileTime,
16}
17
18#[derive(Clone, Debug, PartialEq, Eq)]
19pub enum Resolution {
20    Bound(BindingId),
21    Unbound,
22    Ambiguous(Vec<BindingId>),
23}
24
25#[derive(serde::Serialize, serde::Deserialize)]
26struct Entry {
27    scopes: ScopeSet,
28    binding: BindingId,
29    phase: Phase,
30}
31
32impl Entry {
33    fn is_visible_from_scopes(&self, scopes: &ScopeSet, phase: Phase) -> bool {
34        self.phase_matches(phase) && self.scopes.is_subset_of(scopes)
35    }
36
37    fn is_visible_from_plain_scopes(&self, scopes: &ScopeSet, phase: Phase) -> bool {
38        self.phase_matches(phase) && self.scopes.is_plain_subset_of(scopes)
39    }
40
41    fn phase_matches(&self, phase: Phase) -> bool {
42        phase == Phase::CompileTime || self.phase == Phase::Runtime
43    }
44
45    fn anchor(&self) -> Option<Scope> {
46        self.scopes.plain_largest()
47    }
48}
49
50#[derive(Default, serde::Serialize, serde::Deserialize)]
51pub(super) struct NameEntries {
52    plain_sorted_by_anchor: Vec<Entry>,
53    sharing: Vec<Entry>,
54}
55
56impl NameEntries {
57    const SHORT_LIST_LENGTH: usize = 16;
58
59    fn bind(
60        &mut self,
61        scopes: &ScopeSet,
62        binding: BindingId,
63        phase: Phase,
64    ) -> Result<(), BindingId> {
65        if !self.is_plain_search(scopes) {
66            return self.bind_sharing(scopes, binding, phase);
67        }
68        let anchored_end = self.anchored_end(scopes.plain_largest());
69        match self.entry_with_scopes(anchored_end, scopes) {
70            Some(existing) => Self::existing(existing, binding),
71            None => {
72                let entry = Entry {
73                    scopes: scopes.clone(),
74                    binding,
75                    phase,
76                };
77                self.plain_sorted_by_anchor.insert(anchored_end, entry);
78                Ok(())
79            }
80        }
81    }
82
83    fn existing(existing: &Entry, binding: BindingId) -> Result<(), BindingId> {
84        if existing.binding == binding {
85            Ok(())
86        } else {
87            Err(existing.binding)
88        }
89    }
90
91    #[inline(never)]
92    fn bind_sharing(
93        &mut self,
94        scopes: &ScopeSet,
95        binding: BindingId,
96        phase: Phase,
97    ) -> Result<(), BindingId> {
98        if let Some(existing) = self.all().find(|entry| entry.scopes == *scopes) {
99            return Self::existing(existing, binding);
100        }
101        let entry = Entry {
102            scopes: scopes.clone(),
103            binding,
104            phase,
105        };
106        if scopes.is_plain() {
107            let anchored_end = self.anchored_end(scopes.plain_largest());
108            self.plain_sorted_by_anchor.insert(anchored_end, entry);
109        } else {
110            self.sharing.push(entry);
111        }
112        Ok(())
113    }
114
115    fn anchored_end(&self, anchor: Option<Scope>) -> usize {
116        self.plain_sorted_by_anchor
117            .partition_point(|entry| entry.anchor() <= anchor)
118    }
119
120    fn entry_with_scopes(&self, anchored_end: usize, scopes: &ScopeSet) -> Option<&Entry> {
121        let anchor = scopes.plain_largest();
122        self.plain_sorted_by_anchor[..anchored_end]
123            .iter()
124            .rev()
125            .take_while(|entry| entry.anchor() == anchor)
126            .find(|entry| entry.scopes == *scopes)
127    }
128
129    fn visible(&self, scopes: &ScopeSet, phase: Phase) -> Vec<&Entry> {
130        let mut visible = Vec::new();
131        self.visit_visible(scopes, phase, |entry| visible.push(entry));
132        visible
133    }
134
135    fn visit_visible<'entries>(
136        &'entries self,
137        scopes: &ScopeSet,
138        phase: Phase,
139        visit: impl FnMut(&'entries Entry),
140    ) {
141        if self.is_plain_search(scopes) {
142            self.visit_plain_visible(scopes, phase, visit);
143        } else {
144            self.visit_visible_sharing(scopes, phase, visit);
145        }
146    }
147
148    fn is_plain_search(&self, scopes: &ScopeSet) -> bool {
149        self.sharing.is_empty() && scopes.is_plain()
150    }
151
152    fn visit_plain_visible<'entries>(
153        &'entries self,
154        scopes: &ScopeSet,
155        phase: Phase,
156        mut visit: impl FnMut(&'entries Entry),
157    ) {
158        let mut visit_if_visible = |entry: &'entries Entry| {
159            if entry.is_visible_from_plain_scopes(scopes, phase) {
160                visit(entry);
161            }
162        };
163        if self.is_shorter_than_an_anchor_search(scopes) {
164            self.plain_sorted_by_anchor
165                .iter()
166                .for_each(visit_if_visible);
167            return;
168        }
169        for anchor in Self::possible_anchors(scopes) {
170            self.plain_sorted_by_anchor[self.anchored(anchor)]
171                .iter()
172                .for_each(&mut visit_if_visible);
173        }
174    }
175
176    #[inline(never)]
177    fn visit_visible_sharing<'entries>(
178        &'entries self,
179        scopes: &ScopeSet,
180        phase: Phase,
181        visit: impl FnMut(&'entries Entry),
182    ) {
183        self.all()
184            .filter(|entry| entry.is_visible_from_scopes(scopes, phase))
185            .for_each(visit);
186    }
187
188    fn unbind(&mut self, binding: BindingId) {
189        self.plain_sorted_by_anchor
190            .retain(|entry| entry.binding != binding);
191        self.sharing.retain(|entry| entry.binding != binding);
192    }
193
194    fn forget(&mut self, forgotten: &impl Fn(BindingId) -> bool) {
195        self.plain_sorted_by_anchor
196            .retain(|entry| !forgotten(entry.binding));
197        self.sharing.retain(|entry| !forgotten(entry.binding));
198    }
199
200    fn is_empty(&self) -> bool {
201        self.plain_sorted_by_anchor.is_empty() && self.sharing.is_empty()
202    }
203
204    pub(super) fn is_within(&self, scopes: &Range<Scope>) -> bool {
205        self.all()
206            .all(|entry| entry.scopes.iter().any(|scope| scopes.contains(&scope)))
207    }
208
209    fn all(&self) -> impl Iterator<Item = &Entry> {
210        self.plain_sorted_by_anchor.iter().chain(&self.sharing)
211    }
212
213    fn is_shorter_than_an_anchor_search(&self, scopes: &ScopeSet) -> bool {
214        self.plain_sorted_by_anchor.len() <= scopes.plain_len().max(Self::SHORT_LIST_LENGTH)
215    }
216
217    fn anchored(&self, anchor: Option<Scope>) -> Range<usize> {
218        let start = self
219            .plain_sorted_by_anchor
220            .partition_point(|entry| entry.anchor() < anchor);
221        let length =
222            self.plain_sorted_by_anchor[start..].partition_point(|entry| entry.anchor() == anchor);
223        start..start + length
224    }
225
226    fn possible_anchors(scopes: &ScopeSet) -> impl Iterator<Item = Option<Scope>> + '_ {
227        std::iter::once(None).chain(scopes.plain_iter().map(Some))
228    }
229}
230
231#[derive(Default, serde::Serialize, serde::Deserialize)]
232pub struct BindingTable {
233    #[serde(skip)]
234    saved: SavedNames,
235    entries: FxHashMap<(Rc<str>, Namespace), NameEntries>,
236    qualified_names: QualifiedNames,
237}
238
239impl BindingTable {
240    pub fn bind(
241        &mut self,
242        symbol: &Symbol,
243        namespace: Namespace,
244        binding: BindingId,
245        phase: Phase,
246    ) -> Result<(), BindingId> {
247        let entries = match self.entries.entry((symbol.shared_name(), namespace)) {
248            hash_map::Entry::Occupied(occupied) => occupied.into_mut(),
249            hash_map::Entry::Vacant(vacant) => {
250                self.qualified_names.record(vacant.key());
251                vacant.insert(NameEntries::default())
252            }
253        };
254        entries.bind(symbol.scopes(), binding, phase)
255    }
256
257    pub fn unbind(&mut self, symbol: &Symbol, namespace: Namespace, binding: BindingId) {
258        if let Some(entries) = self.entries.get_mut(&(symbol.shared_name(), namespace)) {
259            entries.unbind(binding);
260        }
261    }
262
263    pub fn forget(&mut self, forgotten: impl Fn(BindingId) -> bool) {
264        for entries in self.entries.values_mut() {
265            entries.forget(&forgotten);
266        }
267        self.entries.retain(|_, entries| !entries.is_empty());
268    }
269
270    #[cfg(test)]
271    pub fn holds(&self, binding: BindingId) -> bool {
272        let saved = self.saved.all().map(|(_, _, entries)| entries);
273        let mut all = self
274            .entries
275            .values()
276            .chain(saved)
277            .flat_map(NameEntries::all);
278        all.any(|entry| entry.binding == binding)
279    }
280
281    pub fn resolve(&self, symbol: &Symbol, namespace: Namespace, phase: Phase) -> Resolution {
282        let mut largest = LargestCandidates::default();
283        for entries in self.entries_named(
284            symbol.scopes(),
285            symbol.name(),
286            symbol.shared_name(),
287            namespace,
288        ) {
289            entries.visit_visible(symbol.scopes(), phase, |entry| largest.consider(entry));
290        }
291        largest.resolution()
292    }
293
294    pub fn visible_name_bindings(
295        &self,
296        symbol: &Symbol,
297        namespace: Namespace,
298        phase: Phase,
299    ) -> Vec<(Rc<str>, BindingId)> {
300        let own = self
301            .entries
302            .iter()
303            .map(|((name, entry_namespace), entries)| (Rc::clone(name), *entry_namespace, entries));
304        own.chain(self.saved.all())
305            .filter(|(_, entry_namespace, _)| *entry_namespace == namespace)
306            .flat_map(|(name, _, entries)| {
307                entries
308                    .visible(symbol.scopes(), phase)
309                    .into_iter()
310                    .map(move |entry| (Rc::clone(&name), entry.binding))
311            })
312            .collect()
313    }
314
315    pub fn visible_bindings(
316        &self,
317        scopes: &ScopeSet,
318        namespace: Namespace,
319        phase: Phase,
320    ) -> Vec<BindingId> {
321        let own = self
322            .entries
323            .iter()
324            .filter(|((_, entry_namespace), _)| *entry_namespace == namespace)
325            .map(|(_, entries)| entries);
326        own.chain(self.saved.all_of(namespace))
327            .flat_map(|entries| entries.visible(scopes, phase))
328            .map(|entry| entry.binding)
329            .collect()
330    }
331
332    pub fn visible_qualified_bindings_ending_in(
333        &self,
334        last_segment: &Symbol,
335        namespace: Namespace,
336        phase: Phase,
337    ) -> Vec<BindingId> {
338        let mut visible = Vec::new();
339        for name in self
340            .qualified_names
341            .ending_in(last_segment.shared_name(), namespace)
342        {
343            for entries in
344                self.entries_named(last_segment.scopes(), name, Rc::clone(name), namespace)
345            {
346                entries.visit_visible(last_segment.scopes(), phase, |entry| {
347                    visible.push(entry.binding);
348                });
349            }
350        }
351        visible
352    }
353
354    pub fn take_saved(&mut self, prelude_scopes: Range<Scope>) -> NameTables {
355        let entries = std::mem::take(&mut self.entries);
356        let keyed = entries
357            .into_iter()
358            .map(|((name, namespace), entries)| (name, namespace, entries));
359        NameTables::of(keyed.collect(), prelude_scopes)
360    }
361
362    pub fn adopt_saved(&mut self, saved: SavedNames) {
363        self.saved = saved;
364    }
365
366    fn entries_named(
367        &self,
368        scopes: &ScopeSet,
369        name: &str,
370        shared: Rc<str>,
371        namespace: Namespace,
372    ) -> impl Iterator<Item = &NameEntries> {
373        let own = self.entries.get(&(shared, namespace));
374        let saved = self.saved.entries_seen_from(scopes, name, namespace);
375        own.into_iter().chain(saved)
376    }
377}
378
379#[derive(Default, serde::Serialize, serde::Deserialize)]
380struct QualifiedNames {
381    by_last_segment: FxHashMap<(Rc<str>, Namespace), Vec<Rc<str>>>,
382}
383
384impl QualifiedNames {
385    const SEPARATOR: char = '/';
386
387    fn record(&mut self, (name, namespace): &(Rc<str>, Namespace)) {
388        if let Some((_, last_segment)) = name.rsplit_once(Self::SEPARATOR) {
389            let names = self
390                .by_last_segment
391                .entry((last_segment.into(), *namespace))
392                .or_default();
393            if !names.contains(name) {
394                names.push(Rc::clone(name));
395            }
396        }
397    }
398
399    fn ending_in(&self, last_segment: Rc<str>, namespace: Namespace) -> &[Rc<str>] {
400        self.by_last_segment
401            .get(&(last_segment, namespace))
402            .map_or(&[], Vec::as_slice)
403    }
404}
405
406#[derive(Default)]
407struct LargestCandidates {
408    size: usize,
409    first: Option<BindingId>,
410    others: Vec<BindingId>,
411}
412
413impl LargestCandidates {
414    fn consider(&mut self, entry: &Entry) {
415        let size = entry.scopes.len();
416        match self.first {
417            Some(_) if size < self.size => {}
418            Some(first) if size == self.size => self.add_equal(first, entry.binding),
419            _ => self.replace(size, entry.binding),
420        }
421    }
422
423    fn add_equal(&mut self, first: BindingId, binding: BindingId) {
424        if binding != first {
425            self.others.push(binding);
426        }
427    }
428
429    fn replace(&mut self, size: usize, binding: BindingId) {
430        self.size = size;
431        self.first = Some(binding);
432        self.others.clear();
433    }
434
435    fn resolution(self) -> Resolution {
436        match self.first {
437            None => Resolution::Unbound,
438            Some(binding) if self.others.is_empty() => Resolution::Bound(binding),
439            Some(binding) => Resolution::Ambiguous(Self::distinct(binding, self.others)),
440        }
441    }
442
443    fn distinct(first: BindingId, mut others: Vec<BindingId>) -> Vec<BindingId> {
444        others.push(first);
445        others.sort();
446        others.dedup();
447        others
448    }
449}
450
451#[cfg(test)]
452mod tests {
453    use super::*;
454    use crate::core::{BindingArena, BindingInfo, BindingKind};
455    use crate::scope::{ChainPrefix, Scope, ScopeAllocator, ScopeChain};
456
457    struct World {
458        table: BindingTable,
459        bindings: BindingArena,
460        scopes: ScopeAllocator,
461    }
462
463    impl World {
464        fn new() -> Self {
465            Self {
466                table: BindingTable::default(),
467                bindings: BindingArena::default(),
468                scopes: ScopeAllocator::default(),
469            }
470        }
471
472        fn scope(&mut self) -> Scope {
473            self.scopes.fresh()
474        }
475
476        fn save_names(&mut self) {
477            let first = ScopeAllocator::default().next_scope();
478            self.save_names_from(first);
479        }
480
481        fn save_names_from(&mut self, first: Scope) {
482            let prelude_scopes = first..self.scopes.next_scope();
483            let tables = self.table.take_saved(prelude_scopes);
484            let encoded = bincode::serialize(&tables).expect("the tables serialize");
485            let saved = bincode::deserialize(encoded.leak()).expect("the tables load");
486            self.table.adopt_saved(saved);
487        }
488
489        fn chain(&mut self, length: usize) -> ScopeChain {
490            let chain = ScopeChain::default();
491            (0..length).for_each(|_| chain.push(self.scope()));
492            chain
493        }
494
495        fn prefix(chain: &ScopeChain) -> ChainPrefix {
496            chain.prefix().expect("a test chain holds scopes")
497        }
498
499        fn sharing_symbol(name: &str, prefix: &ChainPrefix) -> Symbol {
500            let mut scopes = ScopeSet::default();
501            scopes.add_prefix(prefix);
502            Symbol::with_scopes(name, scopes)
503        }
504
505        fn define_sharing(&mut self, name: &str, prefix: &ChainPrefix) -> BindingId {
506            let binding = self.new_binding(name);
507            self.table
508                .bind(
509                    &Self::sharing_symbol(name, prefix),
510                    Namespace::Value,
511                    binding,
512                    Phase::Runtime,
513                )
514                .expect("no duplicate");
515            binding
516        }
517
518        fn new_binding(&mut self, name: &str) -> BindingId {
519            let info = BindingInfo::new(name.into(), BindingKind::Local, None);
520            self.bindings.add(info)
521        }
522
523        fn resolve_sharing(&self, name: &str, prefix: &ChainPrefix) -> Resolution {
524            self.table.resolve(
525                &Self::sharing_symbol(name, prefix),
526                Namespace::Value,
527                Phase::Runtime,
528            )
529        }
530
531        fn symbol(name: &str, scopes: &[Scope]) -> Symbol {
532            Symbol::with_scopes(name, Self::scope_set(scopes))
533        }
534
535        fn scope_set(scopes: &[Scope]) -> ScopeSet {
536            let mut set = ScopeSet::default();
537            scopes.iter().for_each(|scope| set.add(*scope));
538            set
539        }
540
541        fn define(&mut self, name: &str, scopes: &[Scope], phase: Phase) -> BindingId {
542            self.define_in(name, scopes, Namespace::Value, phase)
543        }
544
545        fn define_type(&mut self, name: &str, scopes: &[Scope]) -> BindingId {
546            self.define_in(name, scopes, Namespace::Type, Phase::Runtime)
547        }
548
549        fn define_in(
550            &mut self,
551            name: &str,
552            scopes: &[Scope],
553            namespace: Namespace,
554            phase: Phase,
555        ) -> BindingId {
556            let binding = self.new_binding(name);
557            let symbol = Self::symbol(name, scopes);
558            self.table
559                .bind(&symbol, namespace, binding, phase)
560                .expect("no duplicate");
561            binding
562        }
563
564        fn define_under_subsets(
565            &mut self,
566            name: &str,
567            scopes: &[Scope],
568            count: usize,
569        ) -> Vec<(Vec<Scope>, BindingId)> {
570            (0..count)
571                .map(|index| {
572                    let subset = Self::subset(scopes, index);
573                    let binding = self.define(name, &subset, Phase::Runtime);
574                    (subset, binding)
575                })
576                .collect()
577        }
578
579        fn subset(scopes: &[Scope], index: usize) -> Vec<Scope> {
580            scopes
581                .iter()
582                .enumerate()
583                .filter(|(position, _)| index & (1 << position) != 0)
584                .map(|(_, scope)| *scope)
585                .collect()
586        }
587
588        fn visible(&self, scopes: &[Scope]) -> Vec<BindingId> {
589            let mut bindings = self.table.visible_bindings(
590                &Self::scope_set(scopes),
591                Namespace::Value,
592                Phase::Runtime,
593            );
594            bindings.sort();
595            bindings
596        }
597
598        fn visible_qualified_ending_in(
599            &self,
600            last_segment: &str,
601            scopes: &[Scope],
602        ) -> Vec<BindingId> {
603            let mut bindings = self.table.visible_qualified_bindings_ending_in(
604                &Self::symbol(last_segment, scopes),
605                Namespace::Value,
606                Phase::Runtime,
607            );
608            bindings.sort();
609            bindings
610        }
611
612        fn resolve(&self, name: &str, scopes: &[Scope], phase: Phase) -> Resolution {
613            self.table
614                .resolve(&Self::symbol(name, scopes), Namespace::Value, phase)
615        }
616    }
617
618    #[test]
619    fn taking_the_saved_names_leaves_the_table_empty() {
620        let mut world = World::new();
621        let scope = world.scope();
622        world.define("taken", &[scope], Phase::Runtime);
623        let everything = ScopeAllocator::default().next_scope()..world.scopes.next_scope();
624        world.table.take_saved(everything);
625        assert!(world.table.entries.is_empty());
626    }
627
628    #[test]
629    fn a_symbol_with_a_prelude_scope_finds_a_saved_name() {
630        let mut world = World::new();
631        let scope = world.scope();
632        let saved = world.define("saved", &[scope], Phase::Runtime);
633        world.save_names();
634        let symbol = World::symbol("saved", &[scope]);
635        let resolution = world
636            .table
637            .resolve(&symbol, Namespace::Value, Phase::Runtime);
638        assert_eq!(resolution, Resolution::Bound(saved));
639    }
640
641    #[test]
642    fn a_symbol_with_only_later_scopes_decodes_no_saved_name() {
643        let mut world = World::new();
644        let scope = world.scope();
645        world.define("saved", &[scope], Phase::Runtime);
646        world.save_names();
647        let later = world.scope();
648        let symbol = World::symbol("saved", &[later]);
649        world
650            .table
651            .resolve(&symbol, Namespace::Value, Phase::Runtime);
652        assert!(!world.table.saved.is_decoded("saved", Namespace::Value));
653    }
654
655    #[test]
656    fn a_symbol_with_only_earlier_scopes_decodes_no_saved_name() {
657        let mut world = World::new();
658        let earlier = world.scope();
659        let first = world.scopes.next_scope();
660        let scope = world.scope();
661        world.define("saved", &[scope], Phase::Runtime);
662        world.save_names_from(first);
663        let symbol = World::symbol("saved", &[earlier]);
664        world
665            .table
666            .resolve(&symbol, Namespace::Value, Phase::Runtime);
667        assert!(!world.table.saved.is_decoded("saved", Namespace::Value));
668    }
669
670    #[test]
671    fn a_shared_scope_chain_still_looks_in_the_saved_names() {
672        let mut world = World::new();
673        let scope = world.scope();
674        world.define("saved", &[scope], Phase::Runtime);
675        world.save_names();
676        let chain = world.chain(ScopeSet::SHORTEST_SHARED_PREFIX);
677        world.resolve_sharing("saved", &World::prefix(&chain));
678        assert!(world.table.saved.is_decoded("saved", Namespace::Value));
679    }
680
681    #[test]
682    #[should_panic(expected = "every saved name is bound under a prelude scope")]
683    fn a_saved_name_outside_the_prelude_scopes_stops_the_build() {
684        let mut world = World::new();
685        let scope = world.scope();
686        world.define("saved", &[scope], Phase::Runtime);
687        let later = world.scopes.next_scope();
688        world.table.take_saved(later..later);
689    }
690
691    #[test]
692    fn a_saved_type_name_is_listed_in_the_type_namespace_only() {
693        let mut world = World::new();
694        let scope = world.scope();
695        let saved = world.define_type("saved", &[scope]);
696        world.save_names();
697        let symbol = World::symbol("anything", &[scope]);
698        let types = world
699            .table
700            .visible_name_bindings(&symbol, Namespace::Type, Phase::Runtime);
701        let values = world
702            .table
703            .visible_name_bindings(&symbol, Namespace::Value, Phase::Runtime);
704        assert_eq!(types, vec![(Rc::from("saved"), saved)]);
705        assert!(values.is_empty());
706    }
707
708    #[test]
709    fn a_qualified_name_bound_again_after_a_save_is_recorded_once() {
710        let mut world = World::new();
711        let (scope, other) = (world.scope(), world.scope());
712        world.define("option/some", &[scope], Phase::Runtime);
713        world.save_names();
714        world.define("option/some", &[other], Phase::Runtime);
715        let recorded = world
716            .table
717            .qualified_names
718            .ending_in("some".into(), Namespace::Value);
719        assert_eq!(recorded.len(), 1);
720    }
721
722    #[test]
723    #[should_panic(expected = "every saved name is bound under a prelude scope")]
724    fn a_shared_saved_name_outside_the_prelude_scopes_stops_the_build() {
725        let mut world = World::new();
726        let chain = world.chain(ScopeSet::SHORTEST_SHARED_PREFIX);
727        world.define_sharing("saved", &World::prefix(&chain));
728        let later = world.scopes.next_scope();
729        world.table.take_saved(later..later);
730    }
731
732    #[test]
733    fn a_program_name_beside_a_saved_one_still_sees_the_saved_one() {
734        let mut world = World::new();
735        let scope = world.scope();
736        let saved = world.define("shared", &[scope], Phase::Runtime);
737        world.save_names();
738        let later = world.scope();
739        world.define("shared", &[later], Phase::Runtime);
740        let symbol = World::symbol("shared", &[scope]);
741        let resolve = || {
742            world
743                .table
744                .resolve(&symbol, Namespace::Value, Phase::Runtime)
745        };
746        assert_eq!(resolve(), Resolution::Bound(saved));
747        assert_eq!(resolve(), Resolution::Bound(saved));
748    }
749
750    #[test]
751    fn a_program_name_with_only_later_scopes_decodes_no_saved_name() {
752        let mut world = World::new();
753        let scope = world.scope();
754        world.define("shared", &[scope], Phase::Runtime);
755        world.save_names();
756        let later = world.scope();
757        world.define("shared", &[later], Phase::Runtime);
758        let symbol = World::symbol("shared", &[later]);
759        world
760            .table
761            .resolve(&symbol, Namespace::Value, Phase::Runtime);
762        assert!(!world.table.saved.is_decoded("shared", Namespace::Value));
763    }
764
765    #[test]
766    fn a_saved_name_is_listed_beside_the_programs_own() {
767        let mut world = World::new();
768        let scope = world.scope();
769        let saved = world.define("saved", &[scope], Phase::Runtime);
770        world.save_names();
771        let own = world.define("own", &[scope], Phase::Runtime);
772        let symbol = World::symbol("anything", &[scope]);
773        let mut listed =
774            world
775                .table
776                .visible_name_bindings(&symbol, Namespace::Value, Phase::Runtime);
777        listed.sort_by_key(|(_, binding)| *binding);
778        let bindings: Vec<BindingId> = listed.into_iter().map(|(_, binding)| binding).collect();
779        assert_eq!(bindings, vec![saved, own]);
780    }
781
782    #[test]
783    fn a_saved_binding_is_visible_beside_the_programs_own() {
784        let mut world = World::new();
785        let scope = world.scope();
786        let saved = world.define_type("saved", &[scope]);
787        world.save_names();
788        let own = world.define_type("own", &[scope]);
789        let scopes = World::scope_set(&[scope]);
790        let mut visible = world
791            .table
792            .visible_bindings(&scopes, Namespace::Type, Phase::Runtime);
793        visible.sort();
794        assert_eq!(visible, vec![saved, own]);
795    }
796
797    #[test]
798    fn a_saved_qualified_name_is_found_by_its_last_segment() {
799        let mut world = World::new();
800        let scope = world.scope();
801        let saved = world.define("option/some", &[scope], Phase::Runtime);
802        world.save_names();
803        let symbol = World::symbol("some", &[scope]);
804        let found = world.table.visible_qualified_bindings_ending_in(
805            &symbol,
806            Namespace::Value,
807            Phase::Runtime,
808        );
809        assert_eq!(found, vec![saved]);
810    }
811
812    #[test]
813    fn a_forgotten_binding_resolves_no_more() {
814        let mut world = World::new();
815        let scope = world.scope();
816        let kept = world.define("kept", &[scope], Phase::Runtime);
817        let forgotten = world.define("forgotten", &[scope], Phase::Runtime);
818        world.table.forget(|binding| binding == forgotten);
819        let resolve = |name| {
820            world.table.resolve(
821                &World::symbol(name, &[scope]),
822                Namespace::Value,
823                Phase::Runtime,
824            )
825        };
826        assert_eq!(resolve("forgotten"), Resolution::Unbound);
827        assert_eq!(resolve("kept"), Resolution::Bound(kept));
828        assert!(!world.table.holds(forgotten));
829        assert!(world.table.holds(kept));
830    }
831
832    #[test]
833    fn a_forgotten_sharing_binding_resolves_no_more() {
834        let mut world = World::new();
835        let chain = world.chain(ScopeSet::SHORTEST_SHARED_PREFIX);
836        let prefix = World::prefix(&chain);
837        let forgotten = world.define_sharing("shared", &prefix);
838        world.table.forget(|binding| binding == forgotten);
839        assert_eq!(
840            world.resolve_sharing("shared", &prefix),
841            Resolution::Unbound
842        );
843    }
844
845    #[test]
846    fn forgetting_every_binding_of_a_name_drops_the_name() {
847        let mut world = World::new();
848        let scope = world.scope();
849        let forgotten = world.define("gone", &[scope], Phase::Runtime);
850        world.table.forget(|binding| binding == forgotten);
851        assert!(world.table.entries.is_empty());
852    }
853
854    #[test]
855    fn forgetting_one_of_two_bindings_of_a_name_keeps_the_other() {
856        let mut world = World::new();
857        let (outer, inner) = (world.scope(), world.scope());
858        let wide = world.define("x", &[outer], Phase::Runtime);
859        let narrow = world.define("x", &[outer, inner], Phase::Runtime);
860        world.table.forget(|binding| binding == narrow);
861        let symbol = World::symbol("x", &[outer, inner]);
862        let resolution = world
863            .table
864            .resolve(&symbol, Namespace::Value, Phase::Runtime);
865        assert_eq!(resolution, Resolution::Bound(wide));
866    }
867
868    #[test]
869    fn the_binding_with_the_largest_subset_wins() {
870        let mut world = World::new();
871        let (module, inner) = (world.scope(), world.scope());
872        world.define("x", &[module], Phase::Runtime);
873        let shadow = world.define("x", &[module, inner], Phase::Runtime);
874        assert_eq!(
875            world.resolve("x", &[module, inner], Phase::Runtime),
876            Resolution::Bound(shadow)
877        );
878    }
879
880    #[test]
881    fn a_binding_outside_the_reference_scopes_is_invisible() {
882        let mut world = World::new();
883        let (module, macro_introduced) = (world.scope(), world.scope());
884        world.define("tmp", &[module, macro_introduced], Phase::Runtime);
885        assert_eq!(
886            world.resolve("tmp", &[module], Phase::Runtime),
887            Resolution::Unbound
888        );
889    }
890
891    #[test]
892    fn two_bindings_of_equal_size_are_ambiguous() {
893        let mut world = World::new();
894        let (module, left, right) = (world.scope(), world.scope(), world.scope());
895        world.define("x", &[module, left], Phase::Runtime);
896        world.define("x", &[module, right], Phase::Runtime);
897        let resolution = world.resolve("x", &[module, left, right], Phase::Runtime);
898        assert!(matches!(resolution, Resolution::Ambiguous(_)));
899    }
900
901    #[test]
902    fn a_larger_binding_settles_two_smaller_bindings_of_equal_size() {
903        let mut world = World::new();
904        let (module, left, right) = (world.scope(), world.scope(), world.scope());
905        world.define("x", &[module, left], Phase::Runtime);
906        world.define("x", &[module, right], Phase::Runtime);
907        let settled = world.define("x", &[module, left, right], Phase::Runtime);
908        assert_eq!(
909            world.resolve("x", &[module, left, right], Phase::Runtime),
910            Resolution::Bound(settled)
911        );
912    }
913
914    #[test]
915    fn compile_time_bindings_are_invisible_to_runtime_code() {
916        let mut world = World::new();
917        let module = world.scope();
918        world.define("name", &[module], Phase::CompileTime);
919        assert_eq!(
920            world.resolve("name", &[module], Phase::Runtime),
921            Resolution::Unbound
922        );
923    }
924
925    #[test]
926    fn rebinding_a_binding_to_its_own_scopes_is_accepted() {
927        let mut world = World::new();
928        let module = world.scope();
929        let binding = world.define("x", &[module], Phase::Runtime);
930        let rebound = world.table.bind(
931            &World::symbol("x", &[module]),
932            Namespace::Value,
933            binding,
934            Phase::Runtime,
935        );
936        assert_eq!(rebound, Ok(()));
937    }
938
939    #[test]
940    fn rebinding_the_same_scopes_reports_the_existing_binding() {
941        let mut world = World::new();
942        let module = world.scope();
943        let first = world.define("x", &[module], Phase::Runtime);
944        let info = BindingInfo::new("x".into(), BindingKind::Local, None);
945        let second = world.bindings.add(info);
946        let duplicate = world.table.bind(
947            &World::symbol("x", &[module]),
948            Namespace::Value,
949            second,
950            Phase::Runtime,
951        );
952        assert_eq!(duplicate, Err(first));
953    }
954
955    #[test]
956    fn a_long_binding_list_finds_what_a_full_scan_finds() {
957        let mut world = World::new();
958        let scopes: Vec<Scope> = (0..5).map(|_| world.scope()).collect();
959        let entries = world.define_under_subsets("x", &scopes, NameEntries::SHORT_LIST_LENGTH + 4);
960        let reference = [scopes[0], scopes[1], scopes[4]];
961        let scanned: Vec<BindingId> = entries
962            .iter()
963            .filter(|(subset, _)| subset.iter().all(|scope| reference.contains(scope)))
964            .map(|(_, binding)| *binding)
965            .collect();
966        let (_, exact) = entries
967            .iter()
968            .find(|(subset, _)| *subset == reference)
969            .expect("the reference scopes are a defined subset");
970        assert_eq!(world.visible(&reference), scanned);
971        assert_eq!(
972            world.resolve("x", &reference, Phase::Runtime),
973            Resolution::Bound(*exact)
974        );
975    }
976
977    #[test]
978    fn a_qualified_binding_is_found_by_its_last_segment() {
979        let mut world = World::new();
980        let module = world.scope();
981        let circle = world.define("shape/circle", &[module], Phase::Runtime);
982        let nested = world.define("geometry/shape/circle", &[module], Phase::Runtime);
983        world.define("circle", &[module], Phase::Runtime);
984        world.define("shape/square", &[module], Phase::Runtime);
985        assert_eq!(
986            world.visible_qualified_ending_in("circle", &[module]),
987            [circle, nested]
988        );
989    }
990
991    #[test]
992    fn a_qualified_binding_outside_the_reference_scopes_is_not_found() {
993        let mut world = World::new();
994        let (module, inner) = (world.scope(), world.scope());
995        world.define("shape/circle", &[module, inner], Phase::Runtime);
996        assert_eq!(world.visible_qualified_ending_in("circle", &[module]), []);
997    }
998
999    #[test]
1000    fn a_qualified_name_in_another_namespace_is_not_found() {
1001        let mut world = World::new();
1002        let module = world.scope();
1003        world.define_type("shape/circle", &[module]);
1004        assert_eq!(world.visible_qualified_ending_in("circle", &[module]), []);
1005    }
1006
1007    #[test]
1008    fn a_qualified_name_bound_twice_finds_each_binding_once() {
1009        let mut world = World::new();
1010        let (module, inner) = (world.scope(), world.scope());
1011        let outer = world.define("shape/circle", &[module], Phase::Runtime);
1012        let shadow = world.define("shape/circle", &[module, inner], Phase::Runtime);
1013        assert_eq!(
1014            world.visible_qualified_ending_in("circle", &[module, inner]),
1015            [outer, shadow]
1016        );
1017    }
1018
1019    #[test]
1020    fn a_binding_under_a_shared_prefix_is_visible_from_a_longer_prefix() {
1021        let mut world = World::new();
1022        let chain = world.chain(ScopeSet::SHORTEST_SHARED_PREFIX);
1023        let bound = world.define_sharing("x", &World::prefix(&chain));
1024        chain.push(world.scope());
1025        assert_eq!(
1026            world.resolve_sharing("x", &World::prefix(&chain)),
1027            Resolution::Bound(bound)
1028        );
1029    }
1030
1031    #[test]
1032    fn a_shared_binding_is_visible_from_plain_scopes_that_hold_its_prefix() {
1033        let mut world = World::new();
1034        let scopes: Vec<Scope> = (0..ScopeSet::SHORTEST_SHARED_PREFIX)
1035            .map(|_| world.scope())
1036            .collect();
1037        let chain = ScopeChain::default();
1038        scopes.iter().for_each(|scope| chain.push(*scope));
1039        let bound = world.define_sharing("x", &World::prefix(&chain));
1040        assert_eq!(
1041            world.resolve("x", &scopes, Phase::Runtime),
1042            Resolution::Bound(bound)
1043        );
1044    }
1045
1046    #[test]
1047    fn a_compile_time_shared_binding_is_invisible_to_runtime_code() {
1048        let mut world = World::new();
1049        let prefix = World::prefix(&world.chain(ScopeSet::SHORTEST_SHARED_PREFIX));
1050        let binding = world.new_binding("x");
1051        world
1052            .table
1053            .bind(
1054                &World::sharing_symbol("x", &prefix),
1055                Namespace::Value,
1056                binding,
1057                Phase::CompileTime,
1058            )
1059            .expect("no duplicate");
1060        assert_eq!(world.resolve_sharing("x", &prefix), Resolution::Unbound);
1061    }
1062
1063    #[test]
1064    fn a_plain_binding_beside_a_shared_one_sees_only_its_own_scopes() {
1065        let mut world = World::new();
1066        let chain = world.chain(ScopeSet::SHORTEST_SHARED_PREFIX);
1067        world.define_sharing("x", &World::prefix(&chain));
1068        let outside = world.scope();
1069        let plain = world.define("x", &[outside], Phase::Runtime);
1070        assert_eq!(
1071            world.resolve("x", &[outside], Phase::Runtime),
1072            Resolution::Bound(plain)
1073        );
1074    }
1075
1076    #[test]
1077    fn a_shared_prefix_sees_the_plain_binding_it_shadows_only_when_larger() {
1078        let mut world = World::new();
1079        let chain = world.chain(ScopeSet::SHORTEST_SHARED_PREFIX);
1080        let first = World::prefix(&chain).first();
1081        world.define("x", &[first], Phase::Runtime);
1082        let shadow = world.define_sharing("x", &World::prefix(&chain));
1083        assert_eq!(
1084            world.resolve_sharing("x", &World::prefix(&chain)),
1085            Resolution::Bound(shadow)
1086        );
1087    }
1088
1089    #[test]
1090    fn rebinding_shared_scopes_reports_the_existing_binding() {
1091        let mut world = World::new();
1092        let chain = world.chain(ScopeSet::SHORTEST_SHARED_PREFIX);
1093        let prefix = World::prefix(&chain);
1094        let first = world.define_sharing("x", &prefix);
1095        let second = world.new_binding("x");
1096        let duplicate = world.table.bind(
1097            &World::sharing_symbol("x", &prefix),
1098            Namespace::Value,
1099            second,
1100            Phase::Runtime,
1101        );
1102        assert_eq!(duplicate, Err(first));
1103    }
1104}