← Prism
Prism
Overview Spec Draft Releases
Features
defer orelse zeroinit raw auto-unreachable auto-static
GitHub ↗

Prism Docs

Prism is a C transpiler that adds defer, orelse, and zero-initialization to any C codebase - no rewrite, no migration. Use it as a drop-in compiler replacement with CC=prism.

Install

Prism is a single C file - no dependencies, no build system required.

Linux / macOS

cc prism.c -flto -s -O3 -o prism && ./prism install

Windows (MSVC)

Open a Developer Command Prompt (or run vcvars64.bat) and build:

cl /Fe:prism.exe prism.c /O2 /D_CRT_SECURE_NO_WARNINGS /nologo

Zero dependencies. Prism is a single C file. No libraries, no runtime, no package manager required. Just a C compiler.

Quick start

Compile a file directly:

prism file.c -o file

Transpile to stdout without compiling:

prism transpile file.c

Compile and run in one step:

prism run file.c

Prism preprocesses your source, injects the transforms, and forwards to your real compiler (cc by default, or whatever $CC is set to). All standard compiler flags pass through.

Drop-in overlay

Prism is designed for zero-migration adoption. You don't need to change your build system, source tree, or CI. Set CC=prism and it works with any build system:

Before
gcc -o app main.c util.c
After
prism -o app main.c util.c

Works with any build system that respects CC:

CC=prism cmake --build .
CC=prism ninja
CC=prism make          # if your project uses make
CC=clang prism file.c  # use clang as the backend

Files that don't use any Prism features pass through unchanged. There is no per-file opt-in required.

CLI reference

Prism v1.1.1 - Robust C transpiler

Usage: prism [options] source.c... [-o output]

Commands:
  run <src.c>           Transpile, compile, and run
  transpile <src.c>     Output transpiled C to stdout
  install [src.c...]    Install prism to /usr/local/bin/prism
FlagDescription
-fno-deferDisable defer
-fno-zeroinitDisable zero-initialization
-fno-orelseDisable orelse keyword
-fno-safetySafety checks warn instead of error
-fno-line-directivesDisable #line directives in output
-fno-auto-unreachableDisable __builtin_unreachable after noreturn calls
-fno-auto-staticDisable automatic static promotion of const arrays
-fflatten-headersFlatten headers into single output
--prism-cc=<compiler>Use a specific backend compiler
--prism-verboseShow commands being run
--versionPrint version and exit
--helpPrint usage and exit

All other flags are forwarded verbatim to the backend compiler (-O2, -Wall, -I, -L, -l, etc.).

Multi-file

Pass multiple source files exactly as you would to GCC or Clang:

prism main.c utils.c -o app
prism main.c utils.c -lpthread -o app

Passthrough files: .s/.S (assembly), .cc/.cpp/.cxx (C++), .m/.mm (Objective-C) are forwarded to the compiler without transpilation.

prism main.c boot.s -o kernel       # mix with assembly
prism main.c helper.cpp -o mixed    # C++ passes through untouched

Error reporting

Prism emits #line directives so all compiler errors point to your original source, not the transpiled output:

main.c:42:5: error: use of undeclared identifier 'foo'

Not:

/tmp/prism_xyz.c:1847:5: error: use of undeclared identifier 'foo'

Disable with prism -fno-line-directives src.c (useful for debugging transpiler output).

Prism's own errors also use GCC-compatible format and are emitted before the backend compiler runs - if Prism rejects a file, the backend never sees it:

main.c:14:5: error: defer used outside of function scope

Library mode

Prism can be compiled as a library for embedding in other tools:

# Compile as library (excludes CLI)
cc -DPRISM_LIB_MODE -c prism.c -o prism.o

API:

PrismFeatures prism_defaults(void);
PrismResult   prism_transpile_file(const char *path, PrismFeatures features);
PrismResult   prism_transpile_source(const char *source, const char *filename,
                                      PrismFeatures features);
void          prism_free(PrismResult *r);
void          prism_reset(void);
void          prism_thread_cleanup(void);

Architecture

Prism is a two-pass transpiler. Pass 1 performs full semantic analysis and catches all user-triggerable errors. Pass 2 is a near-pure code generator that reads Pass 1's immutable artifacts.

PhaseWhat it does
Pass 0 - TokenizerTokenize, delimiter-match, keyword-tag, build setjmp/vfork/asm taint graph per function
Pass 1A - Scope TreeWalk all tokens, assign scope IDs, build parent chain, classify each {
Pass 1B - Type RegistrationFull-depth typedef, enum, VLA tag registration - symbol table frozen after this point
Pass 1C - Shadow TableRecord every variable that shadows a typedef, with scope ID and token index
Pass 1D - CFG CollectionPer-function arrays of labels, gotos, defers, declarations, switch/case entries
Pass 1E-1G - ValidationReturn type capture, defer validation, orelse pre-classification
Phase 2A - CFG VerificationO(N) snapshot-and-sweep: verify every goto→label and switch→case pair
Pass 2 - Code GenerationEmit transformed C. Reads immutable artifacts. No type mutations, no safety checks.

Key invariant: Every semantic error is raised before Pass 2 emits its first byte. If code generation starts, it runs to completion.

Self-hosting

Prism compiles itself - the source is written in C using Prism features. To build Prism with Prism:

CC=prism cc prism.c -flto -s -O3 -o prism

Self-hosting is tested in CI on every commit across Linux (x86_64, arm64, riscv64), macOS (x86_64, arm64), and Windows (x86_64).