Skip to content
Open
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
410 changes: 410 additions & 0 deletions core/engine/src/handler/function/module/mf.rs

Large diffs are not rendered by default.

7 changes: 5 additions & 2 deletions core/engine/src/handler/function/module/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ use rquickjs::module::{Declared, Exports};
use rquickjs::{embed, Ctx, Error, Module, Object};

use crate::handler::function::module::http::HttpModule;
use crate::handler::function::module::mf::ModuforgeModule;
use crate::handler::function::module::zen::ZenModule;

pub(crate) mod console;
pub(crate) mod http;
pub(crate) mod zen;
pub mod mf;

static JS_BUNDLE: Bundle = embed! {
"dayjs": "js/dayjs.mjs",
Expand Down Expand Up @@ -61,7 +63,7 @@ struct BaseModuleLoader {

impl BaseModuleLoader {
pub fn new() -> Self {
let mut hs = HashSet::from(["zen".to_string(), "http".to_string()]);
let mut hs = HashSet::from(["zen".to_string(), "http".to_string(),"mf".to_string()]);

JS_BUNDLE.iter().for_each(|(key, _)| {
hs.insert(key.to_string());
Expand All @@ -72,7 +74,8 @@ impl BaseModuleLoader {
defined_modules: RefCell::new(hs),
md_loader: MDLoader::default()
.with_module("zen", ZenModule)
.with_module("http", HttpModule),
.with_module("http", HttpModule)
.with_module("mf", ModuforgeModule),
}
}

Expand Down
2 changes: 2 additions & 0 deletions core/engine/src/handler/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::handler::decision::DecisionHandler;
use crate::handler::expression::ExpressionHandler;
use crate::handler::function::function::{Function, FunctionConfig};
use crate::handler::function::module::console::ConsoleListener;
use crate::handler::function::module::mf::ModuforgeListener;
use crate::handler::function::module::zen::ZenListener;
use crate::handler::function::FunctionHandler;
use crate::handler::function_v1;
Expand Down Expand Up @@ -110,6 +111,7 @@ impl<L: DecisionLoader + 'static, A: CustomNodeAdapter + 'static> DecisionGraph<
loader: self.loader.clone(),
adapter: self.adapter.clone(),
}),
Box::new(ModuforgeListener{})
]),
})
.await
Expand Down
197 changes: 197 additions & 0 deletions core/expression/examples/compilation_demo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
use zen_expression::{Isolate, evaluate_expression, Variable};
use serde_json::json;
use rust_decimal_macros::dec;

fn main() {
println!("=== rules_expression 编译与VM执行过程演示 ===\n");

// 演示1: 基础表达式编译和执行
demo_basic_compilation();

// 演示2: 复杂表达式的字节码分析
demo_complex_expression();

// 演示3: 高性能重复执行
demo_performance_execution();

// 演示4: 不同数据类型的处理
demo_data_types();

// 演示5: 区间和条件表达式
demo_intervals_and_conditions();
}

fn demo_basic_compilation() {
println!("【演示1: 基础表达式编译和执行】");

// 创建上下文环境
let context = json!({
"tax": {
"percentage": 10
},
"amount": 50
});

let expression = "amount * tax.percentage / 100";
println!("表达式: {}", expression);
println!("上下文: {}", context);

// 方式1: 直接评估(内部完成完整的编译->执行流程)
let result =
evaluate_expression(expression, context.clone().into()).unwrap();
println!("计算结果: {:?}", result);

// 方式2: 使用Isolate查看详细过程
let mut isolate = Isolate::with_environment(context.into());

// 编译表达式获取字节码
let compiled = isolate.compile_standard(expression).unwrap();
println!("编译后的字节码: {:?}", compiled.bytecode());

// 执行编译后的表达式
let new_context = json!({"tax": {"percentage": 15}, "amount": 100});
let result2 = compiled.evaluate(new_context.into()).unwrap();
println!("新上下文执行结果: {:?}\n", result2);
}

fn demo_complex_expression() {
println!("【演示2: 复杂表达式的字节码分析】");

let mut isolate = Isolate::new();
let expression = "(a + b) * c - d / 2";

println!("复杂表达式: {}", expression);

// 编译并查看字节码
let compiled = isolate.compile_standard(expression).unwrap();
println!("生成的字节码指令:");
for (i, opcode) in compiled.bytecode().iter().enumerate() {
println!(" {}: {:?}", i, opcode);
}

// 执行演示
let context = json!({"a": 10, "b": 20, "c": 3, "d": 8});
println!("执行上下文: {}", context);

let result = compiled.evaluate(context.into()).unwrap();
println!("计算结果: {:?}", result);
println!("验证: (10 + 20) * 3 - 8 / 2 = 30 * 3 - 4 = 90 - 4 = 86\n");
}

fn demo_performance_execution() {
println!("【演示3: 高性能重复执行】");

let context = json!({
"items": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
"factor": 0.1
});

let mut isolate = Isolate::with_environment(context.into());

// 预编译表达式
let expression = "sum(items) * factor";
let compiled = isolate.compile_standard(expression).unwrap();

println!("表达式: {}", expression);
println!("预编译完成,开始高性能重复执行...");

// 模拟高频执行
let iterations = 100_000;
let start = std::time::Instant::now();

for _ in 0..iterations {
// 重复使用预编译的字节码,VM重用内存
let _result = isolate.run_standard(expression).unwrap();
}

let duration = start.elapsed();
println!("执行 {} 次耗时: {:?}", iterations, duration);
println!("平均每次执行: {:?}", duration / iterations);
println!(
"每秒执行次数: {:.0}\n",
iterations as f64 / duration.as_secs_f64()
);
}

fn demo_data_types() {
println!("【演示4: 不同数据类型处理】");

let context = json!({
"user": {
"name": "Alice",
"age": 25,
"active": true,
"scores": [85, 92, 78, 96]
},
"settings": {
"threshold": 80
}
});

let mut isolate = Isolate::with_environment(context.into());

let test_cases = vec![
(
"user.name + \" is \" + string(user.age) + \" years old\"",
"字符串拼接",
),
("user.age >= 18", "布尔运算"),
("len(user.scores)", "数组长度"),
("max(user.scores)", "数组最大值"),
("avg(user.scores) > settings.threshold", "数组平均值比较"),
];

for (expr, desc) in test_cases {
let result = isolate.run_standard(expr).unwrap();
println!("{}: {} = {:?}", desc, expr, result);
}
println!();
}

fn demo_intervals_and_conditions() {
println!("【演示5: 区间和条件表达式】");

let context = json!({
"student": {
"age": 20,
"score": 85,
"grade": "B+"
},
"rules": {
"adult_age": 18,
"passing_score": 60,
"excellent_score": 90
}
});

let mut isolate = Isolate::with_environment(context.into());

let test_expressions = vec![
("student.age >= rules.adult_age", "成年判断"),
("student.score in [rules.passing_score..100]", "及格区间判断"),
("student.score in [rules.excellent_score..100]", "优秀区间判断"),
(
"student.score in (rules.passing_score..rules.excellent_score)",
"良好区间判断(开区间)",
),
(
"student.age in [18..65) and student.score >= rules.passing_score",
"复合条件",
),
];

for (expr, desc) in test_expressions {
let result = isolate.run_standard(expr).unwrap();
println!("{}: {} = {:?}", desc, expr, result);
}

// 演示区间转换为数组
println!("\n区间数组转换演示:");
let range_expr = "[1..5]";
let compiled = isolate.compile_standard(range_expr).unwrap();
println!("区间表达式: {}", range_expr);
println!("字节码: {:?}", compiled.bytecode());

let result = compiled.evaluate(Variable::empty_object()).unwrap();
println!("区间结果: {:?}", result);
}
86 changes: 86 additions & 0 deletions core/expression/examples/custom_function_demo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use zen_expression::{Isolate, Variable};
use zen_expression::functions::mf_function::{
MfFunctionHelper, MfFunctionRegistry,
};
use zen_expression::variable::VariableType;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};

// 1. 定义一个简单的、我们自己的状态
#[derive(Debug)]
struct MyState {
call_count: Mutex<u32>,
}

impl MyState {
fn new() -> Self {
Self { call_count: Mutex::new(0) }
}

fn increment(&self) -> u32 {
let mut count = self.call_count.lock().unwrap();
*count += 1;
*count
}
}

fn main() -> anyhow::Result<()> {
println!("=== 自定义函数与泛型State集成演示 ===\n");

// === 第一部分: 演示使用我们自定义的 `MyState` ===
println!("--- 场景1: 使用自定义的 MyState ---");
let my_state = Arc::new(MyState::new());

// 2. 为 `MyState` 创建一个 Helper
let my_helper = MfFunctionHelper::<MyState>::new();

// 3. 注册一个可以访问 `MyState` 的函数
println!("注册函数: getMyStateCallCount()");
my_helper
.register_function(
"getMyStateCallCount".to_string(),
vec![],
VariableType::Number,
Box::new(|_args, state_opt: Option<&MyState>| {
if let Some(state) = state_opt {
// `state` 的类型是 &MyState
let count = state.increment();
Ok(Variable::Number(count.into()))
} else {
Ok(Variable::Number((-1i32).into()))
}
}),
)
.map_err(|e| anyhow::anyhow!(e))?;

// 4. 创建 Isolate 并使用 `MyState` 执行表达式
let mut isolate = Isolate::new();
println!("使用 `MyState` 执行 'getMyStateCallCount()'");
let result1 = isolate
.run_standard_with_state("getMyStateCallCount()", my_state.clone())?;
println!(" 第一次调用结果: {}", result1);
let result2 = isolate
.run_standard_with_state("getMyStateCallCount()", my_state.clone())?;
println!(" 第二次调用结果: {}", result2);

// === 第三部分: 验证两种函数可以共存 ===
println!("\n--- 场景3: 验证两种状态的函数可以共存 ---");
println!("再次调用 `getMyStateCallCount` (应为3)");
let result4 = isolate
.run_standard_with_state("getMyStateCallCount()", my_state.clone())?;
println!(" 结果: {}", result4);

// 显示所有已注册的自定义函数
println!("\n=== 已注册的自定义函数 ===");
let functions = MfFunctionRegistry::list_functions();
for func in functions {
println!("- {}", func);
}

// 清理
println!("\n清理所有自定义函数...");
MfFunctionRegistry::clear();

println!("演示完成!");
Ok(())
}
2 changes: 1 addition & 1 deletion core/expression/src/compiler/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ impl<'arena, 'bytecode_ref> CompilerInner<'arena, 'bytecode_ref> {
}),
},
Node::FunctionCall { kind, arguments } => match kind {
FunctionKind::Internal(_) | FunctionKind::Deprecated(_) => {
FunctionKind::Internal(_) | FunctionKind::Deprecated(_) | FunctionKind::Mf(_) => {
let function = FunctionRegistry::get_definition(kind).ok_or_else(|| {
CompilerError::UnknownFunction {
name: kind.to_string(),
Expand Down
Loading