Better values

This commit is contained in:
2025-08-25 09:57:57 +02:00
parent e940987abb
commit 5f2e8fd25f
5 changed files with 117 additions and 26 deletions
+2 -1
View File
@@ -1,3 +1,4 @@
def hello(name): def hello(name):
print("Hello, bro! " + name) print("Hello, bro! " + name)
return "Idk, return value i guess" # return "Idk, return value i guess"
return 1.1
+14 -5
View File
@@ -1,10 +1,13 @@
#[derive(Debug)] use std::collections::BTreeMap;
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum FluxValue { pub enum FluxValue {
Int(i64), Int(i64),
Float(f64), Float(u64),
Str(String), Str(String),
Null, Null,
// later: List(Vec<FluxValue>), Dict(HashMap<String, FluxValue>) Array(Vec<FluxValue>),
Map(BTreeMap<FluxValue, FluxValue>),
} }
pub trait Serialize { pub trait Serialize {
@@ -21,9 +24,15 @@ pub trait FluxModule {
fn call(&self, func: &str, args: Vec<&dyn Serialize>) -> FluxValue; fn call(&self, func: &str, args: Vec<&dyn Serialize>) -> FluxValue;
} }
pub mod values;
pub mod runtime; pub mod runtime;
pub mod values;
pub mod prelude { pub mod prelude {
pub use crate::{FluxModule, Serialize, Deserialize}; pub use crate::{Deserialize, FluxModule, Serialize};
}
impl FluxValue {
pub fn extract<T: Deserialize>(self) -> T {
T::deserialize(self)
}
} }
+1 -1
View File
@@ -7,5 +7,5 @@ fn main() {
let gil = python::get_gil(); let gil = python::get_gil();
let m = python::import("bro.py", &gil); let m = python::import("bro.py", &gil);
println!("{:?}", m.call("hello", vec![&"leo"])); println!("{:?}", m.call("hello", vec![&"leo"]).extract::<f64>());
} }
+56 -17
View File
@@ -1,7 +1,9 @@
use std::fs; use std::fs;
use crate::FluxModule; use crate::{FluxModule, FluxValue};
use cpython::{GILGuard, ObjectProtocol, PyObject, PyTuple, Python, PythonObject, ToPyObject}; use cpython::{
GILGuard, ObjectProtocol, PyDict, PyList, PyObject, PyTuple, Python, PythonObject, ToPyObject,
};
pub fn import<'a>(path: &str, gil: &'a GILGuard) -> PythonModule<'a> { pub fn import<'a>(path: &str, gil: &'a GILGuard) -> PythonModule<'a> {
let m = PythonModule { let m = PythonModule {
@@ -16,6 +18,30 @@ pub fn get_gil() -> GILGuard {
Python::acquire_gil() Python::acquire_gil()
} }
pub fn flux_to_object(py: Python<'_>, flux: &FluxValue) -> PyObject {
match flux {
crate::FluxValue::Null => py.None(),
crate::FluxValue::Int(i) => i.to_py_object(py).into_object(),
crate::FluxValue::Float(f) => f.to_py_object(py).into_object(),
crate::FluxValue::Str(s) => s.to_py_object(py).into_object(),
crate::FluxValue::Array(a) => PyList::new(
py,
&a.iter()
.map(|f| flux_to_object(py, f))
.collect::<Vec<PyObject>>(),
)
.into_object(),
crate::FluxValue::Map(a) => {
let map = PyDict::new(py);
for (k, v) in a {
map.set_item(py, flux_to_object(py, k), flux_to_object(py, v))
.unwrap();
}
map.into_object()
}
}
}
pub struct PythonModule<'a> { pub struct PythonModule<'a> {
path: String, path: String,
python: Python<'a>, python: Python<'a>,
@@ -33,28 +59,41 @@ impl FluxModule for PythonModule<'_> {
let py_args: Vec<PyObject> = args let py_args: Vec<PyObject> = args
.iter() .iter()
.map(|a| match a.serialize() { .map(|a| flux_to_object(self.python, &a.serialize()))
crate::FluxValue::Int(i) => i.to_py_object(self.python).into_object(),
crate::FluxValue::Float(f) => f.to_py_object(self.python).into_object(),
crate::FluxValue::Str(s) => s.to_py_object(self.python).into_object(),
crate::FluxValue::Null => self.python.None(),
})
.collect(); .collect();
let args_tuple = PyTuple::new(self.python, &py_args); let args_tuple = PyTuple::new(self.python, &py_args);
let result: PyObject = func.call(self.python, args_tuple, None).unwrap(); let result: PyObject = func.call(self.python, args_tuple, None).unwrap();
if let Ok(i) = result.extract::<i64>(self.python) { to_flux_value(self.python, &result)
crate::FluxValue::Int(i)
} else if let Ok(f) = result.extract::<f64>(self.python) {
crate::FluxValue::Float(f)
} else if let Ok(s) = result.extract::<String>(self.python) {
crate::FluxValue::Str(s)
} else {
crate::FluxValue::Null
}
} }
fn end(&self) {} fn end(&self) {}
} }
fn to_flux_value(py: Python, result: &PyObject) -> crate::FluxValue {
if let Ok(i) = result.extract::<i64>(py) {
crate::FluxValue::Int(i)
} else if let Ok(f) = result.extract::<f64>(py) {
crate::FluxValue::Float(f.to_bits())
} else if let Ok(s) = result.extract::<String>(py) {
crate::FluxValue::Str(s)
} else if let Ok(list) = result.cast_as::<PyList>(py) {
let mut items = Vec::new();
for item in list.iter(py) {
items.push(to_flux_value(py, &item));
}
crate::FluxValue::Array(items)
} else if let Ok(dict) = result.cast_as::<PyDict>(py) {
let mut map = std::collections::BTreeMap::new(); // or HashMap if you don’t need ordering
for (k, v) in dict.items(py) {
let key = to_flux_value(py, &k);
let val = to_flux_value(py, &v);
map.insert(key, val);
}
crate::FluxValue::Map(map)
} else {
crate::FluxValue::Null
}
}
+44 -2
View File
@@ -1,3 +1,5 @@
use std::collections::{BTreeMap, HashMap};
use crate::{Deserialize, FluxValue, Serialize}; use crate::{Deserialize, FluxValue, Serialize};
impl Serialize for i64 { impl Serialize for i64 {
@@ -5,21 +7,61 @@ impl Serialize for i64 {
FluxValue::Int(*self) FluxValue::Int(*self)
} }
} }
impl Serialize for f64 { impl Serialize for f64 {
fn serialize(&self) -> FluxValue { fn serialize(&self) -> FluxValue {
FluxValue::Float(*self) FluxValue::Float(self.to_bits())
} }
} }
impl Deserialize for f64 {
fn deserialize(v: FluxValue) -> Self {
match v {
FluxValue::Float(bits) => f64::from_bits(bits),
v => panic!("Expected Int, instead got {v:?}"),
}
}
}
impl Serialize for &str { impl Serialize for &str {
fn serialize(&self) -> FluxValue { fn serialize(&self) -> FluxValue {
FluxValue::Str(self.to_string()) FluxValue::Str(self.to_string())
} }
} }
impl Serialize for String {
fn serialize(&self) -> FluxValue {
FluxValue::Str(self.clone())
}
}
impl Deserialize for i64 { impl Deserialize for i64 {
fn deserialize(v: FluxValue) -> Self { fn deserialize(v: FluxValue) -> Self {
match v { match v {
FluxValue::Int(i) => i, FluxValue::Int(i) => i,
_ => panic!("Expected Int"), v => panic!("Expected Int, instead got {v:?}"),
}
}
}
impl<K: Serialize, V: Serialize> Serialize for HashMap<K, V> {
fn serialize(&self) -> FluxValue {
FluxValue::Map(
self.iter()
.map(|(k, v)| (k.serialize(), v.serialize()))
.collect::<BTreeMap<FluxValue, FluxValue>>(),
)
}
}
impl<K: Deserialize + Ord, V: Deserialize> Deserialize for BTreeMap<K, V> {
fn deserialize(v: FluxValue) -> Self {
match v {
FluxValue::Map(m) => m
.iter()
.map(|(k, v)| (K::deserialize(k.clone()), V::deserialize(v.clone())))
.collect::<BTreeMap<K, V>>(),
v => panic!("Expected Int, instead got {v:?}"),
} }
} }
} }