abacus/abacus-core/src/engine.rs

129 lines
3.5 KiB
Rust

use crate::dataframe;
#[derive(Debug)]
pub struct Engine<'a> {
engine: rhai::Engine,
scope: rhai::Scope<'a>,
}
impl<'a> Default for Engine<'a> {
fn default() -> Self {
let mut engine = rhai::Engine::new();
engine.set_fast_operators(false);
engine.register_static_module("physics", rhai::exported_module!(physics).into());
engine.register_static_module("math", rhai::exported_module!(math).into());
dataframe::setup_engine(&mut engine);
Self {
engine,
scope: rhai::Scope::new(),
}
}
}
impl<'a> Engine<'a> {
pub fn process_script(&mut self, script: &str) -> Output {
match self
.engine
.eval_with_scope::<rhai::Dynamic>(&mut self.scope, script)
{
Ok(res) if res.is::<dataframe::DataFrame>() => {
let frame = rhai::Dynamic::cast::<dataframe::DataFrame>(res);
Output::DataFrame(frame)
}
Ok(res) if res.is::<()>() => Output::None,
Ok(res) if res.is::<dataframe::Series>() => {
let series = rhai::Dynamic::cast::<dataframe::Series>(res);
Output::Series(series)
}
Ok(res) => Output::Scalar(res.to_string()),
Err(e) => Output::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone)]
pub enum Output {
None,
Scalar(String),
DataFrame(dataframe::DataFrame),
Series(dataframe::Series),
Error(String),
}
impl Default for Output {
fn default() -> Self {
Output::None
}
}
impl PartialEq for Output {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::Scalar(l0), Self::Scalar(r0)) => *l0.to_string() == *r0.to_string(),
(Self::DataFrame(l0), Self::DataFrame(r0)) => l0 == r0,
(Self::Series(l0), Self::Series(r0)) => l0 == r0,
(Self::Error(l0), Self::Error(r0)) => l0 == r0,
_ => core::mem::discriminant(self) == core::mem::discriminant(other),
}
}
}
impl Output {
pub fn into_frame(self) -> dataframe::DataFrame {
if let Self::DataFrame(v) = self {
return v;
}
panic!("Not a dataframe");
}
pub fn into_series(self) -> dataframe::Series {
if let Self::Series(v) = self {
return v;
}
panic!("Not a series");
}
pub fn into_scalar(self) -> String {
if let Self::Scalar(v) = self {
return v;
}
panic!("Not a scalar");
}
}
use rhai::plugin::*;
#[rhai::export_module]
mod physics {
pub const PLANK: f64 = 6.626e-34;
pub const G: f64 = 6.67430e-11;
pub const COULUMN: f64 = 8.987;
pub const STEFAN_BOLTZMANN: f64 = 5.670e-8;
pub const BOLTZMANN: f64 = 1.380650e23;
pub const C: f64 = 299792458.0;
pub const AVOGADRO: f64 = 6.02214076e23;
pub const ATOMIC_MASS: f64 = 1.66053906660e-27;
pub const ELECTRON_MASS: f64 = 9.1093837015e-31;
pub const PROTON_MASS: f64 = 1.67262192369e-27;
pub const NEUTRON_MASS: f64 = 1.67492749804e-27;
pub const HUBBLE: f64 = 69.3;
}
#[rhai::export_module]
mod math {
pub const PI: f64 = std::f64::consts::PI;
pub const E: f64 = std::f64::consts::E;
pub const SQRT2: f64 = std::f64::consts::SQRT_2;
pub const TAU: f64 = std::f64::consts::TAU;
}
#[cfg(test)]
pub mod tests {
use super::*;
pub fn process(script: &str) -> Output {
let mut engine = super::Engine::default();
engine.process_script(script)
}
}