feat: new styles
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
use rhai::{Dynamic, Engine, Scope, AST};
|
||||
use rhai::{Dynamic, Engine, Scope, AST, Module};
|
||||
use std::collections::HashMap;
|
||||
use std::cell::RefCell;
|
||||
|
||||
pub const RHEI_PREFIX: &str = "__rhei:";
|
||||
|
||||
pub struct RheiContext {
|
||||
engine: Engine,
|
||||
init_ast: AST,
|
||||
fn_ast: AST,
|
||||
scope: RefCell<Scope<'static>>,
|
||||
}
|
||||
|
||||
impl RheiContext {
|
||||
@@ -29,102 +30,88 @@ impl RheiContext {
|
||||
let mut fn_ast = combined.clone();
|
||||
fn_ast.clear_statements();
|
||||
|
||||
Self {
|
||||
engine,
|
||||
init_ast: combined,
|
||||
fn_ast
|
||||
match Module::eval_ast_as_new(Scope::new(), &fn_ast, &engine) {
|
||||
Ok(module) => {
|
||||
engine.register_global_module(module.into());
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("⚠️ Rhei module creation error: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
Self {
|
||||
engine,
|
||||
init_ast: combined,
|
||||
scope: RefCell::new(Scope::new()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn initialize(&self, variables: &mut HashMap<String, String>) {
|
||||
let mut scope = Scope::new();
|
||||
pub fn sync_scope(&self, variables: &HashMap<String, String>) {
|
||||
let mut scope = self.scope.borrow_mut();
|
||||
|
||||
for (k, v) in variables.iter() {
|
||||
scope.push_dynamic(k.clone(), str_to_dyn(v));
|
||||
}
|
||||
|
||||
if let Err(e) = self.engine.run_ast_with_scope(&mut scope, &self.init_ast) {
|
||||
eprintln!("⚠️ Rhei init error: {e}");
|
||||
}
|
||||
|
||||
let names: Vec<String> = scope.iter_raw()
|
||||
.map(|(name, _, _)| name.to_string())
|
||||
.collect();
|
||||
for name in &names {
|
||||
if let Some(val) = scope.get_value::<Dynamic>(name) {
|
||||
variables.insert(name.clone(), dyn_to_str(&val));
|
||||
if scope.contains(k) {
|
||||
if let Some(old_val) = scope.get_value::<Dynamic>(k) {
|
||||
if dyn_to_str(&old_val) == *v {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
scope.set_value(k, str_to_dyn(v));
|
||||
} else {
|
||||
scope.push_dynamic(k.clone(), str_to_dyn(v));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eval_expr(&self, expr: &str, variables: &HashMap<String, String>) -> Option<String> {
|
||||
let mut scope = Scope::new();
|
||||
for (k, v) in variables {
|
||||
scope.push_dynamic(k.clone(), str_to_dyn(v));
|
||||
pub fn initialize(&self, variables: &mut HashMap<String, String>) {
|
||||
self.sync_scope(variables);
|
||||
|
||||
let mut scope = self.scope.borrow_mut();
|
||||
if let Err(e) = self.engine.run_ast_with_scope(&mut *scope, &self.init_ast) {
|
||||
eprintln!("⚠️ Rhei initialization error: {e}");
|
||||
}
|
||||
|
||||
let expr_ast = self.engine
|
||||
.compile_expression(expr)
|
||||
.or_else(|_| self.engine.compile(expr))
|
||||
.ok()?;
|
||||
for (name, _, val) in scope.iter_raw() {
|
||||
let s_val = dyn_to_str(&val);
|
||||
if variables.get(name).map(|v| v != &s_val).unwrap_or(true) {
|
||||
variables.insert(name.to_string(), s_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let full = self.fn_ast.merge(&expr_ast);
|
||||
pub fn eval_expr(&self, expr: &str, variables: &HashMap<String, String>) -> String {
|
||||
self.sync_scope(variables);
|
||||
let mut scope = self.scope.borrow_mut();
|
||||
|
||||
match self.engine.eval_ast_with_scope::<Dynamic>(&mut scope, &full) {
|
||||
Ok(val) => Some(dyn_to_str(&val)),
|
||||
Err(e) => {
|
||||
eprintln!("⚠️ Rhei eval `{expr}`: {e}");
|
||||
None
|
||||
match self.engine.eval_expression_with_scope::<Dynamic>(&mut *scope, expr) {
|
||||
Ok(val) => dyn_to_str(&val),
|
||||
Err(e) => {
|
||||
eprintln!("⚠️ Rhei eval_expr error: {e}");
|
||||
String::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eval_condition(&self, expr: &str, variables: &HashMap<String, String>) -> bool {
|
||||
let mut scope = Scope::new();
|
||||
for (k, v) in variables {
|
||||
scope.push_dynamic(k.clone(), str_to_dyn(v));
|
||||
}
|
||||
self.sync_scope(variables);
|
||||
let mut scope = self.scope.borrow_mut();
|
||||
|
||||
let ast = match self.engine.compile_expression(expr) {
|
||||
Ok(a) => a,
|
||||
Err(_) => match self.engine.compile(expr) {
|
||||
Ok(a) => a,
|
||||
Err(e) => {
|
||||
eprintln!("⚠️ Rhei condition compile `{expr}`: {e}");
|
||||
return false;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let full = self.fn_ast.merge(&ast);
|
||||
|
||||
match self.engine.eval_ast_with_scope::<Dynamic>(&mut scope, &full) {
|
||||
Ok(val) => {
|
||||
if val.is_bool() { return val.cast::<bool>(); }
|
||||
if val.is_int() { return val.cast::<i64>() != 0; }
|
||||
if val.is_float(){ return val.cast::<f64>() != 0.0; }
|
||||
if val.is_string(){
|
||||
let s = val.cast::<String>();
|
||||
return !matches!(s.trim(), "" | "false" | "0" | "null");
|
||||
}
|
||||
!val.is_unit()
|
||||
}
|
||||
match self.engine.eval_expression_with_scope::<bool>(&mut *scope, expr) {
|
||||
Ok(b) => b,
|
||||
Err(e) => {
|
||||
eprintln!("⚠️ Rhei condition eval `{expr}`: {e}");
|
||||
eprintln!("⚠️ Rhei eval_condition error: {e}");
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn execute_action(&self, script: &str, variables: &mut HashMap<String, String>) {
|
||||
let mut scope = Scope::new();
|
||||
for (k, v) in variables.iter() {
|
||||
scope.push_dynamic(k.clone(), str_to_dyn(v));
|
||||
}
|
||||
self.sync_scope(variables);
|
||||
let mut scope = self.scope.borrow_mut();
|
||||
|
||||
match self.engine.compile(script) {
|
||||
Ok(action_ast) => {
|
||||
let full = self.fn_ast.merge(&action_ast);
|
||||
if let Err(e) = self.engine.run_ast_with_scope(&mut scope, &full) {
|
||||
if let Err(e) = self.engine.run_ast_with_scope(&mut *scope, &action_ast) {
|
||||
eprintln!("⚠️ Rhei action execution error: {e}");
|
||||
}
|
||||
}
|
||||
@@ -133,12 +120,10 @@ impl RheiContext {
|
||||
}
|
||||
}
|
||||
|
||||
let names: Vec<String> = scope.iter_raw()
|
||||
.map(|(name, _, _)| name.to_string())
|
||||
.collect();
|
||||
for name in &names {
|
||||
if let Some(val) = scope.get_value::<Dynamic>(name) {
|
||||
variables.insert(name.clone(), dyn_to_str(&val));
|
||||
for (name, _, val) in scope.iter_raw() {
|
||||
let s_val = dyn_to_str(&val);
|
||||
if variables.get(name).map(|v| v != &s_val).unwrap_or(true) {
|
||||
variables.insert(name.to_string(), s_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -150,7 +135,6 @@ impl Default for RheiContext {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn str_to_dyn(s: &str) -> Dynamic {
|
||||
if let Ok(i) = s.parse::<i64>() { return Dynamic::from(i); }
|
||||
if let Ok(f) = s.parse::<f64>() { return Dynamic::from(f); }
|
||||
@@ -158,12 +142,9 @@ pub fn str_to_dyn(s: &str) -> Dynamic {
|
||||
Dynamic::from(s.to_owned())
|
||||
}
|
||||
|
||||
pub fn dyn_to_str(val: &Dynamic) -> String {
|
||||
if val.is_string() {
|
||||
return val.clone().cast::<String>();
|
||||
pub fn dyn_to_str(d: &Dynamic) -> String {
|
||||
if d.is_string() {
|
||||
return d.clone().into_string().unwrap_or_default();
|
||||
}
|
||||
if val.is_unit() {
|
||||
return String::new();
|
||||
}
|
||||
val.to_string()
|
||||
d.to_string()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user