wootype 0.1.0

Type System as a Service - Rust-powered Go type checker for AI Agents
Documentation
//! Query Engine - High-performance type queries

use crate::core::{TypeUniverse, SharedUniverse, Type, TypeId, TypeKind, TypeFlags, Entity};
use crate::core::types::{TypeFingerprint, InterfaceMethod};

use dashmap::DashMap;
use rayon::prelude::*;
use std::sync::Arc;
use parking_lot::RwLock;

/// Query result with relevance scoring
#[derive(Debug, Clone)]
pub struct QueryResult<T> {
    pub item: T,
    pub score: f32,
    pub match_details: MatchDetails,
}

/// Match details for result ranking
#[derive(Debug, Clone, Default)]
pub struct MatchDetails {
    pub exact_match: bool,
    pub fingerprint_match: bool,
    pub struct_field_matches: Vec<(String, f32)>,
    pub method_matches: Vec<(String, f32)>,
}

/// Type query engine supporting various query patterns
pub struct QueryEngine {
    universe: SharedUniverse,
    // Query result cache
    cache: DashMap<QueryKey, Arc<Vec<QueryResult<TypeId>>>>,
    // Interface implementation cache
    impl_cache: DashMap<(TypeId, TypeId), bool>,
}

/// Cache key for query results
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct QueryKey {
    pattern: QueryPattern,
}

/// Query filter flags
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
pub struct QueryFilterFlags(u32);

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
enum QueryPattern {
    ById(TypeId),
    ByFingerprint(TypeFingerprint),
    Implements(TypeId), // Interface ID
    SimilarTo(TypeId),
    Named(String),
}

impl QueryEngine {
    pub fn new(universe: SharedUniverse) -> Self {
        Self {
            universe,
            cache: DashMap::new(),
            impl_cache: DashMap::new(),
        }
    }
    
    /// Get type by ID - O(1) operation
    pub fn get_type(&self, id: TypeId) -> Option<Arc<Type>> {
        self.universe.get_type(id)
    }
    
    /// Query types by exact fingerprint match
    pub fn query_by_fingerprint(&self, fingerprint: TypeFingerprint) -> Vec<QueryResult<TypeId>> {
        let candidates = self.universe.find_similar_types(fingerprint);
        
        candidates
            .into_iter()
            .filter_map(|id| {
                self.universe.get_type(id).map(|t| QueryResult {
                    item: id,
                    score: 1.0,
                    match_details: MatchDetails {
                        exact_match: t.fingerprint == fingerprint,
                        fingerprint_match: true,
                        ..Default::default()
                    },
                })
            })
            .collect()
    }
    
    /// Check if a type implements an interface
    pub fn implements_interface(&self, typ_id: TypeId, interface_id: TypeId) -> bool {
        // Check cache first
        let cache_key = (typ_id, interface_id);
        if let Some(result) = self.impl_cache.get(&cache_key) {
            return *result;
        }
        
        let result = self.check_interface_impl(typ_id, interface_id);
        self.impl_cache.insert(cache_key, result);
        result
    }
    
    fn check_interface_impl(&self, typ_id: TypeId, interface_id: TypeId) -> bool {
        let (type_kind, interface_kind) = match (
            self.universe.get_type(typ_id),
            self.universe.get_type(interface_id)
        ) {
            (Some(t), Some(i)) => (t.kind.clone(), i.kind.clone()),
            _ => return false,
        };
        
        match (&type_kind, &interface_kind) {
            // Empty interface - everything implements it
            (_, TypeKind::Interface { methods, .. }) if methods.is_empty() => true,
            
            // Interface implementing interface
            (TypeKind::Interface { methods: type_methods, .. }, 
             TypeKind::Interface { methods: iface_methods, .. }) => {
                self.check_method_satisfaction(type_methods, iface_methods)
            }
            
            // Concrete type implementing interface
            (_, TypeKind::Interface { methods, .. }) => {
                self.check_type_implements(typ_id, methods)
            }
            
            _ => false,
        }
    }
    
    fn check_method_satisfaction(
        &self,
        _type_methods: &[InterfaceMethod],
        _iface_methods: &[InterfaceMethod]
    ) -> bool {
        // TODO: Full method signature comparison
        // For now, simplified check
        true
    }
    
    fn check_type_implements(&self, _typ_id: TypeId, _methods: &[InterfaceMethod]) -> bool {
        // TODO: Look up methods on type and compare
        true
    }
    
    /// Find all types that implement a given interface
    pub fn find_implementors(&self, interface_id: TypeId) -> Vec<QueryResult<TypeId>> {
        // Parallel scan through all types
        // In production, this would use an inverted index
        
        // Placeholder: return empty for now
        Vec::new()
    }
    
    /// Find types similar to a reference type
    /// Uses SIMD-accelerated fingerprint comparison
    pub fn find_similar(&self, reference_id: TypeId, threshold: f32) -> Vec<QueryResult<TypeId>> {
        let reference = match self.universe.get_type(reference_id) {
            Some(t) => t,
            None => return Vec::new(),
        };
        
        let fingerprint = reference.fingerprint;
        let candidates = self.universe.find_similar_types(fingerprint);
        
        candidates
            .into_par_iter()
            .filter_map(|id| {
                if id == reference_id {
                    return None;
                }
                
                let typ = self.universe.get_type(id)?;
                let similarity = self.compute_similarity(&reference, &typ);
                
                if similarity >= threshold {
                    Some(QueryResult {
                        item: id,
                        score: similarity,
                        match_details: MatchDetails {
                            fingerprint_match: typ.fingerprint == fingerprint,
                            ..Default::default()
                        },
                    })
                } else {
                    None
                }
            })
            .collect()
    }
    
    /// Compute type similarity score (0.0 to 1.0)
    fn compute_similarity(&self, a: &Type, b: &Type) -> f32 {
        // Exact match
        if a.id == b.id {
            return 1.0;
        }
        
        // Fingerprint match - likely identical
        if a.fingerprint == b.fingerprint {
            return 0.95;
        }
        
        // Structural similarity based on kind
        match (&a.kind, &b.kind) {
            (TypeKind::Struct { fields: a_fields }, TypeKind::Struct { fields: b_fields }) => {
                self.struct_similarity(a_fields, b_fields)
            }
            (TypeKind::Func { params: a_params, results: a_results, .. },
             TypeKind::Func { params: b_params, results: b_results, .. }) => {
                self.func_similarity(a_params, a_results, b_params, b_results)
            }
            (TypeKind::Pointer { elem: a_elem }, TypeKind::Pointer { elem: b_elem }) |
            (TypeKind::Slice { elem: a_elem }, TypeKind::Slice { elem: b_elem }) |
            (TypeKind::Array { elem: a_elem, .. }, TypeKind::Array { elem: b_elem, .. }) => {
                // Compare element types
                match (self.universe.get_type(*a_elem), self.universe.get_type(*b_elem)) {
                    (Some(ae), Some(be)) => self.compute_similarity(&ae, &be) * 0.9,
                    _ => 0.0,
                }
            }
            _ => 0.0,
        }
    }
    
    fn struct_similarity(&self, a: &[crate::core::types::StructField], b: &[crate::core::types::StructField]) -> f32 {
        if a.is_empty() || b.is_empty() {
            return if a.len() == b.len() { 0.5 } else { 0.0 };
        }
        
        let mut matches = 0;
        let mut total_score = 0.0;
        
        for a_field in a {
            for b_field in b {
                if a_field.name == b_field.name {
                    matches += 1;
                    if let (Some(at), Some(bt)) = (
                        self.universe.get_type(a_field.typ),
                        self.universe.get_type(b_field.typ)
                    ) {
                        total_score += self.compute_similarity(&at, &bt);
                    }
                }
            }
        }
        
        let coverage = (matches as f32) / (a.len().max(b.len()) as f32);
        let avg_similarity = if matches > 0 { total_score / matches as f32 } else { 0.0 };
        
        coverage * 0.3 + avg_similarity * 0.7
    }
    
    fn func_similarity(
        &self,
        a_params: &[crate::core::types::FuncParam],
        a_results: &[crate::core::types::FuncParam],
        b_params: &[crate::core::types::FuncParam],
        b_results: &[crate::core::types::FuncParam]
    ) -> f32 {
        let params_match = self.params_similarity(a_params, b_params);
        let results_match = self.params_similarity(a_results, b_results);
        
        params_match * 0.6 + results_match * 0.4
    }
    
    fn params_similarity(
        &self,
        a: &[crate::core::types::FuncParam],
        b: &[crate::core::types::FuncParam]
    ) -> f32 {
        if a.len() != b.len() {
            return 0.0;
        }
        
        let mut total = 0.0;
        for (ap, bp) in a.iter().zip(b.iter()) {
            if let (Some(at), Some(bt)) = (
                self.universe.get_type(ap.typ),
                self.universe.get_type(bp.typ)
            ) {
                total += self.compute_similarity(&at, &bt);
            }
        }
        
        total / a.len() as f32
    }
    
    /// Semantic search using type constraints
    pub fn find_by_constraint(&self, constraint: TypeConstraint) -> Vec<QueryResult<TypeId>> {
        match constraint {
            TypeConstraint::Implements(interface_id) => {
                self.find_implementors(interface_id)
            }
            TypeConstraint::AssignableTo(target_id) => {
                self.find_assignable_to(target_id)
            }
            TypeConstraint::Comparable => {
                self.find_comparable_types()
            }
        }
    }
    
    fn find_assignable_to(&self, target_id: TypeId) -> Vec<QueryResult<TypeId>> {
        // Simplified: return types with matching fingerprint
        if let Some(target) = self.universe.get_type(target_id) {
            self.query_by_fingerprint(target.fingerprint)
        } else {
            Vec::new()
        }
    }
    
    fn find_comparable_types(&self) -> Vec<QueryResult<TypeId>> {
        // Filter by COMPARABLE flag
        Vec::new() // Placeholder
    }
    
    /// Clear caches
    pub fn clear_cache(&self) {
        self.cache.clear();
        self.impl_cache.clear();
    }
}

/// Type constraint for semantic queries
#[derive(Debug, Clone)]
pub enum TypeConstraint {
    Implements(TypeId),
    AssignableTo(TypeId),
    Comparable,
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::core::PrimitiveType;

    fn setup_universe() -> SharedUniverse {
        Arc::new(TypeUniverse::new())
    }

    #[test]
    fn test_get_type() {
        let universe = setup_universe();
        let engine = QueryEngine::new(universe);
        
        // Should find primitive type
        let int_type = engine.get_type(TypeId(1));
        assert!(int_type.is_some());
    }
    
    #[test]
    fn test_fingerprint_query() {
        let universe = setup_universe();
        let engine = QueryEngine::new(universe);
        
        let fingerprint = PrimitiveType::Int.fingerprint();
        let _results = engine.query_by_fingerprint(fingerprint);
        
        // Query may return empty in simplified implementation
        // Test passes if no panic occurs
    }
    
    #[test]
    fn test_query_engine_creation() {
        let universe = setup_universe();
        let engine = QueryEngine::new(universe);
        // Should not panic
        let _ = engine.universe.type_count();
    }
    
    #[test]
    fn test_cache_clear() {
        let universe = setup_universe();
        let engine = QueryEngine::new(universe);
        
        engine.clear_cache();
        // Should not panic
    }
    
    #[test]
    fn test_type_constraint_enum() {
        let universe = setup_universe();
        let engine = QueryEngine::new(universe);
        
        // Test that constraint enum works
        let _constraint = TypeConstraint::Comparable;
        let _constraint2 = TypeConstraint::AssignableTo(TypeId(1));
        
        // Query may not return results in simplified impl
        let _results = engine.find_by_constraint(TypeConstraint::Comparable);
    }
}