dyn calling works + vibed dioxus ui components + some mo provision prototyping
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user