Expand description
§dew-core
Minimal expression language, multiple backends.
This crate provides a simple expression parser that compiles string expressions into evaluable ASTs. Variables and functions are provided by the caller—nothing is hardcoded—making it suitable for user-facing expression inputs, shader parameter systems, and dynamic computation pipelines.
§Design Philosophy
- Minimal by default: Core supports only arithmetic and variables
- Opt-in complexity: Enable
condfor conditionals,funcfor function calls - No runtime dependencies: Pure Rust, no allocations during evaluation
- Backend-agnostic: AST can be compiled to WGSL, Lua, Cranelift, or evaluated directly
§Features
| Feature | Description |
|---|---|
introspect | AST introspection (free_vars, etc.) - enabled by default |
cond | Conditionals (if/then/else), comparisons (<, <=, etc.), boolean logic (and, or, not) |
func | Function calls via [ExprFn] trait and [FunctionRegistry] |
§Syntax Reference
§Operators (by precedence, low to high)
| Precedence | Operators | Description |
|---|---|---|
| 1 | if c then a else b | Conditional (requires cond) |
| 2 | a or b | Logical OR, short-circuit (requires cond) |
| 3 | a and b | Logical AND, short-circuit (requires cond) |
| 4 | < <= > >= == != | Comparison (requires cond) |
| 5 | a + b, a - b | Addition, subtraction |
| 6 | a * b, a / b | Multiplication, division |
| 7 | a ^ b | Exponentiation (right-associative) |
| 8 | -a, not a | Negation, logical NOT (not requires cond) |
| 9 | (a), f(a, b) | Grouping, function calls (calls require func) |
§Literals and Identifiers
- Numbers:
42,3.14,.5,1.0 - Variables: Any identifier (
x,time,my_var) - Functions: Identifier followed by parentheses (
sin(x),clamp(x, 0, 1))
§Boolean Semantics (with cond feature)
0.0is false, any non-zero value is true- Comparisons and boolean operators return
1.0(true) or0.0(false) and/oruse short-circuit evaluation
§Examples
§Basic Arithmetic
use wick_core::Expr;
use std::collections::HashMap;
let expr = Expr::parse("x * 2 + y").unwrap();
let mut vars = HashMap::new();
vars.insert("x".to_string(), 3.0);
vars.insert("y".to_string(), 1.0);
let value = expr.eval(&vars).unwrap();
assert_eq!(value, 7.0); // 3 * 2 + 1 = 7§Working with the AST
use wick_core::{Expr, Ast, BinOp};
let expr = Expr::parse("a + b * c").unwrap();
// Inspect the AST structure
match expr.ast() {
Ast::BinOp(BinOp::Add, left, right) => {
assert!(matches!(left.as_ref(), Ast::Var(name) if name == "a"));
assert!(matches!(right.as_ref(), Ast::BinOp(BinOp::Mul, _, _)));
}
_ => panic!("unexpected AST structure"),
}§Custom Functions (with func feature)
ⓘ
use wick_core::{Expr, ExprFn, FunctionRegistry, Ast};
use std::collections::HashMap;
struct Clamp;
impl ExprFn for Clamp {
fn name(&self) -> &str { "clamp" }
fn arg_count(&self) -> usize { 3 }
fn call(&self, args: &[f32]) -> f32 {
args[0].clamp(args[1], args[2])
}
}
let mut registry = FunctionRegistry::new();
registry.register(Clamp);
let expr = Expr::parse("clamp(x, 0, 1)").unwrap();
let mut vars = HashMap::new();
vars.insert("x".to_string(), 1.5);
let value = expr.eval(&vars, ®istry).unwrap();
assert_eq!(value, 1.0); // clamped to [0, 1]§Conditionals (with cond feature)
ⓘ
use wick_core::Expr;
use std::collections::HashMap;
let expr = Expr::parse("if x > 0 then x else -x").unwrap(); // absolute value
let mut vars = HashMap::new();
vars.insert("x".to_string(), -5.0);
let value = expr.eval(&vars).unwrap();
assert_eq!(value, 5.0);Structs§
- Expr
- A parsed expression that can be evaluated or inspected.
Enums§
- Ast
- Abstract syntax tree node for expressions.
- BinOp
- Binary operators for arithmetic and bitwise operations.
- Eval
Error - Expression evaluation error.
- Parse
Error - Expression parse error.
- UnaryOp
- Unary operators.
Traits§
- Numeric
- Trait for types that can be used as numeric values in expressions.