Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: add rust kcl plugin guide documents #466

Merged
merged 1 commit into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions docs/reference/plugin/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<ValueRef> {
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<RefCell<Context>> {
let mut plugin_functions: IndexMap<String, PluginFunction> = 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)
```
Original file line number Diff line number Diff line change
Expand Up @@ -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<ValueRef> {
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<RefCell<Context>> {
let mut plugin_functions: IndexMap<String, PluginFunction> = 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)
```
Loading