use sim_kernel::{
Claim, ClaimKind, ClaimPattern, Cx, LibId, Ref, Result, Symbol, card::card_requires_predicate,
};
use crate::{FidelityBadge, LanguageProfile};
pub fn standard_reader_predicate() -> Symbol {
standard_symbol("reader")
}
pub fn standard_lowering_predicate() -> Symbol {
standard_symbol("lowering")
}
pub fn standard_eval_policy_predicate() -> Symbol {
standard_symbol("eval-policy")
}
pub fn standard_numeric_predicate() -> Symbol {
standard_symbol("numeric")
}
pub fn standard_capability_predicate() -> Symbol {
standard_symbol("capability")
}
pub fn standard_unsupported_predicate() -> Symbol {
standard_symbol("unsupported")
}
pub fn publish_profile_claims(cx: &mut Cx, profile: &LanguageProfile) -> Result<()> {
publish_profile_claims_with_owner(cx, None, profile)
}
pub fn publish_profile_claims_for_lib(
cx: &mut Cx,
lib_id: LibId,
profile: &LanguageProfile,
) -> Result<()> {
publish_profile_claims_with_owner(cx, Some(lib_id), profile)
}
fn publish_profile_claims_with_owner(
cx: &mut Cx,
owner: Option<LibId>,
profile: &LanguageProfile,
) -> Result<()> {
match owner {
Some(lib_id) => sim_kernel::standard::publish_profile_claims_for_lib(
cx,
lib_id,
profile.symbol.clone(),
profile.organs.iter().map(|organ| organ.organ.clone()),
profile.conformance_tests.iter().cloned(),
)?,
None => sim_kernel::standard::publish_profile_claims(
cx,
profile.symbol.clone(),
profile.organs.iter().map(|organ| organ.organ.clone()),
profile.conformance_tests.iter().cloned(),
)?,
}
let subject = Ref::Symbol(profile.symbol.clone());
insert_once(
cx,
owner,
subject.clone(),
standard_reader_predicate(),
Ref::Symbol(profile.reader.clone()),
)?;
insert_once(
cx,
owner,
subject.clone(),
standard_lowering_predicate(),
Ref::Symbol(profile.lowering.clone()),
)?;
insert_once(
cx,
owner,
subject.clone(),
standard_eval_policy_predicate(),
Ref::Symbol(profile.eval_policy.clone()),
)?;
if let Some(numeric_tower) = &profile.numeric_tower {
insert_once(
cx,
owner,
subject.clone(),
standard_numeric_predicate(),
Ref::Symbol(numeric_tower.clone()),
)?;
}
for capability in &profile.capabilities {
insert_once(
cx,
owner,
subject.clone(),
standard_capability_predicate(),
Ref::Symbol(capability.as_symbol()),
)?;
insert_once(
cx,
owner,
subject.clone(),
card_requires_predicate(),
Ref::Symbol(capability.as_symbol()),
)?;
}
for form in &profile.unsupported_forms {
insert_once(
cx,
owner,
subject.clone(),
standard_unsupported_predicate(),
Ref::Symbol(form.clone()),
)?;
}
for badge in &profile.fidelity_badges {
publish_badge_claims_with_owner(cx, owner, badge)?;
}
Ok(())
}
pub fn publish_badge_claims(cx: &mut Cx, badge: &FidelityBadge) -> Result<()> {
publish_badge_claims_with_owner(cx, None, badge)
}
pub fn publish_badge_claims_for_lib(
cx: &mut Cx,
lib_id: LibId,
badge: &FidelityBadge,
) -> Result<()> {
publish_badge_claims_with_owner(cx, Some(lib_id), badge)
}
fn publish_badge_claims_with_owner(
cx: &mut Cx,
owner: Option<LibId>,
badge: &FidelityBadge,
) -> Result<()> {
match owner {
Some(lib_id) => sim_kernel::standard::publish_fidelity_badge_for_lib(
cx,
lib_id,
badge.subject.clone(),
badge.badge.clone(),
badge.evidence.clone(),
)?,
None => sim_kernel::standard::publish_fidelity_badge(
cx,
badge.subject.clone(),
badge.badge.clone(),
badge.evidence.clone(),
)?,
}
insert_once(
cx,
owner,
badge.subject.clone(),
standard_symbol("fidelity-level"),
Ref::Symbol(Symbol::qualified(
"standard/fidelity-level",
badge.level.to_string(),
)),
)?;
insert_observed_once(
cx,
owner,
badge.subject.clone(),
standard_symbol("fidelity-badge"),
Ref::Symbol(badge.badge.clone()),
)
}
fn insert_once(
cx: &mut Cx,
owner: Option<LibId>,
subject: Ref,
predicate: Symbol,
object: Ref,
) -> Result<()> {
let exists = !cx
.query_facts(ClaimPattern::exact(
subject.clone(),
predicate.clone(),
object.clone(),
))?
.is_empty();
if !exists {
insert_claim(cx, owner, Claim::public(subject, predicate, object))?;
}
Ok(())
}
fn insert_observed_once(
cx: &mut Cx,
owner: Option<LibId>,
subject: Ref,
predicate: Symbol,
object: Ref,
) -> Result<()> {
let exists = !cx
.query_facts(ClaimPattern::exact(
subject.clone(),
predicate.clone(),
object.clone(),
))?
.is_empty();
if !exists {
insert_claim(
cx,
owner,
Claim::public(subject, predicate, object).with_kind(ClaimKind::Observed),
)?;
}
Ok(())
}
fn insert_claim(cx: &mut Cx, owner: Option<LibId>, claim: Claim) -> Result<()> {
match owner {
Some(lib_id) => {
cx.insert_fact_for_lib(lib_id, claim)?;
}
None => {
cx.insert_fact(claim)?;
}
}
Ok(())
}
fn standard_symbol(name: &str) -> Symbol {
Symbol::qualified("standard", name.to_owned())
}