Skip to content

thiremani/pluto

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

962 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

2 stars

Watchers

2 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors