Getting started

code-lang is an interpreted language with a clean syntax and a complete standard library. This guide gets you from zero to running your first script.

Install

Build from source with Cargo. The repo is a Cargo workspace — the interpreter lives at the root.

git clone https://github.com/Walon-Foundation/code-lang
cd code-lang
cargo build --release

The interpreter binary lands at target/release/code-lang. Add it to your PATH or run it directly.

See the full install guide for more detail, including the upcoming formatter (code-lang-fmt) and language server (code-lang-lsp).

Hello, World!

The smallest possible code-lang program. Create a file called hello.cl:

import "fmt";

fmt.print("Hello, World!");

Run it:

code-lang hello.cl
Hello, World!

fmt is the standard output module. fmt.print writes to stdout with a newline. All stdlib modules are built in — just import and use.

The REPL

Run code-lang with no arguments to start the interactive shell. History is saved across sessions.

>> let name = "world";
>> "Hello, " + name + "!";
Hello, world!
>> 2 ** 10;
1024
>> typeof 42;
integer
>> exit

Exit with exit, exit(), or Ctrl-C.

A longer script

Scripts use the .cl extension. Here is a program that uses structs, functions, and the math module:

import "fmt";
import "math";

struct Point {
    x: 0,
    y: 0,
    distance: fn(self) {
        math.sqrt(self.x ** 2 + self.y ** 2);
    },
};

let greet = fn(name, msg = "Hello") {
    fmt.print(msg + ", " + name + "!");
};

let p = Point { x: 3, y: 4 };
greet("world");
fmt.print("distance:", p.distance());
code-lang hello.cl
Hello, world!
distance: 5

Importing modules

All standard library modules are built in — no installation or setup needed. Import any module by name and call its functions with dot notation:

import "fmt";
import "strings";
import "arrays";
import "json";

strings.to_upper("hello");                        # HELLO
arrays.map([1, 2, 3], fn(x) { x * 2; });         # [2, 4, 6]
arrays.filter([1, 2, 3, 4], fn(x) { x % 2 == 0; }); # [2, 4]
json.stringify({ "ok": true });                   # {"ok":true}

fmt.print(strings.to_upper("hello"));             # HELLO

See the standard library reference for all 12 modules and their return types.

Language features at a glance

A quick tour of the key language features. Read the full reference for detail.

null and ??

let x;              # uninitialized — defaults to null
let y = x ?? 0;     # 0  (x is null, so fall back to 0)
let z = 5 ?? 0;     # 5  (5 is not null, keep it)

Destructuring

let [a, b, c] = [1, 2, 3];
let { name, age } = { "name": "Walon", "age": 25 };

fmt.print(a);     # 1
fmt.print(name);  # Walon

Enums and switch

import "fmt";

enum Status { Ok, Pending, Err }

let s = Status.Ok;
switch (s) {
    Status.Ok      => fmt.print("all good"),
    Status.Pending => fmt.print("waiting"),
    Status.Err     => fmt.print("failed"),
    default        => fmt.print("unknown"),
};

typeof

typeof 42;        # "integer"
typeof "hello";   # "string"
typeof null;      # "null"
typeof [1, 2];    # "array"
typeof true;      # "boolean"

Error format

Errors include the source line, a caret pointing to the exact position, and a hint on how to fix it:

error: identifier not found: foo
  --> 3:9
   |
 3 | let x = foo + 1;
   |         ^
hint: declare it first with 'let foo = value'

Script mode exits with code 1 on any error.

Next steps

Read the language reference for a complete guide to syntax, types, functions, structs, enums, modules, and error handling.