diff --git a/turing/src/engine/types.rs b/turing/src/engine/types.rs index 3b431f3..0f8b3a9 100644 --- a/turing/src/engine/types.rs +++ b/turing/src/engine/types.rs @@ -1,5 +1,6 @@ use crate::interop::params::{DataType, FfiParam, FfiParamArray}; use anyhow::anyhow; +use convert_case::{Case, Casing}; pub type ScriptCallback = extern "C" fn(FfiParamArray) -> FfiParam; @@ -92,6 +93,26 @@ impl ScriptFnMetadata { self.return_type.push((r, type_name)); Ok(self) } + + /// Determines if function is an instance method + pub fn is_instance_method(fn_name: &str) -> bool { + fn_name.contains(".") + } + + /// Determines if function is a static method + pub fn is_static_method(fn_name: &str) -> bool { + fn_name.contains("::") + } + + /// Converts function name to internal representation + /// e.g. `Class::functionName` becomes `capability_class_function_name` + pub fn as_internal_name(&self, fn_name: &str) -> String { + format!( + "_{}_{}", + self.capability.to_case(Case::Snake), + fn_name.to_case(Case::Snake).replace("::", "__").replace(".", "__") + ) + } } impl DataType { diff --git a/turing/src/engine/wasm_engine.rs b/turing/src/engine/wasm_engine.rs index 3c00613..cbe3a0c 100644 --- a/turing/src/engine/wasm_engine.rs +++ b/turing/src/engine/wasm_engine.rs @@ -609,10 +609,15 @@ impl WasmInterpreter { for (name, metadata) in wasm_fns.iter() { // Convert from `ClassName::functionName` to `_class_name_function_name` - let mut name = name.replace("::", "__").replace(".", "__").to_case(Case::Snake); - name.insert(0, '_'); + let mut internal_name = name.replace("::", "__").replace(".", "__").to_case(Case::Snake); + internal_name.insert(0, '_'); - let p_types = metadata.param_types.iter().map(|d| d.data_type.to_val_type()).collect::>>()?; + let mut p_types = metadata.param_types.iter().map(|d| d.data_type.to_val_type()).collect::>>()?; + + if ScriptFnMetadata::is_instance_method(name) { + // instance methods get an extra first parameter for the instance pointer + p_types.insert(0, DataType::Object.to_val_type().unwrap()); + } // if the only return type is void, we treat it as no return types let r_types = if metadata.return_type.len() == 1 && metadata.return_type.first().cloned().map(|r| r.0) == Some(DataType::Void) { @@ -627,11 +632,11 @@ impl WasmInterpreter { let data2 = Arc::clone(&data); - Ext::log_debug(format!("Registered wasm function: env::{name}")); + Ext::log_debug(format!("Registered wasm function: env::{internal_name} {}", ft)); linker.func_new( "env", - name.as_str(), + internal_name.as_str(), ft, move |caller, ps, rs| { wasm_bind_env::(&data2, caller, &cap, ps, rs, pts.as_slice(), &callback) diff --git a/turing/src/lib.rs b/turing/src/lib.rs index 7a108ad..a2bf1ee 100644 --- a/turing/src/lib.rs +++ b/turing/src/lib.rs @@ -183,6 +183,11 @@ impl Turing { "script file has no extension, must be either .wasm or .lua" )); }; + + + for cap in &capabilities { + Ext::log_info(format!("Registered capability: {}", cap)); + } match extension.to_string_lossy().as_ref() { #[cfg(feature = "wasm")] "wasm" => {