diff --git a/docs/reference/plugin/overview.md b/docs/reference/plugin/overview.md index e1005a57..23d66642 100644 --- a/docs/reference/plugin/overview.md +++ b/docs/reference/plugin/overview.md @@ -174,3 +174,79 @@ import kcl_plugin.my_plugin result = my_plugin.add(1, 1) ``` + +## Use Rust to Write Plugins + +### 0. Prerequisites + +Using the KCL Rust plugin requires the presence of `Rust 1.79+` in your `PATH` and install the KCL Rust SDK. + +```shell +cargo add anyhow +cargo add kclvm-parser --git https://github.com/kcl-lang/kcl +cargo add kclvm-loader --git https://github.com/kcl-lang/kcl +cargo add kclvm-evaluator --git https://github.com/kcl-lang/kcl +cargo add kclvm-runtime --git https://github.com/kcl-lang/kcl +``` + +### 1. Hello Plugin + +Write the following Rust code and add the the plugin named `my_plugin`. + +```rust +use anyhow::{anyhow, Result}; +use kclvm_evaluator::Evaluator; +use kclvm_loader::{load_packages, LoadPackageOptions}; +use kclvm_parser::LoadProgramOptions; +use kclvm_runtime::{Context, IndexMap, PluginFunction, ValueRef}; +use std::{cell::RefCell, rc::Rc, sync::Arc}; + +fn my_plugin_sum(_: &Context, args: &ValueRef, _: &ValueRef) -> Result { + let a = args + .arg_i_int(0, Some(0)) + .ok_or(anyhow!("expect int value for the first param"))?; + let b = args + .arg_i_int(1, Some(0)) + .ok_or(anyhow!("expect int value for the second param"))?; + Ok((a + b).into()) +} + +fn context_with_plugin() -> Rc> { + let mut plugin_functions: IndexMap = Default::default(); + let func = Arc::new(my_plugin_sum); + plugin_functions.insert("my_plugin.add".to_string(), func); + let mut ctx = Context::new(); + ctx.plugin_functions = plugin_functions; + Rc::new(RefCell::new(ctx)) +} + +fn main() -> Result<()> { + let src = r#" +import kcl_plugin.my_plugin + +sum = my_plugin.add(1, 1) +"#; + let p = load_packages(&LoadPackageOptions { + paths: vec!["test.k".to_string()], + load_opts: Some(LoadProgramOptions { + load_plugins: true, + k_code_list: vec![src.to_string()], + ..Default::default() + }), + load_builtin: false, + ..Default::default() + })?; + let evaluator = Evaluator::new_with_runtime_ctx(&p.program, context_with_plugin()); + let result = evaluator.run()?; + println!("yaml result {}", result.1); + Ok(()) +} +``` + +The content of `test.k` are: + +```python +import kcl_plugin.my_plugin + +result = my_plugin.add(1, 1) +``` diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/reference/plugin/overview.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/reference/plugin/overview.md index 5a0504e0..e9f8dbea 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/reference/plugin/overview.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/reference/plugin/overview.md @@ -173,3 +173,79 @@ import kcl_plugin.my_plugin result = my_plugin.add(1, 1) ``` + +## 使用 Rust 编写插件 + +### 0. 先决条件 + +使用 KCL Rust 插件需要在您的 PATH 中具有 Rust 1.79+,并安装 KCL Rust SDK。 + +```shell +cargo add anyhow +cargo add kclvm-parser --git https://github.com/kcl-lang/kcl +cargo add kclvm-loader --git https://github.com/kcl-lang/kcl +cargo add kclvm-evaluator --git https://github.com/kcl-lang/kcl +cargo add kclvm-runtime --git https://github.com/kcl-lang/kcl +``` + +### 1. 你好插件 + +编写以下 Rust 代码并添加名为 `my_plugin` 的插件。 + +```rust +use anyhow::{anyhow, Result}; +use kclvm_evaluator::Evaluator; +use kclvm_loader::{load_packages, LoadPackageOptions}; +use kclvm_parser::LoadProgramOptions; +use kclvm_runtime::{Context, IndexMap, PluginFunction, ValueRef}; +use std::{cell::RefCell, rc::Rc, sync::Arc}; + +fn my_plugin_sum(_: &Context, args: &ValueRef, _: &ValueRef) -> Result { + let a = args + .arg_i_int(0, Some(0)) + .ok_or(anyhow!("expect int value for the first param"))?; + let b = args + .arg_i_int(1, Some(0)) + .ok_or(anyhow!("expect int value for the second param"))?; + Ok((a + b).into()) +} + +fn context_with_plugin() -> Rc> { + let mut plugin_functions: IndexMap = Default::default(); + let func = Arc::new(my_plugin_sum); + plugin_functions.insert("my_plugin.add".to_string(), func); + let mut ctx = Context::new(); + ctx.plugin_functions = plugin_functions; + Rc::new(RefCell::new(ctx)) +} + +fn main() -> Result<()> { + let src = r#" +import kcl_plugin.my_plugin + +sum = my_plugin.add(1, 1) +"#; + let p = load_packages(&LoadPackageOptions { + paths: vec!["test.k".to_string()], + load_opts: Some(LoadProgramOptions { + load_plugins: true, + k_code_list: vec![src.to_string()], + ..Default::default() + }), + load_builtin: false, + ..Default::default() + })?; + let evaluator = Evaluator::new_with_runtime_ctx(&p.program, context_with_plugin()); + let result = evaluator.run()?; + println!("yaml result {}", result.1); + Ok(()) +} +``` + +test.k 的内容为: + +```python +import kcl_plugin.my_plugin + +result = my_plugin.add(1, 1) +```