Skip to main content

Crate wick_core

Crate wick_core 

Source
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 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

FeatureDescription
introspectAST introspection (free_vars, etc.) - enabled by default
condConditionals (if/then/else), comparisons (<, <=, etc.), boolean logic (and, or, not)
funcFunction calls via [ExprFn] trait and [FunctionRegistry]

§Syntax Reference

§Operators (by precedence, low to high)

PrecedenceOperatorsDescription
1if c then a else bConditional (requires cond)
2a or bLogical OR, short-circuit (requires cond)
3a and bLogical AND, short-circuit (requires cond)
4< <= > >= == !=Comparison (requires cond)
5a + b, a - bAddition, subtraction
6a * b, a / bMultiplication, division
7a ^ bExponentiation (right-associative)
8-a, not aNegation, 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);

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, &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);

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.
EvalError
Expression evaluation error.
ParseError
Expression parse error.
UnaryOp
Unary operators.

Traits§

Numeric
Trait for types that can be used as numeric values in expressions.