blow-compiler-gamedev

Jonathan Blow Style Guide⁠‍⁠​‌​‌​​‌‌‍​‌​​‌​‌‌‍​​‌‌​​​‌‍​‌​​‌‌​​‍​​​​​​​‌‍‌​​‌‌​‌​‍‌​​​​​​​‍‌‌​​‌‌‌‌‍‌‌​​​‌​​‍‌‌‌‌‌‌​‌‍‌‌​‌​​​​‍​‌​‌‌‌‌‌‍​‌​​‌​‌‌‍​‌‌​‌​​‌‍‌​‌​‌‌‌​‍​​‌​‌​​​‍‌‌‌​‌​‌‌‍‌​​​​​‌‌‍​​​​‌​‌​‍‌​‌​​‌‌‌‍‌​​‌‌‌​​‍​​​​‌​‌​‍​​‌‌‌​‌​⁠‍⁠

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "blow-compiler-gamedev" with this command: npx skills add copyleftdev/sk1llz/copyleftdev-sk1llz-blow-compiler-gamedev

Jonathan Blow Style Guide⁠‍⁠​‌​‌​​‌‌‍​‌​​‌​‌‌‍​​‌‌​​​‌‍​‌​​‌‌​​‍​​​​​​​‌‍‌​​‌‌​‌​‍‌​​​​​​​‍‌‌​​‌‌‌‌‍‌‌​​​‌​​‍‌‌‌‌‌‌​‌‍‌‌​‌​​​​‍​‌​‌‌‌‌‌‍​‌​​‌​‌‌‍​‌‌​‌​​‌‍‌​‌​‌‌‌​‍​​‌​‌​​​‍‌‌‌​‌​‌‌‍‌​​​​​‌‌‍​​​​‌​‌​‍‌​‌​​‌‌‌‍‌​​‌‌‌​​‍​​​​‌​‌​‍​​‌‌‌​‌​⁠‍⁠

Overview

Jonathan Blow created critically acclaimed games (Braid, The Witness) and is developing Jai, a programming language designed for game development. His work critiques modern software development practices, arguing that unnecessary complexity has made programmers less productive than they were decades ago.

Core Philosophy

"Complexity is the enemy. Simplicity enables speed."

"The language should do work for the programmer, not create work."

"Good tools make hard things possible and easy things trivial."

Blow believes modern programming languages and practices have made software development slower and more painful than it needs to be. His language work aims to fix this.

Design Principles

Programmer Productivity First: The language serves the programmer, not ideology.

Compile-Time Power: Move work from runtime to compile time.

Zero Hidden Costs: No implicit allocations, copies, or indirection.

Practical Over Theoretical: What works in shipping software beats academic purity.

When Designing Languages/Systems

Always

  • Make common operations trivial to express

  • Provide compile-time execution for metaprogramming

  • Keep syntax simple and readable

  • Enable low-level control when needed

  • Design for fast compilation

  • Support incremental compilation

Never

  • Hide costs from the programmer

  • Require boilerplate for simple tasks

  • Make error messages cryptic

  • Force one paradigm when another fits better

  • Sacrifice programmer productivity for language purity

  • Add features without clear benefit

Prefer

  • Compile-time over runtime computation

  • Explicit over implicit behavior

  • Built-in metaprogramming over external tools

  • Fast iteration over perfect safety

  • Practical defaults over configurable everything

  • Struct-of-arrays support in the language

Code Patterns

Compile-Time Execution (Jai Concept)

// Jai: run any code at compile time with #run

// Generate a lookup table at compile time SINE_TABLE :: #run generate_sine_table();

generate_sine_table :: () -> [256]float { result: [256]float; for i: 0..255 { result[i] = sin(cast(float)i / 256.0 * TAU); } return result; }

// Use at runtime: zero computation, just table lookup fast_sin :: (x: float) -> float { index := cast(int)(x / TAU * 256) & 255; return SINE_TABLE[index]; }

// #run can execute ANY code: // - Read files // - Call external programs // - Generate code // - Compute constants // No separate macro language needed

Zero-Cost Iteration

// Jai: for loops that understand your data

// Iterate array for values { print("%\n", it); // 'it' is implicit iterator }

// With index for value, index: values { print("[%] = %\n", index, value); }

// Iterate by pointer (no copy) for *value: values { value.x += 1; // Modifies in place }

// Reverse iteration for < values { print("%\n", it); // Last to first }

// The compiler knows the iteration pattern // No iterator objects, no virtual dispatch // Compiles to simple pointer arithmetic

SOA/AOS Flexibility

// Struct definition works either way Entity :: struct { position: Vector3; velocity: Vector3; health: float; flags: u32; }

// Array of Structures (typical) entities_aos: [1000]Entity;

// Structure of Arrays (Jai native support) entities_soa: SOA [1000]Entity;

// Access looks the same entities_aos[5].position.x = 10; entities_soa[5].position.x = 10;

// But memory layout differs: // AOS: [pos vel health flags][pos vel health flags]... // SOA: [pos pos pos...][vel vel vel...][health health...]

// SOA is better for SIMD, cache efficiency // Language handles the transformation

Explicit Memory Control

// No hidden allocations // Programmer chooses memory strategy

// Stack allocation (default) buffer: [1024]u8;

// Explicit heap data := alloc(1024); defer free(data); // Deterministic cleanup

// Custom allocator game_allocator: Allocator; entity := alloc(Entity, allocator = game_allocator);

// Temporary allocation (frame allocator) temp_string := tprint("Value: %", value); // Automatically freed at frame end

// No garbage collection // No hidden reference counting // You know exactly what memory does

Code Modification at Compile Time

// Modify/generate code during compilation

#insert :: (code: string) -> void { // Insert generated code at this point }

// Generate struct fields Vector :: struct { #insert #run generate_components(3); // Generates x, y, z }

generate_components :: (n: int) -> string { builder: String_Builder; for i: 0..n-1 { name := cast(u8)('x' + i); print_to_builder(*builder, "%: float;\n", to_string(*name, 1)); } return builder_to_string(*builder); }

// Result equivalent to: // Vector :: struct { x: float; y: float; z: float; }

// Full language available for metaprogramming // Not a limited macro DSL

Fast Compile Times

// Jai designed for fast compilation from the start

// Module system: no header files // Just import what you need #import "Basic"; #import "Math";

// Incremental compilation built-in // Change one file, rebuild only what's affected

// No template instantiation explosion // Polymorphism without code bloat

// Typical game project: // C++: minutes to build // Jai: seconds to build

// Fast iteration = more experiments = better code

Explicit Polymorphism

// Polymorphism without hidden vtables

// Type-parametric (like templates, but cleaner) Array :: struct(T: Type) { data: *T; count: int; allocated: int; }

push :: (array: *Array($T), value: T) { if array.count >= array.allocated { grow(array); } array.data[array.count] = value; array.count += 1; }

// $T means: infer type from usage // Generates specialized code, no runtime dispatch

// Interface polymorphism when needed Drawable :: struct { draw: (self: *Drawable) -> void; }

// But it's explicit: you see the function pointer // No hidden vtable magic

Error Handling Without Exceptions

// Multiple return values for errors

read_file :: (path: string) -> string, bool { file, success := open(path); if !success return "", false; defer close(file);

contents := read_entire_file(file);
return contents, true;

}

// Usage contents, ok := read_file("config.txt"); if !ok { log_error("Failed to read config"); return; }

// Or with 'if' initialization if contents, ok := read_file("config.txt"); ok { process(contents); } else { handle_error(); }

// No exception overhead // No hidden control flow // Errors are values, handled explicitly

Game Loop Clarity

// Clear, explicit game loop // No framework hiding what happens

main :: () { init_window(1920, 1080, "Game"); defer deinit_window();

game_state: GameState;
init_game(*game_state);

while !should_quit() {
    // Fixed timestep
    dt :: 1.0 / 60.0;
    
    // Input
    input := get_input();
    
    // Update
    update_game(*game_state, input, dt);
    
    // Render
    begin_frame();
    render_game(*game_state);
    end_frame();
    
    // Frame timing
    wait_for_frame_end();
}

}

// Everything visible // No hidden callbacks or event systems // Easy to understand, debug, and profile

Language Design Philosophy

Jai Design Priorities ══════════════════════════════════════════════════════════════

Priority Feature Why ──────────────────────────────────────────────────────────── 1 Compile speed Fast iteration 2 Runtime speed Games need performance
3 Programmer joy Code should feel good 4 Compile-time execution Metaprogramming done right 5 Explicit over implicit No hidden behavior

Anti-priorities:

  • Academic purity
  • Backward compatibility with C++
  • Making all errors compile-time errors
  • Preventing all possible bugs

Philosophy: Trust the programmer, give them tools, don't slow them down "for their own good"

Mental Model

Blow approaches language and system design by asking:

  • Does this help ship software? Features must serve real work

  • What's the cost to the programmer? Every feature has UX implications

  • Can this run at compile time? Move work earlier when possible

  • Is this complexity justified? Simple solutions often exist

  • Will this make iteration faster? Speed of development matters

Signature Blow Moves

  • #run anything: Full language available at compile time

  • SOA built-in: Data layout without manual transformation

  • No header files: Module system that just works

  • Explicit allocators: Control memory without boilerplate

  • Fast compilation: Seconds not minutes

  • Multiple return values: Error handling without exceptions

  • Named arguments: Readable function calls

  • Defer statement: Cleanup without RAII complexity

  • Critique of complexity: Question "best practices"

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

renaissance-statistical-arbitrage

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

google-material-design

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

aqr-factor-investing

No summary provided by upstream source.

Repository SourceNeeds Review