use super::{TLink, TLinkType, TLinkage, TermLinkTemplate};
use crate::{
entity::{BudgetValue, Item, ShortFloat, Token},
inference::Budget,
language::Term,
util::ToDisplayAndBrief,
};
use nar_dev_utils::join;
use serde::{Deserialize, Serialize};
use std::ops::{Deref, DerefMut};
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct TermLink {
inner: TLinkage<Term>,
token: Token,
}
impl TermLink {
fn new(
target: Term,
budget: BudgetValue,
link_type: TLinkType,
indexes: impl Into<Box<[usize]>>,
) -> Self {
let indexes = indexes.into();
let key = Self::generate_key_for_term_link(&target, link_type, &indexes);
let inner = TLinkage::new_direct(target, link_type, indexes);
Self {
token: Token::new(key, budget),
inner,
}
}
pub fn from_template(target: Term, template: &TermLinkTemplate, budget: BudgetValue) -> Self {
let link_type = Self::generate_type_from_template(&target, template);
let indexes = template.indexes().to_vec().into_boxed_slice();
Self::new(target, budget, link_type, indexes)
}
fn generate_key_for_term_link(
target: &Term,
link_type: TLinkType,
indexes: &[usize],
) -> String {
Self::generate_key_base(link_type, indexes) + &target.to_string()
}
fn generate_type_from_template(target: &Term, template: &TermLinkTemplate) -> TLinkType {
let template_type = template.link_type();
debug_assert!(
template_type.is_to_compound(),
"模板必定是「从元素链接到整体」"
);
match template.will_from_self_to() == target {
true => template_type.try_point_to_component(),
false => template_type,
}
}
}
impl Budget for TermLink {
fn priority(&self) -> ShortFloat {
self.token.priority()
}
fn __priority_mut(&mut self) -> &mut ShortFloat {
self.token.__priority_mut()
}
fn durability(&self) -> ShortFloat {
self.token.durability()
}
fn __durability_mut(&mut self) -> &mut ShortFloat {
self.token.__durability_mut()
}
fn quality(&self) -> ShortFloat {
self.token.quality()
}
fn __quality_mut(&mut self) -> &mut ShortFloat {
self.token.__quality_mut()
}
}
impl Item for TermLink {
fn key(&self) -> &String {
self.token.key()
}
}
impl TLink<Term> for TermLink {
fn target<'r, 's: 'r>(&'s self) -> impl Deref<Target = Term> + 'r {
self.inner.target()
}
fn target_mut<'r, 's: 'r>(&'s mut self) -> impl DerefMut<Target = Term> + 'r {
self.inner.target_mut()
}
fn link_type(&self) -> super::TLinkType {
self.inner.link_type()
}
fn indexes(&self) -> &[usize] {
self.inner.indexes()
}
}
impl ToDisplayAndBrief for TermLink {
fn to_display(&self) -> String {
join! {
=> self.token.budget_to_display()
=> " "
=> self.key()
}
}
fn to_display_brief(&self) -> String {
join! {
=> self.token.budget_to_display_brief()
=> " "
=> self.key()
}
}
}