Pry is a simple, statically-typed programming language that compiles to native code via LLVM. It features a minimal C-like syntax with basic functional programming elements. Pry is fully self-hosted, meaning the compiler is written in Pry itself and can compile its own source code.
- Static typing with explicit type annotations
- Basic functions with parameters and return types
- Structs with field access
- Manual memory management via C library functions
- C interoperability through extern declarations
- Simple import system for code organization
- LLVM backend for native code generation
- LLVM development libraries
- A C compiler (gcc/clang) for linking
If you have Nix with flakes enabled:
# Enter development shell with all dependencies
nix develop
The flake provides LLVM and debugging tools.
Pry is now fully self-hosted! The compiler is written in Pry and compiles itself through a multi-stage bootstrap process:
-
Bootstrap the compiler:
./bootstrap.sh
This creates a 3-stage bootstrap:
- Stage 0: Compiles the initial LLVM IR (
bootstrap/output.ll
) to create the first compiler - Stage 1: Uses stage0 to compile the Pry source code (
src/main.pry
) - Stage 2: Uses stage1 to recompile itself (verification step)
- Stage 3: Uses stage2 to recompile itself again (final verification)
- Stage 0: Compiles the initial LLVM IR (
-
Compile a Pry program:
./stage3 examples/1.pry
-
Link and create executable:
cc bootstrap_output.o -o program
-
Run the program:
./program
/* Hello World */
import "!stdlib.pry";
let main = () => i64 {
printf("Hello, World!\n");
return 0;
};
let x = 42; /* i64 integer */
let name = "Alice"; /* String literal (*i8) */
let flag = true; /* Boolean */
Built-in types:
i64
,i32
,i8
- Signed integersbool
- Boolean values*T
- Pointers to type Tvoid
- Unit type
/* Function with explicit parameter types */
let add = (a: i64, b: i64) => i64 {
return a + b;
};
/* Recursive function */
let fib = (n: i64) => i64 {
if n == 0 {
return 0;
};
if n == 1 {
return 1;
};
return fib(n-2) + fib(n-1);
};
/* If statements (no else yet) */
if condition {
// statements
};
/* While loops */
let i = 0;
while i < 10 {
printf("%d\n", i);
i = i + 1;
};
/* Define a struct type */
let Point = struct {
x: i64,
y: i64
};
let main = () => i64 {
let p = Point{}; /* Empty initialization */
p.x = 10; /* Field assignment */
p.y = 20;
return 0;
};
/* Use C library functions for memory management */
extern malloc = (i64) => *void;
extern free = (*void) => void;
let main = () => i64 {
let ptr = cast(*i64, malloc(8));
*ptr = 42;
free(cast(*void, ptr));
return 0;
};
/* Declare external C functions */
extern putchar = (i64) => i64;
let main = () => i64 {
putchar(72); // 'H'
putchar(105); // 'i'
putchar(10); // '\n'
return 0;
};
Pry is a work-in-progress language with several limitations:
- Very basic type system
- Limited error handling
- No arrays (use pointers and manual indexing)
- No string manipulation beyond C functions
- No generics or templates
- No pattern matching
The examples/
directory contains test programs showing:
- Basic I/O (
examples/1.pry
) - Recursive functions (
examples/8.pry
) - Memory management (
examples/20.pry
) - Struct usage (
examples/22.pry
,examples/24.pry
) - C library integration (
examples/15.pry
)
Try running:
./stage3 examples/8.pry && cc bootstrap_output.o -o fib && ./fib # Fibonacci sequence
./stage3 examples/1.pry && cc bootstrap_output.o -o hello && ./hello # Hello world
./stage3 examples/20.pry && cc bootstrap_output.o -o array && ./array # Array manipulation
The minimal standard library (std/stdlib.pry
) provides:
printf
- C printf wrapperstrcmp
- String comparisonisdigit
,isalpha
- Character classification helpersassert
- Simple assertion function
Pry is now fully self-hosted! The compiler is written in Pry itself:
src/main.pry
- Compiler entry pointsrc/tokenizer.pry
- Lexical analysissrc/parser.pry
- Syntax analysis and AST generationsrc/codegen.pry
- LLVM IR generationbootstrap/output.ll
- Initial LLVM IR for bootstrappingbootstrap.sh
- Multi-stage bootstrap script
The grammar is formally defined in grammar.ebnf
.
Pry is an experimental language that has achieved full self-hosting! The compiler successfully compiles itself through a multi-stage bootstrap process. While functional for basic programs, it's still evolving with new features being added.
Pry is a minimal, self-hosted systems programming language focused on simplicity and clean design.