diff --git a/README.md b/README.md index 7b6537b..8269650 100644 --- a/README.md +++ b/README.md @@ -298,11 +298,11 @@ was used to build adana. The rust version is specified when running the repl. -To load a dynamic library, you can either specify a relative path, or an +To load a library dynamically, you can either specify a relative path, or an absolute path. In case of a relative path, it should be relative to the shared lib path (by default: `$HOME/.local/share/.libs_adana`). -You can override this by providing a path when starting the repl (e.g: `adana --slp /tmp`). +You can override this by providing a path when starting the repl (e.g: `adana -slp /tmp`). If the path is a directory, it will try to build it using `cargo`, so you need to have rust installed on your machine. @@ -322,6 +322,12 @@ For example: text = lib.hello("Nordine", "la", "forme?") ``` +Or in one line: + +```python + text = require("libplugin_example.so").hello("Nordine", "la", "forme?") +``` +
### Loops diff --git a/src/adana_script/compute.rs b/src/adana_script/compute.rs index 32fd668..8579be2 100644 --- a/src/adana_script/compute.rs +++ b/src/adana_script/compute.rs @@ -19,9 +19,31 @@ use adana_script_core::{ Primitive, RefPrimitive, Rem, Sin, Sqrt, Sub, Tan, ToBool, ToNumber, TypeOf, }, - Operator, TreeNodeValue, Value, + BuiltInFunctionType, Operator, TreeNodeValue, Value, }; +/// copy existing functions in a new ctx +fn scoped_ctx( + ctx: &mut BTreeMap, +) -> anyhow::Result> { + let mut scope_ctx = BTreeMap::new(); + + // copy also the function definition to the scoped ctx + for (k, p) in ctx.iter() { + let maybe_fn = p + .read() + .map_err(|e| anyhow::format_err!("could not acquire lock {e}"))?; + if matches!( + *maybe_fn, + Primitive::Function { parameters: _, exprs: _ } + | Primitive::NativeLibrary(_) + ) { + scope_ctx.insert(k.to_string(), p.clone()); + } + } + + Ok(scope_ctx) +} fn compute_recur( node: Option>, ctx: &mut BTreeMap, @@ -503,6 +525,24 @@ fn compute_recur( Ok(struc.index_at(key)) } } + ( + v @ Value::BuiltInFunction { + fn_type: BuiltInFunctionType::Require, + .. + }, + key @ Primitive::String(k), + ) => { + let native_lib = compute_lazy(v.clone(), ctx, shared_lib)?; + if let Primitive::NativeLibrary(lib) = + native_lib.as_ref_ok()? + { + Ok(Primitive::NativeFunction(k.clone(), lib.clone())) + } else { + Err(anyhow::format_err!( + "could not parse built in fn {key} => {native_lib:?}" + )) + } + } (s @ Value::Struct(_), key @ Primitive::String(_)) | ( s @ Value::StructAccess { struc: _, key: _ }, @@ -579,24 +619,7 @@ fn compute_recur( exprs, } = function { - let mut scope_ctx = BTreeMap::new(); - - // copy also the function definition to the scoped ctx - for (k, p) in ctx.iter() { - let maybe_fn = p.read().map_err(|e| { - anyhow::format_err!( - "could not acquire lock {e}" - ) - })?; - if matches!( - *maybe_fn, - Primitive::Function { parameters: _, exprs: _ } - | Primitive::NativeLibrary(_) - ) { - scope_ctx.insert(k.to_string(), p.clone()); - } - } - + let mut scope_ctx = scoped_ctx(ctx)?; for (i, param) in function_parameters.iter().enumerate() { if let Some(value) = param_values.get(i) { @@ -619,7 +642,6 @@ fn compute_recur( ))); } } - // TODO remove this and replace Arc> by Arc // call function in a specific os thread with its own stack // This was relative to a small stack allocated by musl @@ -675,11 +697,12 @@ fn compute_recur( dbg!(¶meters); } - let mut cloned_ctx = ctx.clone(); + let mut scope_ctx = scoped_ctx(ctx)?; + let slb = shared_lib.as_ref().to_path_buf(); let fun = move |v, extra_ctx| { - cloned_ctx.extend(extra_ctx); - compute_lazy(v, &mut cloned_ctx, &slb) + scope_ctx.extend(extra_ctx); + compute_lazy(v, &mut scope_ctx, &slb) }; unsafe { lib.call_function( diff --git a/src/adana_script/parser.rs b/src/adana_script/parser.rs index 7a8c13e..9d59375 100644 --- a/src/adana_script/parser.rs +++ b/src/adana_script/parser.rs @@ -467,6 +467,7 @@ fn parse_struct_access(s: &str) -> Res { pair(alt((parse_struct, parse_variable)), parse_key_dots), pair(parse_array_access, parse_key_brackets), pair(parse_array_access, parse_key_dots), + pair(parse_builtin_fn, parse_key_dots), )), |(s, key)| Value::StructAccess { struc: Box::new(s), diff --git a/src/adana_script/tests/dynload.rs b/src/adana_script/tests/dynload.rs index 9b4cd15..af57613 100644 --- a/src/adana_script/tests/dynload.rs +++ b/src/adana_script/tests/dynload.rs @@ -82,3 +82,21 @@ fn build_from_adana_dynamic_lib_test() { dbg!(ctx); println!("{res:?}"); } +#[test] +#[serial] +fn require_direct_call_test() { + let mut ctx = BTreeMap::new(); + + let q = r#" + text = require("example_lib_src").hello("Nordine", "la", "forme?") + "#; + let res = compute(q, &mut ctx, "dynamic_lib").unwrap(); + + assert_eq!( + Primitive::String("Hello Nordine la forme?".to_string()), + ctx["text"].read().unwrap().clone() + ); + + dbg!(ctx); + println!("{res:?}"); +}