wick-core 0.1.0

Core expression language for wick
Documentation
  • Coverage
  • 80.95%
    34 out of 42 items documented6 out of 16 items with examples
  • Size
  • Source code size: 118.72 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 4.39 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 18s Average build duration of successful builds.
  • all releases: 18s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • rhi-zone/wick
    0 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • pterror

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 cond for conditionals, func for 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.0 is false, any non-zero value is true
  • Comparisons and boolean operators return 1.0 (true) or 0.0 (false)
  • and/or use 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);

# #[cfg(not(feature = "func"))]
let value = expr.eval(&vars).unwrap();
# #[cfg(feature = "func")]
# let value = expr.eval(&vars, &wick_core::FunctionRegistry::new()).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, &registry).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);

# #[cfg(not(feature = "func"))]
let value = expr.eval(&vars).unwrap();
# #[cfg(feature = "func")]
# let value = expr.eval(&vars, &wick_core::FunctionRegistry::new()).unwrap();
assert_eq!(value, 5.0);