Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DSL for effect creation and composition #20

Merged
merged 104 commits into from
Mar 1, 2025

Conversation

junkdog
Copy link
Owner

@junkdog junkdog commented Feb 2, 2025

This PR adds a new DSL feature that allows effects to be created and composed using a string-based syntax, in appearance identical to (a tiny subset of) rust. The DSL makes ad-hoc runtime effect debugging/iteration feasible, plus is a pretty neat serialization format.

New Public API

Core Types

  • EffectDsl: Reusable registry and compiler for effect expressions
  • DslCompiler: Produces effects from input DSL. Single use.
  • EffectExpression: Parsed representation of a DSL expression (typically produced by Effect::to_dsl)
  • DslError: Error types for DSL parsing and evaluation
  • Shader::to_dsl: (optional) required for serializing effects to DSL strings.
  • DslFormat: Helper trait for converting types to DSL representation

Key Functions

// Create and configure any custom DSL compilers
let dsl = EffectDsl::new()
    .register("custom_effect", |args| { ... });

// Create a compiler and bind variables
let effect = dsl.compiler()
    .bind("color", Color::Blue)
    .bind("duration", 1000)
    .compile("fx::fade_to(color, (duration, Linear))");

// Convert effects to DSL expressions
let expr = effect.to_dsl()?;
println!("{}", expr); // Prints formatted DSL code

Features

  • String-based syntax for creating and composing effects
  • Variable binding for dynamic values
  • Type-safe argument parsing and validation
  • Pretty-printing of DSL expressions
  • Extension point for custom effects

Examples (tachyonfx DSL)

Basic Effect

fx::fade_to(Color::from_u32(0), (500, Linear))

Complex composition

The DSL, while limited in scope, has bindings and parsers for the more frequently used types and methods.

// line comments are supported by the DSL 
/* and block comments */
let layout = Layout::horizontal([Percentage(50), Percentage(50)])
    .spacing(1)
    .vertical_margin(1)
    .horizontal_margin(2);

let cell_filter = CellFilter::Not(Box::new(CellFilter::Layout(layout, 1)));
let content_area = Rect::new(0, 0, 10, 10);

fx::sweep_in(
    Motion::LeftToRight,
    10,
    0,
    Color::from_u32(0x1d2021), 
    EffectTimer::from_ms(1000, QuadOut)
).with_filter(cell_filter).with_area(content_area);

(The DSL above is valid rust code too, in case it wasn't obvious)

Implementation notes

  • Uses a recursive descent parser for expressions
  • Leverages trait system for type-safe argument handling
  • No breaking changes to the effect API
  • Performance overhead is only at creation time

todo

  • parser-related error reporting
  • docs
  • add example
  • parser: discard comments
  • parser: Offset
  • simple let assignments
  • fix remaining todo:s
  • ops on Rect
  • ensure all parsers correctly identify vars
  • consider simplifying complex parsers with argument() parser
  • parser: CellFilter + apply filter, except Fn-based
  • parser: RepeatMode + repeat compiler
  • parser: Layout
  • use compact_str instead of String
  • Shader::to_dsl/Shader::to_expr
  • parser: Rect
  • parser: Margin
  • FxArg::Var (ref variables must be registered with the script exec context)
  • resolve ambiguity: u32, Duration, EffectTimer
  • script exec context (registered serializers, bound variables; rects, colors etc)
  • deserialization functionality (read args, auto match against input)
  • "compiler"-related error reporting
  • save effect instance to String with pretty formatting

the future

  • rework parsers; split into tokenization and expr parsing
  • improve struct parsing to be agnostic to field declaration order
  • wasmify dsl playground
  • better type introspection for bound variables; remove need for chained method to return self

@junkdog junkdog force-pushed the scriptlike-serialization branch from d2d0fb2 to 3d5d87c Compare February 3, 2025 17:49
@junkdog junkdog self-assigned this Feb 25, 2025
@junkdog junkdog merged commit 978f270 into development Mar 1, 2025
2 checks passed
@junkdog junkdog deleted the scriptlike-serialization branch March 2, 2025 17:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant