1use sim_kernel::{
4 Claim, ClaimKind, ClaimPattern, Cx, LibId, Ref, Result, Symbol, card::card_requires_predicate,
5};
6
7use crate::{FidelityBadge, LanguageProfile};
8
9pub fn standard_reader_predicate() -> Symbol {
11 standard_symbol("reader")
12}
13
14pub fn standard_lowering_predicate() -> Symbol {
16 standard_symbol("lowering")
17}
18
19pub fn standard_eval_policy_predicate() -> Symbol {
21 standard_symbol("eval-policy")
22}
23
24pub fn standard_numeric_predicate() -> Symbol {
26 standard_symbol("numeric")
27}
28
29pub fn standard_capability_predicate() -> Symbol {
31 standard_symbol("capability")
32}
33
34pub fn standard_unsupported_predicate() -> Symbol {
36 standard_symbol("unsupported")
37}
38
39pub fn publish_profile_claims(cx: &mut Cx, profile: &LanguageProfile) -> Result<()> {
46 publish_profile_claims_with_owner(cx, None, profile)
47}
48
49pub fn publish_profile_claims_for_lib(
51 cx: &mut Cx,
52 lib_id: LibId,
53 profile: &LanguageProfile,
54) -> Result<()> {
55 publish_profile_claims_with_owner(cx, Some(lib_id), profile)
56}
57
58fn publish_profile_claims_with_owner(
59 cx: &mut Cx,
60 owner: Option<LibId>,
61 profile: &LanguageProfile,
62) -> Result<()> {
63 match owner {
64 Some(lib_id) => sim_kernel::standard::publish_profile_claims_for_lib(
65 cx,
66 lib_id,
67 profile.symbol.clone(),
68 profile.organs.iter().map(|organ| organ.organ.clone()),
69 profile.conformance_tests.iter().cloned(),
70 )?,
71 None => sim_kernel::standard::publish_profile_claims(
72 cx,
73 profile.symbol.clone(),
74 profile.organs.iter().map(|organ| organ.organ.clone()),
75 profile.conformance_tests.iter().cloned(),
76 )?,
77 }
78
79 let subject = Ref::Symbol(profile.symbol.clone());
80 insert_once(
81 cx,
82 owner,
83 subject.clone(),
84 standard_reader_predicate(),
85 Ref::Symbol(profile.reader.clone()),
86 )?;
87 insert_once(
88 cx,
89 owner,
90 subject.clone(),
91 standard_lowering_predicate(),
92 Ref::Symbol(profile.lowering.clone()),
93 )?;
94 insert_once(
95 cx,
96 owner,
97 subject.clone(),
98 standard_eval_policy_predicate(),
99 Ref::Symbol(profile.eval_policy.clone()),
100 )?;
101 if let Some(numeric_tower) = &profile.numeric_tower {
102 insert_once(
103 cx,
104 owner,
105 subject.clone(),
106 standard_numeric_predicate(),
107 Ref::Symbol(numeric_tower.clone()),
108 )?;
109 }
110 for capability in &profile.capabilities {
111 insert_once(
112 cx,
113 owner,
114 subject.clone(),
115 standard_capability_predicate(),
116 Ref::Symbol(capability.as_symbol()),
117 )?;
118 insert_once(
119 cx,
120 owner,
121 subject.clone(),
122 card_requires_predicate(),
123 Ref::Symbol(capability.as_symbol()),
124 )?;
125 }
126 for form in &profile.unsupported_forms {
127 insert_once(
128 cx,
129 owner,
130 subject.clone(),
131 standard_unsupported_predicate(),
132 Ref::Symbol(form.clone()),
133 )?;
134 }
135 for badge in &profile.fidelity_badges {
136 publish_badge_claims_with_owner(cx, owner, badge)?;
137 }
138 Ok(())
139}
140
141pub fn publish_badge_claims(cx: &mut Cx, badge: &FidelityBadge) -> Result<()> {
144 publish_badge_claims_with_owner(cx, None, badge)
145}
146
147pub fn publish_badge_claims_for_lib(
149 cx: &mut Cx,
150 lib_id: LibId,
151 badge: &FidelityBadge,
152) -> Result<()> {
153 publish_badge_claims_with_owner(cx, Some(lib_id), badge)
154}
155
156fn publish_badge_claims_with_owner(
157 cx: &mut Cx,
158 owner: Option<LibId>,
159 badge: &FidelityBadge,
160) -> Result<()> {
161 match owner {
162 Some(lib_id) => sim_kernel::standard::publish_fidelity_badge_for_lib(
163 cx,
164 lib_id,
165 badge.subject.clone(),
166 badge.badge.clone(),
167 badge.evidence.clone(),
168 )?,
169 None => sim_kernel::standard::publish_fidelity_badge(
170 cx,
171 badge.subject.clone(),
172 badge.badge.clone(),
173 badge.evidence.clone(),
174 )?,
175 }
176 insert_once(
177 cx,
178 owner,
179 badge.subject.clone(),
180 standard_symbol("fidelity-level"),
181 Ref::Symbol(Symbol::qualified(
182 "standard/fidelity-level",
183 badge.level.to_string(),
184 )),
185 )?;
186 insert_observed_once(
187 cx,
188 owner,
189 badge.subject.clone(),
190 standard_symbol("fidelity-badge"),
191 Ref::Symbol(badge.badge.clone()),
192 )
193}
194
195fn insert_once(
196 cx: &mut Cx,
197 owner: Option<LibId>,
198 subject: Ref,
199 predicate: Symbol,
200 object: Ref,
201) -> Result<()> {
202 let exists = !cx
203 .query_facts(ClaimPattern::exact(
204 subject.clone(),
205 predicate.clone(),
206 object.clone(),
207 ))?
208 .is_empty();
209 if !exists {
210 insert_claim(cx, owner, Claim::public(subject, predicate, object))?;
211 }
212 Ok(())
213}
214
215fn insert_observed_once(
216 cx: &mut Cx,
217 owner: Option<LibId>,
218 subject: Ref,
219 predicate: Symbol,
220 object: Ref,
221) -> Result<()> {
222 let exists = !cx
223 .query_facts(ClaimPattern::exact(
224 subject.clone(),
225 predicate.clone(),
226 object.clone(),
227 ))?
228 .is_empty();
229 if !exists {
230 insert_claim(
231 cx,
232 owner,
233 Claim::public(subject, predicate, object).with_kind(ClaimKind::Observed),
234 )?;
235 }
236 Ok(())
237}
238
239fn insert_claim(cx: &mut Cx, owner: Option<LibId>, claim: Claim) -> Result<()> {
240 match owner {
241 Some(lib_id) => {
242 cx.insert_fact_for_lib(lib_id, claim)?;
243 }
244 None => {
245 cx.insert_fact(claim)?;
246 }
247 }
248 Ok(())
249}
250
251fn standard_symbol(name: &str) -> Symbol {
252 Symbol::qualified("standard", name.to_owned())
253}