Skip to main content

Getting Started

This guide will help you install Script and build your first program.

Installation

Step 1: Install Prerequisites

macOS:

# Install Rust (if not already installed)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Install LLVM 18 (required for AOT compilation)
brew install llvm@18

# Install zstd (required for linking)
brew install zstd

# Set LLVM environment variable (add to ~/.zshrc or ~/.bashrc)
echo 'export LLVM_SYS_180_PREFIX=$(brew --prefix llvm@18)' >> ~/.zshrc
source ~/.zshrc

Linux (Ubuntu/Debian):

# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Install LLVM 18
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 18

# Install zstd
sudo apt install libzstd-dev

# Set LLVM path
echo 'export LLVM_SYS_180_PREFIX=/usr/lib/llvm-18' >> ~/.bashrc
source ~/.bashrc
note

The Cranelift JIT backend works without LLVM. LLVM is only required for AOT (ahead-of-time) compilation to native binaries.

Step 2: Clone and Build Script

# Clone the repository
git clone https://github.com/aspect/script.git
cd script

# Build in release mode
cargo build --release

# Verify installation
./target/release/script --help

Step 3: Add to PATH (Optional)

# Add Script to your PATH
echo 'export PATH="$PATH:/path/to/script/target/release"' >> ~/.zshrc
source ~/.zshrc

# Now you can run from anywhere
script --help

Your First Script Program

Hello World

Create a file called hello.tscl:

console.log("Hello, Script!");

Run it:

./target/release/script run hello.tscl

A More Complete Example

Create fibonacci.tscl:

function fib(n: number): number {
if (n < 2) return n;
return fib(n - 1) + fib(n - 2);
}

let result = fib(25);
console.log("Fibonacci(25) =", result);

Run with different backends:

# VM (interpreted, good for debugging)
./target/release/script run fibonacci.tscl

# JIT (fast compilation, good for development)
./target/release/script jit fibonacci.tscl

# AOT (native binary, best performance)
./target/release/script build fibonacci.tscl --release -o fib
./fib

Execution Modes

Script provides multiple ways to run your code:

ModeCommandUse CasePerformance
VMscript run app.tsclDebugging, REPLSlowest
JITscript jit app.tsclDevelopment, testingFast
AOT Releasescript build app.tscl --release -o appProduction (ThinLTO)Faster
AOT Distscript build app.tscl --dist -o appMaximum optimization (Full LTO)Fastest

JIT Compilation (Development)

./target/release/script jit app.tscl

Uses Cranelift for fast compilation. Perfect for rapid iteration.

AOT Compilation (Production)

# Release build with ThinLTO
./target/release/script build app.tscl --release -o app

# Distribution build with Full LTO (slower compile, faster runtime)
./target/release/script build app.tscl --dist -o app

# Run the native binary
./app

Produces standalone executables with no runtime dependencies.

VM Execution (Debugging)

./target/release/script run app.tscl

Interpreted execution for debugging and testing.

CLI Reference

# Run with VM
script run <file.tscl>

# Run with JIT
script jit <file.tscl>

# Build native binary
script build <file.tscl> [--release|--dist] -o <output>

# Show SSA IR (debugging)
script ir <file.tscl>

# Show AST (debugging)
script ast <file.tscl>

# Type check only
script check <file.tscl>

Project Structure

A typical Script project looks like:

my-project/
├── main.tscl # Entry point
├── lib/
│ ├── utils.tscl # Utility functions
│ └── types.tscl # Type definitions
└── tests/
└── test_utils.tscl # Tests

Importing Modules

// main.tscl
import { helper } from "./lib/utils";

let result = helper(42);
console.log(result);
// lib/utils.tscl
export function helper(x: number): number {
return x * 2;
}

What's Next?

Now that you have Script running, explore: