use std::collections::BTreeMap;
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct LocalSlot(u32);
impl LocalSlot {
#[must_use]
pub const fn new(index: u32) -> Self {
Self(index)
}
#[must_use]
pub const fn index(self) -> u32 {
self.0
}
}
#[derive(Clone, Debug, Default)]
pub struct ParagraphNormalizer {
slots: BTreeMap<String, LocalSlot>,
next_slot: u32,
}
impl ParagraphNormalizer {
#[must_use]
pub const fn new() -> Self {
Self {
slots: BTreeMap::new(),
next_slot: 0,
}
}
#[must_use]
pub fn local_slot(&mut self, local_name: impl Into<String>) -> LocalSlot {
let local_name = local_name.into();
if let Some(slot) = self.slots.get(&local_name) {
return *slot;
}
let slot = LocalSlot::new(self.next_slot);
self.next_slot += 1;
self.slots.insert(local_name, slot);
slot
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum CalleeShape {
DefPath(String),
Unknown,
}
impl CalleeShape {
#[must_use]
pub fn def_path(def_path: impl Into<String>) -> Self {
Self::DefPath(def_path.into())
}
#[must_use]
pub const fn unknown() -> Self {
Self::Unknown
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum ExprShape {
Call { callee: CalleeShape, argc: usize },
MethodCall { method: String, argc: usize },
Path,
Lit,
Other,
}
impl ExprShape {
#[must_use]
pub const fn call(callee: CalleeShape, argc: usize) -> Self {
Self::Call { callee, argc }
}
#[must_use]
pub fn method_call(method: impl Into<String>, argc: usize) -> Self {
Self::MethodCall {
method: method.into(),
argc,
}
}
#[must_use]
pub const fn path() -> Self {
Self::Path
}
#[must_use]
pub const fn lit() -> Self {
Self::Lit
}
#[must_use]
pub const fn other() -> Self {
Self::Other
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum StmtShape {
Let { init: ExprShape },
MutCall {
receiver: Option<LocalSlot>,
callee: CalleeShape,
},
}
impl StmtShape {
#[must_use]
pub const fn let_binding(init: ExprShape) -> Self {
Self::Let { init }
}
#[must_use]
pub const fn mutable_call(receiver: Option<LocalSlot>, callee: CalleeShape) -> Self {
Self::MutCall { receiver, callee }
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
pub struct ParagraphFingerprint {
shapes: Vec<StmtShape>,
}
impl ParagraphFingerprint {
#[must_use]
pub fn new<I>(shapes: I) -> Self
where
I: IntoIterator<Item = StmtShape>,
{
Self {
shapes: shapes.into_iter().collect(),
}
}
#[must_use]
pub fn shapes(&self) -> &[StmtShape] {
&self.shapes
}
#[must_use]
pub fn into_shapes(self) -> Vec<StmtShape> {
self.shapes
}
}