Skip to content

Instantly share code, notes, and snippets.

@wizardbeard
Last active April 21, 2026 08:07
Show Gist options
  • Select an option

  • Save wizardbeard/d25090e4ff54d426471a9567650ae8ff to your computer and use it in GitHub Desktop.

Select an option

Save wizardbeard/d25090e4ff54d426471a9567650ae8ff to your computer and use it in GitHub Desktop.
More Aesthetically Pleasing than Rust

Better than Rust?

(c) 2026, Ray Long

License: MIT License

# ------------------------------------------------------------
# package and imports
# ------------------------------------------------------------

package drivers.uart

import
    console from io
    Logger as Log from diagnostics.logger
    random_int from math.random
    Reader from io.streams
    UartRegisters from devices.uart.types

# ------------------------------------------------------------
# type aliases
# ------------------------------------------------------------

type UserId = UInt64
type Port = UInt16

# ------------------------------------------------------------
# records
# ------------------------------------------------------------

record User
    id: UserId
    name: Text
    age: UInt8

record Box<T>
    value: T

record Pair<A, B>
    first: A
    second: B

# growable owned contiguous storage
record Buffer
    data: DynamicArray<Byte>

record BufferReader
    data: DynamicArray<Byte>
    cursor: IntSize

# fixed-size contiguous inline storage
record Header
    magic: Array<Byte, 4>
    version: UInt16

# typed MMIO register block
record UartRegisters
    data: UInt32
    status: UInt32
    control: UInt32

# ------------------------------------------------------------
# sum types / tagged unions
# ------------------------------------------------------------

choice IOError
    Closed
    EndOfInput
    PermissionDenied

choice ParseError
    EmptyInput
    InvalidDigit

choice Expression
    Int(value: Int64)
    Add(left: Box<Expression>, right: Box<Expression>)
    Neg(inner: Box<Expression>)

# recursive algebraic data type
choice List<T>
    Empty
    Node(head: T, tail: Box<List<T>>)

choice Task
    Local(next: Int64)
    Remote(done: Outcome<Int64, IOError>)

# ------------------------------------------------------------
# interfaces
# ------------------------------------------------------------

interface Reader
    function read(this: exclusive This, into: exclusive View<Byte>) -> Outcome<IntSize, IOError>

interface Display
    function display(this: shared This) -> Text

interface Iterator<T>
    function next(this: exclusive This) -> Maybe<T>

# concurrency safety marker interfaces
interface Transferable
interface Shareable

# ------------------------------------------------------------
# interface implementations
# ------------------------------------------------------------

implements Reader for BufferReader
    function read(this: exclusive This, into: exclusive View<Byte>) -> Outcome<IntSize, IOError>
        switch this.cursor >= this.data.length()
            true => Error(IOError.EndOfInput)
            false => Ok(0)

implements Display for User
    function display(this: shared This) -> Text
        this.name

# ------------------------------------------------------------
# inherent methods
# ------------------------------------------------------------

extend Buffer
    function append(this: exclusive This, b: Byte) -> Unit
        this.data.push(b)

    function length(this: shared This) -> IntSize
        this.data.length()

    function first(this: shared This) -> Maybe<Byte>
        switch this.data.length()
            0 => Empty
            default => Some(this.data[0])

extend BufferReader
    function reset(this: exclusive This) -> Unit
        this.cursor = 0

    function remaining(this: shared This) -> IntSize
        this.data.length() - this.cursor

# ------------------------------------------------------------
# plain functions
# ------------------------------------------------------------

function add(a: Int64, b: Int64) -> Int64
    a + b

function consume(buf: Buffer) -> Unit
    sink(buf)

function first<T>(items: shared View<T>) -> Maybe<shared T>
    switch items.length()
        0 => Empty
        default => Some(items[0])

# ------------------------------------------------------------
# generic functions with constraints
# ------------------------------------------------------------

function max<T>(left: T, right: T) -> T
where T: Ordered
    switch left >= right
        true => left
        false => right

function sort_copy<T>(items: shared View<T>) -> DynamicArray<T>
where T: Ordered + Cloneable
    clone_and_sort(items)

function fill<R>(source: exclusive R, into: exclusive View<Byte>) -> Outcome<IntSize, IOError>
where R: Reader
    source.read(into)

# ------------------------------------------------------------
# local bindings
# ------------------------------------------------------------

function sum(items: shared View<Int64>) -> Int64
    let label: Text = "sum"
    var total = 0

    for item in items
        total = total + item

    total

# ------------------------------------------------------------
# control flow
# ------------------------------------------------------------

# guard with early return
function parse_port(text: shared Text) -> Outcome<Port, ParseError>
    guard text.length() > 0 else
        return Error(ParseError.EmptyInput)

    Ok(parse_digits(text))

# small boolean branch
function clamp_to_zero(x: Int64) -> Int64
    if x < 0
        return 0

    x

# switch over values
function sign(x: Int64) -> Int64
    switch x
        0 => 0
        default => 1

# switch over patterns
function evaluate(expr: shared Expression) -> Int64
    switch expr
        Int(value) => value
        Add(left, right) => evaluate(left.value) + evaluate(right.value)
        Neg(inner) => -evaluate(inner.value)

# while loop
function count_down(n: Int64) -> Unit
    var current = n

    while current > 0
        console.print(current)
        current = current - 1

# for loop, continue, early return
function first_even(items: shared View<Int64>) -> Maybe<Int64>
    for item in items
        if item % 2 != 0
            continue

        return Some(item)

    Empty

# repeat loop
function poll() -> Unit
    repeat
        step()
    while ready() == false

# defer
function use_file(path: Text) -> Outcome<Unit, IOError>
    let file = open(path)
    defer
        file.close()

    Ok(unit)

# ------------------------------------------------------------
# implicit Unit returns and naked return
# ------------------------------------------------------------

# implicit Unit at end of block
function log_message(text: Text) -> Unit
    console.print(text)

# naked return is allowed in Unit functions
function maybe_log(text: Text, enabled: Bool) -> Unit
    if enabled == false
        return

    console.print(text)

# explicit unit is still legal, though usually unnecessary
function explicit_unit_demo() -> Unit
    side_effect()
    unit

# ------------------------------------------------------------
# recursion and tail forms
# ------------------------------------------------------------

# ordinary recursion
function factorial(n: Int64) -> Int64
    switch n
        0 => 1
        default => n * factorial(n - 1)

# self tail recursion
function sum_list(xs: shared List<Int64>, acc: Int64) -> Int64
    switch xs
        Empty => acc
        Node(head, tail) => recur(tail.value, acc + head)

# general tail call
function dispatch(task: Task) -> Outcome<Int64, IOError>
    switch task
        Local(next) => return tail run(next)
        Remote(done) => done

# ------------------------------------------------------------
# built-in Maybe and Outcome constructors
# ------------------------------------------------------------

function demo_constructors() -> Outcome<Maybe<Int64>, IOError>
    Ok(Some(42))

# ------------------------------------------------------------
# arrays, views, and dynamic arrays
# ------------------------------------------------------------

# fixed-size inline array
function make_magic() -> Array<Byte, 4>
    [0x7F, 0x45, 0x4C, 0x46]

# borrowed view over contiguous data
function checksum(data: shared View<Byte>) -> UInt32
    var total: UInt32 = 0

    for b in data
        total = total + b as UInt32

    total

# growable owned contiguous storage
function collect_bytes() -> DynamicArray<Byte>
    let bytes = DynamicArray<Byte>()
    bytes.push(0x41)
    bytes.push(0x42)
    bytes.push(0x43)
    bytes

# ------------------------------------------------------------
# foreign function interface
# ------------------------------------------------------------

# import foreign symbols with an explicit ABI
foreign "c"
    function puts(text: Pointer<Byte>) -> Int32
    function strlen(text: Pointer<Byte>) -> UIntSize

# import foreign symbols from a specific library
foreign "c" library "m"
    function sin(x: Float64) -> Float64
    function cos(x: Float64) -> Float64

# rename a foreign symbol locally
foreign "c"
    function print_line(text: Pointer<Byte>) -> Int32 as "puts"

# export a language function to foreign callers
export foreign "c"
function ffi_add(a: Int32, b: Int32) -> Int32
    a + b

# export with an explicit external symbol name
export foreign "c" as "device_init"
function initialize_device() -> Int32
    0

# ------------------------------------------------------------
# unsafe and raw memory
# ------------------------------------------------------------

# first-class raw addresses
const SRAM_BASE: Address = 0x2000_0000
const SRAM_END: Address  = 0x2001_0000

# raw pointer construction from an address
unsafe function read_byte(addr: Address) -> Byte
    let p: Pointer<Byte> = Pointer<Byte>(addr)
    raw_read(p)

unsafe function write_byte(addr: Address, value: Byte) -> Unit
    let p: Pointer<Byte> = Pointer<Byte>(addr)
    raw_write(p, value)

# typed raw memory access
unsafe function read_word(addr: Address) -> UInt32
    let p: Pointer<UInt32> = Pointer<UInt32>(addr)
    raw_read(p)

unsafe function write_word(addr: Address, value: UInt32) -> Unit
    let p: Pointer<UInt32> = Pointer<UInt32>(addr)
    raw_write(p, value)

# pointer arithmetic
unsafe function zero_bytes(start: Address, count: UInt64) -> Unit
    let p: Pointer<Byte> = Pointer<Byte>(start)
    var i = 0

    while i < count
        raw_write(raw_offset(p, i), 0)
        i = i + 1

# explicit unsafe block
function scribble(addr: Address) -> Unit
    unsafe
        let p = Pointer<Byte>(addr)
        raw_write(p, 0xFF)

# address_of for existing storage
unsafe function poke_first(buf: exclusive Buffer, value: Byte) -> Unit
    let p = address_of(buf.data[0])
    raw_write(p, value)

# ------------------------------------------------------------
# embedded / MMIO
# ------------------------------------------------------------

# memory-mapped register addresses
const UART0_BASE: Address    = 0x4000_1000
const UART0_DATA: Address    = UART0_BASE + 0x00
const UART0_STATUS: Address  = UART0_BASE + 0x04
const UART0_CONTROL: Address = UART0_BASE + 0x08

const GPIO_BASE: Address = 0x4800_0000
const GPIO_OUT: Address  = GPIO_BASE + 0x14
const GPIO_IN: Address   = GPIO_BASE + 0x10

# MMIO should use volatile operations
unsafe function uart_enable() -> Unit
    volatile_write<UInt32>(UART0_CONTROL, 0x01)

unsafe function uart_ready() -> Bool
    (volatile_read<UInt32>(UART0_STATUS) & 0x01) != 0

unsafe function uart_send(byte: Byte) -> Unit
    while uart_ready() == false
        ()

    volatile_write<UInt32>(UART0_DATA, byte as UInt32)

unsafe function gpio_set(mask: UInt32) -> Unit
    volatile_write<UInt32>(GPIO_OUT, mask)

unsafe function gpio_read() -> UInt32
    volatile_read<UInt32>(GPIO_IN)

# typed register block view
const UART0: Pointer<UartRegisters> = Pointer<UartRegisters>(UART0_BASE)

unsafe function uart_status() -> UInt32
    volatile_read(address_of(UART0.status))

unsafe function uart_enable_via_block() -> Unit
    volatile_write(address_of(UART0.control), 0x01)

# ------------------------------------------------------------
# native threads
# ------------------------------------------------------------

# spawn an OS thread and join it later
function parallel_sum(data: shared View<Int64>) -> Int64
    let left = thread
        sum(data)

    let right = sum(data)
    let left_result = left.join()

    left_result + right

# moving owned data into a thread requires concurrency-safe transfer
function launch_processing(buffer: Buffer) -> Unit
    let worker = thread
        process(buffer)

    let result = worker.join()
    consume(result)

# ------------------------------------------------------------
# async tasks and coroutines
# ------------------------------------------------------------

# async functions may suspend
async function fetch(url: Text) -> Outcome<Text, IOError>
    Ok(url)

# lightweight runtime-scheduled tasks
async function fetch_pair() -> Outcome<Pair<Text, Text>, IOError>
    let a = task
        fetch("https://a.example")

    let b = task
        fetch("https://b.example")

    let left = await a
    let right = await b

    Ok(Pair(left, right))

# async code with an early return
async function maybe_fetch(url: Text, enabled: Bool) -> Outcome<Text, IOError>
    if enabled == false
        return Error(IOError.Closed)

    await fetch(url)

Type System Overview

The language uses a static, explicit, mostly nominal, ownership-aware systems type system with:

  • product types via record
  • sum types via choice
  • parametric polymorphism via generics
  • interface-based ad hoc polymorphism via interface and implements
  • explicit access modes via shared, exclusive, owned values, and raw Pointer<T>
  • safe and unsafe separation via unsafe
  • fixed-size and dynamic contiguous collections via Array<T, N>, View<T>, and DynamicArray<T>

It is designed for readable systems programming: explicit enough for performance and memory reasoning, though approachable for engineers new to traditional systems-language syntax.


Keywords and Features

Language Feature Reference

This document gives a concise explanation of each major surface feature in the language, with small examples.


package

Declares the package namespace for the current source file.

package drivers.uart

A file belongs to exactly one package.


import

Imports named items from another package.

import
    console from io
    Logger as Log from diagnostics.logger
    random_int from math.random

Imported names can then be used directly.

function demo() -> Unit
    console.print("hello")
    let n = random_int()

export

Marks a declaration as visible outside the current package.

export function parse_port(text: shared Text) -> Outcome<UInt16, ParseError>
    guard text.length() > 0 else
        return Error(ParseError.EmptyInput)

    Ok(parse_digits(text))

export also works with foreign functions.

export foreign "c"
function ffi_add(a: Int32, b: Int32) -> Int32
    a + b

type

Defines a type alias.

type UserId = UInt64
type Port = UInt16

Aliases improve readability without introducing a new runtime representation.


record

Defines a product type with named fields.

record User
    id: UserId
    name: Text
    age: UInt8

Records are used for plain structured data.

Generic records are supported.

record Pair<A, B>
    first: A
    second: B

choice

Defines a tagged sum type.

choice IOError
    Closed
    EndOfInput
    PermissionDenied

A choice may also attach payloads to variants.

choice Expression
    Int(value: Int64)
    Add(left: Box<Expression>, right: Box<Expression>)
    Neg(inner: Box<Expression>)

This is the main algebraic data type mechanism.


interface

Defines a behavioral abstraction.

interface Display
    function display(this: shared This) -> Text

Interfaces can also be generic.

interface Iterator<T>
    function next(this: exclusive This) -> Maybe<T>

implements

Attaches an interface implementation to a concrete type.

implements Display for User
    function display(this: shared This) -> Text
        this.name

This is the language’s main form of ad hoc polymorphism.


extend

Adds inherent methods directly to a type.

extend Buffer
    function length(this: shared This) -> IntSize
        this.data.length()

    function append(this: exclusive This, b: Byte) -> Unit
        this.data.push(b)

Use extend for methods that belong to the type itself rather than to an interface.


function

Defines a function or method.

function add(a: Int64, b: Int64) -> Int64
    a + b

The final expression is the returned value for non-Unit functions.


where

Adds generic constraints.

function max<T>(left: T, right: T) -> T
where T: Ordered
    switch left >= right
        true => left
        false => right

Multiple constraints can be combined.

function sort_copy<T>(items: shared View<T>) -> DynamicArray<T>
where T: Ordered + Cloneable
    clone_and_sort(items)

this

Refers to the current receiver value inside a method.

extend User
    function display_name(this: shared This) -> Text
        this.name

This

Refers to the receiver type inside an interface, implements, or extend block.

interface Reader
    function read(this: exclusive This, into: exclusive View<Byte>) -> Outcome<IntSize, IOError>

Ownership and Access

owned value

A bare type usually means owned value semantics.

function consume(buf: Buffer) -> Unit
    sink(buf)

Owned values can be moved, stored, or transferred.


shared

Marks a read-only non-owning access view.

function first<T>(items: shared View<T>) -> Maybe<shared T>
    switch items.length()
        0 => Empty
        default => Some(items[0])

Multiple shared views may coexist.


exclusive

Marks a unique mutable non-owning access view.

function fill<R>(source: exclusive R, into: exclusive View<Byte>) -> Outcome<IntSize, IOError>
where R: Reader
    source.read(into)

exclusive is the primary mutable-borrow form.


Pointer<T>

Represents a raw typed pointer for unsafe operations.

unsafe function read_word(addr: Address) -> UInt32
    let p: Pointer<UInt32> = Pointer<UInt32>(addr)
    raw_read(p)

Raw pointers are explicit and machine-facing.


Address

Represents a raw machine address.

const UART0_BASE: Address = 0x4000_1000

Addresses are first-class and support embedded/MMIO work.


Built-In Type Families

Fixed-width signed integers

  • Int8
  • Int16
  • Int32
  • Int64
  • Int128
  • IntSize

Example:

function add(a: Int64, b: Int64) -> Int64
    a + b

Fixed-width unsigned integers

  • UInt8
  • UInt16
  • UInt32
  • UInt64
  • UInt128
  • UIntSize

Example:

function increment(x: UInt32) -> UInt32
    x + 1

Floating-point types

  • Float32
  • Float64

Example:

function half(x: Float64) -> Float64
    x / 2.0

Other core built-ins

  • Bool
  • Byte
  • Char
  • Text
  • Unit
  • Address
  • Pointer<T>

Algebraic Helpers

Maybe<T>

Represents an optional value.

Example:

function first<T>(items: shared View<T>) -> Maybe<shared T>
    switch items.length()
        0 => Empty
        default => Some(items[0])

Some(...)

The present-value constructor.

Some(42)

Empty

The absent-value constructor.

Empty

Outcome<T, E>

Represents success or failure.

Example:

function parse_port(text: shared Text) -> Outcome<UInt16, ParseError>
    guard text.length() > 0 else
        return Error(ParseError.EmptyInput)

    Ok(parse_digits(text))

Ok(...)

The success constructor.

Ok(8080)

Error(...)

The failure constructor.

Error(ParseError.InvalidDigit)

Box<T>

Represents explicit owning heap indirection.

record Box<T>
    value: T

It is especially useful for recursive data.

choice List<T>
    Empty
    Node(head: T, tail: Box<List<T>>)

Collections and Views

Array<T, N>

Represents fixed-size contiguous inline storage.

record Header
    magic: Array<Byte, 4>
    version: UInt16

Example:

function make_magic() -> Array<Byte, 4>
    [0x7F, 0x45, 0x4C, 0x46]

View<T>

Represents a non-owning contiguous view over data.

function checksum(data: shared View<Byte>) -> UInt32
    var total: UInt32 = 0

    for b in data
        total = total + b as UInt32

    total

Use View<T> for read-only or borrowed APIs over contiguous memory.


DynamicArray<T>

Represents growable owned contiguous storage.

record Buffer
    data: DynamicArray<Byte>

Example:

function collect_bytes() -> DynamicArray<Byte>
    let bytes = DynamicArray<Byte>()
    bytes.push(0x41)
    bytes.push(0x42)
    bytes.push(0x43)
    bytes

List<T>

Represents a recursive sequence type.

choice List<T>
    Empty
    Node(head: T, tail: Box<List<T>>)

This is a logical recursive structure, not the primary growable contiguous container.


Local Bindings

let

Introduces a fixed local binding.

let label: Text = "sum"

var

Introduces a reassignable local binding.

var total = 0
total = total + 1

Control Flow

switch

Primary branching construct for values and patterns.

Value-based switching:

function sign(x: Int64) -> Int64
    switch x
        0 => 0
        default => 1

Pattern-based switching:

function evaluate(expr: shared Expression) -> Int64
    switch expr
        Int(value) => value
        Add(left, right) => evaluate(left.value) + evaluate(right.value)
        Neg(inner) => -evaluate(inner.value)

default

Fallback branch in a switch.

switch code
    200 => "ok"
    default => "unexpected"

guard

Checks a precondition and exits early if it fails.

function parse_port(text: shared Text) -> Outcome<UInt16, ParseError>
    guard text.length() > 0 else
        return Error(ParseError.EmptyInput)

    Ok(parse_digits(text))

else

Introduces the failure branch of a guard.

guard file.exists() else
    return Error(IOError.Closed)

if

Small boolean branch form.

function clamp_to_zero(x: Int64) -> Int64
    if x < 0
        return 0

    x

while

Condition-driven loop.

function count_down(n: Int64) -> Unit
    var current = n

    while current > 0
        print(current)
        current = current - 1

for

Iterates over a sequence or view.

function sum(items: shared View<Int64>) -> Int64
    var total = 0

    for item in items
        total = total + item

    total

repeat

Runs a post-test loop.

function poll() -> Unit
    repeat
        step()
    while ready() == false

break

Exits the nearest loop.

function find_stop(items: shared View<Int64>) -> Unit
    for item in items
        if item == 0
            break

        print(item)

continue

Skips to the next loop iteration.

function first_even(items: shared View<Int64>) -> Maybe<Int64>
    for item in items
        if item % 2 != 0
            continue

        return Some(item)

    Empty

defer

Schedules cleanup when the current scope exits.

function use_file(path: Text) -> Outcome<Unit, IOError>
    let file = open(path)
    defer
        file.close()

    Ok(unit)

return

Performs an early return.

function clamp_to_zero(x: Int64) -> Int64
    if x < 0
        return 0

    x

In Unit functions, a bare return is allowed.

function maybe_log(text: Text, enabled: Bool) -> Unit
    if enabled == false
        return

    print(text)

Implicit final result

A non-Unit function returns its final expression.

function add(a: Int64, b: Int64) -> Int64
    a + b

Implicit unit

A Unit function may reach the end of its block without spelling unit.

function log_message(text: Text) -> Unit
    print(text)

Explicit unit remains legal.

function explicit_unit_demo() -> Unit
    side_effect()
    unit

Recursion and Tail Forms

Ordinary recursion

Uses direct self-calls.

function factorial(n: Int64) -> Int64
    switch n
        0 => 1
        default => n * factorial(n - 1)

recur

Represents self-tail-recursive re-entry.

function sum_list(xs: shared List<Int64>, acc: Int64) -> Int64
    switch xs
        Empty => acc
        Node(head, tail) => recur(tail.value, acc + head)

tail

Marks a guaranteed general tail call when used in return tail ....

function dispatch(task: Task) -> Outcome<Int64, IOError>
    switch task
        Local(next) => return tail run(next)
        Remote(done) => done

Foreign Function Interface

foreign "abi"

Declares foreign imports for a specific ABI.

foreign "c"
    function puts(text: Pointer<Byte>) -> Int32
    function strlen(text: Pointer<Byte>) -> UIntSize

library

Narrows foreign imports to a specific linked library.

foreign "c" library "m"
    function sin(x: Float64) -> Float64
    function cos(x: Float64) -> Float64

as in foreign declarations

Renames an imported foreign symbol locally.

foreign "c"
    function print_line(text: Pointer<Byte>) -> Int32 as "puts"

export foreign

Exports a language-defined function to foreign callers.

export foreign "c"
function ffi_add(a: Int32, b: Int32) -> Int32
    a + b

You can also export under a specific external symbol.

export foreign "c" as "device_init"
function initialize_device() -> Int32
    0

Unsafe, Raw Memory, and MMIO

unsafe

Enters the unsafe subset of the language.

Unsafe function:

unsafe function read_byte(addr: Address) -> Byte
    let p: Pointer<Byte> = Pointer<Byte>(addr)
    raw_read(p)

Unsafe block:

function scribble(addr: Address) -> Unit
    unsafe
        let p = Pointer<Byte>(addr)
        raw_write(p, 0xFF)

raw_read / raw_write

Perform raw typed memory access.

unsafe function read_word(addr: Address) -> UInt32
    let p: Pointer<UInt32> = Pointer<UInt32>(addr)
    raw_read(p)

unsafe function write_word(addr: Address, value: UInt32) -> Unit
    let p: Pointer<UInt32> = Pointer<UInt32>(addr)
    raw_write(p, value)

raw_offset

Performs pointer arithmetic.

unsafe function zero_bytes(start: Address, count: UInt64) -> Unit
    let p: Pointer<Byte> = Pointer<Byte>(start)
    var i = 0

    while i < count
        raw_write(raw_offset(p, i), 0)
        i = i + 1

address_of

Takes the address of an existing object or field.

unsafe function poke_first(buf: exclusive Buffer, value: Byte) -> Unit
    let p = address_of(buf.data[0])
    raw_write(p, value)

volatile_read / volatile_write

Perform MMIO-safe volatile access.

const UART0_BASE: Address    = 0x4000_1000
const UART0_DATA: Address    = UART0_BASE + 0x00
const UART0_STATUS: Address  = UART0_BASE + 0x04
const UART0_CONTROL: Address = UART0_BASE + 0x08

unsafe function uart_enable() -> Unit
    volatile_write<UInt32>(UART0_CONTROL, 0x01)

unsafe function uart_ready() -> Bool
    (volatile_read<UInt32>(UART0_STATUS) & 0x01) != 0

unsafe function uart_send(byte: Byte) -> Unit
    while uart_ready() == false
        ()

    volatile_write<UInt32>(UART0_DATA, byte as UInt32)

Concurrency and Tasks

thread

Spawns an OS thread.

function parallel_sum(data: shared View<Int64>) -> Int64
    let left = thread
        sum(data)

    let right = sum(data)
    let left_result = left.join()

    left_result + right

The returned handle supports .join().


task

Spawns a lightweight runtime-scheduled task.

async function fetch_pair() -> Outcome<Pair<Text, Text>, IOError>
    let a = task
        fetch("https://a.example")

    let b = task
        fetch("https://b.example")

    let left = await a
    let right = await b

    Ok(Pair(left, right))

async function

Declares a coroutine-enabled function that may suspend.

async function fetch(url: Text) -> Outcome<Text, IOError>
    Ok(url)

await

Suspends until an async result is ready.

async function maybe_fetch(url: Text, enabled: Bool) -> Outcome<Text, IOError>
    if enabled == false
        return Error(IOError.Closed)

    await fetch(url)

Transferable

Marks values safe to move across thread or task boundaries.

interface Transferable

This is part of the concurrency safety model.


Shareable

Marks values safe to share across thread or task boundaries.

interface Shareable

This is part of the concurrency safety model.


Summary

This language currently has a:

  • static type system
  • mostly nominal type identity model
  • ownership-aware access discipline
  • generic / parametric abstraction model
  • algebraic data-modeling core
  • interface-based behavioral abstraction model
  • explicit FFI and module system
  • explicit unsafe boundary for raw memory, pointers, and MMIO
  • thread, task, and async support designed around the safety model

In one sentence:

A static, mostly nominal, ownership-aware systems type system with records, choices, generics, interfaces, explicit views and pointers, clear package and FFI boundaries, and a readable concurrency model spanning threads, tasks, and async functions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment