Pyro Documentation

Welcome to the official documentation for the Pyro programming language. Pyro is a compiled language with 23 keywords, 76 built-in modules, and native C++ speed.

Installation

Install Pyro on your system in under a minute. Pre-built binaries — no compilers or build tools needed.

Linux / macOS

curl -fsSL https://aravindlabs.tech/pyro-lang/install.sh | bash

Windows (PowerShell)

irm https://aravindlabs.tech/pyro-lang/install.ps1 | iex

Downloads Pyro + MinGW C++ toolchain automatically. No Visual Studio, no restarts, no admin needed.

Build from Source (advanced)

Only needed if you want to modify Pyro itself
git clone https://github.com/krish9219/pyro.git
cd pyro
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
sudo make install

Verify the installation:

pyro --version
# Pyro Programming Language v1.0.0

Hello World

Create a file called hello.ro:

# No main() needed — just write code
print("Hello, World!")

Run it:

pyro run hello.ro

Or compile and run the binary:

pyro build hello.ro -o hello
./hello

Your First Program

Let's build a small program that reads a name and greets the user:

import io

print("What is your name?")
name = io.readline()
print("Hello, " + name + "! Welcome to Pyro.")

# Pipe operator example
squares = [1, 2, 3, 4, 5] |> map(|x| x * x)
big = squares |> filter(|x| x > 5)
big |> each(|x| print("Square: {x}"))

Using the REPL

Start the interactive REPL with:

pyro repl
Pyro 1.0.0 REPL — Type :help for commands, :quit to exit
>>> x = 42
>>> x * 2
84
>>> [1,2,3] |> map(|x| x + 10)
[11, 12, 13]

Variables & Types

Pyro is statically typed with type inference. Just assign values directly — no keyword needed. Use mut for mutable variables. The optional let keyword can enforce immutability explicitly.

# Simple assignment (no keyword needed)
name = "Pyro"            # type inferred as str
age = 1                  # int
pi = 3.14159             # float
active = true            # bool
data = nil               # nil value

# Mutable (use mut when you need to reassign)
mut counter = 0
counter = counter + 1

# Optional: use let for explicit immutability
# let locked = 42  # compiler enforces no reassignment

# Collections
list = [1, 2, 3]                        # List<int>
map = { "a": 1, "b": 2 }               # Map<str, int>
tuple = (1, "hello", true)              # (int, str, bool)

Built-in Types

TypeDescriptionExample
int64-bit signed integer42
float64-bit floating point3.14
boolBooleantrue, false
strUTF-8 string"hello"
List<T>Growable array[1, 2, 3]
Map<K,V>Hash map{"a": 1}
nilAbsence of valuenil

Functions

Functions are first-class citizens in Pyro. Declare them with fn.

# Basic function
fn greet(name)
    return "Hello, " + name + "!"

# One-liner
fn add(a, b) = a + b

# Default parameters
fn power(base, exp = 2)
    mut result = 1
    for _ in 0..exp
        result = result * base
    return result

# Higher-order functions
fn apply_twice(f, val)
    return f(f(val))

print(greet("World"))
print(power(3))         # 9 (default exp=2)
print(power(2, 10))    # 1024
print(apply_twice(|x| x * 2, 3))  # 12

Control Flow

# If / else
if score >= 90
    status = "A"
else if score >= 80
    status = "B"
else
    status = "C"

# For loops
for i in 0..10
    print(i)

for item in my_list
    print(item)

# While loop
mut n = 10
while n > 0
    print(n)
    n = n - 1

# While true with break
while true
    input = io.readline()
    if input == "quit"
        return
    print("You said: " + input)

Structs

import math

# Structs hold data
struct Point
    x = 0.0
    y = 0.0

# Use functions to operate on structs
fn distance(a, b)
    dx = a.x - b.x
    dy = a.y - b.y
    return math.sqrt(dx * dx + dy * dy)

mut a = Point()
a.x = 0.0
a.y = 0.0

mut b = Point()
b.x = 3.0
b.y = 4.0

print(distance(a, b))   # 5.0
print("Point: ({b.x}, {b.y})")

Enums

enum Color
    Red
    Green
    Blue

fn describe(c)
    if c == Color.Red
        return "red"
    if c == Color.Green
        return "green"
    return "blue"

print(describe(Color.Red))    # "red"
print(describe(Color.Green))  # "green"

Pattern Matching

fn classify(n)
    if n == 0
        return "zero"
    if n < 10
        return "small"
    if n < 100
        return "medium"
    if n < 1000
        return "large"
    return "huge"

print(classify(0))      # "zero"
print(classify(5))      # "small"
print(classify(50))     # "medium"
print(classify(500))    # "large"
print(classify(5000))   # "huge"

Structs & Functions

# Structs are data containers; use functions to operate on them
import math

struct Circle
    radius = 0.0

fn circle_area(c)
    return math.PI * c.radius * c.radius

fn circle_info(c)
    return "Circle(r={c.radius})"

mut c = Circle()
c.radius = 5.0
print(circle_area(c))   # 78.539...
print(circle_info(c))   # Circle(r=5.0)

Pipe Operator

The pipe operator |> passes the result of the left expression as the first argument to the right function. This makes data transformations read naturally from left to right.

# Without pipes (nested, hard to read)
print(join(sort(filter(map(data, square), is_even)), ", "))

# With pipes (clear, left to right)
result = data |> map(square) |> filter(is_even)
result = result |> sort |> join(", ")
print(result)

Closures

# Closures capture their environment
fn make_adder(n)
    return |x| x + n  # captures 'n'

add5 = make_adder(5)
print(add5(10))  # 15

# Lambdas with pipe operator
data = [-3, 1, -1, 4, 2]
result = data |> filter(|x| x > 0) |> map(|x| x * 2) |> sort
print(result)  # [2, 4, 8]

Error Handling

import fs

# try/catch/finally — like Python but without colons
fn read_config(path)
    try
        content = fs.read(path)
        return content
    catch err
        print("Error: {err}")
        return nil

# throw to raise errors
fn divide(a, b)
    if b == 0
        throw "Division by zero!"
    return a / b

try
    result = divide(10, 0)
catch e
    print("Caught: {e}")
finally
    print("Cleanup done")

Async / Await

Pyro supports timing and scheduling with the time module. For concurrent tasks, use the thread module.

import time

# Measure execution time
start = time.now()

mut sum = 0
for i in 0..1000000
    sum = sum + i

elapsed = time.now() - start
print("Sum: {sum}")
print("Computed in {elapsed} ms")

Modules

# Import a standard library module
import json
import http
import math

# Use dot notation to access module functions
print(math.PI)
print(math.sqrt(144))
data = json.parse("{\"key\": \"value\"}")

# Create a public module
# file: mylib.ro
pub fn hello()
    return "hello from mylib"

# file: main.ro
import mylib
print(mylib.hello())

Core Modules (12)

ModuleDescription
stdCore utilities, print, assert, type conversions
ioInput/output streams, stdin/stdout, file handles
osOperating system interfaces, environment variables
fsFile system operations: read, write, mkdir, walk
pathPath manipulation: join, dirname, basename, ext
fmtString formatting with templates and alignment
mathMath constants and functions: PI, sqrt, sin, cos, log
timeTime, date, duration, timers, sleep
logStructured logging: info, warn, error, debug
errorsError types and construction utilities
typesType checking and casting utilities
reflectRuntime reflection and introspection

Data Modules (12)

ModuleDescription
jsonJSON parsing and serialization
csvCSV reading/writing with headers and type inference
xmlXML parsing and generation
yamlYAML parsing and serialization
tomlTOML configuration file support
base64Base64 encoding and decoding
hexHexadecimal encoding and decoding
sqliteEmbedded SQLite database with prepared statements
collectionsHashMap, HashSet, Deque, PriorityQueue, BTree
iterIterator adapters: chain, zip, enumerate, take, skip
serializeBinary serialization and deserialization
compressGzip, zlib, and deflate compression

Web Modules (10)

ModuleDescription
httpHTTP client and server with routing
urlURL parsing, encoding, query string handling
websocketWebSocket client and server
htmlHTML parsing and generation
templateTemplate engine with logic and loops
mimeMIME type detection and handling
cookieHTTP cookie parsing and creation
routerURL routing with path parameters
corsCross-Origin Resource Sharing middleware
sseServer-Sent Events support

Security Modules (8)

ModuleDescription
cryptoHigh-level cryptography: encrypt, decrypt, hash
hashSHA-256, SHA-512, MD5, BLAKE2
hmacHMAC message authentication
aesAES-128/256 CBC and GCM modes
rsaRSA key generation, encrypt, decrypt, sign, verify
tlsTLS/SSL connections and certificate handling
jwtJSON Web Token creation and verification
pbkdf2PBKDF2 key derivation with configurable rounds

Algorithm Modules (8)

ModuleDescription
sortSorting algorithms: quicksort, mergesort, timsort
searchBinary search, linear search, pattern search
graphGraph algorithms: BFS, DFS, Dijkstra, topological sort
matrixMatrix operations: multiply, transpose, determinant
statsStatistics: mean, median, stdev, linreg, correlation
randomRandom number generation, distributions, shuffle
bigintArbitrary precision integer arithmetic
bitopsBitwise operations and bit manipulation

Networking Modules (10)

ModuleDescription
netLow-level networking: sockets, addresses
tcpTCP client and server
udpUDP sockets and datagrams
dnsDNS resolution and lookup
smtpSMTP email sending
ftpFTP client for file transfers
sshSSH client and remote execution
grpcgRPC client and server with protobuf
mqttMQTT messaging protocol client
redisRedis client with pub/sub support

System Modules (8)

ModuleDescription
processProcess spawning, pipes, signals
threadOS threads with shared memory
asyncAsync runtime, tasks, channels, join
signalOS signal handling
envEnvironment variable access
sysSystem information: arch, OS, CPU count
memMemory allocation and management
ffiForeign Function Interface for C libraries

Text Modules (8)

ModuleDescription
stringString utilities: split, trim, replace, pad
regexRegular expressions with capture groups
unicodeUnicode normalization and properties
globGlob pattern matching for paths
diffText diffing and patching
colorTerminal color and styling (ANSI codes)
tableASCII table formatting for terminal output
plotTerminal-based charts and graphs

CLI Commands

All commands available in the Pyro CLI:

CommandDescription
pyro run <file.ro>Run a Pyro program
pyro build <file.ro>Compile to native binary
pyro watch <file.ro>Watch and auto-restart on changes
pyro new <type> <name>Create new project (webapp, api, cli)
pyro install <package>Install package from GitHub
pyro deploy <platform> <file>Deploy (docker, binary)
pyro check <file.ro>Type check without running
pyro fmt <file.ro>Format source code
pyro updateUpdate Pyro to latest version
pyro emit <file.ro>Show generated C++ code
pyro bench <file.ro>Run benchmarks
pyro doc <file.ro>Generate documentation
pyro debug <file.ro>Run with debugger
pyro profile <file.ro>CPU profiling
pyro tokens <file.ro>Show lexer tokens
pyro initInitialize a new project
pyro replStart interactive REPL
pyro versionShow version
pyro helpShow help

Keywords (23)

Pyro has exactly 23 reserved keywords:

KeywordPurpose
letDeclare an immutable variable (optional — bare assignment works too)
mutMake a variable mutable
fnDeclare a function
returnReturn a value from a function
ifConditional branch
elseAlternative branch
forLoop over a range or iterator
inIterator binding in for loops
whileLoop with condition
matchPattern matching expression
structDefine a data structure
enumDefine an enumeration
importImport a module
pubMark item as public
asyncDeclare an async function
awaitAwait an async value
trueBoolean true literal
falseBoolean false literal
nilNull/absence of value
tryBegin error handling block
catchHandle errors from try block
throwThrow an error
finallyAlways-execute block after try/catch

Operators

OperatorDescriptionExample
+ - * / %Arithmetica + b
== != < > <= >=Comparisona == b
&& || !Logicala && b
|>Pipex |> f
..Range0..10
?Error propagationval?
.Member accessmodule.func
=>Match arm1 => "one"

Type System

Pyro uses a static type system with full type inference. The compiler infers types at compile time, but you can always annotate explicitly for clarity.

# Type inference — just assign, no annotations needed
x = 42                    # int
y = 3.14                  # float
z = "hello"               # str
nums = [1, 2, 3]         # list

# mut for mutable variables
mut counter = 0
counter = counter + 1

# Functions work on any type
fn first(items)
    if items.len() == 0
        return nil
    return items[0]

print(first([10, 20, 30]))  # 10
print(first([]))             # nil

Grammar Summary

Pyro's grammar is intentionally small. The complete formal grammar fits on a single page:

program     = declaration*
declaration = fn_decl | struct_decl | enum_decl | import_decl | statement
fn_decl     = ["pub"] ["async"] "fn" IDENT "(" params? ")" block
struct_decl = ["pub"] "struct" IDENT NEWLINE INDENT fields
enum_decl   = ["pub"] "enum" IDENT NEWLINE INDENT variants
import_decl = "import" path
statement   = let_stmt | expr_stmt | return_stmt | for_stmt | while_stmt
expression  = assignment | pipe | logical | comparison | arithmetic | unary | call | primary
pipe        = expression "|>" expression