radlang — System & Process (sys)

This document covers the sys namespace: radlang’s interface to standard I/O, the process environment, command-line arguments, and timing.

For language fundamentals see the Overview.


Overview

sys is a compiler-intrinsic namespace. Like math and fs, the name is reserved and dispatched straight to the runtime — it needs no import and is available everywhere:

fn main() {
    sys.output("Hello, radlang")
    string name = sys.input("Your name? ")
    sys.output("Hi, " + name)
}

Everything here is a thin wrapper over the C standard library and POSIX, so it behaves exactly as you would expect from a native program.


Standard output

sys.output(value?) : void

Prints a value followed by a newline. It accepts any type — strings, numbers, booleans, lists, structs, null, and any — and stringifies it automatically. Called with no argument it prints a blank line.

fn main() {
    sys.output("plain string")
    sys.output(42)                 // 42
    sys.output(3.14)               // 3.14
    sys.output(true)               // true
    sys.output([1, 2, 3])          // [1, 2, 3]
    sys.output()                   // (blank line)
}

Standard error

sys.error(message?) : void

Same idea as sys.output, but writes to stderr instead of stdout. Use it for diagnostics and error messages so they can be redirected separately from normal program output.

fn main() {
    sys.error("warning: config file missing, using defaults")
}

Standard input

sys.input(prompt?) : string

Reads a line from stdin and returns it as a string (without the trailing newline). If a prompt is given it is printed first, with no added newline.

fn main() {
    string city = sys.input("Where do you live? ")
    sys.output("You live in " + city)
}

Process control

Exit

sys.exit(code: int) : void

Terminates the process immediately with the given status code (0 means success). Code after sys.exit in the same path does not run.

fn main() {
    if !fs.exists("config.toml") {
        sys.error("no config found")
        sys.exit(1)
    }
    sys.output("config OK")
}

Environment variables

sys.env(name: string) : string
sys.env(name: string, value: string) : string
  • sys.env(name) returns the value of an environment variable from the real OS environment, or the empty string if it is not set. It reads only the process environment — it does not see values from your project’s config.yaml env: block. For config-managed values use the cfg namespace’s cfg.env(key) (see cfg.md).
  • sys.env(name, value) sets an environment variable to the specified value in the process environment.
fn main() {
    string home = sys.env("HOME")
    sys.env("MY_VAR", "my_value")
    sys.output("home: " + home)
    sys.output("var: " + sys.env("MY_VAR"))
}

Command-line arguments

sys.args() : string[]

Returns the program’s arguments as a list of strings. By convention the first element is the program/invocation name, and the rest are user arguments.

fn main() {
    string[] argv = sys.args()
    sys.output("arg count: " + argv.length().toString())
    for (string arg in argv) {
        sys.output(arg)
    }
}

Process execution

Running shell commands

sys.cli(cmd: string) : Future<int>

Executes a shell command in the background via the worker thread pool. Returns a Future<int> resolving with the process exit code.

async fn test() {
    int code = await sys.cli("ls -la")
    sys.output("exit code: " + code.toString())
}

Spawning subprocesses

sys.spawn(exe: string, args: string[]) : Future<int>

Spawns a child process with arguments directly, bypassing the shell. Returns a Future<int> resolving with the process exit code.

async fn test() {
    int code = await sys.spawn("echo", ["hello", "world"])
    sys.output("exit code: " + code.toString())
}

Timing

Blocking sleep

sys.sleep(ms: int) : void

Pauses the current thread for ms milliseconds. This blocks everything, including the async scheduler.

fn main() {
    sys.output("waiting one second...")
    sys.sleep(1000)
    sys.output("done")
}

Non-blocking sleep

sys.sleepAsync(ms: int) : Future<void>

A cooperative sleep for use with await inside an async fn. Unlike sys.sleep, it does not stall other pending async tasks — the scheduler is free to run them while this one waits.

async fn tick() {
    await sys.sleepAsync(500)
    sys.output("half a second later")
}

System information

MethodReturnsDescription
sys.cwd()stringCurrent working directory
sys.pid()intProcess ID
sys.platform()string"darwin", "linux", "windows", or "unknown"
sys.arch()string"arm64", "x86_64", or "unknown"
sys.hostname()stringThe machine’s hostname
sys.cores()intNumber of online logical CPU cores
sys.home()stringThe user’s home directory
sys.tmp()stringThe system temporary directory
fn main() {
    sys.output("running on " + sys.platform() + "/" + sys.arch())
    sys.output("pid " + sys.pid().toString() + " in " + sys.cwd())
    sys.output("host: " + sys.hostname())
}

Note. platform() and arch() are resolved at compile time for the target the binary is built for, so they reflect the build host/target rather than being probed at runtime.


Quick reference

CallReturnsPurpose
sys.output(v?)voidPrint to stdout with newline
sys.error(v?)voidPrint to stderr with newline
sys.input(p?)stringRead a line from stdin
sys.exit(code)voidTerminate the process
sys.env(name)stringRead an OS environment variable
sys.env(name, val)stringSet an OS environment variable
sys.args()string[]Command-line arguments
sys.sleep(ms)voidBlock for ms milliseconds
sys.sleepAsync(ms)Future\<void>Cooperative async sleep
sys.cwd()stringCurrent working directory
sys.pid()intProcess ID
sys.platform()stringOS name
sys.arch()stringCPU architecture
sys.hostname()stringMachine hostname
sys.cores()intCPU core count
sys.home()stringHome directory
sys.tmp()stringTemporary directory
sys.cli(cmd)Future\<int>Run shell command in the background
sys.spawn(exe, args)Future\<int>Spawn subprocess directly with arguments

Picking the right tool

  • Print results a user should see → sys.output.
  • Print warnings/errors that shouldn’t mix with output → sys.error.
  • Read interactive input → sys.input.
  • Read an OS environment variable → sys.env; read project config → cfg.env (see cfg.md).
  • Fail a script with a status code → sys.exit.
  • Delay in a normal program → sys.sleep; delay inside asyncsys.sleepAsync.