use super::{Accessor, Method, MethodBody, Name, Param, Type, value_param};
use crate::source::token::Span;
use crate::system::INDEXER;
use crate::words::{get, set};
const ACCESSOR_SEP: char = '_';
#[derive(Debug, Clone, PartialEq)]
pub struct Indexer {
pub ty: Type,
pub params: Vec<Param>,
pub accessors: Vec<Accessor>,
pub span: Span,
}
pub fn accessor_name(word: &str) -> String {
format!("{word}{ACCESSOR_SEP}{INDEXER}")
}
impl Indexer {
pub fn getter(&self) -> Option<Method> {
let body = self.accessor(get::WORD.text)?;
Some(self.method(
get::WORD.text,
Some(self.ty.clone()),
self.params.clone(),
body,
))
}
pub fn setter(&self) -> Option<Method> {
let body = self.accessor(set::WORD.text)?;
let mut params = self.params.clone();
let at = Name {
text: set::WORD.text.to_string(),
span: self.span,
};
params.push(value_param(&self.ty, &at));
Some(self.method(set::WORD.text, None, params, body))
}
fn accessor(&self, word: &str) -> Option<Option<MethodBody>> {
self.accessors
.iter()
.find(|a| a.name.text == word)
.map(|a| a.body.clone())
}
fn method(
&self,
word: &str,
ret: Option<Type>,
params: Vec<Param>,
body: Option<MethodBody>,
) -> Method {
Method {
ret,
name: Name {
text: accessor_name(word),
span: self.span,
},
generics: Vec::new(),
params,
constraints: Vec::new(),
requires: None,
body,
}
}
}