varpulis-core 0.11.0

Core types and AST for VPL
Documentation
//! Symbol table for tracking declarations during validation.

use std::collections::HashMap;

use crate::span::Span;

/// Information about a declared event type.
#[derive(Debug, Clone)]
pub struct EventInfo {
    /// Source span of the event declaration.
    pub span: Span,
    /// Names of declared fields.
    pub field_names: Vec<String>,
}

/// Information about a declared stream.
#[derive(Debug, Clone)]
pub struct StreamInfo {
    /// Source span of the stream declaration.
    pub span: Span,
}

/// Information about a declared function.
#[derive(Debug, Clone)]
pub struct FunctionInfo {
    /// Source span of the function declaration.
    pub span: Span,
    /// Number of declared parameters.
    pub param_count: usize,
}

/// Information about a declared connector.
#[derive(Debug, Clone)]
pub struct ConnectorInfo {
    /// Source span of the connector declaration.
    pub span: Span,
    /// Connector protocol type (e.g., `"mqtt"`, `"kafka"`).
    pub connector_type: String,
}

/// Information about a declared context.
#[derive(Debug, Clone)]
pub struct ContextInfo {
    /// Source span of the context declaration.
    pub span: Span,
}

/// Information about a declared pattern.
#[derive(Debug, Clone)]
pub struct PatternInfo {
    /// Source span of the pattern declaration.
    pub span: Span,
}

/// Information about a declared variable.
#[derive(Debug, Clone)]
pub struct VarInfo {
    /// Source span of the variable declaration.
    pub span: Span,
    /// Whether the variable is mutable.
    pub mutable: bool,
}

/// Information about a declared type (alias or struct).
#[derive(Debug, Clone)]
pub struct TypeInfo {
    /// Source span of the type declaration.
    pub span: Span,
    /// Struct fields: `(field_name, field_type)`. Empty for type aliases.
    pub fields: Vec<(String, crate::types::Type)>,
}

/// Symbol table built during Pass 1.
#[derive(Debug)]
pub struct SymbolTable {
    /// Declared event types.
    pub events: HashMap<String, EventInfo>,
    /// Declared streams.
    pub streams: HashMap<String, StreamInfo>,
    /// Declared functions.
    pub functions: HashMap<String, FunctionInfo>,
    /// Declared connectors.
    pub connectors: HashMap<String, ConnectorInfo>,
    /// Declared execution contexts.
    pub contexts: HashMap<String, ContextInfo>,
    /// Declared SASE+ patterns.
    pub patterns: HashMap<String, PatternInfo>,
    /// Declared variables.
    pub variables: HashMap<String, VarInfo>,
    /// Declared type aliases.
    pub types: HashMap<String, TypeInfo>,
}

impl Default for SymbolTable {
    fn default() -> Self {
        Self::new()
    }
}

impl SymbolTable {
    /// Creates an empty symbol table.
    pub fn new() -> Self {
        Self {
            events: HashMap::new(),
            streams: HashMap::new(),
            functions: HashMap::new(),
            connectors: HashMap::new(),
            contexts: HashMap::new(),
            patterns: HashMap::new(),
            variables: HashMap::new(),
            types: HashMap::new(),
        }
    }

    /// Check if any declaration table contains the given name.
    pub fn is_declared(&self, name: &str) -> bool {
        self.events.contains_key(name)
            || self.streams.contains_key(name)
            || self.functions.contains_key(name)
            || self.connectors.contains_key(name)
            || self.contexts.contains_key(name)
            || self.patterns.contains_key(name)
            || self.variables.contains_key(name)
            || self.types.contains_key(name)
    }

    /// Collect all declared names for "did you mean?" suggestions.
    pub fn all_names(&self) -> Vec<&str> {
        let mut names: Vec<&str> = Vec::new();
        for k in self.events.keys() {
            names.push(k);
        }
        for k in self.streams.keys() {
            names.push(k);
        }
        for k in self.functions.keys() {
            names.push(k);
        }
        for k in self.connectors.keys() {
            names.push(k);
        }
        for k in self.contexts.keys() {
            names.push(k);
        }
        for k in self.patterns.keys() {
            names.push(k);
        }
        for k in self.variables.keys() {
            names.push(k);
        }
        for k in self.types.keys() {
            names.push(k);
        }
        names
    }

    /// Collect connector names for suggestions.
    pub fn connector_names(&self) -> Vec<&str> {
        self.connectors.keys().map(|s| s.as_str()).collect()
    }

    /// Collect context names for suggestions.
    pub fn context_names(&self) -> Vec<&str> {
        self.contexts.keys().map(|s| s.as_str()).collect()
    }

    /// Collect event and stream names for source resolution suggestions.
    pub fn source_names(&self) -> Vec<&str> {
        let mut names: Vec<&str> = Vec::new();
        for k in self.events.keys() {
            names.push(k);
        }
        for k in self.streams.keys() {
            names.push(k);
        }
        names
    }

    /// Collect user-declared function names for suggestions.
    pub fn function_names(&self) -> Vec<&str> {
        self.functions.keys().map(|s| s.as_str()).collect()
    }

    /// Resolve field names for a given event type, returns None if not declared.
    pub fn event_field_names(&self, event_name: &str) -> Option<&[String]> {
        self.events
            .get(event_name)
            .map(|e| e.field_names.as_slice())
    }
}