1use crate::metta::runner::*;
4use hyperon_common::owned_or_borrowed::OwnedOrBorrowed;
5
6pub const TOP_MOD_NAME: &'static str = "top";
8
9pub const SELF_MOD_NAME: &'static str = "self";
11
12pub const MOD_NAME_SEPARATOR: char = ':';
14
15#[derive(Clone, Debug, Default)]
24pub(crate) struct ModNameNode {
25 pub mod_id: ModId,
26 children: Option<HashMap<String, ModNameNode>>
27}
28
29pub(crate) fn mod_name_relative_path(name: &str) -> Option<&str> {
32 mod_name_remove_prefix(name, SELF_MOD_NAME)
33}
34
35pub(crate) fn mod_name_remove_prefix<'a>(name: &'a str, prefix: &str) -> Option<&'a str> {
38 if name.starts_with(prefix) {
39 if name.len() == prefix.len() {
40 Some("")
41 } else {
42 if name.as_bytes()[prefix.len()] == MOD_NAME_SEPARATOR as u8 {
43 Some(&name[(prefix.len()+1)..])
44 } else {
45 None
46 }
47 }
48 } else {
49 None
50 }
51}
52
53pub(crate) fn mod_name_from_path(path: &str) -> &str {
56 let mut start_idx = 0;
57 for (idx, the_char) in path.char_indices() {
58 if the_char == MOD_NAME_SEPARATOR {
59 start_idx = idx+1;
60 }
61 }
62 &path[start_idx..]
63}
64
65pub(crate) fn chop_trailing_separator(path: &str) -> &str {
66 if path.ends_with(MOD_NAME_SEPARATOR) {
67 &path[0..path.len()-1]
68 } else {
69 path
70 }
71}
72
73pub(crate) fn concat_relative_module_path(base_path: &str, relative_path: &str) -> String {
75 if relative_path.len() > 0 {
76 format!("{base_path}:{relative_path}")
77 } else {
78 base_path.to_string()
79 }
80}
81
82pub(crate) fn normalize_relative_module_name(base_path: &str, mod_name: &str) -> Result<String, String> {
88 let mod_name = chop_trailing_separator(mod_name);
89 let full_name_path = match mod_name_relative_path(mod_name) {
90 Some(remainder) => concat_relative_module_path(base_path, remainder),
91 None => {
92 match mod_name_remove_prefix(mod_name, TOP_MOD_NAME) {
93 Some(remainder) => {
94 if remainder.len() > 0 {
95 format!("{}:{}", TOP_MOD_NAME, remainder)
96 } else {
97 TOP_MOD_NAME.to_string()
98 }
99 },
100 None => concat_relative_module_path(base_path, mod_name),
101 }
102 },
103 };
104 Ok(full_name_path)
105}
106
107#[allow(dead_code)] pub(crate) fn decompose_name_path(name: &str) -> Result<Vec<&str>, String> {
110 let mut components: Vec<&str> = vec![];
111 let (_, _, last) = ModNameNode::parse_parent_generic(ModNameNode::top(), name, &OverlayMap::none(),
112 |node, _| Some(node),
113 |_, component| {components.push(component)})?;
114 if last.len() > 0 {
115 components.push(last);
116 }
117 Ok(components)
118}
119
120#[allow(dead_code)] pub(crate) fn compose_name_path(components: &[&str]) -> Result<String, String> {
123 let mut new_name = TOP_MOD_NAME.to_string();
124 for component in components {
125 new_name.push_str(":");
126 new_name.push_str(component);
127 }
128 Ok(new_name)
129}
130
131#[derive(Debug)]
133struct OverlayMap<'a>(Option<smallvec::SmallVec<[(*const ModNameNode, &'a str, usize); 4]>>);
134
135impl<'a> OverlayMap<'a> {
136 fn none() -> Self {
137 Self(None)
138 }
139 fn with_capacity(capacity: usize) -> Self {
140 Self(Some(smallvec::SmallVec::with_capacity(capacity)))
141 }
142 fn push(&mut self, parent_node: *const ModNameNode, name: &'a str, subtree_idx: usize) {
143 match &mut self.0 {
144 Some(map) => map.push((parent_node, name, subtree_idx)),
145 None => panic!()
146 }
147 }
148 fn get(&self, parent_node: *const ModNameNode, name: &str) -> Option<usize> {
149 match &self.0 {
150 Some(map) => for (map_parent_node, map_name, subtree_idx) in map.iter() {
151 if std::ptr::eq(parent_node, *map_parent_node) && name == *map_name {
152 return Some(*subtree_idx);
153 }
154 }
155 None => {}
156 }
157 None
158 }
159}
160
161impl ModNameNode {
162
163 pub fn top() -> Self {
165 Self::new(ModId::TOP)
166 }
167
168 pub fn new(mod_id: ModId) -> Self {
169 Self {
170 mod_id,
171 children: None,
172 }
173 }
174
175 pub fn update(&mut self, name: &str, mod_id: ModId) -> Result<(), String> {
178 self.update_in_layered(&mut[], name, mod_id)
179 }
180
181 pub fn update_in_layered(&mut self, subtrees: &mut[(&str, &mut Self)], name: &str, mod_id: ModId) -> Result<(), String> {
183 if name == TOP_MOD_NAME || name.len() == 0 {
184 self.mod_id = mod_id;
185 return Ok(());
186 }
187 let (parent_node, mod_name) = self.parse_parent_layered_mut(subtrees, name)?;
188 if mod_name == TOP_MOD_NAME || mod_name == SELF_MOD_NAME || mod_name.len() == 0 {
189 return Err(format!("illegal module name: {name}"));
190 }
191 match parent_node.get_child_mut(mod_name) {
192 Some(node) => node.mod_id = mod_id,
193 None => parent_node.add_child_node(mod_name.to_string(), Self::new(mod_id))
194 }
195 Ok(())
196 }
197
198 pub fn add(&mut self, name: &str, mod_id: ModId) -> Result<(), String> {
202 self.merge_subtree_into(name, Self::new(mod_id))
203 }
204
205 #[allow(dead_code)] pub fn add_to_layered(&mut self, subtrees: &mut[(&str, &mut Self)], name: &str, mod_id: ModId) -> Result<(), String> {
208 self.merge_subtree_into_layered(subtrees, name, Self::new(mod_id))
209 }
210
211 pub fn merge_subtree_into(&mut self, root_name: &str, new_subtree: Self) -> Result<(), String> {
213 self.merge_subtree_into_layered(&mut[], root_name, new_subtree)
214 }
215
216 pub fn merge_subtree_into_layered(&mut self, layered_subtrees: &mut[(&str, &mut Self)], root_name: &str, new_subtree: Self) -> Result<(), String> {
218 let (parent_node, mod_name) = self.parse_parent_layered_mut(layered_subtrees, root_name)?;
219 if mod_name == TOP_MOD_NAME || mod_name == SELF_MOD_NAME || mod_name.len() == 0 {
220 return Err(format!("illegal module name: {root_name}"));
221 }
222 parent_node.add_child_node(mod_name.to_string(), new_subtree);
223 Ok(())
224 }
225
226 fn get_child(&self, child_name: &str) -> Option<&Self> {
228 match &self.children {
229 Some(children) => children.get(child_name),
230 None => None
231 }
232 }
233
234 fn get_child_mut(&mut self, child_name: &str) -> Option<&mut Self> {
236 match &mut self.children {
237 Some(children) => children.get_mut(child_name),
238 None => None
239 }
240 }
241
242 fn add_child_node(&mut self, child_name: String, child_node: Self) {
244 if self.children.is_none() {
245 self.children = Some(HashMap::new());
246 }
247 self.children.as_mut().unwrap().insert(child_name, child_node);
248 }
249
250 pub fn visit_mut<F: FnMut(&str, &mut Self)>(&mut self, root_node_name: &str, mut f: F) {
252 self.visit_mut_internal(root_node_name, &mut f);
253 }
254
255 fn visit_mut_internal<F: FnMut(&str, &mut Self)>(&mut self, root_node_name: &str, f: &mut F) {
256 f(root_node_name, self);
257 if let Some(children) = &mut self.children {
258 for (child_name, child_node) in children.iter_mut() {
259 child_node.visit_mut_internal(child_name, f);
260 }
261 }
262 }
263
264 pub fn resolve(&self, name: &str) -> Option<ModId> {
266 self.name_to_node::<&Self>(&[], name).map(|node| node.mod_id)
267 }
268
269 pub fn resolve_layered<SelfRefT: core::borrow::Borrow<Self>>(&self, subtrees: &[(&str, SelfRefT)], name: &str) -> Option<ModId> {
277 self.name_to_node(subtrees, name).map(|node| node.mod_id)
278 }
279
280 pub fn name_to_node<'a, 'slice, 'out, SelfRefT: core::borrow::Borrow<Self>>(&'a self, subtrees: &'slice[(&str, SelfRefT)], name: &str) -> Option<&'out Self>
282 where 'a: 'out, 'slice: 'out
283 {
284 if name == TOP_MOD_NAME || name.len() == 0 {
285 Some(self)
286 } else {
287 let map = self.build_overlay_map(subtrees).ok()?;
288 let (parent_node, mod_name) = self.parse_parent_layered_internal(name, &map, subtrees).ok()?;
289
290 if let Some(subtree_idx) = map.get(parent_node, mod_name) {
291 Some(subtrees.get(subtree_idx).unwrap().1.borrow())
292 } else {
293 parent_node.get_child(mod_name)
294 }
295 }
296 }
297
298 #[allow(dead_code)] pub fn name_to_node_mut<'a, 'b, 'slice, 'out>(&'a mut self, subtrees: &'slice mut[(&str, &'b mut Self)], name: &str) -> Option<&'out mut Self>
301 where 'a: 'out, 'slice: 'out, 'b: 'out
302 {
303 _ = subtrees;
304 _ = name;
305 panic!("Need Polonius or Rust 2024 edition");
306 }
322
323 #[allow(dead_code)] pub fn parse_parent<'a, 'b>(&'a self, name: &'b str) -> Result<(&'a Self, &'b str), String> {
327 self.parse_parent_layered::<&Self>(&[], name)
328 }
329
330 pub fn parse_parent_mut<'a, 'b>(&'a mut self, name: &'b str) -> Result<(&'a mut Self, &'b str), String> {
332 Self::parse_parent_generic(self, name, &OverlayMap::none(),
334 |node, name| node.get_child_mut(name),
335 |_, _| {}).map(|(node, _subtree_idx, remaining)| (node, remaining))
336 }
337
338 fn parse_parent_generic<'a, SelfT, GetF, PushParentF>(gen_self: SelfT, name: &'a str, overlay_map: &OverlayMap, get_f: GetF, mut push_f: PushParentF) -> Result<(SelfT, Option<usize>, &'a str), String>
343 where
344 SelfT: core::borrow::Borrow<Self>,
345 GetF: Fn(SelfT, &str) -> Option<SelfT>,
346 PushParentF: FnMut(&mut SelfT, &'a str),
347 {
348 if name.len() == 0 {
349 return Ok((gen_self, None, &name))
350 }
351 let mut cur_node = gen_self;
352 let mut sym_start = 0;
353 for (idx, the_char) in name.char_indices() {
354 match the_char {
355 MOD_NAME_SEPARATOR => {
356 let sym = &name[sym_start..idx];
357 if sym == TOP_MOD_NAME && sym_start == 0 {
358 sym_start = idx+1;
359 continue;
360 }
361 push_f(&mut cur_node, sym);
362 match overlay_map.get(cur_node.borrow(), sym) {
363 Some(subtree_idx) => {
364 sym_start = idx+1;
365 return if sym_start < name.len() {
366 Ok((cur_node, Some(subtree_idx), &name[sym_start..]))
367 } else {
368 Err(format!("Invalid module name format: {name}"))
369 };
370 },
371 None => {
372 match get_f(cur_node, sym) {
373 Some(new_node) => {
374 cur_node = new_node;
375 sym_start = idx+1;
376 },
377 None => return Err(format!("Parent module not loaded: {sym}"))
378 }
379 }
380 }
381 },
382 _ => {},
383 }
384 }
385 if sym_start < name.len() {
386 Ok((cur_node, None, &name[sym_start..]))
387 } else {
388 Err(format!("Invalid module name format: {name}"))
389 }
390 }
391
392 pub fn parse_parent_layered<'a, 'slice, 'out, 'str, SelfRefT: core::borrow::Borrow<Self>>(&'a self, subtrees: &'slice[(&str, SelfRefT)], name: &'str str) -> Result<(&'out Self, &'str str), String>
395 where 'a: 'out, 'slice: 'out
396 {
397 let map = self.build_overlay_map(subtrees)?;
398 self.parse_parent_layered_internal(name, &map, subtrees)
399 }
400
401 fn build_overlay_map<'str, SelfRefT: core::borrow::Borrow<Self>>(&self, subtrees: &[(&'str str, SelfRefT)]) -> Result<OverlayMap<'str>, String> {
403 let mut map = OverlayMap::with_capacity(subtrees.len());
404 for (idx, (subtree_root_name, _subtree_root_node)) in subtrees.iter().enumerate() {
405 let (parent_node, remaining_name) = self.parse_parent_layered_internal(subtree_root_name, &map, subtrees)?;
406 map.push(parent_node, remaining_name, idx);
407 }
408 Ok(map)
409 }
410
411 fn parse_parent_layered_internal<'a, 'slice, 'out, 'str, SelfT: core::borrow::Borrow<Self>>(&'a self, name: &'str str, overlay_map: &OverlayMap, subtrees: &'slice[(&str, SelfT)]) -> Result<(&'out Self, &'str str), String>
413 where 'a: 'out, 'slice: 'out
414 {
415 let mut cur_node = self;
416 let mut remaining_name = name;
417 loop {
418 let (parent_node, subtree_idx, remainder) = Self::parse_parent_generic(cur_node, remaining_name, overlay_map,
419 |node, name| node.get_child(name),
420 |_, _| {})?;
421
422 match subtree_idx {
423 None => {return Ok((parent_node, remainder))},
424 Some(subtree_idx) => {
425 cur_node = subtrees.get(subtree_idx).unwrap().1.borrow();
426 remaining_name = remainder;
427 }
428 }
429 }
430 }
431
432 pub fn parse_parent_layered_mut<'a, 'b, 'slice, 'out, 'str>(&'a mut self, subtrees: &'slice mut[(&str, &'b mut Self)], name: &'str str) -> Result<(&'out mut Self, &'str str), String>
434 where 'a: 'out, 'b: 'out, 'slice: 'out
435 {
436 let map = self.build_overlay_map(subtrees)?;
437 self.parse_parent_layered_internal_mut(name, &map, subtrees)
438 }
439
440 fn parse_parent_layered_internal_mut<'a, 'b, 'slice, 'out, 'str>(&'a mut self, name: &'str str, overlay_map: &OverlayMap, subtrees: &'slice mut[(&str, &'b mut Self)]) -> Result<(&'out mut Self, &'str str), String>
442 where 'a: 'out, 'b: 'out, 'slice: 'out
443 {
444 let mut cur_node = &*self;
445 let mut remaining_name = name;
446 let mut last_subtree_idx = None;
447 let (subtree_idx, local_name_path) = loop {
448 let (_parent_node, subtree_idx, remainder) = Self::parse_parent_generic(&*cur_node, remaining_name, overlay_map,
449 |node, name| node.get_child(name),
450 |_, _| {})?;
451
452 match subtree_idx {
453 None => {break (last_subtree_idx, remaining_name)},
454 Some(subtree_idx) => {
455 cur_node = subtrees.get(subtree_idx).unwrap().1;
456 last_subtree_idx = Some(subtree_idx);
457 remaining_name = remainder;
458 }
459 }
460 };
461
462 let subtree_root = match subtree_idx {
463 None => self,
464 Some(subtree_idx) => subtrees.get_mut(subtree_idx).unwrap().1
465 };
466 subtree_root.parse_parent_mut(local_name_path)
467 }
468}
469
470pub(crate) struct ModNameNodeDisplayWrapper<'a, F> {
472 node_name: Option<&'a str>,
473 node: &'a ModNameNode,
474 indent: &'a str,
475 mod_id_renderer: OwnedOrBorrowed<'a, F>,
476}
477
478impl<'a, F> ModNameNodeDisplayWrapper<'a, F>
479 where F: Fn(ModId, &mut std::fmt::Formatter<'_>) -> std::fmt::Result
480{
481 const TEE: &'static str = " ├─";
482 const CORNER: &'static str = " └─";
483 const PIPE: &'static str = " │ ";
484 const SPACE: &'static str = " ";
485
486 pub fn new(root_name: &'a str, node: &'a ModNameNode, mod_id_renderer: F) -> Self {
488 Self {
489 node_name: Some(root_name),
490 node,
491 indent: "",
492 mod_id_renderer: OwnedOrBorrowed::from(mod_id_renderer),
493 }
494 }
495
496 fn new_subtree(child_node: &'a ModNameNode, child_indent: &'a str, mod_id_renderer: &'a F) -> Self {
498 Self {
499 node_name: None,
500 node: child_node,
501 indent: child_indent,
502 mod_id_renderer: OwnedOrBorrowed::from(mod_id_renderer),
503 }
504 }
505}
506
507impl<F> std::fmt::Display for ModNameNodeDisplayWrapper<'_, F>
508 where F: Fn(ModId, &mut std::fmt::Formatter<'_>) -> std::fmt::Result
509{
510 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
511 match self.node_name {
512 Some(node_name) => {
513 let subtree = ModNameNodeDisplayWrapper::new_subtree(self.node, self.indent, self.mod_id_renderer.as_ref());
514 write!(f, "{node_name} = {subtree}")
515 },
516 None => {
517 (self.mod_id_renderer.as_ref())(self.node.mod_id, f)?;
518 writeln!(f)?;
519 if let Some(children) = &self.node.children {
520 let mut iter = children.iter().peekable();
521 while let Some((child_name, child_node)) = iter.next() {
522 write!(f, "{}", self.indent)?;
523 let child_indent = if iter.peek().is_some() {
524 write!(f, "{}", Self::TEE)?;
525 format!("{}{}", self.indent, Self::PIPE)
526 } else {
527 write!(f, "{}", Self::CORNER)?;
528 format!("{}{}", self.indent, Self::SPACE)
529 };
530 let subtree = ModNameNodeDisplayWrapper::new_subtree(child_node, &child_indent, self.mod_id_renderer.as_ref());
531 write!(f, "{child_name} = {subtree}")?;
532 }
533 }
534 Ok(())
535 }
536 }
537 }
538}
539
540impl std::fmt::Display for ModNameNode {
541 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
542 let wrapper = ModNameNodeDisplayWrapper::new(SELF_MOD_NAME, self, |mod_id: ModId, f: &mut std::fmt::Formatter| write!(f, "{}", mod_id.0));
543 write!(f, "{wrapper}")
544 }
545}
546
547#[allow(dead_code)] pub fn module_name_is_legal(name: &str) -> bool {
552 for the_char in name.chars() {
553 if !the_char.is_ascii() {
554 return false;
555 }
556 if !the_char.is_ascii_alphanumeric() &&
557 the_char != '-' &&
558 the_char != '_' {
559 return false;
560 }
561 }
562 return true;
563}
564
565#[allow(dead_code)] pub fn module_name_make_legal(name: &str) -> Option<String> {
569 let new_name: String = name.chars().filter(|&the_char| {
570 the_char.is_ascii_alphanumeric() ||
571 the_char == '-' ||
572 the_char != '_'
573 }).collect();
574 if new_name.len() > 0 {
575 Some(new_name)
576 } else {
577 None
578 }
579}
580
581#[test]
584fn module_name_parse_test() {
585 let mut top = ModNameNode::top();
586
587 assert!(top.add("top:sub1", ModId(1)).is_ok());
588 assert!(top.add("sub2", ModId(2)).is_ok());
589 assert!(top.add("sub2:suba", ModId(3)).is_ok());
590 assert!(top.add("sub2:suba:subA", ModId(4)).is_ok());
591 assert!(top.add("top:sub1:subb", ModId(5)).is_ok());
592
593 assert!(top.add("", ModId(6)).is_err());
594 assert!(top.add("top", ModId(6)).is_err());
595 assert!(top.add("sub2::suba:subB", ModId(7)).is_err());
596 assert!(top.add("sub2:suba:subB:", ModId(7)).is_err());
597
598 assert_eq!(top.resolve("top").unwrap(), top.mod_id);
599 assert_eq!(top.resolve("").unwrap(), top.mod_id);
600 assert!(top.resolve("top:").is_none());
601 assert!(top.resolve(":").is_none());
602
603 assert_eq!(top.resolve("sub1").unwrap(), ModId(1));
604 assert_eq!(top.resolve("top:sub2:suba:subA").unwrap(), ModId(4));
605 assert!(top.resolve("sub2:suba:subA:").is_none());
606 assert!(top.resolve("sub1:suba").is_none());
607
608}
619
620#[test]
622fn module_name_layered_parse_test() {
623 let mut top = ModNameNode::top();
624
625 assert!(top.add("A", ModId(1)).is_ok());
626 assert!(top.add("A:B", ModId(2)).is_ok());
627 assert!(top.add("A:B:C", ModId(3)).is_ok());
628
629 let mut branch = ModNameNode::new(ModId(10));
630 assert!(branch.add("b", ModId(11)).is_ok());
631 assert!(branch.add("b:c", ModId(12)).is_ok());
632 assert!(branch.add("b:c:d", ModId(13)).is_ok());
633
634 let mut leaf = ModNameNode::new(ModId(100));
635 assert!(leaf.add("1", ModId(101)).is_ok());
636 assert!(leaf.add("2", ModId(102)).is_ok());
637 assert!(leaf.add("3", ModId(103)).is_ok());
638
639 let subtrees = [("A:B:a", &branch)];
641 assert_eq!(ModNameNode::resolve_layered(&top, &subtrees, "A:B:a").unwrap(), ModId(10));
642 assert_eq!(ModNameNode::resolve_layered(&top, &subtrees, "A:B:a:b").unwrap(), ModId(11));
643 assert_eq!(ModNameNode::resolve_layered(&top, &subtrees, "A:B:C").unwrap(), ModId(3));
644
645 let subtrees = [("A:B:a", &branch), ("A:B:a:b:c:d:digits", &leaf)];
647 assert_eq!(ModNameNode::resolve_layered(&top, &subtrees, "A:B:a:b:c:d:digits:2").unwrap(), ModId(102));
648
649 let mut subtrees = [("A:B:a", &mut branch), ("A:B:a:b:c:d:digits", &mut leaf)];
651 let (parent, _remaining_name) = ModNameNode::parse_parent_layered_mut(&mut top, &mut subtrees, "A:B:a:b:c:d:digits:1").unwrap();
652 assert!(parent.add("1:one", ModId(1001)).is_ok());
653 assert_eq!(ModNameNode::resolve_layered(&top, &subtrees, "A:B:a:b:c:d:digits:1:one").unwrap(), ModId(1001));
654}
655