sim_lib_numbers_numeric/
function.rs1use std::{any::Any, sync::Arc};
6
7use sim_kernel::{
8 AbiVersion, Args, Callable, ClassRef, Cx, DefaultFactory, Dependency, Export, Expr, Factory,
9 Lib, LibManifest, LibTarget, Linker, Object, RawArgs, Result, Symbol, Value, Version,
10};
11use sim_lib_numbers_core::domains;
12
13use super::runtime;
14
15pub fn numeric_diff_symbol() -> Symbol {
30 Symbol::new("numeric-diff")
31}
32
33pub fn integrate_symbol() -> Symbol {
35 Symbol::new("integrate")
36}
37
38pub fn integrate_adapt_symbol() -> Symbol {
40 Symbol::new("integrate-adapt")
41}
42
43pub fn ode_solve_symbol() -> Symbol {
45 Symbol::new("ode-solve")
46}
47
48pub fn numeric_compose_symbol() -> Symbol {
50 Symbol::qualified("numeric", "compose")
51}
52
53pub fn numeric_run_composed_symbol() -> Symbol {
55 Symbol::qualified("numeric", "run-composed")
56}
57
58fn function_symbols() -> [Symbol; 6] {
59 [
60 numeric_diff_symbol(),
61 integrate_symbol(),
62 integrate_adapt_symbol(),
63 ode_solve_symbol(),
64 numeric_compose_symbol(),
65 numeric_run_composed_symbol(),
66 ]
67}
68
69#[derive(Clone)]
70struct NumericFunction {
71 symbol: Symbol,
72}
73
74impl Object for NumericFunction {
75 fn display(&self, _cx: &mut Cx) -> Result<String> {
76 Ok(format!("#<function {}>", self.symbol))
77 }
78
79 fn as_any(&self) -> &dyn Any {
80 self
81 }
82}
83
84impl sim_kernel::ObjectCompat for NumericFunction {
85 fn class(&self, cx: &mut Cx) -> Result<ClassRef> {
86 if let Some(value) = cx
87 .registry()
88 .class_by_symbol(&Symbol::qualified("core", "Function"))
89 {
90 return Ok(value.clone());
91 }
92 DefaultFactory.class_stub(
93 sim_kernel::CORE_FUNCTION_CLASS_ID,
94 Symbol::qualified("core", "Function"),
95 )
96 }
97 fn as_expr(&self, _cx: &mut Cx) -> Result<Expr> {
98 Ok(Expr::Symbol(self.symbol.clone()))
99 }
100 fn as_callable(&self) -> Option<&dyn Callable> {
101 Some(self)
102 }
103}
104
105impl Callable for NumericFunction {
106 fn call(&self, cx: &mut Cx, args: Args) -> Result<Value> {
107 if self.symbol == numeric_diff_symbol() {
108 runtime::call_numeric_diff(cx, args)
109 } else if self.symbol == integrate_symbol() {
110 runtime::call_integrate(cx, args)
111 } else if self.symbol == integrate_adapt_symbol() {
112 runtime::call_integrate_adapt(cx, args)
113 } else if self.symbol == numeric_compose_symbol() {
114 runtime::call_numeric_compose(cx, args)
115 } else if self.symbol == numeric_run_composed_symbol() {
116 runtime::call_numeric_run_composed(cx, args)
117 } else {
118 runtime::call_ode_solve(cx, args)
119 }
120 }
121
122 fn call_exprs(&self, cx: &mut Cx, args: RawArgs) -> Result<Value> {
123 let args = args.into_exprs();
124 if self.symbol == numeric_diff_symbol() {
125 runtime::call_numeric_diff_exprs(cx, args)
126 } else if self.symbol == integrate_symbol() {
127 runtime::call_integrate_exprs(cx, args)
128 } else if self.symbol == integrate_adapt_symbol() {
129 runtime::call_integrate_adapt_exprs(cx, args)
130 } else if self.symbol == numeric_compose_symbol() {
131 runtime::call_numeric_compose_exprs(cx, args)
132 } else if self.symbol == numeric_run_composed_symbol() {
133 runtime::call_numeric_run_composed_exprs(cx, args)
134 } else {
135 runtime::call_ode_solve_exprs(cx, args)
136 }
137 }
138}
139
140pub struct NumericNumbersLib;
145
146impl NumericNumbersLib {
147 pub fn new() -> Self {
149 Self
150 }
151}
152
153impl Default for NumericNumbersLib {
154 fn default() -> Self {
155 Self::new()
156 }
157}
158
159impl Lib for NumericNumbersLib {
160 fn manifest(&self) -> LibManifest {
161 LibManifest {
162 id: domains::numeric(),
163 version: Version(env!("CARGO_PKG_VERSION").to_owned()),
164 abi: AbiVersion { major: 0, minor: 1 },
165 target: LibTarget::HostRegistered,
166 requires: Vec::<Dependency>::new(),
167 capabilities: Vec::new(),
168 exports: function_symbols()
169 .into_iter()
170 .map(|symbol| Export::Function {
171 symbol,
172 function_id: None,
173 })
174 .collect(),
175 }
176 }
177
178 fn load(&self, _cx: &mut sim_kernel::LoadCx, linker: &mut Linker<'_>) -> Result<()> {
179 for symbol in function_symbols() {
180 linker.function_value(
181 symbol.clone(),
182 DefaultFactory.opaque(Arc::new(NumericFunction { symbol }))?,
183 )?;
184 }
185 Ok(())
186 }
187}