Skip to content

ats-lang/cargo-ats3

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cargo-ats3

A Cargo-style subcommand for building, managing, and publishing ATS3 projects.

Prerequisites

  • Node.js — the ATS3 compilers (xats2js, xats2py) are JavaScript programs
  • XATSHOME environment variable pointing to a valid XATSHOME directory
  • XATSXANADU environment variable pointing to ATS-Xanadu source

You can set these up manually by cloning XATSHOME and ATS-Xanadu, or use the ATS flake which sets everything up automatically:

nix develop github:ats-lang/ATS   # optional, if you use Nix

cargo-ats3 also has its own flake.nix for building from source with Nix:

nix build   # in the cargo-ats3 checkout

Installation

cargo install cargo-ats3

For development of cargo-ats3, install from a local checkout:

cargo install --path .

Quick Start

# Create a new binary project
cargo ats3 new hello-world

# Build (JS backend by default)
cd hello-world
cargo ats3 build

# Run
cargo ats3 run

Example: matrix library with a git dependency

The ats3-matrix project depends on ats3-vec via a git dependency:

$ cargo ats3 build
  Fetching ats3-vec (/home/user/workspace/ats3-vec)
  Compiling ats3-matrix (JS backend)

$ cargo ats3 run
m1 = list(list(1,2,3),list(4,5,6))
2 * m1 = list(list(2,4,6),list(8,10,12))
m1 + 2*m1 = list(list(3,6,9),list(12,15,18))
m1 * [1,0,1] = list(4,10)

On subsequent builds, if sources haven't changed, the build is skipped:

$ cargo ats3 build
    Fresh (JS backend)

$ cargo ats3 run
    Fresh (JS backend)
m1 = list(list(1,2,3),list(4,5,6))
...

Use --force to rebuild regardless:

$ cargo ats3 build --force

Commands

Command Description
new <name> Create a new ATS3 project (--template lib or bin)
init Initialize a project in the current directory
build Compile ATS3 source (--backend js|python, --force, --wheel)
clean Remove build artifacts (--deps to also remove .deps/)
run Build and run a binary (-- args passed through)
check Type-check without producing output
test Build and run tests/test.dats
add <pkg> Add a dependency (--path, --git, --version, --dev)
remove <pkg> Remove a dependency
fetch Update cached git dependencies
lock Generate or update Ats3.lock
tree Display the dependency tree (including transitive deps)
package Create a source tarball for distribution
version Show current version or bump via git tag (--bump patch|minor|major)
publish Build and publish to npm/PyPI (--backend, --all-backends)

Project Layout

my-project/
├── Ats3.toml          # Project manifest
├── Ats3.lock          # Lockfile (generated, commit to VCS)
├── src/
│   ├── bin/main.dats  # Binary entry point
│   └── lib.dats       # Library entry point
├── tests/
│   └── test.dats      # Test entry point
├── .deps/             # Symlinks to resolved dependencies
└── target/ats3/
    ├── js/index.js          # JS build output
    ├── python/              # Python build output
    │   ├── <pkg>/           # Package directory
    │   └── dist/*.whl       # Wheel (with --wheel)
    └── package/             # Source tarball (with `package`)

Ats3.toml

[package]
name = "my-project"
version = "0.0.1"

[dependencies]
# Semver requirement resolved against v* git tags (uses pubgrub solver)
ats3-vec = { git = "https://github.com/ats-lang/ats3-vec", version = "^0.1.0" }

# Pinned to an exact git tag
my-utils = { git = "https://github.com/user/my-utils", tag = "v0.2.0" }

# Local path dependency
my-lib = { path = "../my-lib" }

[backends.js]
enabled = true

[backends.python]
enabled = true
wheel = true          # auto-build wheel on `cargo ats3 build`

Dependencies

Dependencies are resolved transitively into .deps/ as symlinks. Include them in your ATS3 source via:

#include ".deps/my-lib/src/lib.dats"

Each dependency must be a valid ATS3 project (i.e., contain an Ats3.toml). Transitive dependencies (dependencies of your dependencies) are resolved automatically and included in .deps/.

Path dependencies

cargo ats3 add my-lib --path ../my-lib

Git dependencies

cargo ats3 add my-utils --git https://github.com/user/my-utils
cargo ats3 add my-utils --git https://github.com/user/my-utils --tag v0.2.0

Git dependencies support --tag, --branch, and --rev options.

Git repos are cached in ~/.cache/cargo-ats3/git/. The fetch policy on build is:

  • Pinned (tag or rev): cached after first clone, no refetch needed
  • Unpinned (branch or default): refetched on every build
  • Local git URL (filesystem path): always refetched

To manually update all cached git deps, run:

cargo ats3 fetch

Version resolution

When a git dependency includes a version field, cargo-ats3 uses the pubgrub SAT solver to resolve compatible versions from v*-prefixed git tags:

ats3-vec = { git = "https://github.com/ats-lang/ats3-vec", version = "^0.1.0" }

This runs git ls-remote --tags to discover available versions and picks the best match. The resolved version is recorded in Ats3.lock for reproducibility.

Lockfile

Ats3.lock records the exact resolved state of all dependencies (commit SHAs for git deps, paths for local deps). Commit it to version control for reproducible builds. To regenerate:

cargo ats3 lock

How Include Resolution Works

The ATS3 compiler resolves #include directives in three ways depending on the path prefix:

  1. Absolute (/path/to/file.dats) — direct file lookup
  2. Current-dir relative (./path/to/file.dats) — resolved relative to the directory of the file containing the #include
  3. Bare path (path/to/file.dats) — searched in $XATSHOME

Standard library includes like #include "prelude/HATS/prelude_dats.hats" use case 3, resolving to $XATSHOME/prelude/HATS/prelude_dats.hats.

The XATSHOME overlay

Dependency includes (e.g., #include ".deps/my-lib/src/lib.dats") also use case 3 — the .deps prefix does not start with ./, so the compiler searches $XATSHOME for it.

To make this work, cargo-ats3 creates a temporary overlay directory at target/ats3/.xatshome-overlay/ that contains:

  • Symlinks to all real $XATSHOME contents (prelude/, xassets/, etc.)
  • A .deps/ directory with symlinks to resolved path dependencies

The compiler is then invoked with XATSHOME pointing to this overlay. From the compiler's perspective, .deps/my-lib/src/lib.dats is just another file inside XATSHOME.

The overlay is only created when the project has path dependencies; projects without dependencies use the real XATSHOME directly.

Note: cargo-ats3 invokes node directly with the compiler JS files from $XATSHOME rather than relying on wrapper scripts. This ensures cargo-ats3 controls the XATSHOME environment variable (which wrapper scripts may override) and works the same regardless of how the ATS3 toolchain was installed.

Backends

Backend Compiler Runtime Output
JS xats2js Node.js target/ats3/js/index.js
Python xats2py Python 3 target/ats3/python/<pkg>/__init__.py
C xats2c (planned) gcc/cc target/ats3/c/

Python Wheels

Build a PEP 427 wheel for PyPI distribution:

cargo ats3 build --backend python --wheel

This creates target/ats3/python/dist/<pkg>-<version>-py3-none-any.whl containing the compiled Python output, py.typed marker, and standard dist-info metadata (METADATA, WHEEL, RECORD).

You can also set wheel = true in [backends.python] to build wheels automatically on every Python build.

Packaging and Publishing

Source tarball

cargo ats3 package

Creates target/ats3/package/<name>-<version>.tar.gz containing Ats3.toml, src/, tests/ (if present), and Ats3.lock (if present). A .sha256 checksum file is written alongside the tarball.

Publishing

# Publish to npm (builds JS, then runs `npm publish`)
cargo ats3 publish --backend js

# Publish to PyPI (builds Python + wheel, then runs `twine upload`)
cargo ats3 publish --backend python

# Publish to all enabled backends
cargo ats3 publish --all-backends

Prerequisites for publishing:

  • npm: npm on PATH, authenticated (npm login)
  • PyPI: twine installed (pip install twine), authenticated

Pre-publish validation warns if description, license, or a matching git tag (v<version>) are missing.

Running Tests

# Unit tests + CLI tests (no toolchain required)
cargo test

# Full suite including integration tests (requires ATS3 toolchain)
CARGO_ATS3_INTEGRATION=1 XATSHOME=/path/to/XATSHOME cargo test

License

MPL-2.0

About

A Cargo subcommand for building ATS3 projects

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors