1use super::functions::*;
6use oxilean_kernel::{Expr, Name};
7
8use std::collections::{HashMap, HashSet};
9
10#[derive(Debug, Clone, PartialEq)]
12pub enum ResolutionResult {
13 Found(Name),
15 Ambiguous(Vec<Name>),
17 NotFound,
19 DepthExceeded,
21}
22#[derive(Debug, Default)]
24pub struct InstanceResolutionTrace {
25 entries: Vec<ResolutionTraceEntry>,
26 pub(crate) enabled: bool,
27}
28impl InstanceResolutionTrace {
29 pub fn new() -> Self {
31 Self::default()
32 }
33 pub fn enabled() -> Self {
35 Self {
36 entries: Vec::new(),
37 enabled: true,
38 }
39 }
40 pub fn enable(&mut self) {
42 self.enabled = true;
43 }
44 pub fn disable(&mut self) {
46 self.enabled = false;
47 }
48 pub fn log(&mut self, class: Name, instance: Name, outcome: impl Into<String>, depth: usize) {
50 if !self.enabled {
51 return;
52 }
53 self.entries.push(ResolutionTraceEntry {
54 class,
55 instance,
56 outcome: outcome.into(),
57 depth,
58 });
59 }
60 pub fn len(&self) -> usize {
62 self.entries.len()
63 }
64 pub fn is_empty(&self) -> bool {
66 self.entries.is_empty()
67 }
68 pub fn clear(&mut self) {
70 self.entries.clear();
71 }
72 pub fn entries_for_class(&self, class: &Name) -> Vec<&ResolutionTraceEntry> {
74 self.entries.iter().filter(|e| &e.class == class).collect()
75 }
76}
77#[derive(Debug, Default)]
79pub struct InstanceScopeStack {
80 scopes: Vec<InstanceScope>,
81}
82impl InstanceScopeStack {
83 pub fn new() -> Self {
85 Self::default()
86 }
87 pub fn push_scope(&mut self) {
89 self.scopes.push(InstanceScope::new());
90 }
91 pub fn pop_scope(&mut self) -> Option<InstanceScope> {
93 self.scopes.pop()
94 }
95 pub fn add_to_top(&mut self, inst: TypeclassInstance) {
97 if let Some(top) = self.scopes.last_mut() {
98 top.add(inst);
99 }
100 }
101 pub fn local_instances_for_class(&self, class: &Name) -> Vec<&TypeclassInstance> {
103 self.scopes
104 .iter()
105 .rev()
106 .flat_map(|s| s.instances_for_class(class))
107 .collect()
108 }
109 pub fn depth(&self) -> usize {
111 self.scopes.len()
112 }
113 pub fn is_empty(&self) -> bool {
115 self.scopes.is_empty()
116 }
117}
118#[derive(Clone, Debug)]
120pub struct InstanceSnapshot {
121 pub class: Name,
123 pub candidates: Vec<InstanceDecl>,
125 pub cache_size: usize,
127}
128impl InstanceSnapshot {
129 pub fn new(class: Name, candidates: Vec<InstanceDecl>, cache_size: usize) -> Self {
131 Self {
132 class,
133 candidates,
134 cache_size,
135 }
136 }
137 pub fn candidate_count(&self) -> usize {
139 self.candidates.len()
140 }
141}
142pub struct InstanceResolver {
147 instances: HashMap<Name, Vec<InstanceDecl>>,
149 max_depth: usize,
151 cache: InstanceCache,
153 cache_enabled: bool,
155 total_registered: usize,
157}
158impl InstanceResolver {
159 pub fn new() -> Self {
161 Self {
162 instances: HashMap::new(),
163 max_depth: 10,
164 cache: InstanceCache::new(),
165 cache_enabled: true,
166 total_registered: 0,
167 }
168 }
169 pub fn with_max_depth(max_depth: usize) -> Self {
171 let mut r = Self::new();
172 r.max_depth = max_depth;
173 r
174 }
175 pub fn register(&mut self, instance: InstanceDecl) {
177 self.total_registered += 1;
178 let bucket = self.instances.entry(instance.class.clone()).or_default();
179 bucket.push(instance);
180 bucket.sort_by(compare_priority);
181 }
182 pub fn register_many(&mut self, instances: impl IntoIterator<Item = InstanceDecl>) {
184 for inst in instances {
185 self.register(inst);
186 }
187 }
188 pub fn clear_class(&mut self, class: &Name) {
190 if let Some(bucket) = self.instances.get_mut(class) {
191 self.total_registered -= bucket.len();
192 bucket.clear();
193 }
194 }
195 pub fn find_instance(&mut self, class: &Name, ty: &Expr) -> Option<&InstanceDecl> {
200 if self.cache_enabled {
201 let key = CacheKey::new(class, ty);
202 if self.cache.get(&key).is_some() {}
203 let _ = key;
204 }
205 if let Some(instances) = self.instances.get(class) {
206 instances.first()
207 } else {
208 None
209 }
210 }
211 pub fn resolve(&mut self, class: &Name, ty: &Expr) -> ResolutionResult {
215 let instances = match self.instances.get(class) {
216 Some(v) if !v.is_empty() => v.clone(),
217 _ => return ResolutionResult::NotFound,
218 };
219 let candidates: Vec<InstanceDecl> = instances
220 .into_iter()
221 .filter(|i| structural_match(&i.ty, ty))
222 .collect();
223 if candidates.is_empty() {
224 return ResolutionResult::NotFound;
225 }
226 let best_priority = candidates
227 .iter()
228 .map(|i| i.priority)
229 .min()
230 .expect("candidates is non-empty (checked above)");
231 let best: Vec<&InstanceDecl> = candidates
232 .iter()
233 .filter(|i| i.priority == best_priority)
234 .collect();
235 if best.len() == 1 {
236 let name = best[0].name.clone();
237 if self.cache_enabled {
238 let key = CacheKey::new(class, ty);
239 self.cache.insert(key, name.clone());
240 }
241 ResolutionResult::Found(name)
242 } else {
243 ResolutionResult::Ambiguous(best.iter().map(|i| i.name.clone()).collect())
244 }
245 }
246 pub fn resolve_or_error(&mut self, class: &Name, ty: &Expr) -> Result<Name, InstanceError> {
248 match self.resolve(class, ty) {
249 ResolutionResult::Found(name) => Ok(name),
250 ResolutionResult::NotFound => Err(InstanceError::NotFound {
251 class: class.clone(),
252 }),
253 ResolutionResult::Ambiguous(candidates) => Err(InstanceError::Ambiguous {
254 class: class.clone(),
255 candidates,
256 }),
257 ResolutionResult::DepthExceeded => Err(InstanceError::MaxDepthExceeded {
258 depth: self.max_depth,
259 }),
260 }
261 }
262 pub fn get_instances(&self, class: &Name) -> Vec<&InstanceDecl> {
264 self.instances
265 .get(class)
266 .map(|v| v.iter().collect())
267 .unwrap_or_default()
268 }
269 pub fn class_count(&self) -> usize {
271 self.instances.len()
272 }
273 pub fn total_registered(&self) -> usize {
275 self.total_registered
276 }
277 pub fn set_max_depth(&mut self, depth: usize) {
279 self.max_depth = depth;
280 }
281 pub fn max_depth(&self) -> usize {
283 self.max_depth
284 }
285 pub fn set_cache_enabled(&mut self, enabled: bool) {
287 self.cache_enabled = enabled;
288 }
289 pub fn cache_enabled(&self) -> bool {
291 self.cache_enabled
292 }
293 pub fn cache(&self) -> &InstanceCache {
295 &self.cache
296 }
297 pub fn clear_cache(&mut self) {
299 self.cache.clear();
300 }
301 pub fn has_instances_for(&self, class: &Name) -> bool {
303 self.instances
304 .get(class)
305 .map(|v| !v.is_empty())
306 .unwrap_or(false)
307 }
308 pub fn registered_classes(&self) -> Vec<&Name> {
310 self.instances
311 .iter()
312 .filter(|(_, v)| !v.is_empty())
313 .map(|(k, _)| k)
314 .collect()
315 }
316}
317#[derive(Debug, Default)]
319pub struct InstanceMatcher;
320impl InstanceMatcher {
321 pub fn new() -> Self {
323 Self
324 }
325 pub fn match_class(&self, query_class: &Name, inst_class: &Name) -> MatchOutcome {
328 if query_class == inst_class {
329 MatchOutcome::Match
330 } else {
331 MatchOutcome::NoMatch
332 }
333 }
334 pub fn filter_candidates<'a>(
336 &self,
337 class: &Name,
338 instances: &'a [TypeclassInstance],
339 ) -> Vec<&'a TypeclassInstance> {
340 instances
341 .iter()
342 .filter(|inst| self.match_class(class, inst.class()) == MatchOutcome::Match)
343 .collect()
344 }
345}
346#[derive(Debug, Clone)]
348pub struct ResolutionTraceEntry {
349 pub class: Name,
351 pub instance: Name,
353 pub outcome: String,
355 pub depth: usize,
357}
358#[derive(Debug, Clone, PartialEq)]
360pub enum InstanceError {
361 NotFound {
363 class: Name,
365 },
366 Ambiguous {
368 class: Name,
370 candidates: Vec<Name>,
372 },
373 MaxDepthExceeded {
375 depth: usize,
377 },
378 CircularDependency {
380 chain: Vec<Name>,
382 },
383 UnresolvableSubgoal {
385 instance: Name,
387 subgoal: Name,
389 },
390}
391#[derive(Debug, Clone)]
394pub struct TypeclassInstance {
395 pub decl: InstanceDecl,
397 pub dependencies: Vec<Name>,
399 pub super_instances: Vec<Name>,
401 pub is_default: bool,
403 pub is_local: bool,
405}
406impl TypeclassInstance {
407 pub fn new(decl: InstanceDecl) -> Self {
409 Self {
410 decl,
411 dependencies: Vec::new(),
412 super_instances: Vec::new(),
413 is_default: false,
414 is_local: false,
415 }
416 }
417 pub fn default_instance(mut self) -> Self {
419 self.is_default = true;
420 self
421 }
422 pub fn local(mut self) -> Self {
424 self.is_local = true;
425 self
426 }
427 pub fn add_dependency(&mut self, dep: Name) {
429 self.dependencies.push(dep);
430 }
431 pub fn add_super(&mut self, sup: Name) {
433 self.super_instances.push(sup);
434 }
435 pub fn class(&self) -> &Name {
437 &self.decl.class
438 }
439 pub fn name(&self) -> &Name {
441 &self.decl.name
442 }
443 pub fn priority(&self) -> u32 {
445 self.decl.priority
446 }
447}
448#[derive(Debug, Clone)]
450pub struct InstanceCacheEntry {
451 pub key: String,
453 pub chain: InstanceChain,
455 pub hit_count: usize,
457}
458#[derive(Debug, Default)]
460pub struct InstanceChainCache {
461 entries: HashMap<String, InstanceCacheEntry>,
462}
463impl InstanceChainCache {
464 pub fn new() -> Self {
466 Self::default()
467 }
468 pub fn store(&mut self, key: impl Into<String>, chain: InstanceChain) {
470 let key = key.into();
471 self.entries.insert(
472 key.clone(),
473 InstanceCacheEntry {
474 key,
475 chain,
476 hit_count: 0,
477 },
478 );
479 }
480 pub fn lookup(&mut self, key: &str) -> Option<&InstanceChain> {
482 if let Some(entry) = self.entries.get_mut(key) {
483 entry.hit_count += 1;
484 Some(&entry.chain)
485 } else {
486 None
487 }
488 }
489 pub fn len(&self) -> usize {
491 self.entries.len()
492 }
493 pub fn is_empty(&self) -> bool {
495 self.entries.is_empty()
496 }
497 pub fn clear(&mut self) {
499 self.entries.clear();
500 }
501 pub fn total_hits(&self) -> usize {
503 self.entries.values().map(|e| e.hit_count).sum()
504 }
505}
506#[derive(Debug, Clone)]
508pub struct SynthConfig {
509 pub max_depth: usize,
511 pub max_instances: usize,
513 pub allow_defaults: bool,
515 pub diamond_strategy: DiamondResolutionStrategy,
517}
518#[derive(Debug, Clone, PartialEq, Eq)]
520pub enum MatchOutcome {
521 Match,
523 NoMatch,
525 Deferred,
527}
528#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
530pub enum DiamondResolutionStrategy {
531 Strict,
533 #[default]
535 PreferLowestPriority,
536 PreferMostRecent,
538 DepthFirst,
540}
541#[derive(Debug, Clone, Default)]
543pub struct InstanceRegistryStats {
544 pub successes: usize,
546 pub failures: usize,
548 pub ambiguous: usize,
550 pub total_depth: usize,
552}
553impl InstanceRegistryStats {
554 pub fn new() -> Self {
556 Self::default()
557 }
558 pub fn record_success(&mut self, depth: usize) {
560 self.successes += 1;
561 self.total_depth += depth;
562 }
563 pub fn record_failure(&mut self) {
565 self.failures += 1;
566 }
567 pub fn record_ambiguous(&mut self) {
569 self.ambiguous += 1;
570 }
571 pub fn total(&self) -> usize {
573 self.successes + self.failures + self.ambiguous
574 }
575 pub fn success_rate(&self) -> f64 {
577 if self.total() == 0 {
578 0.0
579 } else {
580 self.successes as f64 / self.total() as f64
581 }
582 }
583 pub fn average_depth(&self) -> f64 {
585 if self.successes == 0 {
586 0.0
587 } else {
588 self.total_depth as f64 / self.successes as f64
589 }
590 }
591}
592#[derive(Debug, Clone, Default)]
594pub struct InstancePriorityQueue {
595 candidates: Vec<TypeclassInstance>,
597}
598impl InstancePriorityQueue {
599 pub fn new() -> Self {
601 Self::default()
602 }
603 pub fn push(&mut self, inst: TypeclassInstance) {
605 let pos = self
606 .candidates
607 .partition_point(|c| c.priority() <= inst.priority());
608 self.candidates.insert(pos, inst);
609 }
610 pub fn pop_best(&mut self) -> Option<TypeclassInstance> {
612 if self.candidates.is_empty() {
613 None
614 } else {
615 Some(self.candidates.remove(0))
616 }
617 }
618 pub fn peek_best(&self) -> Option<&TypeclassInstance> {
620 self.candidates.first()
621 }
622 pub fn best_candidates(&self) -> Vec<&TypeclassInstance> {
624 if self.candidates.is_empty() {
625 return Vec::new();
626 }
627 let best_priority = self.candidates[0].priority();
628 self.candidates
629 .iter()
630 .take_while(|c| c.priority() == best_priority)
631 .collect()
632 }
633 pub fn len(&self) -> usize {
635 self.candidates.len()
636 }
637 pub fn is_empty(&self) -> bool {
639 self.candidates.is_empty()
640 }
641 pub fn clear(&mut self) {
643 self.candidates.clear();
644 }
645 pub fn all_candidates(&self) -> &[TypeclassInstance] {
647 &self.candidates
648 }
649}
650#[derive(Debug, Default)]
652pub struct InstanceScope {
653 local_instances: Vec<TypeclassInstance>,
655 active: bool,
657}
658impl InstanceScope {
659 pub fn new() -> Self {
661 Self {
662 local_instances: Vec::new(),
663 active: true,
664 }
665 }
666 pub fn add(&mut self, inst: TypeclassInstance) {
668 self.local_instances.push(inst);
669 }
670 pub fn instances_for_class(&self, class: &Name) -> Vec<&TypeclassInstance> {
672 if !self.active {
673 return Vec::new();
674 }
675 self.local_instances
676 .iter()
677 .filter(|i| i.class() == class)
678 .collect()
679 }
680 pub fn len(&self) -> usize {
682 self.local_instances.len()
683 }
684 pub fn is_empty(&self) -> bool {
686 self.local_instances.is_empty()
687 }
688 pub fn deactivate(&mut self) {
690 self.active = false;
691 }
692 pub fn is_active(&self) -> bool {
694 self.active
695 }
696}
697#[derive(Debug, Clone)]
699pub struct InstanceDecl {
700 pub name: Name,
702 pub class: Name,
704 pub ty: Expr,
706 pub priority: u32,
708}
709#[derive(Debug, Clone)]
711pub enum SynthResult {
712 Success(InstanceChain),
714 Failure(InstanceError),
716 Ambiguous(Vec<InstanceChain>),
718}
719impl SynthResult {
720 pub fn is_success(&self) -> bool {
722 matches!(self, SynthResult::Success(_))
723 }
724 pub fn is_failure(&self) -> bool {
726 matches!(self, SynthResult::Failure(_))
727 }
728 pub fn is_ambiguous(&self) -> bool {
730 matches!(self, SynthResult::Ambiguous(_))
731 }
732 pub fn chain(&self) -> Option<&InstanceChain> {
734 match self {
735 SynthResult::Success(chain) => Some(chain),
736 _ => None,
737 }
738 }
739}
740#[derive(Debug, Default)]
744pub struct InstanceGraph {
745 edges: HashMap<Name, Vec<Name>>,
746}
747impl InstanceGraph {
748 pub fn new() -> Self {
750 Self::default()
751 }
752 pub fn add_edge(&mut self, from: Name, to: Name) {
754 self.edges.entry(from).or_default().push(to);
755 }
756 pub fn dependencies(&self, name: &Name) -> &[Name] {
758 self.edges.get(name).map(|v| v.as_slice()).unwrap_or(&[])
759 }
760 pub fn has_edge(&self, from: &Name, to: &Name) -> bool {
762 self.edges
763 .get(from)
764 .map(|deps| deps.contains(to))
765 .unwrap_or(false)
766 }
767 pub fn nodes(&self) -> Vec<&Name> {
769 self.edges.keys().collect()
770 }
771 pub fn has_cycle(&self) -> bool {
773 let mut visited = std::collections::HashSet::new();
774 let mut rec_stack = std::collections::HashSet::new();
775 for node in self.edges.keys() {
776 if self.dfs_cycle_check(node, &mut visited, &mut rec_stack) {
777 return true;
778 }
779 }
780 false
781 }
782 fn dfs_cycle_check(
783 &self,
784 node: &Name,
785 visited: &mut std::collections::HashSet<Name>,
786 rec_stack: &mut std::collections::HashSet<Name>,
787 ) -> bool {
788 if rec_stack.contains(node) {
789 return true;
790 }
791 if visited.contains(node) {
792 return false;
793 }
794 visited.insert(node.clone());
795 rec_stack.insert(node.clone());
796 for dep in self.dependencies(node) {
797 if self.dfs_cycle_check(dep, visited, rec_stack) {
798 return true;
799 }
800 }
801 rec_stack.remove(node);
802 false
803 }
804}
805#[derive(Debug, Clone)]
807pub struct InstanceReport {
808 pub class: Name,
810 pub chain: Option<InstanceChain>,
812 pub error: Option<InstanceError>,
814 pub instances_explored: usize,
816}
817impl InstanceReport {
818 pub fn success(class: Name, chain: InstanceChain, explored: usize) -> Self {
820 Self {
821 class,
822 chain: Some(chain),
823 error: None,
824 instances_explored: explored,
825 }
826 }
827 pub fn failure(class: Name, error: InstanceError, explored: usize) -> Self {
829 Self {
830 class,
831 chain: None,
832 error: Some(error),
833 instances_explored: explored,
834 }
835 }
836 pub fn is_success(&self) -> bool {
838 self.chain.is_some()
839 }
840}
841#[derive(Debug, Default)]
843pub struct InstanceCache {
844 entries: HashMap<CacheKey, Name>,
845 hits: u64,
846 misses: u64,
847}
848impl InstanceCache {
849 pub fn new() -> Self {
851 Self::default()
852 }
853 pub fn insert(&mut self, key: CacheKey, instance_name: Name) {
855 self.entries.insert(key, instance_name);
856 }
857 pub fn get(&mut self, key: &CacheKey) -> Option<&Name> {
859 if let Some(v) = self.entries.get(key) {
860 self.hits += 1;
861 Some(v)
862 } else {
863 self.misses += 1;
864 None
865 }
866 }
867 pub fn hits(&self) -> u64 {
869 self.hits
870 }
871 pub fn misses(&self) -> u64 {
873 self.misses
874 }
875 pub fn total_queries(&self) -> u64 {
877 self.hits + self.misses
878 }
879 pub fn clear(&mut self) {
881 self.entries.clear();
882 }
883 pub fn len(&self) -> usize {
885 self.entries.len()
886 }
887 pub fn is_empty(&self) -> bool {
889 self.entries.is_empty()
890 }
891}
892#[derive(Debug, Clone)]
894pub struct InstanceChain {
895 pub steps: Vec<Name>,
897 pub total_cost: u32,
899 pub has_default: bool,
901}
902impl InstanceChain {
903 pub fn empty() -> Self {
905 Self {
906 steps: Vec::new(),
907 total_cost: 0,
908 has_default: false,
909 }
910 }
911 pub fn single(name: Name, cost: u32) -> Self {
913 Self {
914 steps: vec![name],
915 total_cost: cost,
916 has_default: false,
917 }
918 }
919 pub fn extend(&self, name: Name, cost: u32, is_default: bool) -> Self {
921 let mut new_chain = self.clone();
922 new_chain.steps.push(name);
923 new_chain.total_cost += cost;
924 if is_default {
925 new_chain.has_default = true;
926 }
927 new_chain
928 }
929 pub fn len(&self) -> usize {
931 self.steps.len()
932 }
933 pub fn is_empty(&self) -> bool {
935 self.steps.is_empty()
936 }
937 pub fn leaf(&self) -> Option<&Name> {
939 self.steps.last()
940 }
941}
942pub struct TracedResolver {
944 pub resolver: InstanceResolver,
946 pub stats: SearchStats,
948}
949impl TracedResolver {
950 pub fn new() -> Self {
952 Self {
953 resolver: InstanceResolver::new(),
954 stats: SearchStats::new(),
955 }
956 }
957 pub fn register(&mut self, inst: InstanceDecl) {
959 self.resolver.register(inst);
960 }
961 pub fn resolve(&mut self, class: &Name, ty: &Expr) -> ResolutionResult {
963 let n_before = self.resolver.get_instances(class).len() as u64;
964 let result = self.resolver.resolve(class, ty);
965 match &result {
966 ResolutionResult::Found(_) => self.stats.record_success(n_before),
967 ResolutionResult::NotFound => self.stats.record_failure(),
968 ResolutionResult::Ambiguous(_) => self.stats.record_ambiguous(),
969 ResolutionResult::DepthExceeded => self.stats.record_depth_exceeded(),
970 }
971 result
972 }
973}
974#[derive(Debug, Default)]
976pub struct InstanceSearchState {
977 pub tried: std::collections::HashSet<Name>,
979 pub depth: usize,
981 pub max_depth_reached: usize,
983 pub nodes_explored: usize,
985}
986impl InstanceSearchState {
987 pub fn new() -> Self {
989 Self::default()
990 }
991 pub fn mark_tried(&mut self, name: Name) {
993 self.tried.insert(name);
994 }
995 pub fn already_tried(&self, name: &Name) -> bool {
997 self.tried.contains(name)
998 }
999 pub fn enter_depth(&mut self) {
1001 self.depth += 1;
1002 if self.depth > self.max_depth_reached {
1003 self.max_depth_reached = self.depth;
1004 }
1005 self.nodes_explored += 1;
1006 }
1007 pub fn exit_depth(&mut self) {
1009 if self.depth > 0 {
1010 self.depth -= 1;
1011 }
1012 }
1013 pub fn depth_exceeded(&self, limit: usize) -> bool {
1015 self.depth > limit
1016 }
1017}
1018#[derive(Debug, Default, Clone)]
1020pub struct SearchStats {
1021 pub successes: u64,
1023 pub failures: u64,
1025 pub ambiguous: u64,
1027 pub depth_exceeded: u64,
1029 pub instances_inspected: u64,
1031}
1032impl SearchStats {
1033 pub fn new() -> Self {
1035 Self::default()
1036 }
1037 pub fn record_success(&mut self, candidates_inspected: u64) {
1039 self.successes += 1;
1040 self.instances_inspected += candidates_inspected;
1041 }
1042 pub fn record_failure(&mut self) {
1044 self.failures += 1;
1045 }
1046 pub fn record_ambiguous(&mut self) {
1048 self.ambiguous += 1;
1049 }
1050 pub fn record_depth_exceeded(&mut self) {
1052 self.depth_exceeded += 1;
1053 }
1054 pub fn total_queries(&self) -> u64 {
1056 self.successes + self.failures + self.ambiguous + self.depth_exceeded
1057 }
1058 pub fn success_rate(&self) -> f64 {
1060 let total = self.total_queries();
1061 if total == 0 {
1062 1.0
1063 } else {
1064 self.successes as f64 / total as f64
1065 }
1066 }
1067}
1068#[derive(Debug, Default)]
1073pub struct LocalInstanceScope {
1074 stack: Vec<Vec<InstanceDecl>>,
1075}
1076impl LocalInstanceScope {
1077 pub fn new() -> Self {
1079 Self::default()
1080 }
1081 pub fn push_layer(&mut self) {
1083 self.stack.push(Vec::new());
1084 }
1085 pub fn pop_layer(&mut self) -> Vec<InstanceDecl> {
1089 self.stack.pop().unwrap_or_default()
1090 }
1091 pub fn add_to_current(&mut self, inst: InstanceDecl) -> bool {
1095 if let Some(top) = self.stack.last_mut() {
1096 top.push(inst);
1097 true
1098 } else {
1099 false
1100 }
1101 }
1102 pub fn visible_instances(&self) -> Vec<&InstanceDecl> {
1104 self.stack.iter().flatten().collect()
1105 }
1106 pub fn depth(&self) -> usize {
1108 self.stack.len()
1109 }
1110 pub fn is_empty(&self) -> bool {
1112 self.stack.is_empty()
1113 }
1114}
1115#[derive(Default)]
1117pub struct InstanceSynthesizer {
1118 config: SynthConfig,
1119 graph: InstanceGraph,
1120}
1121impl InstanceSynthesizer {
1122 pub fn new() -> Self {
1124 Self::default()
1125 }
1126 pub fn with_config(config: SynthConfig) -> Self {
1128 Self {
1129 config,
1130 graph: InstanceGraph::new(),
1131 }
1132 }
1133 pub fn config(&self) -> &SynthConfig {
1135 &self.config
1136 }
1137 pub fn graph(&self) -> &InstanceGraph {
1139 &self.graph
1140 }
1141 pub fn add_dependency(&mut self, from: Name, to: Name) {
1143 self.graph.add_edge(from, to);
1144 }
1145 pub fn has_circular_deps(&self) -> bool {
1147 self.graph.has_cycle()
1148 }
1149}
1150#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1154pub struct CacheKey {
1155 pub class: Name,
1157 pub ty_repr: String,
1159}
1160impl CacheKey {
1161 pub fn new(class: &Name, ty: &Expr) -> Self {
1163 Self {
1164 class: class.clone(),
1165 ty_repr: format!("{:?}", ty),
1166 }
1167 }
1168}
1169#[derive(Clone, Debug)]
1171pub struct PriorityGroup {
1172 pub priority: u32,
1174 pub instances: Vec<InstanceDecl>,
1176}
1177impl PriorityGroup {
1178 pub fn new(priority: u32) -> Self {
1180 Self {
1181 priority,
1182 instances: Vec::new(),
1183 }
1184 }
1185 pub fn add(&mut self, inst: InstanceDecl) {
1187 self.instances.push(inst);
1188 }
1189 pub fn len(&self) -> usize {
1191 self.instances.len()
1192 }
1193 pub fn is_empty(&self) -> bool {
1195 self.instances.is_empty()
1196 }
1197 pub fn is_unambiguous(&self) -> bool {
1199 self.instances.len() == 1
1200 }
1201}
1202#[derive(Clone, Debug, Default)]
1205pub struct SearchPath {
1206 steps: Vec<(Name, Name)>,
1208}
1209impl SearchPath {
1210 pub fn new() -> Self {
1212 Self::default()
1213 }
1214 pub fn push(&mut self, class: Name, instance: Name) {
1216 self.steps.push((class, instance));
1217 }
1218 pub fn len(&self) -> usize {
1220 self.steps.len()
1221 }
1222 pub fn is_empty(&self) -> bool {
1224 self.steps.is_empty()
1225 }
1226 pub fn get(&self, i: usize) -> Option<&(Name, Name)> {
1228 self.steps.get(i)
1229 }
1230 pub fn has_class(&self, class: &Name) -> bool {
1232 self.steps.iter().any(|(c, _)| c == class)
1233 }
1234 pub fn clear(&mut self) {
1236 self.steps.clear();
1237 }
1238}