dyn calling works + vibed dioxus ui components + some mo provision prototyping

This commit is contained in:
Sebastian Moser
2026-10-31 17:50:46 +01:00
parent 37cb94d1d4
commit 66b8713e3a
60 changed files with 9056 additions and 201 deletions

View File

@@ -7,12 +7,12 @@ use interner::shared::{StringPool, VecStringPool};
use std::any::Any;
use std::collections::HashMap;
use std::ops::{Deref, DerefMut};
use std::sync::{Arc, Mutex};
use std::sync::{Arc, Mutex, RwLock};
use std::{thread, vec};
use tracing::{debug, info, trace};
use crate::set_global_mize;
use crate::config::{ConfigOpt, ConfigOptId};
use crate::config::{ConfigOpt, ConfigOptId, MizeFun};
use crate::error::{MizeError, MizeResult};
use crate::id::{IntoMizeId, MizeId, Namespace};
use crate::instance::store::Store;
@@ -86,11 +86,51 @@ pub struct Mize {
pub native_values: Arc<Mutex<HashMap<u32, Box<dyn Any + Send + Sync>>>>,
pub next_native_value_id: Arc<Mutex<u32>>,
pub fun_values: Arc<Mutex<HashMap<MizeId, MizeFun>>>,
pub next_fun_values_id: Arc<Mutex<u32>>,
// generate mode: when true, part_smth functions record metadata instead of executing
pub generate_mode: Arc<RwLock<bool>>,
// recorded metadata per part (keyed by part id) while in generate mode
pub part_metadata: Arc<Mutex<HashMap<MizeId, PartMetadata>>>,
#[cfg(feature = "async")]
pub runtime: Arc<Mutex<Runtime>>,
}
/// Metadata recorded about a part while in generate mode
#[derive(Clone, Debug, Default)]
pub struct PartMetadata {
pub part_name: String,
pub opts: Vec<OptMetadata>,
pub methods: Vec<MethodMetadata>,
pub effects: Vec<MethodMetadata>,
pub threads: Vec<MethodMetadata>,
pub natives: Vec<NativeMetadata>,
}
#[derive(Clone, Debug)]
pub struct OptMetadata {
pub name: String,
pub id: MizeId,
pub default_val: Option<ItemData>,
}
#[derive(Clone, Debug)]
pub struct MethodMetadata {
pub name: String,
pub id: MizeId,
pub kind: String, // "method", "effect", "thread"
}
#[derive(Clone, Debug)]
pub struct NativeMetadata {
pub name: String,
pub type_name: String,
pub associated: Vec<String>,
pub methods: Vec<String>,
}
pub struct InstanceRef {
inner: Arc<Mutex<Mize>>,
}
@@ -160,6 +200,10 @@ impl Mize {
cur_eval_part: Arc::new(Mutex::new(None)),
native_values: Arc::new(Mutex::new(HashMap::new())),
next_native_value_id: Arc::new(Mutex::new(0)),
fun_values: Arc::new(Mutex::new(HashMap::new())),
next_fun_values_id: Arc::new(Mutex::new(0)),
generate_mode: Arc::new(RwLock::new(false)),
part_metadata: Arc::new(Mutex::new(HashMap::new())),
#[cfg(feature = "async")]
runtime: Arc::new(Mutex::new(
@@ -242,7 +286,6 @@ impl Mize {
name: &str,
handler: Box<dyn Fn(MizeMessage, &mut Mize) -> MizeResult<()> + Send + Sync>,
) -> MizeResult<()> {
println!("adding listener: {}", name);
let name = name.to_owned();
let mut listeners = self.listeners.lock().unwrap();
listeners.insert(name, Arc::new(handler));
@@ -260,7 +303,7 @@ impl Mize {
// end of platform specific init code
// load the modules, as specified in the parts config
// load the parts, as specified in the parts config
match self
.get_config("parts")
{
@@ -274,7 +317,6 @@ impl Mize {
}
}
Err(_err) => {
println!("hooooo");
// no parts to load
}
}
@@ -286,7 +328,6 @@ impl Mize {
pub fn with_config(config: ItemData) -> MizeResult<Mize> {
trace!("[ {} ] Instance::with_config()", "CALL".yellow());
trace!("config: {}", config);
println!("here ....");
let mut mize = Mize::empty()?;
@@ -354,7 +395,6 @@ impl Mize {
drop(msg_wait_inner);
let id = rx.recv()?;
println!("new_item namespace: {:?}", id.namespace());
return Ok(Item::new(id, self));
}
@@ -463,7 +503,7 @@ impl Mize {
}
pub fn fetch_part(&mut self, name: &str) -> MizeResult<String> {
// platform specific way to fetch a module
// platform specific way to fetch a part
crate::platform::fetch_part(self, name)
}
@@ -472,6 +512,98 @@ impl Mize {
crate::platform::load_part(self, name, Some(path))
}
// ===== generate mode accessors =====
/// Enable or disable generate mode. When enabled, part_smth functions record
/// metadata (methods, opts, natives) instead of performing their normal operations.
pub fn set_generate_mode(&self, enabled: bool) -> MizeResult<()> {
let mut mode = self.generate_mode.write().map_err(|_| mize_err!("generate_mode lock poisoned"))?;
*mode = enabled;
Ok(())
}
/// Check if generate mode is currently enabled.
pub fn is_generate_mode(&self) -> MizeResult<bool> {
let mode = self.generate_mode.read().map_err(|_| mize_err!("generate_mode lock poisoned"))?;
Ok(*mode)
}
/// Record an opt declaration while in generate mode.
pub fn record_opt(&self, name: &str, id: MizeId, default_val: Option<ItemData>) -> MizeResult<()> {
let cur_part = self.cur_eval_part.lock()?.clone()
.ok_or_else(|| mize_err!("no cur_eval_part set"))?;
let mut metadata_map = self.part_metadata.lock()?;
let metadata = metadata_map.entry(cur_part.clone()).or_insert_with(|| PartMetadata {
part_name: cur_part.dot(),
..Default::default()
});
metadata.opts.push(OptMetadata {
name: name.to_string(),
id,
default_val,
});
Ok(())
}
/// Record a method/effect/thread declaration while in generate mode.
pub fn record_method(&self, name: &str, id: MizeId, kind: &str) -> MizeResult<()> {
let cur_part = self.cur_eval_part.lock()?.clone()
.ok_or_else(|| mize_err!("no cur_eval_part set"))?;
let mut metadata_map = self.part_metadata.lock()?;
let metadata = metadata_map.entry(cur_part.clone()).or_insert_with(|| PartMetadata {
part_name: cur_part.dot(),
..Default::default()
});
let m = MethodMetadata {
name: name.to_string(),
id,
kind: kind.to_string(),
};
match kind {
"effect" => metadata.effects.push(m),
"thread" => metadata.threads.push(m),
_ => metadata.methods.push(m),
}
Ok(())
}
/// Record a native type inclusion while in generate mode.
pub fn record_native(&self, name: &str, type_name: &str, associated: Vec<String>, methods: Vec<String>) -> MizeResult<()> {
let cur_part = self.cur_eval_part.lock()?.clone()
.ok_or_else(|| mize_err!("no cur_eval_part set"))?;
let mut metadata_map = self.part_metadata.lock()?;
let metadata = metadata_map.entry(cur_part.clone()).or_insert_with(|| PartMetadata {
part_name: cur_part.dot(),
..Default::default()
});
metadata.natives.push(NativeMetadata {
name: name.to_string(),
type_name: type_name.to_string(),
associated,
methods,
});
Ok(())
}
/// Get recorded metadata for a specific part.
pub fn get_metadata(&self, part_id: &MizeId) -> MizeResult<Option<PartMetadata>> {
let metadata_map = self.part_metadata.lock()?;
Ok(metadata_map.get(part_id).cloned())
}
/// Get all recorded metadata (for all parts).
pub fn get_all_metadata(&self) -> MizeResult<Vec<PartMetadata>> {
let metadata_map = self.part_metadata.lock()?;
Ok(metadata_map.values().cloned().collect())
}
/// Clear all recorded metadata.
pub fn clear_metadata(&self) -> MizeResult<()> {
let mut metadata_map = self.part_metadata.lock()?;
metadata_map.clear();
Ok(())
}
pub fn namespace_from_string(&self, ns_str: String) -> MizeResult<Namespace> {
let namespace_pool_inner = self.namespace_pool.lock()?;
let namespace = Namespace(namespace_pool_inner.get(ns_str));
@@ -812,32 +944,65 @@ impl Mize {
pub fn get_config(&mut self, name: &str) -> MizeResult<ItemData> {
let mut config_opts = self.config_opts.lock().unwrap();
let opt = config_opts
.get_mut(&self.clone().id_new_dots(name)?)
.ok_or_else(|| mize_err!("Config opt for {name} not in config_opts"))?;
// Evaluate the fun if present
if let Some(fun) = &opt.fun {
let result = fun()?;
return Ok(ItemData::from(result));
let mut id;
let mut split = name.split(".");
if split.nth(0).unwrap() == "self" {
let cur_part = self.cur_eval_part.lock()?.clone().ok_or(mize_err!("get_config called but no curr eval part set"))?;
id = cur_part.clone();
for el in split {
id = id.join(el)?;
}
} else {
id = self.clone().id_new_dots(name)?;
}
// Return cached value
let mut opt = config_opts
.get_mut(&id)
.ok_or_else(|| mize_err!("Config opt for {name} not in config_opts"))?;
if let Some(val) = opt.val.clone() {
return Ok(val);
}
// in case it is not cached run the fun if it exists
if let Some(fun) = &opt.fun {
let res = fun()?;
opt.val = Some(res.clone());
return Ok(res);
}
Err(mize_err!("ConfigOpt {name} has no fun and no cached value"))
}
pub fn dyn_call(&mut self, part_id: MizeId, method: &str, args: ItemData) -> MizeResult<ItemData> {
let mut opts = self.config_opts.lock()?;
let part = opts.get_mut(&part_id).ok_or(mize_err!("part {} is not loaded", part_id.dot()))?;
let fun = part.val.ok_or(mize_err!("fun has no val"))?.native::<Fn(ItemData) -> MizeResult<ItemData>>()?;
println!("dyn_call ing from part, {:?}, {method}, {:?}", part_id, args);
fun(args)
debug!("dyn call {}.{} with args: {}", part_id, method, args);
let mut fun_values = self.fun_values.lock()?;
let id = part_id.clone().join(method)?;
//let part = opts.get_mut(&id).ok_or(mize_err!("part {} is not loaded", part_id.dot()))?;
let fun = fun_values.remove(&id).ok_or(mize_err!("fun value for {id} not found"))?;
drop(fun_values);
let calling_part = self.clone().cur_eval_part()?;
self.clone().set_cur_eval_part(Some(part_id));
let res = fun(args);
self.clone().set_cur_eval_part(calling_part);
let mut fun_values = self.fun_values.lock()?;
fun_values.insert(id, fun);
return res;
}
pub fn cur_eval_part(&mut self) -> MizeResult<Option<MizeId>> {
Ok(self.cur_eval_part.lock()?.clone())
}
pub fn set_cur_eval_part(&mut self, part: Option<MizeId>) -> MizeResult<()> {
let mut guard = self.cur_eval_part.lock()?;
*guard = part;
Ok(())
}
pub fn get_part_gen<T: MizePart + Send + Sync + 'static>(
&mut self,
name: &str,