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.get_mut(other).ok_or_else(|| {
225 format!("module `{other}` is missing from the in-degree map")
226 })?;
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 earlier: Vec<T>,
261 current: T,
263}
264#[allow(dead_code)]
265impl<T: Clone> VersionedRecord<T> {
266 pub fn new(initial: T) -> Self {
268 Self {
269 earlier: Vec::new(),
270 current: initial,
271 }
272 }
273 pub fn update(&mut self, val: T) {
275 let previous = std::mem::replace(&mut self.current, val);
276 self.earlier.push(previous);
277 }
278 pub fn current(&self) -> &T {
280 &self.current
281 }
282 pub fn at_version(&self, n: usize) -> Option<&T> {
284 match self.earlier.get(n) {
285 Some(value) => Some(value),
286 None if n == self.earlier.len() => Some(&self.current),
287 None => None,
288 }
289 }
290 pub fn version(&self) -> usize {
292 self.earlier.len()
293 }
294 pub fn has_history(&self) -> bool {
296 !self.earlier.is_empty()
297 }
298}
299#[allow(dead_code)]
301pub struct NonEmptyVec<T> {
302 head: T,
303 tail: Vec<T>,
304}
305#[allow(dead_code)]
306impl<T> NonEmptyVec<T> {
307 pub fn singleton(val: T) -> Self {
309 Self {
310 head: val,
311 tail: Vec::new(),
312 }
313 }
314 pub fn push(&mut self, val: T) {
316 self.tail.push(val);
317 }
318 pub fn first(&self) -> &T {
320 &self.head
321 }
322 pub fn last(&self) -> &T {
324 self.tail.last().unwrap_or(&self.head)
325 }
326 pub fn len(&self) -> usize {
328 1 + self.tail.len()
329 }
330 pub fn is_empty(&self) -> bool {
332 self.len() == 0
333 }
334 pub fn to_vec(&self) -> Vec<&T> {
336 let mut v = vec![&self.head];
337 v.extend(self.tail.iter());
338 v
339 }
340}
341#[derive(Debug, Default)]
346pub struct ModuleRegistry {
347 decl_to_module: HashMap<Name, String>,
349 module_to_decls: HashMap<String, Vec<Name>>,
351}
352impl ModuleRegistry {
353 pub fn new() -> Self {
355 Self::default()
356 }
357 pub fn register(&mut self, decl_name: Name, module_name: String) {
359 self.decl_to_module
360 .insert(decl_name.clone(), module_name.clone());
361 self.module_to_decls
362 .entry(module_name)
363 .or_default()
364 .push(decl_name);
365 }
366 pub fn register_module(&mut self, module: &ExportedModule) {
368 for name in module.declaration_names() {
369 self.register(name.clone(), module.name.clone());
370 }
371 }
372 pub fn module_for(&self, decl: &Name) -> Option<&str> {
374 self.decl_to_module.get(decl).map(|s| s.as_str())
375 }
376 pub fn decls_for_module(&self, module: &str) -> &[Name] {
378 self.module_to_decls
379 .get(module)
380 .map(|v| v.as_slice())
381 .unwrap_or(&[])
382 }
383 pub fn all_module_names(&self) -> Vec<&str> {
385 self.module_to_decls.keys().map(|s| s.as_str()).collect()
386 }
387 pub fn contains_decl(&self, decl: &Name) -> bool {
389 self.decl_to_module.contains_key(decl)
390 }
391 pub fn num_decls(&self) -> usize {
393 self.decl_to_module.len()
394 }
395 pub fn num_modules(&self) -> usize {
397 self.module_to_decls.len()
398 }
399}
400#[allow(dead_code)]
402pub struct StatSummary {
403 count: u64,
404 sum: f64,
405 min: f64,
406 max: f64,
407}
408#[allow(dead_code)]
409impl StatSummary {
410 pub fn new() -> Self {
412 Self {
413 count: 0,
414 sum: 0.0,
415 min: f64::INFINITY,
416 max: f64::NEG_INFINITY,
417 }
418 }
419 pub fn record(&mut self, val: f64) {
421 self.count += 1;
422 self.sum += val;
423 if val < self.min {
424 self.min = val;
425 }
426 if val > self.max {
427 self.max = val;
428 }
429 }
430 pub fn mean(&self) -> Option<f64> {
432 if self.count == 0 {
433 None
434 } else {
435 Some(self.sum / self.count as f64)
436 }
437 }
438 pub fn min(&self) -> Option<f64> {
440 if self.count == 0 {
441 None
442 } else {
443 Some(self.min)
444 }
445 }
446 pub fn max(&self) -> Option<f64> {
448 if self.count == 0 {
449 None
450 } else {
451 Some(self.max)
452 }
453 }
454 pub fn count(&self) -> u64 {
456 self.count
457 }
458}
459#[allow(dead_code)]
461pub struct SlidingSum {
462 window: Vec<f64>,
463 capacity: usize,
464 pos: usize,
465 sum: f64,
466 count: usize,
467}
468#[allow(dead_code)]
469impl SlidingSum {
470 pub fn new(capacity: usize) -> Self {
472 Self {
473 window: vec![0.0; capacity],
474 capacity,
475 pos: 0,
476 sum: 0.0,
477 count: 0,
478 }
479 }
480 pub fn push(&mut self, val: f64) {
482 let oldest = self.window[self.pos];
483 self.sum -= oldest;
484 self.sum += val;
485 self.window[self.pos] = val;
486 self.pos = (self.pos + 1) % self.capacity;
487 if self.count < self.capacity {
488 self.count += 1;
489 }
490 }
491 pub fn sum(&self) -> f64 {
493 self.sum
494 }
495 pub fn mean(&self) -> Option<f64> {
497 if self.count == 0 {
498 None
499 } else {
500 Some(self.sum / self.count as f64)
501 }
502 }
503 pub fn count(&self) -> usize {
505 self.count
506 }
507}
508#[allow(dead_code)]
510pub struct WindowIterator<'a, T> {
511 pub(super) data: &'a [T],
512 pub(super) pos: usize,
513 pub(super) window: usize,
514}
515#[allow(dead_code)]
516impl<'a, T> WindowIterator<'a, T> {
517 pub fn new(data: &'a [T], window: usize) -> Self {
519 Self {
520 data,
521 pos: 0,
522 window,
523 }
524 }
525}
526#[derive(Debug, Clone)]
528pub struct ExportedModule {
529 pub name: String,
531 pub declarations: Vec<(Name, Declaration)>,
533 pub constants: Vec<(Name, ConstantInfo)>,
535 pub dependencies: Vec<String>,
537 pub version: String,
539 pub metadata: HashMap<String, String>,
541}
542impl ExportedModule {
543 pub fn new(name: String) -> Self {
545 Self {
546 name,
547 declarations: Vec::new(),
548 constants: Vec::new(),
549 dependencies: Vec::new(),
550 version: "0.1.1".to_string(),
551 metadata: HashMap::new(),
552 }
553 }
554 pub fn add_declaration(&mut self, name: Name, decl: Declaration) {
556 self.declarations.push((name, decl));
557 }
558 pub fn add_constant(&mut self, name: Name, ci: ConstantInfo) {
560 self.constants.push((name, ci));
561 }
562 pub fn add_dependency(&mut self, dep: String) {
564 if !self.dependencies.contains(&dep) {
565 self.dependencies.push(dep);
566 }
567 }
568 pub fn set_metadata(&mut self, key: String, value: String) {
570 self.metadata.insert(key, value);
571 }
572 pub fn declaration_names(&self) -> Vec<&Name> {
574 let mut names: Vec<&Name> = self.declarations.iter().map(|(name, _)| name).collect();
575 names.extend(self.constants.iter().map(|(name, _)| name));
576 names
577 }
578 pub fn num_entries(&self) -> usize {
580 self.declarations.len() + self.constants.len()
581 }
582 pub fn is_empty(&self) -> bool {
584 self.declarations.is_empty() && self.constants.is_empty()
585 }
586}
587#[allow(dead_code)]
589pub struct PathBuf {
590 components: Vec<String>,
591}
592#[allow(dead_code)]
593impl PathBuf {
594 pub fn new() -> Self {
596 Self {
597 components: Vec::new(),
598 }
599 }
600 pub fn push(&mut self, comp: impl Into<String>) {
602 self.components.push(comp.into());
603 }
604 pub fn pop(&mut self) {
606 self.components.pop();
607 }
608 pub fn as_str(&self) -> String {
610 self.components.join("/")
611 }
612 pub fn depth(&self) -> usize {
614 self.components.len()
615 }
616 pub fn clear(&mut self) {
618 self.components.clear();
619 }
620}
621#[allow(dead_code)]
623pub struct StringPool {
624 free: Vec<String>,
625}
626#[allow(dead_code)]
627impl StringPool {
628 pub fn new() -> Self {
630 Self { free: Vec::new() }
631 }
632 pub fn take(&mut self) -> String {
634 self.free.pop().unwrap_or_default()
635 }
636 pub fn give(&mut self, mut s: String) {
638 s.clear();
639 self.free.push(s);
640 }
641 pub fn free_count(&self) -> usize {
643 self.free.len()
644 }
645}
646#[allow(dead_code)]
648pub struct SmallMap<K: Ord + Clone, V: Clone> {
649 entries: Vec<(K, V)>,
650}
651#[allow(dead_code)]
652impl<K: Ord + Clone, V: Clone> SmallMap<K, V> {
653 pub fn new() -> Self {
655 Self {
656 entries: Vec::new(),
657 }
658 }
659 pub fn insert(&mut self, key: K, val: V) {
661 match self.entries.binary_search_by_key(&&key, |(k, _)| k) {
662 Ok(i) => self.entries[i].1 = val,
663 Err(i) => self.entries.insert(i, (key, val)),
664 }
665 }
666 pub fn get(&self, key: &K) -> Option<&V> {
668 self.entries
669 .binary_search_by_key(&key, |(k, _)| k)
670 .ok()
671 .map(|i| &self.entries[i].1)
672 }
673 pub fn len(&self) -> usize {
675 self.entries.len()
676 }
677 pub fn is_empty(&self) -> bool {
679 self.entries.is_empty()
680 }
681 pub fn keys(&self) -> Vec<&K> {
683 self.entries.iter().map(|(k, _)| k).collect()
684 }
685 pub fn values(&self) -> Vec<&V> {
687 self.entries.iter().map(|(_, v)| v).collect()
688 }
689}
690#[allow(dead_code)]
692pub struct TransitiveClosure {
693 adj: Vec<Vec<usize>>,
694 n: usize,
695}
696#[allow(dead_code)]
697impl TransitiveClosure {
698 pub fn new(n: usize) -> Self {
700 Self {
701 adj: vec![Vec::new(); n],
702 n,
703 }
704 }
705 pub fn add_edge(&mut self, from: usize, to: usize) {
707 if from < self.n {
708 self.adj[from].push(to);
709 }
710 }
711 pub fn reachable_from(&self, start: usize) -> Vec<usize> {
713 let mut visited = vec![false; self.n];
714 let mut queue = std::collections::VecDeque::new();
715 queue.push_back(start);
716 while let Some(node) = queue.pop_front() {
717 if node >= self.n || visited[node] {
718 continue;
719 }
720 visited[node] = true;
721 for &next in &self.adj[node] {
722 queue.push_back(next);
723 }
724 }
725 (0..self.n).filter(|&i| visited[i]).collect()
726 }
727 pub fn can_reach(&self, from: usize, to: usize) -> bool {
729 self.reachable_from(from).contains(&to)
730 }
731}
732#[derive(Debug, Clone, Default)]
734pub struct ModuleDiff {
735 pub added: Vec<Name>,
737 pub removed: Vec<Name>,
739 pub changed: Vec<Name>,
741}
742impl ModuleDiff {
743 pub fn new() -> Self {
745 Self::default()
746 }
747 pub fn is_empty(&self) -> bool {
749 self.added.is_empty() && self.removed.is_empty() && self.changed.is_empty()
750 }
751 pub fn total_changes(&self) -> usize {
753 self.added.len() + self.removed.len() + self.changed.len()
754 }
755}
756#[allow(dead_code)]
758pub struct RewriteRuleSet {
759 rules: Vec<RewriteRule>,
760}
761#[allow(dead_code)]
762impl RewriteRuleSet {
763 pub fn new() -> Self {
765 Self { rules: Vec::new() }
766 }
767 pub fn add(&mut self, rule: RewriteRule) {
769 self.rules.push(rule);
770 }
771 pub fn len(&self) -> usize {
773 self.rules.len()
774 }
775 pub fn is_empty(&self) -> bool {
777 self.rules.is_empty()
778 }
779 pub fn conditional_rules(&self) -> Vec<&RewriteRule> {
781 self.rules.iter().filter(|r| r.conditional).collect()
782 }
783 pub fn unconditional_rules(&self) -> Vec<&RewriteRule> {
785 self.rules.iter().filter(|r| !r.conditional).collect()
786 }
787 pub fn get(&self, name: &str) -> Option<&RewriteRule> {
789 self.rules.iter().find(|r| r.name == name)
790 }
791}
792#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
794pub struct ModuleVersion {
795 pub major: u32,
797 pub minor: u32,
799 pub patch: u32,
801}
802impl ModuleVersion {
803 pub fn new(major: u32, minor: u32, patch: u32) -> Self {
805 Self {
806 major,
807 minor,
808 patch,
809 }
810 }
811 pub fn parse(s: &str) -> Option<Self> {
813 let parts: Vec<&str> = s.split('.').collect();
814 if parts.len() != 3 {
815 return None;
816 }
817 let major = parts[0].parse().ok()?;
818 let minor = parts[1].parse().ok()?;
819 let patch = parts[2].parse().ok()?;
820 Some(Self {
821 major,
822 minor,
823 patch,
824 })
825 }
826 pub fn is_compatible_with(&self, other: &Self) -> bool {
830 self.major == other.major && *self >= *other
831 }
832}
833#[allow(dead_code)]
835pub struct TokenBucket {
836 capacity: u64,
837 tokens: u64,
838 refill_per_ms: u64,
839 last_refill: crate::wall_clock::Instant,
840}
841#[allow(dead_code)]
842impl TokenBucket {
843 pub fn new(capacity: u64, refill_per_ms: u64) -> Self {
845 Self {
846 capacity,
847 tokens: capacity,
848 refill_per_ms,
849 last_refill: crate::wall_clock::Instant::now(),
850 }
851 }
852 pub fn try_consume(&mut self, n: u64) -> bool {
854 self.refill();
855 if self.tokens >= n {
856 self.tokens -= n;
857 true
858 } else {
859 false
860 }
861 }
862 fn refill(&mut self) {
863 let now = crate::wall_clock::Instant::now();
864 let elapsed_ms = now.duration_since(self.last_refill).as_millis() as u64;
865 if elapsed_ms > 0 {
866 let new_tokens = elapsed_ms * self.refill_per_ms;
867 self.tokens = (self.tokens + new_tokens).min(self.capacity);
868 self.last_refill = now;
869 }
870 }
871 pub fn available(&self) -> u64 {
873 self.tokens
874 }
875 pub fn capacity(&self) -> u64 {
877 self.capacity
878 }
879}
880#[allow(dead_code)]
882pub struct RawFnPtr {
883 ptr: usize,
885 arity: usize,
886 name: String,
887}
888#[allow(dead_code)]
889impl RawFnPtr {
890 pub fn new(ptr: usize, arity: usize, name: impl Into<String>) -> Self {
892 Self {
893 ptr,
894 arity,
895 name: name.into(),
896 }
897 }
898 pub fn arity(&self) -> usize {
900 self.arity
901 }
902 pub fn name(&self) -> &str {
904 &self.name
905 }
906 pub fn raw(&self) -> usize {
908 self.ptr
909 }
910}
911#[derive(Clone, Debug, Default)]
913pub struct ModuleInfo {
914 pub version: Option<ModuleVersion>,
916 pub author: Option<String>,
918 pub license: Option<String>,
920 pub description: Option<String>,
922}
923impl ModuleInfo {
924 pub fn new() -> Self {
926 Self::default()
927 }
928 pub fn with_version(mut self, v: ModuleVersion) -> Self {
930 self.version = Some(v);
931 self
932 }
933 pub fn with_author(mut self, a: impl Into<String>) -> Self {
935 self.author = Some(a.into());
936 self
937 }
938 pub fn with_license(mut self, l: impl Into<String>) -> Self {
940 self.license = Some(l.into());
941 self
942 }
943 pub fn with_description(mut self, d: impl Into<String>) -> Self {
945 self.description = Some(d.into());
946 self
947 }
948}
949pub struct ModuleCache {
951 modules: HashMap<String, ExportedModule>,
953 import_order: Vec<String>,
955}
956impl ModuleCache {
957 pub fn new() -> Self {
959 Self {
960 modules: HashMap::new(),
961 import_order: Vec::new(),
962 }
963 }
964 pub fn add(&mut self, module: ExportedModule) {
966 let name = module.name.clone();
967 self.modules.insert(name.clone(), module);
968 if !self.import_order.contains(&name) {
969 self.import_order.push(name);
970 }
971 }
972 pub fn get(&self, name: &str) -> Option<&ExportedModule> {
974 self.modules.get(name)
975 }
976 pub fn contains(&self, name: &str) -> bool {
978 self.modules.contains_key(name)
979 }
980 pub fn all_modules(&self) -> Vec<&str> {
982 self.import_order.iter().map(|s| s.as_str()).collect()
983 }
984 pub fn num_modules(&self) -> usize {
986 self.modules.len()
987 }
988 pub fn import_all(&self, env: &mut Environment) -> Result<(), String> {
990 for name in &self.import_order {
991 if let Some(module) = self.modules.get(name) {
992 import_module(env, module)?;
993 }
994 }
995 Ok(())
996 }
997 pub fn import_with_deps(&self, env: &mut Environment, name: &str) -> Result<(), String> {
999 let module = self
1000 .modules
1001 .get(name)
1002 .ok_or_else(|| format!("Module '{}' not found in cache", name))?;
1003 for dep in &module.dependencies {
1004 if self.contains(dep) {
1005 self.import_with_deps(env, dep)?;
1006 }
1007 }
1008 import_module(env, module)
1009 }
1010 pub fn remove(&mut self, name: &str) -> Option<ExportedModule> {
1012 self.import_order.retain(|n| n != name);
1013 self.modules.remove(name)
1014 }
1015 pub fn clear(&mut self) {
1017 self.modules.clear();
1018 self.import_order.clear();
1019 }
1020}
1021#[allow(dead_code)]
1023pub struct SimpleDag {
1024 edges: Vec<Vec<usize>>,
1026}
1027#[allow(dead_code)]
1028impl SimpleDag {
1029 pub fn new(n: usize) -> Self {
1031 Self {
1032 edges: vec![Vec::new(); n],
1033 }
1034 }
1035 pub fn add_edge(&mut self, from: usize, to: usize) {
1037 if from < self.edges.len() {
1038 self.edges[from].push(to);
1039 }
1040 }
1041 pub fn successors(&self, node: usize) -> &[usize] {
1043 self.edges.get(node).map(|v| v.as_slice()).unwrap_or(&[])
1044 }
1045 pub fn can_reach(&self, from: usize, to: usize) -> bool {
1047 let mut visited = vec![false; self.edges.len()];
1048 self.dfs(from, to, &mut visited)
1049 }
1050 fn dfs(&self, cur: usize, target: usize, visited: &mut Vec<bool>) -> bool {
1051 if cur == target {
1052 return true;
1053 }
1054 if cur >= visited.len() || visited[cur] {
1055 return false;
1056 }
1057 visited[cur] = true;
1058 for &next in self.successors(cur) {
1059 if self.dfs(next, target, visited) {
1060 return true;
1061 }
1062 }
1063 false
1064 }
1065 pub fn topological_sort(&self) -> Option<Vec<usize>> {
1067 let n = self.edges.len();
1068 let mut in_degree = vec![0usize; n];
1069 for succs in &self.edges {
1070 for &s in succs {
1071 if s < n {
1072 in_degree[s] += 1;
1073 }
1074 }
1075 }
1076 let mut queue: std::collections::VecDeque<usize> =
1077 (0..n).filter(|&i| in_degree[i] == 0).collect();
1078 let mut order = Vec::new();
1079 while let Some(node) = queue.pop_front() {
1080 order.push(node);
1081 for &s in self.successors(node) {
1082 if s < n {
1083 in_degree[s] -= 1;
1084 if in_degree[s] == 0 {
1085 queue.push_back(s);
1086 }
1087 }
1088 }
1089 }
1090 if order.len() == n {
1091 Some(order)
1092 } else {
1093 None
1094 }
1095 }
1096 pub fn num_nodes(&self) -> usize {
1098 self.edges.len()
1099 }
1100}
1101#[allow(dead_code)]
1103#[allow(missing_docs)]
1104pub struct RewriteRule {
1105 pub name: String,
1107 pub lhs: String,
1109 pub rhs: String,
1111 pub conditional: bool,
1113}
1114#[allow(dead_code)]
1115impl RewriteRule {
1116 pub fn unconditional(
1118 name: impl Into<String>,
1119 lhs: impl Into<String>,
1120 rhs: impl Into<String>,
1121 ) -> Self {
1122 Self {
1123 name: name.into(),
1124 lhs: lhs.into(),
1125 rhs: rhs.into(),
1126 conditional: false,
1127 }
1128 }
1129 pub fn conditional(
1131 name: impl Into<String>,
1132 lhs: impl Into<String>,
1133 rhs: impl Into<String>,
1134 ) -> Self {
1135 Self {
1136 name: name.into(),
1137 lhs: lhs.into(),
1138 rhs: rhs.into(),
1139 conditional: true,
1140 }
1141 }
1142 pub fn display(&self) -> String {
1144 format!("{}: {} → {}", self.name, self.lhs, self.rhs)
1145 }
1146}
1147#[allow(dead_code)]
1149pub struct FocusStack<T> {
1150 items: Vec<T>,
1151}
1152#[allow(dead_code)]
1153impl<T> FocusStack<T> {
1154 pub fn new() -> Self {
1156 Self { items: Vec::new() }
1157 }
1158 pub fn focus(&mut self, item: T) {
1160 self.items.push(item);
1161 }
1162 pub fn blur(&mut self) -> Option<T> {
1164 self.items.pop()
1165 }
1166 pub fn current(&self) -> Option<&T> {
1168 self.items.last()
1169 }
1170 pub fn depth(&self) -> usize {
1172 self.items.len()
1173 }
1174 pub fn is_empty(&self) -> bool {
1176 self.items.is_empty()
1177 }
1178}
1179#[cfg(test)]
1180mod topo_order_tests;