use std::{fmt, rc::Rc};
use crate::{
ll::{
bytecode::{Environment, TraitIndex},
codegen,
gc::{Gc, Memory},
value::create_trait,
},
Error, Hidden, LanguageErrorKind, MethodId, MethodParameterCount, Value,
};
pub struct TraitBuilder<'e> {
pub(crate) inner: codegen::TraitBuilder<'e>,
pub(crate) gc: &'e mut Memory,
}
impl<'e> TraitBuilder<'e> {
pub fn add_function(&mut self, name: &str, arity: u8) -> Result<MethodId, Error> {
let arity = MethodParameterCount::from_count_without_self(arity)
.map_err(|_| Error::TooManyParametersInTraitMethod)?;
self.inner.add_method(Rc::from(name), arity).map(MethodId).map_err(|e| match e {
LanguageErrorKind::TooManyTraits => Error::TooManyTraits,
LanguageErrorKind::TooManyFunctions => Error::TooManyFunctions,
LanguageErrorKind::TooManyMethods => Error::TooManyMethods,
LanguageErrorKind::TooManyParameters => Error::TooManyParametersInTraitMethod,
_ => unreachable!(),
})
}
pub fn build(self) -> Value {
let (trait_id, env) = self.inner.build();
create_trait_value(env, self.gc, trait_id)
}
}
impl<'e> fmt::Debug for TraitBuilder<'e> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("TraitBuilder").finish_non_exhaustive()
}
}
pub(crate) fn create_trait_value(
env: &mut Environment,
gc: &mut Memory,
trait_id: TraitIndex,
) -> Value {
let instance = create_trait(env, gc, trait_id);
let instance = unsafe { Gc::from_raw(instance) };
Value::Trait(Hidden(instance))
}