Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Architecture

This is a brief overview for contributors. For detailed implementation notes, see the project’s CLAUDE.md.

Compilation Pipeline

TypeScript (.ts)
    ↓ Parse (SWC)
    ↓ AST
    ↓ Lower (perry-hir)
    ↓ HIR (High-level IR)
    ↓ Transform (inline, closure conversion, async lowering)
    ↓ Codegen (Cranelift)
    ↓ Object file (.o)
    ↓ Link (system cc)
    ↓
Native Executable

Crate Map

CratePurpose
perryCLI driver, command parsing, compilation orchestration
perry-parserSWC wrapper for TypeScript parsing
perry-typesType system definitions
perry-hirHIR data structures (ir.rs) and AST→HIR lowering (lower.rs)
perry-transformIR passes: function inlining, closure conversion, async lowering
perry-codegenCranelift-based native code generation (12 modules)
perry-codegen-jsJavaScript code generation for --target web
perry-codegen-swiftuiSwiftUI code generation for WidgetKit extensions
perry-runtimeRuntime library: NaN-boxed values, GC, arena allocator, objects, arrays, strings
perry-stdlibNode.js API implementations: mysql2, redis, fastify, bcrypt, etc.
perry-uiShared UI types
perry-ui-macosmacOS UI (AppKit)
perry-ui-iosiOS UI (UIKit)
perry-jsruntimeJavaScript interop via QuickJS

Key Concepts

NaN-Boxing

All JavaScript values are represented as 64-bit NaN-boxed values. The upper 16 bits encode the type tag:

TagType
0x7FFFString (lower 48 bits = pointer)
0x7FFDPointer/Object (lower 48 bits = pointer)
0x7FFEInt32 (lower 32 bits = integer)
0x7FFABigInt (lower 48 bits = pointer)
Special constantsundefined, null, true, false
Any otherFloat64 (the full 64 bits)

Garbage Collection

Mark-sweep GC with conservative stack scanning. Arena-allocated objects (arrays, objects) are found by linear block walking. Malloc-allocated objects (strings, closures, promises) are tracked in a thread-local Vec.

Handle-Based UI

UI widgets are represented as small integer handles NaN-boxed with POINTER_TAG. Each handle maps to a native platform widget (NSButton, UILabel, GtkButton, etc.). Two dispatch tables route method calls and property accesses to the correct FFI function.

Source Code Organization

The codegen crate was split into 12 focused modules:

perry-codegen/src/
  codegen.rs       # Main entry, module compilation
  types.rs         # Type definitions, context structs
  util.rs          # Helper functions
  stubs.rs         # Stub generation for unresolved deps
  runtime_decls.rs # Runtime function declarations
  classes.rs       # Class compilation
  functions.rs     # Function compilation
  closures.rs      # Closure compilation
  module_init.rs   # Module initialization
  stmt.rs          # Statement compilation
  expr.rs          # Expression compilation

The HIR lowering was split into 8 modules:

perry-hir/src/
  lower.rs           # Main lowering entry
  analysis.rs        # Code analysis passes
  enums.rs           # Enum lowering
  jsx.rs             # JSX lowering
  lower_types.rs     # Type lowering
  lower_patterns.rs  # Pattern lowering
  destructuring.rs   # Destructuring lowering
  lower_decl.rs      # Declaration lowering

Next Steps