feat: new styles

This commit is contained in:
faynot
2026-07-08 23:45:37 +03:00
parent 9c279015dc
commit 75af23930f
18 changed files with 3556 additions and 816 deletions

View File

@@ -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()
}