From 71eea1bdb75ed9795b6c0b37a76610653e919928 Mon Sep 17 00:00:00 2001 From: Richard Carson Date: Mon, 23 Oct 2023 10:13:54 -0400 Subject: [PATCH] Modify extensions for better legacy support --- src/extensions/extension.rs | 124 ++++++++----------------------- src/extensions/function.rs | 103 ++++++++++++++----------- src/extensions/js/extension.js | 8 +- src/extensions/mod.rs | 1 + src/functions/builtins/system.rs | 14 ++-- 5 files changed, 104 insertions(+), 146 deletions(-) diff --git a/src/extensions/extension.rs b/src/extensions/extension.rs index 0cacae4..e40a102 100644 --- a/src/extensions/extension.rs +++ b/src/extensions/extension.rs @@ -40,20 +40,12 @@ pub struct Extension { pub version: String, #[serde(default)] - /// Defines all the functions provided by this extension - pub function_definitions: Option>, + /// Functions supported by this extension + pub functions: HashMap, #[serde(default)] - /// Defines all the decorators provided by this extension - pub decorator_definitions: Option>, - - #[serde(default)] - /// Legacy extension support - pub functions: Option>, - - #[serde(default)] - /// Legacy extension support - pub decorators: Option>, + /// Decorators supported by this extension + pub decorators: HashMap, } impl std::fmt::Display for Extension { @@ -73,14 +65,7 @@ impl Extension { /// # Arguments /// * `name` - Function name pub fn has_function(&self, name: &str) -> bool { - if let Some(functions) = &self.function_definitions { - functions.contains_key(name) - } else if let Some(functions) = &self.functions { - // Legacy function support - functions.contains_key(name) - } else { - false - } + self.functions.contains_key(name) } /// Call a function from the extension @@ -94,22 +79,11 @@ impl Extension { args: &[Value], variables: &mut HashMap, ) -> Result { - if let Some(functions) = &self.function_definitions { - let function_properties = functions - .get(name) - .ok_or(rustyscript::Error::ValueNotFound(name.to_string()))?; - function_properties.call(&self.module, args, variables) - } else if let Some(functions) = &self.functions { - // Legacy function support - let function_name = functions - .get(name) - .ok_or(rustyscript::Error::ValueNotFound(name.to_string()))?; - ExtensionFunction::call_legacy(function_name, &self.module, args) - } else { - Err(rustyscript::Error::JsonDecode( - "invalid extension definition".to_string(), - )) - } + let function_properties = self + .functions + .get(name) + .ok_or(rustyscript::Error::ValueNotFound(name.to_string()))?; + function_properties.call(&self.module, args, variables) } /// Determine if a decorator exists in the extension @@ -117,14 +91,7 @@ impl Extension { /// # Arguments /// * `name` - Decorator name pub fn has_decorator(&self, name: &str) -> bool { - if let Some(decorators) = &self.decorator_definitions { - decorators.contains_key(name) - } else if let Some(decorators) = &self.decorators { - // Legacy function support - decorators.contains_key(name) - } else { - false - } + self.decorators.contains_key(name) } /// Call a decorator from the extension @@ -138,24 +105,13 @@ impl Extension { token: &Token, variables: &mut HashMap, ) -> Result { - if let Some(decorator) = &self.decorator_definitions { - let function_properties = decorator - .get(name) - .ok_or(rustyscript::Error::ValueNotFound(name.to_string()))?; - Ok(function_properties - .call(&self.module, &[token.value()], variables)? - .to_string()) - } else if let Some(decorator) = &self.decorators { - // Legacy function support - let function_name = decorator - .get(name) - .ok_or(rustyscript::Error::ValueNotFound(name.to_string()))?; - ExtensionFunction::call_legacy_decorator(function_name, &self.module, token.value()) - } else { - Err(rustyscript::Error::JsonDecode( - "invalid extension definition".to_string(), - )) - } + let function_properties = self + .decorators + .get(name) + .ok_or(rustyscript::Error::ValueNotFound(name.to_string()))?; + function_properties + .call(&self.module, &[token.value()], variables) + .and_then(|v| Ok(v.to_string())) } /// Returns the file from which an extension was loaded @@ -180,56 +136,36 @@ impl Extension { /// Return the list of all functions in the extension pub fn functions(&self) -> Vec { - let mut function_keys = if let Some(functions) = &self.function_definitions { - functions.keys().cloned().collect() - } else if let Some(functions) = &self.functions { - functions.keys().cloned().collect() - } else { - vec![] - }; - + let mut function_keys: Vec = self.functions.keys().cloned().collect(); function_keys.sort(); function_keys } /// Return the list of all functions, with complete signatures pub fn function_signatures(&self) -> Vec { - let mut function_keys = if let Some(functions) = &self.function_definitions { - functions.values().map(|k| k.signature()).collect() - } else if let Some(functions) = &self.functions { - functions.keys().map(|k| format!("{}()", k)).collect() - } else { - vec![] - }; - + let mut function_keys: Vec = self + .functions + .values() + .map(|k| k.function_signature()) + .collect(); function_keys.sort(); function_keys } /// Return the list of all decorators in the extension pub fn decorators(&self) -> Vec { - let mut decorator_keys = if let Some(decorators) = &self.decorator_definitions { - decorators.keys().cloned().collect() - } else if let Some(decorators) = &self.decorators { - decorators.keys().cloned().collect() - } else { - vec![] - }; - + let mut decorator_keys: Vec = self.decorators.keys().cloned().collect(); decorator_keys.sort(); decorator_keys } /// Return the list of all decorators, with complete signatures pub fn decorator_signatures(&self) -> Vec { - let mut decorator_keys = if let Some(decorators) = &self.decorator_definitions { - decorators.values().map(|k| k.signature()).collect() - } else if let Some(decorators) = &self.decorators { - decorators.keys().map(|k| format!("@{}", k)).collect() - } else { - vec![] - }; - + let mut decorator_keys: Vec = self + .decorators + .values() + .map(|k| k.decorator_signature()) + .collect(); decorator_keys.sort(); decorator_keys } diff --git a/src/extensions/function.rs b/src/extensions/function.rs index 825034b..3b93a46 100644 --- a/src/extensions/function.rs +++ b/src/extensions/function.rs @@ -7,46 +7,51 @@ use std::collections::HashMap; use super::runtime::ExtensionsRuntime; #[derive(Deserialize, Serialize, Clone, Debug, Eq, PartialEq)] -pub struct ExtensionFunction { +pub struct ExtensionFunctionDefinition { pub returns: String, pub argument_types: Vec, pub fname: String, pub ftype: String, } -impl ExtensionFunction { - fn decorator_signature(&self) -> String { - format!( - "[{}] @{}", - self.argument_types - .get(0) - .unwrap_or(&"Any".to_string().to_lowercase()), - self.fname - ) - } +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] +#[serde(untagged)] +pub enum ExtensionFunction { + Legacy(String), + Standard(ExtensionFunctionDefinition), +} - fn function_signature(&self) -> String { - format!( - "{}({}) -> {}", - self.fname, - self.argument_types - .iter() - .map(|a| format!("[{}]", a.to_lowercase())) - .collect::>() - .join(", "), - self.returns.to_lowercase() - ) +impl ExtensionFunction { + pub fn decorator_signature(&self) -> String { + match self { + Self::Legacy(f) => format!("@{}", f), + Self::Standard(f) => format!( + "[{}] @{}", + f.argument_types + .get(0) + .unwrap_or(&"Any".to_string().to_lowercase()), + f.fname + ), + } } - pub fn signature(&self) -> String { - if self.ftype == "decorator" { - self.decorator_signature() - } else { - self.function_signature() + pub fn function_signature(&self) -> String { + match self { + Self::Legacy(f) => format!("{}( ... )", f), + Self::Standard(f) => format!( + "{}({}) -> {}", + f.fname, + f.argument_types + .iter() + .map(|a| format!("[{}]", a.to_lowercase())) + .collect::>() + .join(", "), + f.returns.to_lowercase() + ), } } - pub fn call_legacy( + fn call_legacy( name: &str, module: &Module, args: &[Value], @@ -60,21 +65,7 @@ impl ExtensionFunction { }) } - pub fn call_legacy_decorator( - name: &str, - module: &Module, - arg: Value, - ) -> Result { - ExtensionsRuntime::with(|runtime| match runtime.load_module(module) { - Ok(module_context) => { - let mut _arg = serde_json::to_value(arg.clone())?; - runtime.call_function::(&module_context, name, &[_arg]) - } - Err(e) => Err(e), - }) - } - - pub fn call( + fn call_standard( &self, module: &Module, args: &[Value], @@ -121,4 +112,30 @@ impl ExtensionFunction { } }) } + + pub fn call_legacy_decorator( + name: &str, + module: &Module, + arg: Value, + ) -> Result { + ExtensionsRuntime::with(|runtime| match runtime.load_module(module) { + Ok(module_context) => { + let mut _arg = serde_json::to_value(arg.clone())?; + runtime.call_function::(&module_context, name, &[_arg]) + } + Err(e) => Err(e), + }) + } + + pub fn call( + &self, + module: &Module, + args: &[Value], + variables: &mut HashMap, + ) -> Result { + match self { + Self::Legacy(f) => Self::call_legacy(f, module, args), + Self::Standard(_) => self.call_standard(module, args, variables), + } + } } diff --git a/src/extensions/js/extension.js b/src/extensions/js/extension.js index 73f77d5..cfeffc1 100644 --- a/src/extensions/js/extension.js +++ b/src/extensions/js/extension.js @@ -74,17 +74,17 @@ export class LavendeuxExtension { export() { let properties = { - 'function_definitions': {}, - 'decorator_definitions': {} + 'functions': {}, + 'decorators': {} }; Object.assign(properties, this.properties); for (const name in this.functions) { - properties.function_definitions[name] = this.functions[name].properties; + properties.functions[name] = this.functions[name].properties; } for (const name in this.decorators) { - properties.decorator_definitions[name] = this.decorators[name].properties; + properties.decorators[name] = this.decorators[name].properties; } return properties; diff --git a/src/extensions/mod.rs b/src/extensions/mod.rs index 63c77a4..30fc831 100644 --- a/src/extensions/mod.rs +++ b/src/extensions/mod.rs @@ -4,4 +4,5 @@ mod runtime; mod table; pub use extension::Extension; +pub use function::ExtensionFunction; pub use table::ExtensionTable; diff --git a/src/functions/builtins/system.rs b/src/functions/builtins/system.rs index 0e808c2..04c6e34 100644 --- a/src/functions/builtins/system.rs +++ b/src/functions/builtins/system.rs @@ -130,6 +130,7 @@ pub fn register_functions(table: &mut FunctionTable) { mod test_token { use super::*; + use crate::extensions::ExtensionFunction; #[cfg(feature = "extensions")] use crate::Extension; @@ -213,11 +214,14 @@ mod test_token { name: "Unnamed Extension".to_string(), author: "@anon".to_string(), version: "0.0.0".to_string(), - functions: Some(HashMap::from([("test".to_string(), "test2".to_string())])), - decorators: Some(HashMap::from([("test3".to_string(), "test4".to_string())])), - - function_definitions: None, - decorator_definitions: None, + functions: HashMap::from([( + "test".to_string(), + ExtensionFunction::Legacy("test2".to_string()), + )]), + decorators: HashMap::from([( + "test3".to_string(), + ExtensionFunction::Legacy("test4".to_string()), + )]), }, );