use super::type_inference::{PerlType, ScalarType};
use perl_semantic_facts::Confidence;
use std::collections::BTreeMap;
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub struct TypeFact {
pub ty: PerlType,
pub confidence: Confidence,
pub evidence: Vec<TypeEvidence>,
pub dynamic_boundary: Option<DynamicBoundary>,
pub shape: Option<ShapeFact>,
}
impl TypeFact {
pub fn new(ty: PerlType, confidence: Confidence) -> Self {
Self { ty, confidence, evidence: Vec::new(), dynamic_boundary: None, shape: None }
}
pub fn from_type(ty: PerlType) -> Self {
Self::new(ty, Confidence::High)
}
pub fn unknown() -> Self {
Self::new(PerlType::Any, Confidence::Low)
}
pub fn dynamic(boundary: DynamicBoundary) -> Self {
Self {
ty: PerlType::Any,
confidence: Confidence::Low,
evidence: Vec::new(),
dynamic_boundary: Some(boundary),
shape: None,
}
}
pub fn any_low_confidence(reason: impl Into<String>) -> Self {
Self {
evidence: vec![TypeEvidence::Heuristic { reason: reason.into() }],
..Self::unknown()
}
}
pub fn unknown_hash() -> Self {
Self::new(
PerlType::Hash {
key: Box::new(PerlType::Scalar(ScalarType::String)),
value: Box::new(PerlType::Any),
},
Confidence::Low,
)
}
pub fn erased_type(&self) -> PerlType {
self.ty.clone()
}
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum ShapeFact {
Hash(HashShape),
Array(ArrayShape),
Object(ObjectShape),
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub struct HashShape {
pub slots: BTreeMap<String, TypeFact>,
pub fallback_value: Option<Box<TypeFact>>,
}
impl HashShape {
pub fn new(slots: BTreeMap<String, TypeFact>, fallback_value: Option<TypeFact>) -> Self {
Self { slots, fallback_value: fallback_value.map(Box::new) }
}
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub struct ArrayShape {
pub indexed: BTreeMap<usize, TypeFact>,
pub element: Option<Box<TypeFact>>,
}
impl ArrayShape {
pub fn new(indexed: BTreeMap<usize, TypeFact>, element: Option<TypeFact>) -> Self {
Self { indexed, element: element.map(Box::new) }
}
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub struct ObjectShape {
pub package: String,
pub fields: BTreeMap<String, TypeFact>,
}
impl ObjectShape {
pub fn new(package: String, fields: BTreeMap<String, TypeFact>) -> Self {
Self { package, fields }
}
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum TypeEvidence {
Literal,
VariableInitializer {
name: String,
},
Assignment {
name: String,
},
HashSlot {
hash: String,
key: String,
},
HashRefSlot {
base: String,
key: String,
},
ConstructorCall {
package: String,
},
BlessLiteral {
package: String,
},
AccessorReturn {
method: String,
field: String,
},
MethodReturn {
method: String,
package: String,
},
MooseIsa {
attr: String,
isa: String,
},
ObjectPadField {
field: String,
},
WorkspaceSymbol {
package: String,
},
Heuristic {
reason: String,
},
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum DynamicBoundary {
DynamicHashKey,
DynamicBlessClass,
DynamicMethodName,
RuntimeImport,
UnknownReceiver,
}