Talor is a systems language with static memory safety and
no garbage collector. Regions are inferred rather than
annotated, a borrow needs no sigil and no lifetime written
(string, never &string), and what a function does to its caller's values
is one optional clause after the signature instead of a mode keyword on
every parameter.
There is no runtime ownership check: the compiler proves it, emits LLVM IR, and gets out of the way.
Everything on this page compiles and runs today, checked by the compiler before the page was built.
use std.map.{Map};
use std.math.{PI};
variant Shape { Dot, Circle(f64), Rect { w: f64, h: f64 } }
struct Counter { seen: Map<string, i64> }
fn area(s: Shape): f64 {
match s {
Shape.Dot => 0.0,
Shape.Circle(r) => PI * r.powi(2),
Shape.Rect { w, h } => w * h,
}
}
impl Counter {
fn empty(): Counter { Counter { seen: Map.empty() } }
fn note(self, name: string) {
let before = match self.seen.get(name.clone()) { Some(n) => n, None => 0 };
self.seen.set(name, before + 1);
}
}
fn main(): i32 {
let c = Counter.empty();
c.note("circle");
c.note("rect");
let shapes = [Shape.Circle(1.0), Shape.Rect { w: 2.0, h: 3.0 }, Shape.Dot];
let total = 0.0;
for s in shapes { total += area(s); }
println(`${c.seen.len()} kinds, area ${total}`);
0
}
string, never &string, and nothing
written for the borrow itself: a place handed to a function that only
reads it becomes a borrow of that place, so a call site carries
nothing, and regions are inferred - no lifetime parameters to write
and none to read.
Types, regions and what a function does to a parameter are inferred:
edits self is how an author states an effect, and a
function that says nothing is checked exactly as strictly.
mutA move is a consuming use, and the compiler knows one when it sees one: the last read of a place takes it rather than copying it.
variant and enumTwo declarations for two different things: a tagged union and a numbered
set. A recursive variant needs no Box.
// A borrow has no sigil: `string`, never `&string`. Nothing is written for the
// borrow itself - a place handed to a function that only reads it becomes a
// borrow of that place, and the callee reads it where it lies.
fn longest_len(a: string, b: string): i64 {
if a.len() >= b.len() { a.len() } else { b.len() }
}
// The clause after a signature says what a function does to the caller's
// values. `edits` mutates, `takes` keeps. Both are optional, and a function
// that says nothing is checked exactly as strictly.
fn push_twice(xs: Array<i64>, v: i64) {
xs.push(v);
xs.push(v);
}
fn consume(name: string) {
println(name);
}
// There is no move operator and no `mut`. A move is a consuming use, and the
// compiler knows one when it sees one: the last read of a place takes it
// rather than copying it.
fn main(): i32 {
let xs = [1, 2];
push_twice(xs, 7);
consume("kept");
let a = "abc";
let b = "de";
// Nothing is written at the call site: `a` and `b` are read, not copied.
println(`${xs.len()} items, longest ${longest_len(a, b)}`);
0
}
// `variant` is the tagged union and `enum` is the numbered set: two
// declarations, because they are two different things.
use std.math.{PI};
variant Shape { Dot, Circle(f64), Rect { w: f64, h: f64 } }
enum Level { Low, Medium, High }
fn area(s: Shape): f64 {
match s {
Shape.Dot => 0.0,
Shape.Circle(r) => PI * r.powi(2),
Shape.Rect { w, h } => w * h,
}
}
// An `enum` case carries no data and answers the number it was given.
fn threshold(l: Level): i64 {
match l {
Level.Low => 10,
Level.Medium => 100,
Level.High => 1000,
}
}
fn main(): i32 {
println(`${area(Shape.Rect { w: 2.0, h: 3.0 })} and ${threshold(Level.High)}`);
0
}
Map is not built in either: it is ordinary Talor over
Array and the structural hash.Not yet : and this section says so rather than pretending otherwise. Talor is in internal beta: the compiler builds, passes its gates and compiles itself, but the source is not published, so there is nothing to clone today. This is what the first public beta will look like.
# when the public beta lands:
git clone <repository> talor && cd talor
make # the C core and talorboot
make stage1 # build/stage1/talor-stage1
make verify-stage1 # gen2 == gen3: the compiler is a fixpoint of itself
make install # puts it on PATH as `talor`
talor run program.talor
make install puts on your PATH is gen2, the
compiler the language compiled, not the one the C seed compiled.The grammar is published on npm, so a site, a documentation build
or an editor can highlight .talor source without vendoring a copy.
This page is coloured by it.
npm install talorlang
gen2 == gen3, byte-identical IR