Code Generation Overview

Paradox generates idiomatic code from .dox source files in fifteen target languages. Every target produces type definitions, validators, and (where applicable) serialization code.

How It Works

  1. Parse .dox files into the internal AST

  2. Type-check and validate (including SMT verification)

  3. Traverse the checked AST to emit target-specific code

  4. Write output files to the working directory

Universal Type Mapping

Paradox TypeScript Haskell Rust Python C++ Elixir OCaml Scala C# Java SQL Bash Nix

Integer

number

Integer

i64

int

int64_t

integer()

int

Long

long

long

INTEGER

integer

int

Text

string

Text

String

str

std::string

String.t()

string

String

string

String

TEXT

string

string

Char

string

Char

char

str

char

char()

char

Char

char

char

TEXT

char

string

Boolean

boolean

Bool

bool

bool

bool

boolean()

bool

Boolean

bool

boolean

INTEGER

boolean

bool

Double

number

Double

f64

float

double

float()

float

Double

double

double

REAL

float

float

Unit

null

()

()

None

std::monostate

nil

unit

Unit

void

Void

 — 

null

null

[T]

T[]

[T]

Vec<T>

list[T]

std::vector<T>

[T]

T list

Vector[T]

IReadOnlyList<T>

List<T>

 — 

array[T]

list

{T}

Set<T>

Set T

BTreeSet<T>

set[T]

std::unordered_set<T>

MapSet.t(T)

T list

Set[T]

IReadOnlySet<T>

Set<T>

 — 

array[T]

list

T?

T | null

Maybe T

Option<T>

T | None

std::optional<T>

T | nil

T option

Option[T]

T?

T (nullable)

NULLABLE

T|null

T|null

wrap N: T

branded type

newtype

struct(T)

NewType

struct

struct

abstract type

opaque type

readonly record struct

record

column + CHECK

alias

{ _unwrap = T; }

OCaml and Nix represent sets as sorted lists (Nix deduplicates on cast). Bash has no distinct set type; sets are stored as arrays. SQL does not support collection-typed columns.

Targets

Target Extension Notes

TypeScript

.ts

Interfaces, branded wraps, source maps

Haskell

.hs

Data types, newtypes, Aeson JSON

Rust

.rs

Structs, enums, serde

Python

.py

Dataclasses

Elixir

.ex

Structs, typespecs

C++

.cpp

C++23, nlohmann/json

OCaml

.ml

Records, variants, Yojson

Scala

.scala

Scala 3 case classes

C#

.cs

C# 10 records, nullable types

Java

.java

Records, sealed interfaces, pattern matching

SQL

.sql

SQLite and PostgreSQL DDL

Bash

.sh

Shell constructors and validators

Nix

.nix

Attribute sets, builtins validation

JSON / YAML

.json / .yaml

Constant serialization

Spec

.json

Typed AST output

Framework Generators

Beyond per-language code generation, Paradox includes higher-level generators that produce complete server and client scaffolds from URI specifications:

Generator Description

paradox-express

Express.js server with typed handler stubs

paradox-servant

Haskell Servant API type from URI declarations

paradox-gloo-net

Rust/WASM async HTTP client via gloo-net

paradox-node

Full-stack Express + PostgreSQL CRUD server with auth and HTML views

State Machine Generation

When a specification contains Machine constants, Paradox automatically extracts them and generates standalone state machine modules alongside the normal type codegen. Each generated module includes a state enum, event enum, context struct, and a transition function.

State machines are verified at compile time for determinism, reachability, deadlock freedom, complete event coverage, and liveness before code generation proceeds.

State machine code generation supports eleven targets: TypeScript, Haskell, Rust, Python, C++, Elixir, Scala, OCaml, Nix, Bash, and C#.

See State Machines for the full reference.

Output Conventions

  • Each .dox source file produces one output file per target

  • Files include a "do not edit by hand" header

  • Module naming follows the source file name (e.g., product.doxDox.Product in Haskell)

  • Validators are always generated, even when no valid block exists (they pass all values through)