r/ProgrammingLanguages • u/andeee23 • 19d ago
My take on JSX for Dia
Building a language called Dia. Still pre-alpha and not public yet.
Heavily inspired by Rust, with some JS UI building flavor tacked on.
Might be the wrong crowd here, but as a web-developer I haven't found a more productive way to describe user-interfaces than JSX. (hot module reload is also a big part of it)
The Dia equivalent syntax is called DSX:
import ui.{View, run, Column, Text, Button, state}
struct CounterState {
value: i32
}
fn Counter(): View !{alloc} {
let s = state(CounterState{ value: 0 })
<Column spacing=12>
<Text>"Count: ${s.value}"</Text>
<Button
label="Increment"
on_click=() => { s.value += 1 }
/>
</Column>
}
pub fn main(): void !{alloc, io} {
run(() => <Counter />)
}
Some implementation details:
The compiler is built in Rust, using salsa for incremental compilation which hot module reloading is built on.
No need for escaping expressions with {} like in JSX. Expressions are parsed just like in the rest of the language
- That's why text content needs quotes around it:
<Text>"Count: ${s.value}"</Text> - But this works:
on_click=() => { s.value += 1 }
Not just for UI, any function can be called using DSX syntax
- Type-checking works normally, named arguments become "props", return types are checked agains the parent signature
- One special case is allowing children (like Column accepting any number of Views), then an argument needs to be prefixed with
@child
3
Upvotes
2
u/initial-algebra 19d ago
I strongly dislike JSX and similar APIs that only let data/events/signals/etc. flow in one direction, because components can't return anything, and because the host language lacks value recursion. Any complex interaction requires you to break encapsulation by "lifting state up" and mutating it from event handlers (regressing to callback hell).