Klee: A Language for Describing Shapes

Klee is a language that actors can use to communicate a potentially dynamic graphic to render to the screen, and also subscribe to specific user input events. For those with React js experience, it is similar to the JSX language you return from react components, except more generalized for native GPU-accelerated computer graphics (e.g. easier to draw raw animated shapes and curves).

Please read the Overview section for more details.

Follow along with the latest developments in the Devlog.

Devlog

Jul 11, 2025

Flexbox sorta working?

Lots of bugs to fix and the current impl is atrocious but it sorta works?

Jun 20, 2025

Ideas Around Entity State

In traditional Syndicate implementations, Entities respond to patterns that get asserted to dataspaces. In the Rust implementation of Syndicate, there are two levels of state management, Actors-level, which are fields that are globally accessible to all Entities within that actor, and Entity-local Rust structs to hold state isolated to that entity.

Syntax Experiments

One way I’ve been working on Klee, is to sketch out example programs and explain how they should behave, before the implementation can sufficiently execute the commands I’m drawing out.

During

The during keyword is used in proper syndicate implementations, and plays the same roll in Klee. It takes the default form:

(during P <E_b> <E> <E_r>)
  • P is the pattern we are matching the dataspace against

  • E_b denotes “expression before” and is the expression run for a defined amount of time “before” the assertion appears. The idea here is to have three dedicated lifetimes of a shape “before” “during” and “after”. Because we cannot predict the future, before instead needs to start when the assertion is first asserted, and as mentioned previously, lives for a defined amount of time in this state. One major use case for this is fade-in animations.

Overview

A diagram of 2 actors, A and B asserting fragments of a klee program to a third actor, K.

Two Syndicate actors, A and B, make assertions into a Klee dataspace.

Background

The problem: We have an actor that has a rich internal model of some domain, and we want to use this model to generate a graphic design and render it to the user, how do we do this?

Notes

Current Object type definition

Will try to keep this updated as currently there’s a lot of placeholders:

pub enum Object {
    Void,
    Keyword(String),
    BinaryOp(String),
    Integer(i64),
    Float(f64),
    Bool(bool),
    String(String),
    Symbol(String),
    ListData(Vec<Object>),
    Lambda(Vec<String>, Rc<Vec<Object>>, Rc<RefCell<Env>>),
    List(Rc<Vec<Object>>),
    Now, //value that get's replaced with the current instant when it is eval'd
    Instant(std::time::Instant), //timestamp 
    Duration(std::time::Duration),
    // relative dimensions get replaced with absolute positions 
    // when evaluated in environments with absolute parent dimensions
    // top level view evals always have absolute sizes which "trickle down"
    ParentWidth(f64),     
    ParentHeight(f64),
    ViewWidth(f64),
    ViewHeight(f64),
    Shape(i64), //placeholder
    Color(DynamicColor),
    Brush(i64), //placeholder
    Draw(Draw), //drawop is a (brush, shape) tuple
    Text(i64), //placeholder
    Image(peniko::Image), //placeholder
    // no real clue yet how I want to deal with these
    Texture(i64),
    Shader(i64),
    Pipeline,
}

Actor and process overview of current wayland actor implementation:

A diagram of 2 actors, A and B asserting fragments of a klee program to a third actor, K.

Two Syndicate actors, A and B, make assertions into a Klee dataspace, DS_k. Klee actor, K is also connected to the dataspace, and has a linked task, K_L running, which forks off a separate thread K_i, which runs the wayland client and klee interpreter.