use std::{
collections::{HashMap, HashSet},
rc::Rc,
};
use super::{Environment, FunctionIndex, MethodIndex, TraitIndex};
use crate::{
ll::{codegen::TraitBuilder, error::LanguageErrorKind},
MethodParameterCount,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct ImplementedTraitIndex(u16);
impl ImplementedTraitIndex {
pub(crate) fn to_usize(self) -> usize {
usize::from(self.0)
}
}
#[derive(Debug, Default)]
pub(crate) struct Prototype {
pub(crate) instance: HashMap<MethodIndex, FunctionIndex>,
pub(crate) trait_instance:
HashMap<(Rc<str>, MethodParameterCount, ImplementedTraitIndex), FunctionIndex>,
pub(crate) statics: HashMap<MethodIndex, FunctionIndex>,
pub(crate) implemented_trait_count: u16,
}
impl Prototype {
pub(crate) fn implement_next_trait(
&mut self,
) -> Result<ImplementedTraitIndex, LanguageErrorKind> {
let trait_index = self.implemented_trait_count;
self.implemented_trait_count = self
.implemented_trait_count
.checked_add(1)
.ok_or(LanguageErrorKind::TooManyTraitsInImpl)?;
Ok(ImplementedTraitIndex(trait_index))
}
}
#[derive(Debug)]
pub struct TraitPrototype {
pub name: Rc<str>,
pub required: HashSet<MethodIndex>,
pub shims: Vec<(MethodIndex, FunctionIndex)>,
}
#[derive(Debug)]
pub struct BuiltinTraits {
pub iterator: TraitIndex,
pub iterator_has_next: MethodIndex,
pub iterator_next: MethodIndex,
}
impl BuiltinTraits {
fn try_register_in(env: &mut Environment) -> Result<Self, LanguageErrorKind> {
let mut builder = TraitBuilder::new(env, None, Rc::from("Iterator"))?;
let iterator_has_next = builder
.add_method(Rc::from("has_next"), MethodParameterCount::from_count_with_self(1))?;
let iterator_next =
builder.add_method(Rc::from("next"), MethodParameterCount::from_count_with_self(1))?;
let (iterator, _) = builder.build();
Ok(Self { iterator, iterator_has_next, iterator_next })
}
pub fn register_in(env: &mut Environment) -> Self {
Self::try_register_in(env)
.expect("environment should have enough space for built-in traits")
}
}