Skip to main content

tensorlogic_adapters/
compiler_integration.rs

1//! Integration utilities for tensorlogic-compiler.
2//!
3//! This module provides utilities for exporting SymbolTable data to
4//! tensorlogic-compiler's CompilerContext and for bidirectional synchronization.
5
6use anyhow::Result;
7use std::collections::HashMap;
8
9use crate::{DomainHierarchy, DomainInfo, PredicateConstraints, PredicateInfo, SymbolTable};
10
11/// Export utilities for compiler integration.
12pub struct CompilerExport;
13
14impl CompilerExport {
15    /// Export domain information as a simple map for compiler consumption.
16    ///
17    /// This returns a HashMap that maps domain names to their cardinalities,
18    /// suitable for direct use in compiler contexts.
19    ///
20    /// # Example
21    ///
22    /// ```rust
23    /// use tensorlogic_adapters::{SymbolTable, DomainInfo, CompilerExport};
24    ///
25    /// let mut table = SymbolTable::new();
26    /// table.add_domain(DomainInfo::new("Person", 100)).expect("unwrap");
27    /// table.add_domain(DomainInfo::new("Location", 50)).expect("unwrap");
28    ///
29    /// let domain_map = CompilerExport::export_domains(&table);
30    /// assert_eq!(domain_map.get("Person"), Some(&100));
31    /// assert_eq!(domain_map.get("Location"), Some(&50));
32    /// ```
33    pub fn export_domains(table: &SymbolTable) -> HashMap<String, usize> {
34        table
35            .domains
36            .iter()
37            .map(|(name, info)| (name.clone(), info.cardinality))
38            .collect()
39    }
40
41    /// Export predicate signatures for type checking.
42    ///
43    /// Returns a HashMap mapping predicate names to their argument domain lists.
44    ///
45    /// # Example
46    ///
47    /// ```rust
48    /// use tensorlogic_adapters::{SymbolTable, DomainInfo, PredicateInfo, CompilerExport};
49    ///
50    /// let mut table = SymbolTable::new();
51    /// table.add_domain(DomainInfo::new("Person", 100)).expect("unwrap");
52    /// table.add_predicate(PredicateInfo::new(
53    ///     "knows",
54    ///     vec!["Person".to_string(), "Person".to_string()]
55    /// )).expect("unwrap");
56    ///
57    /// let signatures = CompilerExport::export_predicate_signatures(&table);
58    /// assert_eq!(signatures.get("knows"), Some(&vec!["Person".to_string(), "Person".to_string()]));
59    /// ```
60    pub fn export_predicate_signatures(table: &SymbolTable) -> HashMap<String, Vec<String>> {
61        table
62            .predicates
63            .iter()
64            .map(|(name, info)| (name.clone(), info.arg_domains.clone()))
65            .collect()
66    }
67
68    /// Export variable bindings for scope analysis.
69    ///
70    /// Returns a HashMap mapping variable names to their domain types.
71    ///
72    /// # Example
73    ///
74    /// ```rust
75    /// use tensorlogic_adapters::{SymbolTable, DomainInfo, CompilerExport};
76    ///
77    /// let mut table = SymbolTable::new();
78    /// table.add_domain(DomainInfo::new("Person", 100)).expect("unwrap");
79    /// table.bind_variable("x", "Person").expect("unwrap");
80    /// table.bind_variable("y", "Person").expect("unwrap");
81    ///
82    /// let bindings = CompilerExport::export_variable_bindings(&table);
83    /// assert_eq!(bindings.get("x"), Some(&"Person".to_string()));
84    /// assert_eq!(bindings.get("y"), Some(&"Person".to_string()));
85    /// ```
86    pub fn export_variable_bindings(table: &SymbolTable) -> HashMap<String, String> {
87        table
88            .variables
89            .iter()
90            .map(|(var, domain)| (var.clone(), domain.clone()))
91            .collect()
92    }
93
94    /// Create a complete export bundle for compiler initialization.
95    ///
96    /// Returns all three maps (domains, signatures, bindings) in a single structure.
97    pub fn export_all(table: &SymbolTable) -> CompilerExportBundle {
98        CompilerExportBundle {
99            domains: Self::export_domains(table),
100            predicate_signatures: Self::export_predicate_signatures(table),
101            variable_bindings: Self::export_variable_bindings(table),
102        }
103    }
104}
105
106/// Complete export bundle for compiler integration.
107///
108/// This structure contains all information needed to initialize a compiler context
109/// from a symbol table.
110#[derive(Clone, Debug)]
111pub struct CompilerExportBundle {
112    /// Domain names mapped to cardinalities.
113    pub domains: HashMap<String, usize>,
114    /// Predicate names mapped to argument domain lists.
115    pub predicate_signatures: HashMap<String, Vec<String>>,
116    /// Variable names mapped to domain types.
117    pub variable_bindings: HashMap<String, String>,
118}
119
120impl CompilerExportBundle {
121    /// Create an empty export bundle.
122    pub fn new() -> Self {
123        Self {
124            domains: HashMap::new(),
125            predicate_signatures: HashMap::new(),
126            variable_bindings: HashMap::new(),
127        }
128    }
129
130    /// Check if the bundle is empty.
131    pub fn is_empty(&self) -> bool {
132        self.domains.is_empty()
133            && self.predicate_signatures.is_empty()
134            && self.variable_bindings.is_empty()
135    }
136}
137
138impl Default for CompilerExportBundle {
139    fn default() -> Self {
140        Self::new()
141    }
142}
143
144/// Import utilities for reverse synchronization.
145pub struct CompilerImport;
146
147impl CompilerImport {
148    /// Import domain information from a compiler context back into a symbol table.
149    ///
150    /// This is useful for synchronizing state after compilation.
151    ///
152    /// # Example
153    ///
154    /// ```rust
155    /// use tensorlogic_adapters::{SymbolTable, CompilerImport};
156    /// use std::collections::HashMap;
157    ///
158    /// let mut domains = HashMap::new();
159    /// domains.insert("Person".to_string(), 100);
160    /// domains.insert("Location".to_string(), 50);
161    ///
162    /// let mut table = SymbolTable::new();
163    /// CompilerImport::import_domains(&mut table, &domains).expect("unwrap");
164    ///
165    /// assert!(table.get_domain("Person").is_some());
166    /// assert!(table.get_domain("Location").is_some());
167    /// ```
168    pub fn import_domains(table: &mut SymbolTable, domains: &HashMap<String, usize>) -> Result<()> {
169        for (name, cardinality) in domains {
170            table.add_domain(DomainInfo::new(name.clone(), *cardinality))?;
171        }
172        Ok(())
173    }
174
175    /// Import predicate signatures from a compiler context.
176    ///
177    /// # Example
178    ///
179    /// ```rust
180    /// use tensorlogic_adapters::{SymbolTable, DomainInfo, CompilerImport};
181    /// use std::collections::HashMap;
182    ///
183    /// let mut table = SymbolTable::new();
184    /// table.add_domain(DomainInfo::new("Person", 100)).expect("unwrap");
185    ///
186    /// let mut signatures = HashMap::new();
187    /// signatures.insert("knows".to_string(), vec!["Person".to_string(), "Person".to_string()]);
188    ///
189    /// CompilerImport::import_predicates(&mut table, &signatures).expect("unwrap");
190    ///
191    /// assert!(table.get_predicate("knows").is_some());
192    /// ```
193    pub fn import_predicates(
194        table: &mut SymbolTable,
195        signatures: &HashMap<String, Vec<String>>,
196    ) -> Result<()> {
197        for (name, arg_domains) in signatures {
198            table.add_predicate(PredicateInfo::new(name.clone(), arg_domains.clone()))?;
199        }
200        Ok(())
201    }
202
203    /// Import variable bindings from a compiler context.
204    ///
205    /// # Example
206    ///
207    /// ```rust
208    /// use tensorlogic_adapters::{SymbolTable, DomainInfo, CompilerImport};
209    /// use std::collections::HashMap;
210    ///
211    /// let mut table = SymbolTable::new();
212    /// table.add_domain(DomainInfo::new("Person", 100)).expect("unwrap");
213    ///
214    /// let mut bindings = HashMap::new();
215    /// bindings.insert("x".to_string(), "Person".to_string());
216    /// bindings.insert("y".to_string(), "Person".to_string());
217    ///
218    /// CompilerImport::import_variables(&mut table, &bindings).expect("unwrap");
219    ///
220    /// assert_eq!(table.get_variable_domain("x"), Some("Person"));
221    /// assert_eq!(table.get_variable_domain("y"), Some("Person"));
222    /// ```
223    pub fn import_variables(
224        table: &mut SymbolTable,
225        bindings: &HashMap<String, String>,
226    ) -> Result<()> {
227        for (var, domain) in bindings {
228            table.bind_variable(var, domain)?;
229        }
230        Ok(())
231    }
232
233    /// Import a complete bundle into a symbol table.
234    pub fn import_all(table: &mut SymbolTable, bundle: &CompilerExportBundle) -> Result<()> {
235        Self::import_domains(table, &bundle.domains)?;
236        Self::import_predicates(table, &bundle.predicate_signatures)?;
237        Self::import_variables(table, &bundle.variable_bindings)?;
238        Ok(())
239    }
240}
241
242/// Bidirectional synchronization utilities.
243pub struct SymbolTableSync;
244
245impl SymbolTableSync {
246    /// Synchronize a symbol table with compiler data, merging information.
247    ///
248    /// This performs a two-way sync:
249    /// 1. Exports current symbol table state
250    /// 2. Imports compiler context data
251    /// 3. Returns the merged export bundle
252    pub fn sync_with_compiler(
253        table: &mut SymbolTable,
254        compiler_bundle: &CompilerExportBundle,
255    ) -> Result<CompilerExportBundle> {
256        // First, import compiler data into the table
257        CompilerImport::import_all(table, compiler_bundle)?;
258
259        // Then, export the merged state
260        Ok(CompilerExport::export_all(table))
261    }
262
263    /// Validate that a compiler bundle is compatible with a symbol table.
264    ///
265    /// Checks that all referenced domains exist.
266    pub fn validate_bundle(
267        table: &SymbolTable,
268        bundle: &CompilerExportBundle,
269    ) -> Result<ValidationResult> {
270        let mut errors = Vec::new();
271        let mut warnings = Vec::new();
272
273        // Check predicate signatures reference existing domains
274        for (pred_name, arg_domains) in &bundle.predicate_signatures {
275            for domain in arg_domains {
276                if !table.domains.contains_key(domain) && !bundle.domains.contains_key(domain) {
277                    errors.push(format!(
278                        "Predicate '{}' references unknown domain '{}'",
279                        pred_name, domain
280                    ));
281                }
282            }
283        }
284
285        // Check variable bindings reference existing domains
286        for (var_name, domain) in &bundle.variable_bindings {
287            if !table.domains.contains_key(domain) && !bundle.domains.contains_key(domain) {
288                errors.push(format!(
289                    "Variable '{}' references unknown domain '{}'",
290                    var_name, domain
291                ));
292            }
293        }
294
295        // Warn about unused domains
296        for domain_name in bundle.domains.keys() {
297            let used_in_predicates = bundle
298                .predicate_signatures
299                .values()
300                .any(|args| args.contains(domain_name));
301            let used_in_variables = bundle.variable_bindings.values().any(|d| d == domain_name);
302
303            if !used_in_predicates && !used_in_variables {
304                warnings.push(format!(
305                    "Domain '{}' is defined but never used",
306                    domain_name
307                ));
308            }
309        }
310
311        Ok(ValidationResult { errors, warnings })
312    }
313}
314
315/// Result of bundle validation.
316#[derive(Clone, Debug)]
317pub struct ValidationResult {
318    /// Validation errors (must be empty for valid bundles).
319    pub errors: Vec<String>,
320    /// Validation warnings (non-critical issues).
321    pub warnings: Vec<String>,
322}
323
324impl ValidationResult {
325    /// Check if validation passed (no errors).
326    pub fn is_valid(&self) -> bool {
327        self.errors.is_empty()
328    }
329}
330
331#[cfg(test)]
332mod tests {
333    use super::*;
334
335    #[test]
336    fn test_export_domains() {
337        let mut table = SymbolTable::new();
338        table
339            .add_domain(DomainInfo::new("Person", 100))
340            .expect("unwrap");
341        table
342            .add_domain(DomainInfo::new("Location", 50))
343            .expect("unwrap");
344
345        let domains = CompilerExport::export_domains(&table);
346        assert_eq!(domains.get("Person"), Some(&100));
347        assert_eq!(domains.get("Location"), Some(&50));
348    }
349
350    #[test]
351    fn test_export_predicate_signatures() {
352        let mut table = SymbolTable::new();
353        table
354            .add_domain(DomainInfo::new("Person", 100))
355            .expect("unwrap");
356        table
357            .add_predicate(PredicateInfo::new(
358                "knows",
359                vec!["Person".to_string(), "Person".to_string()],
360            ))
361            .expect("unwrap");
362
363        let signatures = CompilerExport::export_predicate_signatures(&table);
364        assert_eq!(
365            signatures.get("knows"),
366            Some(&vec!["Person".to_string(), "Person".to_string()])
367        );
368    }
369
370    #[test]
371    fn test_export_all() {
372        let mut table = SymbolTable::new();
373        table
374            .add_domain(DomainInfo::new("Person", 100))
375            .expect("unwrap");
376        table
377            .add_predicate(PredicateInfo::new("knows", vec!["Person".to_string()]))
378            .expect("unwrap");
379        table.bind_variable("x", "Person").expect("unwrap");
380
381        let bundle = CompilerExport::export_all(&table);
382        assert_eq!(bundle.domains.len(), 1);
383        assert_eq!(bundle.predicate_signatures.len(), 1);
384        assert_eq!(bundle.variable_bindings.len(), 1);
385    }
386
387    #[test]
388    fn test_import_domains() {
389        let mut domains = HashMap::new();
390        domains.insert("Person".to_string(), 100);
391
392        let mut table = SymbolTable::new();
393        CompilerImport::import_domains(&mut table, &domains).expect("unwrap");
394
395        assert!(table.get_domain("Person").is_some());
396    }
397
398    #[test]
399    fn test_import_predicates() {
400        let mut table = SymbolTable::new();
401        table
402            .add_domain(DomainInfo::new("Person", 100))
403            .expect("unwrap");
404
405        let mut signatures = HashMap::new();
406        signatures.insert("knows".to_string(), vec!["Person".to_string()]);
407
408        CompilerImport::import_predicates(&mut table, &signatures).expect("unwrap");
409        assert!(table.get_predicate("knows").is_some());
410    }
411
412    #[test]
413    fn test_validation_invalid_domain_reference() {
414        let table = SymbolTable::new();
415        let mut bundle = CompilerExportBundle::new();
416        bundle
417            .predicate_signatures
418            .insert("knows".to_string(), vec!["UnknownDomain".to_string()]);
419
420        let result = SymbolTableSync::validate_bundle(&table, &bundle).expect("unwrap");
421        assert!(!result.is_valid());
422        assert!(!result.errors.is_empty());
423    }
424
425    #[test]
426    fn test_validation_unused_domain_warning() {
427        let table = SymbolTable::new();
428        let mut bundle = CompilerExportBundle::new();
429        bundle.domains.insert("UnusedDomain".to_string(), 100);
430
431        let result = SymbolTableSync::validate_bundle(&table, &bundle).expect("unwrap");
432        assert!(result.is_valid()); // Still valid, just has warnings
433        assert!(!result.warnings.is_empty());
434    }
435
436    #[test]
437    fn test_sync_with_compiler() {
438        let mut table = SymbolTable::new();
439        table
440            .add_domain(DomainInfo::new("Person", 100))
441            .expect("unwrap");
442
443        let mut bundle = CompilerExportBundle::new();
444        bundle.domains.insert("Location".to_string(), 50);
445
446        let result = SymbolTableSync::sync_with_compiler(&mut table, &bundle).expect("unwrap");
447
448        // Table should now have both domains
449        assert!(table.get_domain("Person").is_some());
450        assert!(table.get_domain("Location").is_some());
451
452        // Result should include both
453        assert_eq!(result.domains.len(), 2);
454    }
455}
456
457/// Advanced export utilities for compiler integration with type systems.
458///
459/// This extends the basic CompilerExport with support for advanced type system
460/// features including refinement types, dependent types, linear types, and effects.
461pub struct CompilerExportAdvanced;
462
463impl CompilerExportAdvanced {
464    /// Export domain hierarchy information for subtype checking.
465    ///
466    /// Returns the complete subtype relationships from the hierarchy.
467    ///
468    /// # Example
469    ///
470    /// ```rust
471    /// use tensorlogic_adapters::{DomainHierarchy, CompilerExportAdvanced};
472    ///
473    /// let mut hierarchy = DomainHierarchy::new();
474    /// hierarchy.add_subtype("Student", "Person");
475    /// hierarchy.add_subtype("Person", "Agent");
476    ///
477    /// let relationships = CompilerExportAdvanced::export_hierarchy(&hierarchy);
478    /// assert!(relationships.contains_key("Student"));
479    /// ```
480    pub fn export_hierarchy(hierarchy: &DomainHierarchy) -> HashMap<String, Vec<String>> {
481        let mut result = HashMap::new();
482
483        for domain in hierarchy.all_domains() {
484            // Get all ancestors (transitive closure of parent relationships)
485            let ancestors = hierarchy.get_ancestors(&domain);
486            if !ancestors.is_empty() {
487                result.insert(domain, ancestors);
488            }
489        }
490
491        result
492    }
493
494    /// Export predicate constraints for validation and optimization.
495    ///
496    /// Returns a map of predicate names to their constraint specifications.
497    ///
498    /// # Example
499    ///
500    /// ```rust
501    /// use tensorlogic_adapters::{SymbolTable, DomainInfo, PredicateInfo, PredicateConstraints, CompilerExportAdvanced};
502    ///
503    /// let mut table = SymbolTable::new();
504    /// table.add_domain(DomainInfo::new("Person", 100)).expect("unwrap");
505    ///
506    /// let mut pred = PredicateInfo::new("age", vec!["Person".to_string()]);
507    /// pred.constraints = Some(PredicateConstraints::new());
508    /// table.add_predicate(pred).expect("unwrap");
509    ///
510    /// let constraints = CompilerExportAdvanced::export_constraints(&table);
511    /// assert!(constraints.contains_key("age"));
512    /// ```
513    pub fn export_constraints(table: &SymbolTable) -> HashMap<String, PredicateConstraints> {
514        table
515            .predicates
516            .iter()
517            .filter_map(|(name, info)| info.constraints.as_ref().map(|c| (name.clone(), c.clone())))
518            .collect()
519    }
520
521    /// Export refinement types for compile-time validation.
522    ///
523    /// Returns refinement type specifications that can be used for
524    /// static analysis and runtime validation.
525    pub fn export_refinement_types() -> HashMap<String, String> {
526        // Export built-in refinement types
527        // In a real implementation, this would be populated from a RefinementRegistry
528        let mut types = HashMap::new();
529        types.insert("PositiveInt".to_string(), "{ x: Int | x > 0 }".to_string());
530        types.insert(
531            "Probability".to_string(),
532            "{ x: Float | 0.0 <= x <= 1.0 }".to_string(),
533        );
534        types.insert(
535            "NonZeroFloat".to_string(),
536            "{ x: Float | x != 0.0 }".to_string(),
537        );
538        types
539    }
540
541    /// Export dependent type information for dimension tracking.
542    ///
543    /// Returns dependent type specifications for compile-time dimension checking.
544    pub fn export_dependent_types() -> HashMap<String, String> {
545        // Export common dependent type patterns
546        let mut types = HashMap::new();
547        types.insert("Vector".to_string(), "Vector<T, n>".to_string());
548        types.insert("Matrix".to_string(), "Matrix<T, m, n>".to_string());
549        types.insert("Tensor3D".to_string(), "Tensor<T, i, j, k>".to_string());
550        types.insert("SquareMatrix".to_string(), "Matrix<T, n, n>".to_string());
551        types
552    }
553
554    /// Export linear type resources for lifetime tracking.
555    ///
556    /// Returns linear type specifications for resource management.
557    pub fn export_linear_types() -> HashMap<String, String> {
558        // Export linear type specifications
559        let mut types = HashMap::new();
560        types.insert("GpuTensor".to_string(), "Linear".to_string());
561        types.insert("FileHandle".to_string(), "Linear".to_string());
562        types.insert("NetworkSocket".to_string(), "Linear".to_string());
563        types.insert("MutableReference".to_string(), "Affine".to_string());
564        types.insert("LogMessage".to_string(), "Relevant".to_string());
565        types
566    }
567
568    /// Export effect information for effect tracking.
569    ///
570    /// Returns effect specifications for compile-time effect checking.
571    pub fn export_effects() -> HashMap<String, Vec<String>> {
572        // Export common effect patterns
573        let mut effects = HashMap::new();
574        effects.insert("read_file".to_string(), vec!["IO".to_string()]);
575        effects.insert(
576            "allocate_gpu".to_string(),
577            vec!["GPU".to_string(), "State".to_string()],
578        );
579        effects.insert(
580            "train_model".to_string(),
581            vec!["State".to_string(), "NonDet".to_string()],
582        );
583        effects.insert(
584            "fetch_data".to_string(),
585            vec!["IO".to_string(), "Exception".to_string()],
586        );
587        effects
588    }
589
590    /// Create a complete advanced export bundle.
591    ///
592    /// Returns all advanced type system information in a single structure.
593    pub fn export_all_advanced(
594        table: &SymbolTable,
595        hierarchy: Option<&DomainHierarchy>,
596    ) -> AdvancedExportBundle {
597        AdvancedExportBundle {
598            hierarchy: hierarchy.map(Self::export_hierarchy),
599            constraints: Self::export_constraints(table),
600            refinement_types: Self::export_refinement_types(),
601            dependent_types: Self::export_dependent_types(),
602            linear_types: Self::export_linear_types(),
603            effects: Self::export_effects(),
604        }
605    }
606}
607
608/// Advanced export bundle containing type system information.
609#[derive(Clone, Debug)]
610pub struct AdvancedExportBundle {
611    /// Domain hierarchy (subtype relationships).
612    pub hierarchy: Option<HashMap<String, Vec<String>>>,
613    /// Predicate constraints.
614    pub constraints: HashMap<String, PredicateConstraints>,
615    /// Refinement type specifications.
616    pub refinement_types: HashMap<String, String>,
617    /// Dependent type specifications.
618    pub dependent_types: HashMap<String, String>,
619    /// Linear type specifications.
620    pub linear_types: HashMap<String, String>,
621    /// Effect specifications.
622    pub effects: HashMap<String, Vec<String>>,
623}
624
625impl AdvancedExportBundle {
626    /// Create an empty advanced export bundle.
627    pub fn new() -> Self {
628        Self {
629            hierarchy: None,
630            constraints: HashMap::new(),
631            refinement_types: HashMap::new(),
632            dependent_types: HashMap::new(),
633            linear_types: HashMap::new(),
634            effects: HashMap::new(),
635        }
636    }
637
638    /// Check if the bundle is empty.
639    pub fn is_empty(&self) -> bool {
640        self.hierarchy.is_none()
641            && self.constraints.is_empty()
642            && self.refinement_types.is_empty()
643            && self.dependent_types.is_empty()
644            && self.linear_types.is_empty()
645            && self.effects.is_empty()
646    }
647}
648
649impl Default for AdvancedExportBundle {
650    fn default() -> Self {
651        Self::new()
652    }
653}
654
655/// Complete compiler integration bundle combining basic and advanced exports.
656#[derive(Clone, Debug)]
657pub struct CompleteExportBundle {
658    /// Basic export bundle (domains, predicates, variables).
659    pub basic: CompilerExportBundle,
660    /// Advanced type system export bundle.
661    pub advanced: AdvancedExportBundle,
662}
663
664impl CompleteExportBundle {
665    /// Create a new complete export bundle.
666    pub fn new(basic: CompilerExportBundle, advanced: AdvancedExportBundle) -> Self {
667        Self { basic, advanced }
668    }
669
670    /// Export everything from a symbol table and hierarchy.
671    pub fn from_symbol_table(table: &SymbolTable, hierarchy: Option<&DomainHierarchy>) -> Self {
672        Self {
673            basic: CompilerExport::export_all(table),
674            advanced: CompilerExportAdvanced::export_all_advanced(table, hierarchy),
675        }
676    }
677
678    /// Check if the bundle is completely empty.
679    pub fn is_empty(&self) -> bool {
680        self.basic.is_empty() && self.advanced.is_empty()
681    }
682}
683
684#[cfg(test)]
685mod advanced_tests {
686    use super::*;
687
688    #[test]
689    fn test_export_hierarchy() {
690        let mut hierarchy = DomainHierarchy::new();
691        hierarchy.add_subtype("Student", "Person");
692        hierarchy.add_subtype("Person", "Agent");
693
694        let relationships = CompilerExportAdvanced::export_hierarchy(&hierarchy);
695
696        assert!(relationships.contains_key("Student"));
697        assert!(relationships.contains_key("Person"));
698    }
699
700    #[test]
701    fn test_export_constraints() {
702        let mut table = SymbolTable::new();
703        table
704            .add_domain(DomainInfo::new("Person", 100))
705            .expect("unwrap");
706
707        let mut pred = PredicateInfo::new("age", vec!["Person".to_string()]);
708        pred.constraints = Some(PredicateConstraints::new());
709        table.add_predicate(pred).expect("unwrap");
710
711        let constraints = CompilerExportAdvanced::export_constraints(&table);
712        assert!(constraints.contains_key("age"));
713    }
714
715    #[test]
716    fn test_export_refinement_types() {
717        let types = CompilerExportAdvanced::export_refinement_types();
718        assert!(types.contains_key("PositiveInt"));
719        assert!(types.contains_key("Probability"));
720    }
721
722    #[test]
723    fn test_export_dependent_types() {
724        let types = CompilerExportAdvanced::export_dependent_types();
725        assert!(types.contains_key("Vector"));
726        assert!(types.contains_key("Matrix"));
727    }
728
729    #[test]
730    fn test_export_linear_types() {
731        let types = CompilerExportAdvanced::export_linear_types();
732        assert!(types.contains_key("GpuTensor"));
733        assert!(types.contains_key("FileHandle"));
734    }
735
736    #[test]
737    fn test_export_effects() {
738        let effects = CompilerExportAdvanced::export_effects();
739        assert!(effects.contains_key("read_file"));
740        assert!(effects.contains_key("allocate_gpu"));
741    }
742
743    #[test]
744    fn test_export_all_advanced() {
745        let mut table = SymbolTable::new();
746        table
747            .add_domain(DomainInfo::new("Person", 100))
748            .expect("unwrap");
749
750        let mut hierarchy = DomainHierarchy::new();
751        hierarchy.add_subtype("Student", "Person");
752
753        let bundle = CompilerExportAdvanced::export_all_advanced(&table, Some(&hierarchy));
754
755        assert!(bundle.hierarchy.is_some());
756        assert!(!bundle.refinement_types.is_empty());
757        assert!(!bundle.dependent_types.is_empty());
758    }
759
760    #[test]
761    fn test_complete_export_bundle() {
762        let mut table = SymbolTable::new();
763        table
764            .add_domain(DomainInfo::new("Person", 100))
765            .expect("unwrap");
766
767        let mut hierarchy = DomainHierarchy::new();
768        hierarchy.add_subtype("Student", "Person");
769
770        let bundle = CompleteExportBundle::from_symbol_table(&table, Some(&hierarchy));
771
772        assert!(!bundle.is_empty());
773        assert_eq!(bundle.basic.domains.len(), 1);
774        assert!(bundle.advanced.hierarchy.is_some());
775    }
776
777    #[test]
778    fn test_advanced_bundle_empty() {
779        let bundle = AdvancedExportBundle::new();
780        assert!(bundle.is_empty());
781    }
782}