Skip to content

thiremani/pluto

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

900 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

The Pluto Programming Language

Taking programming to another planet 🚀

Pluto language logo

Pluto is a compiled language that combines the clarity of scripting languages with the type-safety, performance, and determinism of systems languages.

Functions in Pluto are templates defined in .pt files. Call a template with different argument types and Pluto generates specialized native code for each — no generics syntax, no runtime dispatch. Write concise programs that compile into efficient, fully specialized executables.

Philosophy

  • 💎 Purity by design — functions have read-only inputs and writable outputs; structs contain raw data with no hidden pointers
  • ✨ The simplicity of scripting
  • ⚡ The type safety and speed of low-level languages
  • 🧠 Deterministic memory
  • 🔧 Automatic specialization
  • 🔒 Predictable concurrency

Intended for performance-sensitive scripting, numerical work, simulation, and systems tools.


Design highlights:

Purity: Functions have read-only inputs and writable outputs; structs are raw data with no hidden pointers.

Range-driven auto-vectorization, safe arrays and slices.

Scope-based memory (no nulls, no out-of-bounds, no GC), and concurrency by construction.


Highlights

  • Go front-end, LLVM back-end; emits native binaries
  • Template functions in .pt: specialized per argument types (generics by use)
  • Range literals with auto-vectorized execution
  • First-class arrays (safe slicing) and link semantics
  • Scope-based memory: no nulls, no out-of-bounds, no garbage collector
  • printf-style formatting; arrays/ranges printable
  • Cross-platform (Linux/macOS/Windows)

Command name

Release artifacts ship both command names:

  • pluto
  • plt (conflict-safe alias)

If pluto conflicts on your system, use plt.


Quick example

Hello world (tests/helloworld.spt):

"hello world"
x = "hello 🙏"
x, "👍"

No main(), no print(), no imports. Values on a line get printed.

Compile and run:

./pluto tests/helloworld.spt
./tests/helloworld

Output:

hello world
hello 🙏 👍

Pluto can compile a single .spt file or an entire directory — each .spt produces a native executable.


How Pluto programs are structured

Pluto separates reusable templates from executable scripts:

Extension Purpose
.pt Template files — functions, operators, structs, constants (act as libraries)
.spt Script files — executable programs that compile to native binaries

A directory is the unit of compilation:

math/
├── math.pt      # defines Square, etc.
└── func.spt     # uses them → compiles to ./math/func

Compile and run:

./pluto math
./math/func

Templates and specialization

Templates are defined once with a clear input/output contract. The first line declares the output and input — the indented body describes the transformation.

Think of a template as a black box: data flows in through inputs, gets transformed, and flows out through outputs. Outputs work by reference — calling a template directly modifies the output variable in the caller's scope.

math.pt

# y is the output (writable), x is the input (read-only)
y = Square(x)
	y = x * x

Inputs are read-only — they flow in. Outputs are writable — they flow out. Every function is a transformation.

Generics by use

Call Square with different types — Pluto compiles a specialized version for each:

func.spt

arr = [1 2 3 5]

# Basic specializations
a = Square(5)            # int specialization
b = Square(2.2)          # float specialization
c = Square(arr)          # squares each array element
a, b, c

# Range and filter (non-accumulated)
d = Square(1:3)          # range: final iteration result
e = Square(arr[1:3])     # array-range: final iteration result
f = Square(arr > 3)      # filtered array
g = Square(arr[1:3] > 3) # filtered array-range
d, e, f, g

# Accumulation forms
h = [Square(1:3)]          # range accumulation
i = [Square(arr[1:3])]     # array-range accumulation
j = [Square((1:3) > 1)]    # conditional range accumulation
k = [Square(arr[1:4] > 2)] # conditional array-range accumulation
h, i, j, k

Output:

25 4.84 [1 4 9 25]
4 9 [25] 0
[1 4] [4 9] [0 4] [0 9 25]

No generics syntax, no type parameters. Write the template once — call it with a scalar, an array, or a filtered view. arr > 3 filters the array to elements greater than 3 and passes that subset through.

Generated code is equivalent to handwritten specialized code. There is no runtime overhead.


Ranges as the execution primitive

Ranges are first-class values:

Square(1:5)

Passing a range to a template executes it across all values. The compiler can map these operations to SIMD instructions — this is range-driven auto-vectorization.

Data-parallel execution without explicit loop syntax.


Arrays

Arrays use bracket syntax with no commas:

x = [1 2 3 4 5]
y = [1.1 2.2 3.3]

Arrays are safe by construction — out-of-bounds access is not possible. Comparisons like arr > 2 produce filtered views that work anywhere an array does.


Function model

Functions are pure transformations:

  • Inputs are read-only
  • Outputs are writable
  • Global constants allowed
  • No hidden mutation

This keeps behavior predictable and easier to parallelize.


Memory model

Pluto uses deterministic, scope-based memory:

  • No garbage collector
  • No null values
  • No out-of-bounds access
  • Memory freed when scope ends

Predictable performance with minimal runtime overhead.


Concurrency direction

Pluto is designed so that:

  • Structs are pure data
  • Functions are transformations
  • Inputs are read-only

This enables strong guarantees around race-free execution. The concurrency model is evolving but built around deterministic behavior.


Building and Running

Build the compiler:

python3 build.py

If you prefer the conflict-safe command name locally:

python3 build.py -o plt

build.py sets the LLVM 22 byollvm environment for its own subprocess and does not mutate your shell. If you prefer to call Go directly:

eval "$(python3 scripts/llvm_env.py --shell)"
go build -o pluto

Compile a directory:

./pluto tests           # Compiles all .spt files in tests/
./tests/helloworld      # Run the compiled executable

Run tests:

python3 test.py                              # Full E2E suite
python3 test.py --leak-check                 # Full suite + memory leak detection
go test -race ./lexer ./parser ./compiler    # Unit tests only

New project setup:

Add a pt.mod file at your project root to define the module path:

module github.com/you/yourproject

Pluto walks up from the working directory to find pt.mod and treats that directory as the project root.

Other commands:

  • ./pluto -version (or -v) — show version
  • ./pluto -clean (or -c) — clear cache for current version
  • ./pluto -emit-ir [directory] — also write linked pre-optimization script .ll files to the cache
  • PLUTO_TARGET_CPU defaults to native; set it to a CPU name or portable to override host CPU tuning

Requirements

  • Go 1.26+
  • LLVM 22 development libraries and tools on PATH: llvm-config, clang
  • Python 3.x (for build/test helpers)
  • Leak check tools (only for python3 test.py --leak-check):
    • Linux: valgrind
    • macOS: leaks

Pluto builds against LLVM through CGO. python3 build.py and python3 test.py derive the required LLVM 22 byollvm flags from llvm-config for their subprocesses. Direct go build and go test are supported after eval "$(python3 scripts/llvm_env.py --shell)".


Installation

Linux

Install LLVM 22 from apt.llvm.org:

wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && sudo ./llvm.sh 22
sudo apt install llvm-22-dev clang-22 lld-22
export PATH=/usr/lib/llvm-22/bin:$PATH

Build and test:

python3 build.py
python3 test.py
macOS (Homebrew)
brew install llvm lld

Set PATH for your architecture:

# Apple Silicon
export PATH=/opt/homebrew/opt/llvm/bin:$PATH

# Intel
export PATH=/usr/local/opt/llvm/bin:$PATH

Build and test:

python3 build.py
python3 test.py
Windows (MSYS2 UCRT64)

Install MSYS2 and use the "MSYS2 UCRT64" shell.

Install packages:

pacman -S --needed mingw-w64-ucrt-x86_64-{go,llvm,clang,lld,python}

Quick build:

python build.py

Manual build/test:

eval "$(python scripts/llvm_env.py --shell)"
go build -o pluto.exe
python test.py

Notes:

  • On Windows the produced binary is pluto.exe.
  • The runtime enables %n on UCRT to match POSIX printf behavior.

Status

Pluto is under active development.

Working today:

  • 🎯 Template specialization
  • 📊 Arrays and ranges
  • 🖥️ Native binaries
  • 🧞‍♂️ Cross-platform builds

In progress:

  • 🧵 Concurrency model
  • 🧰 Tooling
  • 📘 Documentation

Repository structure

Path Description
main.go CLI entry point
ast/ Abstract syntax tree definitions
lexer/ Tokenizer with indentation-based syntax
parser/ Recursive descent parser
compiler/ Type solving, IR generation, LLVM emission
runtime/ Embedded C runtime linked into executables
tests/ End-to-end tests (.spt inputs, .exp expected outputs)

Architecture

  • Two phases: CodeCompiler parses .pt files and saves function templates and constants; ScriptCompiler compiles specialized versions for each usage in .spt files (if not already cached).
  • Automatic pipeline: generate IR → optimize -O3 and emit objects in-process with LLVM → link with cached runtime objects via clang — all handled transparently.
  • Module resolution: walks up from CWD to find pt.mod and derives module path.
  • Cache layout (versioned to isolate different compiler versions):
    • <PTCACHE>/<version>/runtime/<hash>/ for compiled runtime objects
    • Default host CPU builds: <PTCACHE>/<version>/<module-path>/{code,script}
    • Non-default PLUTO_TARGET_CPU builds: <PTCACHE>/<version>/target_cpu-<setting>/<module-path>/{code,script}

Troubleshooting

Common issues

undefined: llvmHostCPUName or undefined: llvmHostCPUFeatures during build:

  • Use python3 build.py / python build.py, or run eval "$(python3 scripts/llvm_env.py --shell)" before direct go build / go test

Missing LLVM tools:

  • Verify llvm-config and clang from LLVM 22 are on PATH

Stale cache behavior:

  • Clear current version: ./pluto -clean
  • Clear all versions:
    • macOS: rm -rf "$HOME/Library/Caches/pluto"
    • Linux: rm -rf "$HOME/.cache/pluto"
    • Windows: rd /s /q %LocalAppData%\pluto
  • Override cache location with PTCACHE environment variable
  • Override host CPU tuning with PLUTO_TARGET_CPU (portable disables the default -mcpu=native path)

Encoding issues on Windows:

  • Run from the MSYS2 UCRT64 shell; the runner decodes output as UTF-8

Contributing

  • Commit style: Conventional Commits (e.g., feat(parser): ..., fix(compiler): ...)
  • PRs: include a clear description, linked issues, and tests for changes
  • Go formatting: go fmt ./...
  • Run tests before submitting: python3 test.py

License

Pluto is licensed under the MIT License. See LICENSE.

Vendored third-party code:

  • runtime/third_party/klib/ (klib by Attractive Chaos) — MIT License, see runtime/third_party/klib/LICENSE.txt

About

Pluto is a compiled language that aims for the simplicity, readability and expressiveness of scripting languages with the safety and performance of C/C++, Go. A Go front‑end lowers .pt/.spt to LLVM IR and native binaries. Features include range‑driven auto‑vectorization, scope‑based memory (no nulls, no OOB, no GC), and concurrency by construction.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors