Luce Base
LuceSourceLuciaOS

1. Hello, Base

Install#

On macOS or Linux:

curl -fsSL https://luce.luciaos.com/install.sh | sh && . "$HOME/.local/luce/env"

On Windows, in Command Prompt:

curl -fsSLo "%TEMP%\luce-install.cmd" https://luce.luciaos.com/install.cmd && "%TEMP%\luce-install.cmd"

or in PowerShell:

irm https://luce.luciaos.com/install.ps1 | iex

This puts the compiler, luce-base, and the project tool, luc, on your PATH. On macOS and Linux, building a program uses the C toolchain on your machine to assemble and link, so it needs one: the Xcode command line tools on macOS (xcode-select --install) and gcc or clang on Linux; the installer tells you if it is missing. On Windows the compiler assembles and links by itself, so nothing else is needed. Check that it worked:

luce-base --version

A first program#

Save this as hello.lucb:

pub func main(arguments: str[]) -> i32:
    print("Hello, Base!")
    return 0
output
Hello, Base!

Build it and run it:

luce-base build hello.lucb -o hello
./hello

If you know Python, most of this reads as you would expect:

  • Indentation marks blocks, as in Python: a line ending in : opens a block indented four spaces.
  • main is where the program starts, as in C. It receives the command-line arguments, like Python's sys.argv, and returns the exit status. str[] means "a sequence of strings"; Chapter 7 explains the [].
  • Types are written after names, as in Python's type hints, arguments: str[], and a function's result type after ->. Unlike Python's hints, they are checked when the program compiles.
  • pub makes a declaration visible to other files. main must be pub.

luce-base build produces a native executable, hello, which runs on its own.

Formatted strings#

print also takes a formatted string, written as in Python with an f before the quote:

pub func main(arguments: str[]) -> i32:
    let language = "Base"
    let year = 2026
    print(f"Hello from {language}, {year}.")
    print(f"There are {arguments.length} arguments; the first is {arguments[0]}.")
    return 0
output
Hello from Base, 2026.
There are 1 arguments; the first is ./program.

The braces hold any expression, and after a colon a format specification as in Python: {value:x} for hexadecimal, {value:>8} to pad to a width, {price:.2f} for two decimals.

A project#

A single file is enough for a small program. A program with several files or with dependencies is a project, and luc creates one:

luc new greeter --tool
cd greeter
luc run

luc new writes three files:

greeter/
  package.prisma      the project's name, version, kind and dependencies
  src/main.lucb       the entry point
  .gitignore

package.prisma describes the project, much as pyproject.toml does for Python:

#prisma 4.0
def package "greeter" {
    str owner = "you"
    str version = "0.1.0"
    str kind = "tool"
    str language = "luce-base"
    str entry = "src/main.lucb"
}

luc run builds the program into build/greeter and runs it. The other everyday commands:

CommandWhat it does
luc buildbuild without running; --release optimises
luc testbuild and run the tests
luc checktype-check without building
luc fmtformat the sources

--tool makes a command-line program. --application makes a desktop application and --package a library for other projects to use. Chapter 8 covers projects and dependencies.

The compiler on its own#

For single files, luce-base works without luc:

CommandWhat it does
luce-base build file.lucb -o outbuild an executable
luce-base build file.lucb --release -o outbuild it optimised
luce-base check file.lucbtype-check only
luce-base test file.lucbbuild and run the file's tests
luce-base fmt file.lucb --writeformat the file in place

Run luce-base with no arguments for the full list.

Where next#

Chapter 2 covers the building blocks: bindings, numbers and text.