Modules and packages

import loads standard library modules. use loads local files or directories. module defines an inline namespace. The package manager connects to reg.xslang.org.

Importing stdlib

scratch.xs

Every standard library module must be explicitly imported. The semantic analyser reports an error for references to module names that have no matching import.

Importing files

use imports a local .xs file as a module. The namespace is derived from the filename.

-- use "utils.xs" imports as utils.*
use "utils.xs"
println(utils.helper())

-- with alias
use "utils.xs" as u
println(u.helper())

-- selective import
use "utils.xs" { helper, VERSION }
println(helper())

For directories, use "lib/" imports all .xs files in the directory.

Exporting names

A file's public surface is whatever its export { ... } list names. Everything else stays file-local. The list lives at the top level of the file (typically last), and an as clause publishes a name under a different spelling.

-- math_utils.xs
fn double(x) { return x * 2 }
fn triple(x) { return x * 3 }
fn helper(x) { return x + 1 }       -- not in the export list
let TAU = 6.2831
let seed = 42                       -- not in the export list
struct Point { x: int, y: int }

fn rgb_to_hex(r, g, b) { ... }

export { double, triple, TAU, Point, rgb_to_hex as rgbToHex }
use "math_utils.xs"

println(math_utils.double(5))                -- 10
println(math_utils.TAU)                      -- 6.2831
println(math_utils.helper)                   -- null (not exported)
println(math_utils.rgbToHex(255, 0, 0))      -- callable under the alias
println(math_utils.rgb_to_hex)               -- null (alias is the public name)

A file with no export list at all falls back to exposing every top-level binding. Quick scripts work without ceremony; add an export list and strict filtering kicks in.

There is no pub modifier and no @export decorator. The export list is the one and only mechanism.

Inline modules

Declare a named module directly in a file with module:

scratch.xs

Packages

XS packages are hosted on reg.xslang.org. The package manager talks to the registry over HTTPS.

xs new myapp          -- scaffold a project (creates xs.toml)
xs add http-client    -- add a dependency
xs install            -- install all from xs.toml
xs remove http-client -- remove a package
xs update             -- update all to latest compatible versions

Packages install to .xs_lib/ in the project directory. Import them the same way as stdlib:

import http_client
let resp = http_client.get("https://api.example.com/data")

Publishing a package:

xs login              -- store your registry token
xs publish            -- build tarball, POST to reg.xslang.org
xs search json        -- search the registry