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:?}");
+}