1use crate::declaration::ConstantInfo;
6use crate::{
7 BinderInfo, Declaration, Environment, Expr, FVarId, Level, LevelMVarId, Literal, Name,
8};
9use std::collections::HashMap;
10
11use super::functions::import_module;
12
13#[allow(dead_code)]
15pub struct TransformStat {
16 before: StatSummary,
17 after: StatSummary,
18}
19#[allow(dead_code)]
20impl TransformStat {
21 pub fn new() -> Self {
23 Self {
24 before: StatSummary::new(),
25 after: StatSummary::new(),
26 }
27 }
28 pub fn record_before(&mut self, v: f64) {
30 self.before.record(v);
31 }
32 pub fn record_after(&mut self, v: f64) {
34 self.after.record(v);
35 }
36 pub fn mean_ratio(&self) -> Option<f64> {
38 let b = self.before.mean()?;
39 let a = self.after.mean()?;
40 if b.abs() < f64::EPSILON {
41 return None;
42 }
43 Some(a / b)
44 }
45}
46#[derive(Debug, Clone, PartialEq, Eq)]
48pub enum IntegrityCheckResult {
49 Ok,
51 EmptyModule,
53 DuplicateNames(Vec<Name>),
55 BadMagicNumber,
57 UnsupportedVersion(u32),
59}
60#[allow(dead_code)]
62pub struct LabelSet {
63 labels: Vec<String>,
64}
65#[allow(dead_code)]
66impl LabelSet {
67 pub fn new() -> Self {
69 Self { labels: Vec::new() }
70 }
71 pub fn add(&mut self, label: impl Into<String>) {
73 let s = label.into();
74 if !self.labels.contains(&s) {
75 self.labels.push(s);
76 }
77 }
78 pub fn has(&self, label: &str) -> bool {
80 self.labels.iter().any(|l| l == label)
81 }
82 pub fn count(&self) -> usize {
84 self.labels.len()
85 }
86 pub fn all(&self) -> &[String] {
88 &self.labels
89 }
90}
91#[allow(dead_code)]
93pub struct ConfigNode {
94 key: String,
95 value: Option<String>,
96 children: Vec<ConfigNode>,
97}
98#[allow(dead_code)]
99impl ConfigNode {
100 pub fn leaf(key: impl Into<String>, value: impl Into<String>) -> Self {
102 Self {
103 key: key.into(),
104 value: Some(value.into()),
105 children: Vec::new(),
106 }
107 }
108 pub fn section(key: impl Into<String>) -> Self {
110 Self {
111 key: key.into(),
112 value: None,
113 children: Vec::new(),
114 }
115 }
116 pub fn add_child(&mut self, child: ConfigNode) {
118 self.children.push(child);
119 }
120 pub fn key(&self) -> &str {
122 &self.key
123 }
124 pub fn value(&self) -> Option<&str> {
126 self.value.as_deref()
127 }
128 pub fn num_children(&self) -> usize {
130 self.children.len()
131 }
132 pub fn lookup(&self, path: &str) -> Option<&str> {
134 let mut parts = path.splitn(2, '.');
135 let head = parts.next()?;
136 let tail = parts.next();
137 if head != self.key {
138 return None;
139 }
140 match tail {
141 None => self.value.as_deref(),
142 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
143 }
144 }
145 fn lookup_relative(&self, path: &str) -> Option<&str> {
146 let mut parts = path.splitn(2, '.');
147 let head = parts.next()?;
148 let tail = parts.next();
149 if head != self.key {
150 return None;
151 }
152 match tail {
153 None => self.value.as_deref(),
154 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
155 }
156 }
157}
158#[derive(Debug, Default)]
162pub struct ModuleDependencyGraph {
163 edges: HashMap<String, Vec<String>>,
165}
166impl ModuleDependencyGraph {
167 pub fn new() -> Self {
169 Self::default()
170 }
171 pub fn add_module(&mut self, name: String) {
173 self.edges.entry(name).or_default();
174 }
175 pub fn add_dep(&mut self, from: String, to: String) {
177 self.edges.entry(from).or_default().push(to);
178 }
179 pub fn from_cache(cache: &ModuleCache) -> Self {
181 let mut g = Self::new();
182 for name in cache.all_modules() {
183 g.add_module(name.to_string());
184 if let Some(module) = cache.get(name) {
185 for dep in &module.dependencies {
186 g.add_dep(name.to_string(), dep.clone());
187 }
188 }
189 }
190 g
191 }
192 pub fn topological_order(&self) -> Result<Vec<String>, String> {
196 use std::collections::VecDeque;
197 let mut in_degree: HashMap<String, usize> = HashMap::new();
198 for (node, deps) in &self.edges {
199 in_degree.entry(node.clone()).or_insert(0);
200 for dep in deps {
201 in_degree.entry(dep.clone()).or_insert(0);
202 }
203 }
204 for deps in self.edges.values() {
205 for dep in deps {
206 *in_degree.entry(dep.clone()).or_insert(0) += 0;
207 }
208 }
209 let mut in_degree: HashMap<String, usize> = HashMap::new();
210 for node in self.edges.keys() {
211 let deps = self.edges.get(node).map(|v| v.len()).unwrap_or(0);
212 in_degree.insert(node.clone(), deps);
213 }
214 let mut queue: VecDeque<String> = in_degree
215 .iter()
216 .filter(|(_, d)| **d == 0)
217 .map(|(k, _)| k.clone())
218 .collect();
219 let mut order = Vec::new();
220 while let Some(node) = queue.pop_front() {
221 order.push(node.clone());
222 for (other, deps) in &self.edges {
223 if deps.contains(&node) {
224 let deg = in_degree
225 .get_mut(other)
226 .expect("node must exist in in_degree map");
227 *deg = deg.saturating_sub(1);
228 if *deg == 0 {
229 queue.push_back(other.clone());
230 }
231 }
232 }
233 }
234 if order.len() != self.edges.len() {
235 Err("Cycle detected in module dependency graph".to_string())
236 } else {
237 Ok(order)
238 }
239 }
240 pub fn depends_on(&self, a: &str, b: &str) -> bool {
242 if let Some(deps) = self.edges.get(a) {
243 if deps.iter().any(|d| d == b) {
244 return true;
245 }
246 deps.iter().any(|d| self.depends_on(d, b))
247 } else {
248 false
249 }
250 }
251 pub fn num_modules(&self) -> usize {
253 self.edges.len()
254 }
255}
256#[allow(dead_code)]
258pub struct VersionedRecord<T: Clone> {
259 history: Vec<T>,
260}
261#[allow(dead_code)]
262impl<T: Clone> VersionedRecord<T> {
263 pub fn new(initial: T) -> Self {
265 Self {
266 history: vec![initial],
267 }
268 }
269 pub fn update(&mut self, val: T) {
271 self.history.push(val);
272 }
273 pub fn current(&self) -> &T {
275 self.history
276 .last()
277 .expect("VersionedRecord history is always non-empty after construction")
278 }
279 pub fn at_version(&self, n: usize) -> Option<&T> {
281 self.history.get(n)
282 }
283 pub fn version(&self) -> usize {
285 self.history.len() - 1
286 }
287 pub fn has_history(&self) -> bool {
289 self.history.len() > 1
290 }
291}
292#[allow(dead_code)]
294pub struct NonEmptyVec<T> {
295 head: T,
296 tail: Vec<T>,
297}
298#[allow(dead_code)]
299impl<T> NonEmptyVec<T> {
300 pub fn singleton(val: T) -> Self {
302 Self {
303 head: val,
304 tail: Vec::new(),
305 }
306 }
307 pub fn push(&mut self, val: T) {
309 self.tail.push(val);
310 }
311 pub fn first(&self) -> &T {
313 &self.head
314 }
315 pub fn last(&self) -> &T {
317 self.tail.last().unwrap_or(&self.head)
318 }
319 pub fn len(&self) -> usize {
321 1 + self.tail.len()
322 }
323 pub fn is_empty(&self) -> bool {
325 self.len() == 0
326 }
327 pub fn to_vec(&self) -> Vec<&T> {
329 let mut v = vec![&self.head];
330 v.extend(self.tail.iter());
331 v
332 }
333}
334#[derive(Debug, Default)]
339pub struct ModuleRegistry {
340 decl_to_module: HashMap<Name, String>,
342 module_to_decls: HashMap<String, Vec<Name>>,
344}
345impl ModuleRegistry {
346 pub fn new() -> Self {
348 Self::default()
349 }
350 pub fn register(&mut self, decl_name: Name, module_name: String) {
352 self.decl_to_module
353 .insert(decl_name.clone(), module_name.clone());
354 self.module_to_decls
355 .entry(module_name)
356 .or_default()
357 .push(decl_name);
358 }
359 pub fn register_module(&mut self, module: &ExportedModule) {
361 for name in module.declaration_names() {
362 self.register(name.clone(), module.name.clone());
363 }
364 }
365 pub fn module_for(&self, decl: &Name) -> Option<&str> {
367 self.decl_to_module.get(decl).map(|s| s.as_str())
368 }
369 pub fn decls_for_module(&self, module: &str) -> &[Name] {
371 self.module_to_decls
372 .get(module)
373 .map(|v| v.as_slice())
374 .unwrap_or(&[])
375 }
376 pub fn all_module_names(&self) -> Vec<&str> {
378 self.module_to_decls.keys().map(|s| s.as_str()).collect()
379 }
380 pub fn contains_decl(&self, decl: &Name) -> bool {
382 self.decl_to_module.contains_key(decl)
383 }
384 pub fn num_decls(&self) -> usize {
386 self.decl_to_module.len()
387 }
388 pub fn num_modules(&self) -> usize {
390 self.module_to_decls.len()
391 }
392}
393#[allow(dead_code)]
395pub struct StatSummary {
396 count: u64,
397 sum: f64,
398 min: f64,
399 max: f64,
400}
401#[allow(dead_code)]
402impl StatSummary {
403 pub fn new() -> Self {
405 Self {
406 count: 0,
407 sum: 0.0,
408 min: f64::INFINITY,
409 max: f64::NEG_INFINITY,
410 }
411 }
412 pub fn record(&mut self, val: f64) {
414 self.count += 1;
415 self.sum += val;
416 if val < self.min {
417 self.min = val;
418 }
419 if val > self.max {
420 self.max = val;
421 }
422 }
423 pub fn mean(&self) -> Option<f64> {
425 if self.count == 0 {
426 None
427 } else {
428 Some(self.sum / self.count as f64)
429 }
430 }
431 pub fn min(&self) -> Option<f64> {
433 if self.count == 0 {
434 None
435 } else {
436 Some(self.min)
437 }
438 }
439 pub fn max(&self) -> Option<f64> {
441 if self.count == 0 {
442 None
443 } else {
444 Some(self.max)
445 }
446 }
447 pub fn count(&self) -> u64 {
449 self.count
450 }
451}
452#[allow(dead_code)]
454pub struct SlidingSum {
455 window: Vec<f64>,
456 capacity: usize,
457 pos: usize,
458 sum: f64,
459 count: usize,
460}
461#[allow(dead_code)]
462impl SlidingSum {
463 pub fn new(capacity: usize) -> Self {
465 Self {
466 window: vec![0.0; capacity],
467 capacity,
468 pos: 0,
469 sum: 0.0,
470 count: 0,
471 }
472 }
473 pub fn push(&mut self, val: f64) {
475 let oldest = self.window[self.pos];
476 self.sum -= oldest;
477 self.sum += val;
478 self.window[self.pos] = val;
479 self.pos = (self.pos + 1) % self.capacity;
480 if self.count < self.capacity {
481 self.count += 1;
482 }
483 }
484 pub fn sum(&self) -> f64 {
486 self.sum
487 }
488 pub fn mean(&self) -> Option<f64> {
490 if self.count == 0 {
491 None
492 } else {
493 Some(self.sum / self.count as f64)
494 }
495 }
496 pub fn count(&self) -> usize {
498 self.count
499 }
500}
501#[allow(dead_code)]
503pub struct WindowIterator<'a, T> {
504 pub(super) data: &'a [T],
505 pub(super) pos: usize,
506 pub(super) window: usize,
507}
508#[allow(dead_code)]
509impl<'a, T> WindowIterator<'a, T> {
510 pub fn new(data: &'a [T], window: usize) -> Self {
512 Self {
513 data,
514 pos: 0,
515 window,
516 }
517 }
518}
519#[derive(Debug, Clone)]
521pub struct ExportedModule {
522 pub name: String,
524 pub declarations: Vec<(Name, Declaration)>,
526 pub constants: Vec<(Name, ConstantInfo)>,
528 pub dependencies: Vec<String>,
530 pub version: String,
532 pub metadata: HashMap<String, String>,
534}
535impl ExportedModule {
536 pub fn new(name: String) -> Self {
538 Self {
539 name,
540 declarations: Vec::new(),
541 constants: Vec::new(),
542 dependencies: Vec::new(),
543 version: "0.1.0".to_string(),
544 metadata: HashMap::new(),
545 }
546 }
547 pub fn add_declaration(&mut self, name: Name, decl: Declaration) {
549 self.declarations.push((name, decl));
550 }
551 pub fn add_constant(&mut self, name: Name, ci: ConstantInfo) {
553 self.constants.push((name, ci));
554 }
555 pub fn add_dependency(&mut self, dep: String) {
557 if !self.dependencies.contains(&dep) {
558 self.dependencies.push(dep);
559 }
560 }
561 pub fn set_metadata(&mut self, key: String, value: String) {
563 self.metadata.insert(key, value);
564 }
565 pub fn declaration_names(&self) -> Vec<&Name> {
567 let mut names: Vec<&Name> = self.declarations.iter().map(|(name, _)| name).collect();
568 names.extend(self.constants.iter().map(|(name, _)| name));
569 names
570 }
571 pub fn num_entries(&self) -> usize {
573 self.declarations.len() + self.constants.len()
574 }
575 pub fn is_empty(&self) -> bool {
577 self.declarations.is_empty() && self.constants.is_empty()
578 }
579}
580#[allow(dead_code)]
582pub struct PathBuf {
583 components: Vec<String>,
584}
585#[allow(dead_code)]
586impl PathBuf {
587 pub fn new() -> Self {
589 Self {
590 components: Vec::new(),
591 }
592 }
593 pub fn push(&mut self, comp: impl Into<String>) {
595 self.components.push(comp.into());
596 }
597 pub fn pop(&mut self) {
599 self.components.pop();
600 }
601 pub fn as_str(&self) -> String {
603 self.components.join("/")
604 }
605 pub fn depth(&self) -> usize {
607 self.components.len()
608 }
609 pub fn clear(&mut self) {
611 self.components.clear();
612 }
613}
614#[allow(dead_code)]
616pub struct StringPool {
617 free: Vec<String>,
618}
619#[allow(dead_code)]
620impl StringPool {
621 pub fn new() -> Self {
623 Self { free: Vec::new() }
624 }
625 pub fn take(&mut self) -> String {
627 self.free.pop().unwrap_or_default()
628 }
629 pub fn give(&mut self, mut s: String) {
631 s.clear();
632 self.free.push(s);
633 }
634 pub fn free_count(&self) -> usize {
636 self.free.len()
637 }
638}
639#[allow(dead_code)]
641pub struct SmallMap<K: Ord + Clone, V: Clone> {
642 entries: Vec<(K, V)>,
643}
644#[allow(dead_code)]
645impl<K: Ord + Clone, V: Clone> SmallMap<K, V> {
646 pub fn new() -> Self {
648 Self {
649 entries: Vec::new(),
650 }
651 }
652 pub fn insert(&mut self, key: K, val: V) {
654 match self.entries.binary_search_by_key(&&key, |(k, _)| k) {
655 Ok(i) => self.entries[i].1 = val,
656 Err(i) => self.entries.insert(i, (key, val)),
657 }
658 }
659 pub fn get(&self, key: &K) -> Option<&V> {
661 self.entries
662 .binary_search_by_key(&key, |(k, _)| k)
663 .ok()
664 .map(|i| &self.entries[i].1)
665 }
666 pub fn len(&self) -> usize {
668 self.entries.len()
669 }
670 pub fn is_empty(&self) -> bool {
672 self.entries.is_empty()
673 }
674 pub fn keys(&self) -> Vec<&K> {
676 self.entries.iter().map(|(k, _)| k).collect()
677 }
678 pub fn values(&self) -> Vec<&V> {
680 self.entries.iter().map(|(_, v)| v).collect()
681 }
682}
683#[allow(dead_code)]
685pub struct TransitiveClosure {
686 adj: Vec<Vec<usize>>,
687 n: usize,
688}
689#[allow(dead_code)]
690impl TransitiveClosure {
691 pub fn new(n: usize) -> Self {
693 Self {
694 adj: vec![Vec::new(); n],
695 n,
696 }
697 }
698 pub fn add_edge(&mut self, from: usize, to: usize) {
700 if from < self.n {
701 self.adj[from].push(to);
702 }
703 }
704 pub fn reachable_from(&self, start: usize) -> Vec<usize> {
706 let mut visited = vec![false; self.n];
707 let mut queue = std::collections::VecDeque::new();
708 queue.push_back(start);
709 while let Some(node) = queue.pop_front() {
710 if node >= self.n || visited[node] {
711 continue;
712 }
713 visited[node] = true;
714 for &next in &self.adj[node] {
715 queue.push_back(next);
716 }
717 }
718 (0..self.n).filter(|&i| visited[i]).collect()
719 }
720 pub fn can_reach(&self, from: usize, to: usize) -> bool {
722 self.reachable_from(from).contains(&to)
723 }
724}
725#[derive(Debug, Clone, Default)]
727pub struct ModuleDiff {
728 pub added: Vec<Name>,
730 pub removed: Vec<Name>,
732 pub changed: Vec<Name>,
734}
735impl ModuleDiff {
736 pub fn new() -> Self {
738 Self::default()
739 }
740 pub fn is_empty(&self) -> bool {
742 self.added.is_empty() && self.removed.is_empty() && self.changed.is_empty()
743 }
744 pub fn total_changes(&self) -> usize {
746 self.added.len() + self.removed.len() + self.changed.len()
747 }
748}
749#[allow(dead_code)]
751pub struct RewriteRuleSet {
752 rules: Vec<RewriteRule>,
753}
754#[allow(dead_code)]
755impl RewriteRuleSet {
756 pub fn new() -> Self {
758 Self { rules: Vec::new() }
759 }
760 pub fn add(&mut self, rule: RewriteRule) {
762 self.rules.push(rule);
763 }
764 pub fn len(&self) -> usize {
766 self.rules.len()
767 }
768 pub fn is_empty(&self) -> bool {
770 self.rules.is_empty()
771 }
772 pub fn conditional_rules(&self) -> Vec<&RewriteRule> {
774 self.rules.iter().filter(|r| r.conditional).collect()
775 }
776 pub fn unconditional_rules(&self) -> Vec<&RewriteRule> {
778 self.rules.iter().filter(|r| !r.conditional).collect()
779 }
780 pub fn get(&self, name: &str) -> Option<&RewriteRule> {
782 self.rules.iter().find(|r| r.name == name)
783 }
784}
785#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
787pub struct ModuleVersion {
788 pub major: u32,
790 pub minor: u32,
792 pub patch: u32,
794}
795impl ModuleVersion {
796 pub fn new(major: u32, minor: u32, patch: u32) -> Self {
798 Self {
799 major,
800 minor,
801 patch,
802 }
803 }
804 pub fn parse(s: &str) -> Option<Self> {
806 let parts: Vec<&str> = s.split('.').collect();
807 if parts.len() != 3 {
808 return None;
809 }
810 let major = parts[0].parse().ok()?;
811 let minor = parts[1].parse().ok()?;
812 let patch = parts[2].parse().ok()?;
813 Some(Self {
814 major,
815 minor,
816 patch,
817 })
818 }
819 pub fn is_compatible_with(&self, other: &Self) -> bool {
823 self.major == other.major && *self >= *other
824 }
825}
826#[allow(dead_code)]
828pub struct TokenBucket {
829 capacity: u64,
830 tokens: u64,
831 refill_per_ms: u64,
832 last_refill: std::time::Instant,
833}
834#[allow(dead_code)]
835impl TokenBucket {
836 pub fn new(capacity: u64, refill_per_ms: u64) -> Self {
838 Self {
839 capacity,
840 tokens: capacity,
841 refill_per_ms,
842 last_refill: std::time::Instant::now(),
843 }
844 }
845 pub fn try_consume(&mut self, n: u64) -> bool {
847 self.refill();
848 if self.tokens >= n {
849 self.tokens -= n;
850 true
851 } else {
852 false
853 }
854 }
855 fn refill(&mut self) {
856 let now = std::time::Instant::now();
857 let elapsed_ms = now.duration_since(self.last_refill).as_millis() as u64;
858 if elapsed_ms > 0 {
859 let new_tokens = elapsed_ms * self.refill_per_ms;
860 self.tokens = (self.tokens + new_tokens).min(self.capacity);
861 self.last_refill = now;
862 }
863 }
864 pub fn available(&self) -> u64 {
866 self.tokens
867 }
868 pub fn capacity(&self) -> u64 {
870 self.capacity
871 }
872}
873#[allow(dead_code)]
875pub struct RawFnPtr {
876 ptr: usize,
878 arity: usize,
879 name: String,
880}
881#[allow(dead_code)]
882impl RawFnPtr {
883 pub fn new(ptr: usize, arity: usize, name: impl Into<String>) -> Self {
885 Self {
886 ptr,
887 arity,
888 name: name.into(),
889 }
890 }
891 pub fn arity(&self) -> usize {
893 self.arity
894 }
895 pub fn name(&self) -> &str {
897 &self.name
898 }
899 pub fn raw(&self) -> usize {
901 self.ptr
902 }
903}
904#[derive(Clone, Debug, Default)]
906pub struct ModuleInfo {
907 pub version: Option<ModuleVersion>,
909 pub author: Option<String>,
911 pub license: Option<String>,
913 pub description: Option<String>,
915}
916impl ModuleInfo {
917 pub fn new() -> Self {
919 Self::default()
920 }
921 pub fn with_version(mut self, v: ModuleVersion) -> Self {
923 self.version = Some(v);
924 self
925 }
926 pub fn with_author(mut self, a: impl Into<String>) -> Self {
928 self.author = Some(a.into());
929 self
930 }
931 pub fn with_license(mut self, l: impl Into<String>) -> Self {
933 self.license = Some(l.into());
934 self
935 }
936 pub fn with_description(mut self, d: impl Into<String>) -> Self {
938 self.description = Some(d.into());
939 self
940 }
941}
942pub struct ModuleCache {
944 modules: HashMap<String, ExportedModule>,
946 import_order: Vec<String>,
948}
949impl ModuleCache {
950 pub fn new() -> Self {
952 Self {
953 modules: HashMap::new(),
954 import_order: Vec::new(),
955 }
956 }
957 pub fn add(&mut self, module: ExportedModule) {
959 let name = module.name.clone();
960 self.modules.insert(name.clone(), module);
961 if !self.import_order.contains(&name) {
962 self.import_order.push(name);
963 }
964 }
965 pub fn get(&self, name: &str) -> Option<&ExportedModule> {
967 self.modules.get(name)
968 }
969 pub fn contains(&self, name: &str) -> bool {
971 self.modules.contains_key(name)
972 }
973 pub fn all_modules(&self) -> Vec<&str> {
975 self.import_order.iter().map(|s| s.as_str()).collect()
976 }
977 pub fn num_modules(&self) -> usize {
979 self.modules.len()
980 }
981 pub fn import_all(&self, env: &mut Environment) -> Result<(), String> {
983 for name in &self.import_order {
984 if let Some(module) = self.modules.get(name) {
985 import_module(env, module)?;
986 }
987 }
988 Ok(())
989 }
990 pub fn import_with_deps(&self, env: &mut Environment, name: &str) -> Result<(), String> {
992 let module = self
993 .modules
994 .get(name)
995 .ok_or_else(|| format!("Module '{}' not found in cache", name))?;
996 for dep in &module.dependencies {
997 if self.contains(dep) {
998 self.import_with_deps(env, dep)?;
999 }
1000 }
1001 import_module(env, module)
1002 }
1003 pub fn remove(&mut self, name: &str) -> Option<ExportedModule> {
1005 self.import_order.retain(|n| n != name);
1006 self.modules.remove(name)
1007 }
1008 pub fn clear(&mut self) {
1010 self.modules.clear();
1011 self.import_order.clear();
1012 }
1013}
1014#[allow(dead_code)]
1016pub struct SimpleDag {
1017 edges: Vec<Vec<usize>>,
1019}
1020#[allow(dead_code)]
1021impl SimpleDag {
1022 pub fn new(n: usize) -> Self {
1024 Self {
1025 edges: vec![Vec::new(); n],
1026 }
1027 }
1028 pub fn add_edge(&mut self, from: usize, to: usize) {
1030 if from < self.edges.len() {
1031 self.edges[from].push(to);
1032 }
1033 }
1034 pub fn successors(&self, node: usize) -> &[usize] {
1036 self.edges.get(node).map(|v| v.as_slice()).unwrap_or(&[])
1037 }
1038 pub fn can_reach(&self, from: usize, to: usize) -> bool {
1040 let mut visited = vec![false; self.edges.len()];
1041 self.dfs(from, to, &mut visited)
1042 }
1043 fn dfs(&self, cur: usize, target: usize, visited: &mut Vec<bool>) -> bool {
1044 if cur == target {
1045 return true;
1046 }
1047 if cur >= visited.len() || visited[cur] {
1048 return false;
1049 }
1050 visited[cur] = true;
1051 for &next in self.successors(cur) {
1052 if self.dfs(next, target, visited) {
1053 return true;
1054 }
1055 }
1056 false
1057 }
1058 pub fn topological_sort(&self) -> Option<Vec<usize>> {
1060 let n = self.edges.len();
1061 let mut in_degree = vec![0usize; n];
1062 for succs in &self.edges {
1063 for &s in succs {
1064 if s < n {
1065 in_degree[s] += 1;
1066 }
1067 }
1068 }
1069 let mut queue: std::collections::VecDeque<usize> =
1070 (0..n).filter(|&i| in_degree[i] == 0).collect();
1071 let mut order = Vec::new();
1072 while let Some(node) = queue.pop_front() {
1073 order.push(node);
1074 for &s in self.successors(node) {
1075 if s < n {
1076 in_degree[s] -= 1;
1077 if in_degree[s] == 0 {
1078 queue.push_back(s);
1079 }
1080 }
1081 }
1082 }
1083 if order.len() == n {
1084 Some(order)
1085 } else {
1086 None
1087 }
1088 }
1089 pub fn num_nodes(&self) -> usize {
1091 self.edges.len()
1092 }
1093}
1094#[allow(dead_code)]
1096#[allow(missing_docs)]
1097pub struct RewriteRule {
1098 pub name: String,
1100 pub lhs: String,
1102 pub rhs: String,
1104 pub conditional: bool,
1106}
1107#[allow(dead_code)]
1108impl RewriteRule {
1109 pub fn unconditional(
1111 name: impl Into<String>,
1112 lhs: impl Into<String>,
1113 rhs: impl Into<String>,
1114 ) -> Self {
1115 Self {
1116 name: name.into(),
1117 lhs: lhs.into(),
1118 rhs: rhs.into(),
1119 conditional: false,
1120 }
1121 }
1122 pub fn conditional(
1124 name: impl Into<String>,
1125 lhs: impl Into<String>,
1126 rhs: impl Into<String>,
1127 ) -> Self {
1128 Self {
1129 name: name.into(),
1130 lhs: lhs.into(),
1131 rhs: rhs.into(),
1132 conditional: true,
1133 }
1134 }
1135 pub fn display(&self) -> String {
1137 format!("{}: {} → {}", self.name, self.lhs, self.rhs)
1138 }
1139}
1140#[allow(dead_code)]
1142pub struct FocusStack<T> {
1143 items: Vec<T>,
1144}
1145#[allow(dead_code)]
1146impl<T> FocusStack<T> {
1147 pub fn new() -> Self {
1149 Self { items: Vec::new() }
1150 }
1151 pub fn focus(&mut self, item: T) {
1153 self.items.push(item);
1154 }
1155 pub fn blur(&mut self) -> Option<T> {
1157 self.items.pop()
1158 }
1159 pub fn current(&self) -> Option<&T> {
1161 self.items.last()
1162 }
1163 pub fn depth(&self) -> usize {
1165 self.items.len()
1166 }
1167 pub fn is_empty(&self) -> bool {
1169 self.items.is_empty()
1170 }
1171}