1#[macro_export]
3macro_rules! prelude {
4 ($($imports:tt)*) => (
5 use $crate::prelude::{*, $($imports)*};
6 )
7}
8
9pub use std::{
10 borrow::{Borrow, Cow},
11 collections::{BTreeSet, HashMap},
12 fmt::{self, Display},
13 mem,
14};
15
16pub use log;
17pub use regex;
18pub use smallvec::{smallvec, SmallVec};
19
20#[macro_use]
21pub mod res;
22
23pub use crate::{
24 bail,
25 ctx::{self, Ctx},
26 error, parser,
27 prelude::{
28 path_map::PathMap,
29 res::{Res, WithCtx},
30 },
31 repr::{self, builtin, idx},
32 traits::*,
33};
34
35mod path_map {
36 prelude! {
37 repr::Path,
38 }
39
40 pub struct PathMap<K, V>
41 where
42 K: std::hash::Hash + Eq,
43 {
44 map: HashMap<Path, HashMap<K, V>>,
45 }
46
47 impl<K, V> std::ops::Deref for PathMap<K, V>
48 where
49 K: std::hash::Hash + Eq,
50 {
51 type Target = HashMap<Path, HashMap<K, V>>;
52 fn deref(&self) -> &Self::Target {
53 &self.map
54 }
55 }
56 impl<K, V> std::ops::DerefMut for PathMap<K, V>
57 where
58 K: std::hash::Hash + Eq,
59 {
60 fn deref_mut(&mut self) -> &mut Self::Target {
61 &mut self.map
62 }
63 }
64
65 impl<K, V> PathMap<K, V>
66 where
67 K: std::hash::Hash + Eq,
68 {
69 pub fn with_capacity(capa: usize) -> Self {
70 Self {
71 map: HashMap::with_capacity(capa),
72 }
73 }
74 pub fn new() -> Self {
75 Self::with_capacity(3)
76 }
77
78 pub fn at(&self, path: &Path) -> Option<&HashMap<K, V>> {
79 self.map.get(path)
80 }
81 pub fn at_mut(&mut self, path: &Path) -> Option<&mut HashMap<K, V>> {
82 self.map.get_mut(path)
83 }
84 pub fn at_mut_or_new(&mut self, path: Path) -> &mut HashMap<K, V> {
85 self.map.entry(path).or_insert_with(HashMap::new)
86 }
87
88 pub fn unwrap_at(
89 &self,
90 path: &Path,
91 display: impl FnOnce(&Path) -> String,
92 ) -> Res<&HashMap<K, V>> {
93 self.map
94 .get(path)
95 .ok_or_else(|| error!(@unknown("package path") display(path)))
96 }
97 pub fn unwrap_at_mut(
98 &mut self,
99 path: &Path,
100 display: impl FnOnce(&Path) -> String,
101 ) -> Res<&mut HashMap<K, V>> {
102 self.map
103 .get_mut(path)
104 .ok_or_else(|| error!(@unknown("package path") display(path)))
105 }
106 }
107}
108
109pub trait CollPrintExt: Sized {
110 type Elm;
111 fn show_iter<S>(self, show_elm: impl Fn(Self::Elm) -> S, sep: impl AsRef<str>) -> String
112 where
113 S: AsRef<str>;
114
115 fn show_iter_cs<S>(self, show_elm: impl Fn(Self::Elm) -> S) -> String
116 where
117 S: AsRef<str>,
118 {
119 self.show_iter(show_elm, ", ")
120 }
121}
122impl<'a, T, E> CollPrintExt for T
123where
124 T: IntoIterator<Item = E>,
125{
126 type Elm = E;
127 fn show_iter<S>(self, show_elm: impl Fn(Self::Elm) -> S, sep: impl AsRef<str>) -> String
128 where
129 S: AsRef<str>,
130 {
131 let sep = sep.as_ref();
132 let mut s = String::new();
133 for elm in self {
134 if !s.is_empty() {
135 s.push_str(sep);
136 }
137 s.push_str(show_elm(elm).as_ref())
138 }
139 s
140 }
141}