Skip to main content

syn_sem/
lib.rs

1#![doc = include_str!("../README.md")]
2
3pub mod ds;
4pub(crate) mod etc;
5pub(crate) mod semantic;
6pub(crate) mod syntax;
7
8// TODO
9// * Remove tree::item::Local. It should not be in the path tree. Prepare something another for
10//   holding type info of local variables.
11//   - Why?
12//     We cannot put local variables in the path tree if the function is restricted by some bounds.
13//     We should use logic for that instead of the path tree.
14//   - Take account of other items in function blocks.
15//     A function block can contain types, consts, and others like module. They may need to be in
16//     the path tree.
17// * `PathTree::search_type` -> it is supposed to find an item in the type namespace. Is it
18//   doing like so? Also, rename the function to clarify it searches in the type namespace.
19// * `PathTree::search_item` -> it is supposed to find an item in the value namespace. Is it
20//   doing like so? Also, rename the function to clarify it searches in the value namespace.
21
22// === Re-exports ===
23
24pub use etc::util::{cargo_crate_name, get_crate_name, set_crate_name, PathSegments};
25pub use logic_eval::{Intern, Name, Term};
26pub use semantic::{
27    analyze::{Analyzer, Semantics},
28    entry::{AnalysisSession, Analyzed, Config, ConfigLoad, GlobalCx},
29    eval::Evaluated,
30    helper,
31    logic::{term, ImplLogic, Logic},
32    tree::{
33        pub_filter as filter, ArrayLen, Brief, NodeIndex, PathId, PubPathTree as PathTree, Type,
34        TypeArray, TypeId, TypeMut, TypePath, TypeRef, TypeScalar, TypeTuple, UniqueTypes,
35    },
36};
37pub use syntax::common::{AttributeHelper, IdentifySyn, SynId};
38
39pub mod item {
40    pub use super::semantic::tree::{
41        Block, Const, Field, Fn, Local, Mod, Param, PubItem as Item, Struct, Trait, TypeAlias, Use,
42    };
43}
44pub mod value {
45    pub use super::semantic::eval::{ConstGeneric, Enum, Field, Fn, Scalar, Value};
46}
47pub mod locator {
48    pub use syn_locator::{clear, enable_thread_local};
49}
50
51use std::{
52    collections::{HashMap, HashSet},
53    error::Error as StdError,
54    result::Result as StdResult,
55    sync::{Mutex, MutexGuard},
56};
57
58pub type Result<T> = StdResult<T, Error>;
59pub type Error = Box<dyn StdError + Send + Sync>;
60pub type TriResult<T, Se> = StdResult<T, TriError<Se>>;
61pub(crate) type SharedLock<T> = Mutex<T>;
62pub(crate) type SharedLockGuard<'a, T> = MutexGuard<'a, T>;
63
64#[derive(Debug)]
65pub enum TriError<Se> {
66    Soft(Se),
67    Hard(Box<dyn StdError + Send + Sync>),
68}
69
70pub trait TriResultHelper<T, S> {
71    fn on_soft_err<F: FnOnce(S) -> Result<T>>(self, f: F) -> Result<T>;
72
73    fn map_soft_err<F: FnOnce(S) -> U, U>(self, f: F) -> TriResult<T, U>;
74
75    /// If soft error, make it hard error.
76    fn elevate_err(self) -> Result<T>;
77}
78
79impl<T, S> TriResultHelper<T, S> for TriResult<T, S> {
80    fn on_soft_err<F: FnOnce(S) -> Result<T>>(self, f: F) -> Result<T> {
81        match self {
82            Ok(t) => Ok(t),
83            Err(TriError::Soft(s)) => f(s),
84            Err(TriError::Hard(e)) => Err(e),
85        }
86    }
87
88    fn map_soft_err<F: FnOnce(S) -> U, U>(self, f: F) -> TriResult<T, U> {
89        match self {
90            Ok(t) => Ok(t),
91            Err(TriError::Soft(s)) => Err(TriError::Soft(f(s))),
92            Err(TriError::Hard(e)) => Err(TriError::Hard(e)),
93        }
94    }
95
96    fn elevate_err(self) -> Result<T> {
97        match self {
98            Ok(t) => Ok(t),
99            Err(TriError::Soft(_)) => Err("elavated soft error".into()),
100            Err(TriError::Hard(e)) => Err(e),
101        }
102    }
103}
104
105impl<S> From<Error> for TriError<S> {
106    fn from(value: Error) -> Self {
107        Self::Hard(value)
108    }
109}
110
111#[macro_export]
112macro_rules! err {
113    (soft, $expr:expr) => {
114        Err( $crate::error!(soft, $expr) )
115    };
116    (hard, $($t:tt)*) => {
117        Err( $crate::error!(hard, $($t)*) )
118    };
119    ($($t:tt)*) => {
120        Err( $crate::error!($($t)*) )
121    };
122}
123
124#[macro_export]
125macro_rules! error {
126    (soft, $expr:expr) => {
127        $crate::TriError::Soft($expr)
128    };
129    (hard, $($t:tt)*) => {
130        $crate::TriError::Hard( format!($($t)*).into() )
131    };
132    ($($t:tt)*) => {
133        $crate::Error::from( format!($($t)*) )
134    };
135}
136
137#[macro_export]
138macro_rules! log {
139    (E, $($t:tt)*) => {{
140        if log::log_enabled!(log::Level::Error) {
141            log::error!($($t)*);
142        }
143    }};
144    (W, $($t:tt)*) => {{
145        if log::log_enabled!(log::Level::Warn) {
146            log::warn!($($t)*);
147        }
148    }};
149    (I, $($t:tt)*) => {{
150        if log::log_enabled!(log::Level::Info) {
151            log::info!($($t)*);
152        }
153    }};
154    (D, $($t:tt)*) => {{
155        if log::log_enabled!(log::Level::Debug) {
156            log::debug!($($t)*);
157        }
158    }};
159    (T, $($t:tt)*) => {{
160        if log::log_enabled!(log::Level::Trace) {
161            log::trace!($($t)*);
162        }
163    }};
164}
165
166#[macro_export]
167macro_rules! print {
168    ($($t:tt)*) => {
169        println!(
170            "@ {}\n┗ {}",
171            $crate::cur_path!(),
172            format!($($t)*)
173        )
174    };
175}
176
177#[macro_export]
178macro_rules! cur_path {
179    () => {{
180        struct S;
181        let s = std::any::type_name::<S>();
182        &s[..s.len() - 3]
183    }};
184}
185
186#[macro_export]
187macro_rules! pnode {
188    ($ptree:expr, $($path:tt)*) => {{
189        let key = format!($($path)*);
190        let Some(node) = $ptree.search($crate::PathTree::ROOT, key.as_str()) else {
191            panic!("failed to find the given path: `{}`", format!($($path)*));
192        };
193        node
194    }};
195}
196
197#[macro_export]
198macro_rules! pid {
199    ($ptree:expr, $($path:tt)*) => {{
200        let node = $crate::pnode!($ptree, $($path)*);
201        let (ii, _) = $ptree.node(node)
202            .iter()
203            .next()
204            .unwrap();
205        node.to_path_id(ii)
206    }};
207}
208
209#[macro_export]
210macro_rules! pitem {
211    ($ptree:expr, $($path:tt)*) => {{
212        let pid = $crate::pid!($ptree, $($path)*);
213        &$ptree.item(pid)
214    }};
215}
216
217// === Hash map and set used within this crate ===
218
219pub type Map<K, V> = HashMap<K, V, fxhash::FxBuildHasher>;
220pub type Set<T> = HashSet<T, fxhash::FxBuildHasher>;
221
222// === Enum of A or B ===
223
224#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
225pub enum Which2<A, B> {
226    A(A),
227    B(B),
228}
229
230// === Enum of A, B, or C ===
231
232#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
233pub enum Which3<A, B, C> {
234    A(A),
235    B(B),
236    C(C),
237}
238
239impl<A, B, C, VA> FromIterator<Which3<A, B, C>> for Which3<VA, B, C>
240where
241    VA: FromIterator<A>,
242{
243    fn from_iter<T: IntoIterator<Item = Which3<A, B, C>>>(iter: T) -> Self {
244        let mut filtered = None;
245        let va = iter
246            .into_iter()
247            .map(|which| match which {
248                Which3::A(a) => Some(a),
249                Which3::B(b) => {
250                    filtered = Some(Which3::B(b));
251                    None
252                }
253                Which3::C(c) => {
254                    filtered = Some(Which3::C(c));
255                    None
256                }
257            })
258            .take_while(|opt| opt.is_some())
259            .map(|opt| opt.unwrap())
260            .collect::<VA>();
261
262        if let Some(filtered) = filtered {
263            return filtered;
264        }
265
266        Which3::A(va)
267    }
268}
269
270// === Option ===
271
272#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
273pub enum TriOption<T, U> {
274    Some(T),
275    NotYet(U),
276    None,
277}
278
279impl<T, U> TryFrom<TriOption<T, U>> for Option<T> {
280    type Error = Error;
281
282    fn try_from(value: TriOption<T, U>) -> Result<Self> {
283        match value {
284            TriOption::Some(t) => Ok(Some(t)),
285            TriOption::NotYet(_) => err!("`TriOption::NotYet` cannot become `Option`"),
286            TriOption::None => Ok(None),
287        }
288    }
289}
290
291// === GetOwned ===
292
293pub trait GetOwned<Id> {
294    type Owned;
295    fn get_owned(&self, id: Id) -> Self::Owned;
296}
297
298// === Type alias ===
299
300pub(crate) type NameIn<'a> = logic_eval::Name<any_intern::Interned<'a, str>>;
301pub(crate) type TermIn<'a> = logic_eval::Term<NameIn<'a>>;
302pub(crate) type ExprIn<'a> = logic_eval::Expr<NameIn<'a>>;
303pub(crate) type ClauseIn<'a> = logic_eval::Clause<NameIn<'a>>;
304pub(crate) type PredicateIn<'a> = logic_eval::Predicate<NameIn<'a>>;