Skip to main content

sim_lib_numbers_stats/
function.rs

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