Skip to content
dj-lumierePublic

About

A structured SSA language that keeps IR's one-step-at-a-time honesty and tames the pain of writing it by hand. Compiles to LLVM IR.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

Tessera logo

Tessera

A statement-centred low-level language: a value is bound once, memory comes from a manager and is given back by hand, and the build checks it.

Version 0.1.0 Status: early alpha License: MIT

Documentation · Quick start · Reference for AI assistants · Examples · RazorForge

Tessera (.tess) keeps every step of a program on the page, and keeps writing it bearable. Nothing happens between the lines: a value is bound once and never reassigned, a load and a store are calls you can see (p.peek(), p.poke(v)), memory is taken from a manager and given back by hand, and the builder checks that it was.

routine two_sum(list: @S32, count: USize, target: S32) -> Maybe[(USize, USize)]
    each left_idx in 0 til count
        each right_idx in left_idx + 1 til count
            left_val: S32 = list.stride(left_idx).peek()
            right_val: S32 = list.stride(right_idx).peek()
            if left_val + right_val == target
                return (left_idx, right_idx)
    return None()

Two each loops make the O(n²) search, and the numbers come as a pointer and a count: stride is the address of one, read with an explicit peek. The answer is a Maybe of a tuple: the tuple itself, built with (...) from where it goes, or None() when there is none.

Early alpha. The language is still changing, and the builder works but is incomplete. Every commit runs the golden tests on Linux, Windows, and macOS, 64- and 32-bit, and checks 32-bit ARM, aarch64 Linux, and riscv64 builds in CI. Expect changes between releases, and expect bugs.

What we are trying to keep

  • No ceremony. Nothing you write is there only because the language asks for it.
  • Code is the expression of intent. What you write says what you mean.
  • What should work, works. Code that looks like it should work does, and it does what it looks like it does.
  • One acceptable way. There is a way that works for everyone, even if it isn't everyone's favorite.
  • Nothing goes wrong silently. A failure is loud, a hang is reported, and no work is left running that nobody will ever check.

And for Tessera, the satisfaction of building something stitch by stitch, and of growing it into larger code.

What it is like

A program is tiles of tiles. A tessera is one tile of a mosaic, and a Tessera program is put together the same way: each level is made of whole pieces of the level below.

Level What it is
statement One step: a binding (x: S64 = a + b), a load (p.peek()), a store (p.poke(v)), a local slot (local p: @S64 <- 0), a call, a return.
routine A body of statements with a head of local lines: if / else, each / while / until loops with carried values, and when to choose. Every value is bound once, and every path ends in a return.
module A namespace for routines, types, and constants (Standard/Format). It's declared in the source, not tied to files.
solution The code built together to make one application.

Operators are routine calls. a + b is a.add(b), a +% b is a.add_wrap(b), and a >> 1 is a.shr(1) (arithmetic on a signed value, logical on an unsigned one): a type takes an operator by declaring the routine, and an overflow crashes unless the wrapping (+%) or clamping (+^) form was written.

Loops carry their values by name. while n > 1 with n: U64 = start, steps: U64 = 0 names what each pass changes, continue with n: n / 2, steps: steps + 1 passes the next values, and then sees the last ones.

= only binds. Memory is read and written by peek and poke calls, and every binding states its type.

Sum types are variants. Maybe and Result are variants, read with a when whose arms bind the payload; choices and variants print, compare, and hash without being asked. Tuples of two to four values (-> (U64, U64), q, r = div_rem(a, b)) cover results that are just several values; a record names the parts when they mean something.

Nothing hidden. No implicit conversions, destructors, exceptions, vtables, or allocations: every runtime operation is written in the source.

Quick start

From source

You need the .NET 10 SDK and clang 21 or newer on PATH.

git clone https://github.com/dj-lumiere/Tessera.git
cd Tessera
dotnet build                     # builds the `tessera` builder
dotnet test tests                # optional: every golden test and example as an xUnit case

Hello, world

dotnet run -- run examples/hello.tess

examples/ continues from there, one idea per program, in reading order.

Using an AI assistant?

Tessera is not in any model's training data yet, so assistants tend to guess LLVM- or Rust-flavored syntax that does not build. Point yours at TESSERA-FOR-AI.md, a one-page summary of the rules that are easy to get wrong. The programs in examples/ and tests/ run on every commit and make good starting points.

Command line

tessera new   [<folder>]                      Start a solution: config.toml, main.tess, .gitignore, .vscode/
tessera build                                 Build the solution its config.toml describes (here or above)
tessera run                                   Build it and run it
tessera build <file.tess>... [-o <out>]       Build an executable from these files
              [--emit-llvm] [<target>] [--mode <mode>]  (--emit-llvm writes LLVM IR instead)
tessera run   <file.tess>... [<target>] [--mode <mode>]  Build and run these files
tessera test  [<target>] [--mode <mode>] <dir-or-file>...  Run golden tests
tessera check [<target>] [<file.tess>...]     Type-check every non-generic routine, the stdlib included
tessera fmt   [--check] <file-or-dir>...      Format .tess files in place
tessera migrate [--check] <file-or-dir>...    Rewrite .tess files to this release's spellings
tessera help | version

<mode> is debug (-O0, the default), release (-O2), release-time (-O3), or release-space (-Os), as a config.toml's mode. Every mode carries debug information, DWARF or CodeView and a .pdb on Windows MSVC: a debugger stops on Tessera lines and shows routine parameters, bindings, and loop-carried values by name. From a checkout, run it as dotnet run -- <command>. <target> is --target <arch-os-abi> (default: this machine), --cpu <name>, and --feature <name>[,...]. With files, all of them form one solution. Without files, build and run read the nearest config.toml, which names the package and sets the target, mode, sources, library directories, and link options (see Modules → The solution manifest):

[package]
name = "greeter"

[target]
mode = "release"
sources = ["src"]

What works today

  • Modules: namespaces with import, qualified paths, define, and private / internal; Standard/Core is always imported. Two modules may declare the same name, and symbols follow the Itanium C++ mangling.
  • Solutions: described by a config.toml, or every file on the command line; the stdlib is built in with it.
  • Standard library: written in Tessera and layered so that only Standard/Os needs libc; a target without an operating system builds without it.
  • Builder: emits LLVM IR text and links through clang, with a formatter (fmt) and a type-checker (check).
  • Tooling: a TextMate grammar (Tessera.tmbundle/).

Tessera, RazorForge, and Suflae

Tessera is the low-level layer of the same workspace. Anvila, the builder behind RazorForge and Suflae, can emit Tessera source instead of LLVM IR ([target] backend = "tessera"), and Ingrid's shared math, hashing, and algorithm libraries are moving into Tessera so that both languages build on one implementation. Tessera itself stands alone: this repository builds and runs without the others.

Documentation

The documentation lives at tessera.lumi-dev.xyz:

This repository

Tessera/
├── src/                 # The builder, in C#: emits LLVM IR text and links through clang
├── Standard/              # The standard library (.tess), the source of truth for the current design
├── tests/               # Golden tests, including Dijkstra, a lazy segment tree, SHA-256, and a calculator
│   └── Tessera.Tests.csproj  # runs each golden test and example as its own xUnit case
├── examples/            # Introductory programs, one idea each, in reading order
├── playground/          # Gitignored: your own programs (the Rider configuration *Playground* runs main.tess)
├── Tessera.tmbundle/    # TextMate grammar
├── Tessera.csproj       # Builder project
└── TESSERA-FOR-AI.md    # Reference for AI assistants

Each golden test is <name>.tess, or a directory <name>/ whose files are built together (several modules, or a config.toml to build from), with one of:

  • <name>.expected: the program's stdout
  • <name>.exit: its exit code (default 0)
  • <name>.error: text the build error must contain

The programs in examples/ carry <name>.expected files too, so they run as tests alongside tests/.

Contributing

Bug reports, feature suggestions, documentation fixes, and code are all welcome. When the stdlib and the docs disagree, the stdlib wins. Report bugs at github.com/dj-lumiere/Tessera/issues.

License

MIT; see LICENSE. The float math in Standard/B16Core/, B32Core/, B64Core/, and B128Core/ is based on CORE-MATH, also MIT; each of those directories carries its LICENSE-CORE-MATH.

About

A structured SSA language that keeps IR's one-step-at-a-time honesty and tames the pain of writing it by hand. Compiles to LLVM IR.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages