sim_lib_numbers_stats/
function.rs1use std::{any::Any, sync::Arc};
4
5use sim_kernel::{
6 AbiVersion, Args, Callable, ClassRef, Cx, DefaultFactory, Dependency, Export, Expr, Factory,
7 Lib, LibManifest, LibTarget, Linker, Object, RawArgs, Result, Symbol, Value, Version,
8};
9
10use super::runtime;
11
12pub fn stats_disparate_impact_claim_symbol() -> Symbol {
14 Symbol::qualified("stats", "disparate-impact-claim")
15}
16
17pub fn stats_mean_claim_symbol() -> Symbol {
19 Symbol::qualified("stats", "mean-claim")
20}
21
22pub fn stats_variance_claim_symbol() -> Symbol {
24 Symbol::qualified("stats", "variance-claim")
25}
26
27pub fn stats_entropy_claim_symbol() -> Symbol {
29 Symbol::qualified("stats", "entropy-claim")
30}
31
32pub fn stats_claims_symbol() -> Symbol {
34 Symbol::qualified("stats", "claims")
35}
36
37fn function_symbols() -> [Symbol; 5] {
38 [
39 stats_mean_claim_symbol(),
40 stats_variance_claim_symbol(),
41 stats_entropy_claim_symbol(),
42 stats_disparate_impact_claim_symbol(),
43 stats_claims_symbol(),
44 ]
45}
46
47#[derive(Clone)]
48struct StatsFunction {
49 symbol: Symbol,
50}
51
52impl Object for StatsFunction {
53 fn display(&self, _cx: &mut Cx) -> Result<String> {
54 Ok(format!("#<function {}>", self.symbol))
55 }
56
57 fn as_any(&self) -> &dyn Any {
58 self
59 }
60}
61
62impl sim_kernel::ObjectCompat for StatsFunction {
63 fn class(&self, cx: &mut Cx) -> Result<ClassRef> {
64 if let Some(value) = cx
65 .registry()
66 .class_by_symbol(&Symbol::qualified("core", "Function"))
67 {
68 return Ok(value.clone());
69 }
70 DefaultFactory.class_stub(
71 sim_kernel::CORE_FUNCTION_CLASS_ID,
72 Symbol::qualified("core", "Function"),
73 )
74 }
75
76 fn as_expr(&self, _cx: &mut Cx) -> Result<Expr> {
77 Ok(Expr::Symbol(self.symbol.clone()))
78 }
79
80 fn as_callable(&self) -> Option<&dyn Callable> {
81 Some(self)
82 }
83}
84
85impl Callable for StatsFunction {
86 fn call(&self, cx: &mut Cx, args: Args) -> Result<Value> {
87 if self.symbol == stats_mean_claim_symbol() {
88 return runtime::call_stats_mean_claim(cx, args);
89 }
90 if self.symbol == stats_variance_claim_symbol() {
91 return runtime::call_stats_variance_claim(cx, args);
92 }
93 if self.symbol == stats_entropy_claim_symbol() {
94 return runtime::call_stats_entropy_claim(cx, args);
95 }
96 if self.symbol == stats_disparate_impact_claim_symbol() {
97 return runtime::call_stats_disparate_impact_claim(cx, args);
98 }
99 if self.symbol == stats_claims_symbol() {
100 return runtime::call_stats_claims(cx, args);
101 }
102 unreachable!("unregistered stats function {}", self.symbol)
103 }
104
105 fn call_exprs(&self, cx: &mut Cx, args: RawArgs) -> Result<Value> {
106 let values = args
107 .into_exprs()
108 .into_iter()
109 .map(|expr| cx.eval_expr(expr))
110 .collect::<Result<Vec<_>>>()?;
111 self.call(cx, Args::new(values))
112 }
113}
114
115pub struct StatsNumbersLib;
117
118impl StatsNumbersLib {
119 pub fn new() -> Self {
121 Self
122 }
123}
124
125impl Default for StatsNumbersLib {
126 fn default() -> Self {
127 Self::new()
128 }
129}
130
131impl Lib for StatsNumbersLib {
132 fn manifest(&self) -> LibManifest {
133 LibManifest {
134 id: Symbol::qualified("numbers", "stats"),
135 version: Version(env!("CARGO_PKG_VERSION").to_owned()),
136 abi: AbiVersion { major: 0, minor: 1 },
137 target: LibTarget::HostRegistered,
138 requires: Vec::<Dependency>::new(),
139 capabilities: Vec::new(),
140 exports: function_symbols()
141 .into_iter()
142 .map(|symbol| Export::Function {
143 symbol,
144 function_id: None,
145 })
146 .collect(),
147 }
148 }
149
150 fn load(&self, _cx: &mut sim_kernel::LoadCx, linker: &mut Linker<'_>) -> Result<()> {
151 for symbol in function_symbols() {
152 linker.function_value(
153 symbol.clone(),
154 DefaultFactory.opaque(Arc::new(StatsFunction { symbol }))?,
155 )?;
156 }
157 Ok(())
158 }
159}