-- Bee-3 by example
Every program here runs, and the output shown is what it produces.
Generated by tools/build_examples_md.py from the same catalogue the
playground ships, with outputs taken from the recorded expectations the
test suite re-checks — so this file cannot drift from the language.
157 short examples in 17 groups, 18 whole programs, and 26 traps that each demonstrate a safety guarantee firing.
Open playground.html to edit and run any of them in a browser.
- Basics — 11
- Collections — 16
- Concurrency — 5
- Contracts — 8
- Control — 11
- Errors — 6
- Generics — 10
- Library — 18
- Logic — 8
- Numbers — 10
- Objects — 6
- Ranges — 6
- Rationals — 8
- Rules — 13
- Safety — 5
- Strings — 10
- Types — 6
- Whole programs — 18
- Traps — 26
rule main:
print "Hello World";
return;
Hello World
rule main:
write "no";
write " newline";
print;
print "then one";
return;
no newline
then one
rule main:
print (1, 2, 3);
print (1, 2, sep:" ");
return;
1,2,3
1 2
rule main:
new a ∈ Z;
let a := 42;
print a;
return;
42
rule main:
new a: 1, b: 2 ∈ Z;
print (a, b);
return;
1,2
rule main:
new a := 10;
new r := 0.5;
new s := "text";
new f := True;
print (kind(a), kind(r), kind(s), kind(f));
return;
Z,R,S,B
set LIMIT: 10 ∈ Z;
rule main:
print LIMIT;
return;
10
rule zeros() => (z ∈ Z, r ∈ R, f ∈ B):
-- a result starts at its type's zero and needs no assignment
expect True;
return;
rule main:
new a, b, c := zeros();
print (a, b, c);
return;
0,0.0,0B0
-- a whole-line comment
-- another one
rule main:
print 1; -- trailing
return;
1
rule main:
new a: 1, b: 2 ∈ Z;
let a, b := b, a;
print (a, b);
return;
2,1
rule main:
print "before";
over;
print "never";
return;
before
rule main:
new a := [1,2,3];
print a;
print a[0];
print a[-1];
return;
[1,2,3]
1
3
rule main:
new a ∈ [Z](5);
let a[*] := 7;
print a;
return;
[7,7,7,7,7]
rule main:
new a := [1,2,3,4,5];
new w := a[0..2];
let w[*] := 0;
print a;
return;
[0,0,0,4,5]
rule main:
new l := (1,2,3);
print l;
print (l.head, l.tail);
return;
(1,2,3)
1,3
rule main:
new l := (2,3);
let l <+ 4;
let l +> 1;
print l;
let l << 1;
let l >> 1;
print l;
return;
(1,2,3,4)
(2,3)
rule main:
print {3,1,2,1};
return;
{1,2,3}
rule main:
print {1,2} ∪ {2,3};
print {1,2,3} ∩ {2,3};
print {1,2,3} Δ {2,3,4};
print {1,2} ⊂ {1,2,3};
return;
{1,2,3}
{2,3}
{1,4}
0B1
rule main:
print {1,2} union {2,3};
print {1,2,3} inter {2,3};
print {1,2} subset {1,2,3};
return;
{1,2,3}
{2,3}
0B1
rule main:
new s := {1,2};
let s += 3;
let s -= 1;
print s;
print 3 ∈ s;
return;
{2,3}
0B1
rule main:
new m := {1:"a", 2:"b"};
let m[3] := "c";
print m;
print m[2];
scrap m[1];
print m;
return;
{(1:a),(2:b),(3:c)}
b
{(2:b),(3:c)}
rule main:
new m := {1:"a", 2:"b"};
for k, v ∈ m do
write k + "=" + v + " ";
repeat;
print;
return;
1=a 2=b
rule main:
print { x | x ∈ (1..6) ∧ (x % 2 = 0) };
print { x² | x ∈ (1..4) };
print [ x | x ∈ (1..9:2) ];
return;
{2,4,6}
{1,4,9,16}
[1,3,5,7,9]
rule main:
print { (x:x²) | x ∈ (1..4) };
return;
{(1:1),(2:4),(3:9),(4:16)}
rule main:
print ∀ (i ∈ {2,4,6}) ∧ (i % 2 = 0);
print ∃ (i ∈ {1,3,5}) ∧ (i = 3);
return;
0B1
0B1
rule main:
new a := [1,2];
new shared := a;
new copied :: a;
let a[0] := 9;
print (shared[0], copied[0]);
return;
9,1
rule main:
print [1,2] + [3];
new l := (1,2);
new m := (3,);
print l + m;
return;
[1,2,3]
(1,2,3)
rule ticker(n ∈ N) => (v ∈ N):
cycle:
new i ∈ N;
for i ∈ (1..n) do
let v := i;
yield;
repeat;
let v := 0;
return;
rule main:
begin ticker(4);
cycle:
new r ∈ N;
do
yield r << ticker;
write r;
repeat if r > 0;
print;
return;
12340
rule odds(n ∈ N) => (v ∈ N):
cycle:
new i ∈ N;
for i ∈ (1..n) do
let v := i * 2 - 1;
yield;
repeat;
let v := 0;
return;
rule evens(n ∈ N) => (v ∈ N):
cycle:
new i ∈ N;
for i ∈ (1..n) do
let v := i * 2;
yield;
repeat;
let v := 0;
return;
rule main:
begin odds(3);
begin evens(3);
cycle:
new a ∈ N;
new b ∈ N;
do
yield a << odds;
yield b << evens;
write a + "/" + b + " ";
repeat if a > 0;
print;
return;
1/2 3/4 5/6 0/0
rule scaled(x ∈ Z) => (r ∈ Z):
let r := x * 10;
return;
rule main:
new got ∈ (Z);
begin got <+ scaled(1);
begin got <+ scaled(2);
begin got <+ scaled(3);
wait;
print got;
return;
(10,20,30)
rule sum(a, b ∈ Z) => (r ∈ Z):
cycle:
new i ∈ Z;
for i ∈ (a..b) do
let r += i;
repeat;
return;
rule main:
new parts ∈ (Z);
cycle:
new lo ∈ Z;
for lo ∈ (1..76:25) do
begin parts <+ sum(lo, lo + 24);
repeat;
wait;
new total ∈ Z;
for p ∈ parts do
let total += p;
repeat;
print total;
return;
5050
rule main:
new squares ∈ [Z](6);
for ∀ i ∈ (0.!6) do
let squares[i] := i * i;
repeat;
print squares;
return;
[0,1,4,9,16,25]
rule half(n ∈ Z) => (r ∈ Z):
require n % 2 = 0;
let r := n / 2;
return;
rule main:
print half(8);
return;
4
rule bump(n ∈ Z) => (r ∈ Z):
ensure r > n;
let r := n + 1;
return;
rule main:
print bump(1);
return;
2
rule clamp(v, lo, hi ∈ Z) => (r ∈ Z):
require lo ≤ hi;
ensure lo ≤ r ≤ hi;
let r := v;
if v < lo do
let r := lo;
else if v > hi do
let r := hi;
done;
return;
rule main:
print (clamp(-5,0,10), clamp(5,0,10), clamp(99,0,10));
return;
0,5,10
trait Sized:
rule size() => (s ∈ Z)
ensure s > 0;
done;
rule Box(n ∈ Z) => (self ∈ Box <: Sized):
new self.n := n;
rule .size() => (s ∈ Z):
let s := self.n;
return;
return;
rule main:
print Box(4).size();
return;
4
rule bump(n ∈ @Z):
let n += 1;
return;
rule main:
new counter: 10 ∈ Z;
apply bump(@counter);
print counter;
return;
11
rule bump(n ∈ @Z):
ensure n = old n + 1;
let n += 1;
return;
rule main:
new counter: 10 ∈ Z;
apply bump(@counter);
print counter;
return;
11
rule grow(items ∈ [Z], by ∈ Z):
require by ≥ 0;
ensure items.length = old items.length + by;
let items ++ by;
return;
rule main:
new xs ∈ [Z](2);
print xs.length;
apply grow(xs, 3);
print xs.length;
return;
2
5
rule deposit(balance ∈ @Q, amount ∈ Q):
require amount > 0;
ensure balance > old balance;
let balance += amount;
return;
rule main:
new balance: 10 ∈ Q;
apply deposit(@balance, 1\4);
print balance;
return;
10.25
rule main:
new n := 7;
if n > 10 do
print "big";
else
print "small";
done;
return;
small
rule main:
new n := 0;
if n > 0 do
print "positive";
else if n < 0 do
print "negative";
else
print "zero";
done;
return;
zero
rule main:
start:
new hidden := 1;
do
print hidden;
done;
return;
1
rule main:
new n := 3;
cycle:
do
write n;
let n -= 1;
repeat if n > 0;
print;
return;
321
rule main:
new n := 0;
cycle:
while n < 3 do
write n;
let n += 1;
repeat;
print;
return;
012
rule main:
new n := 0;
cycle:
while n < 3 do
let n += 1;
then
print "finished at " + n;
repeat;
return;
finished at 3
rule main:
for i ∈ (1..10) do
next if i % 2 = 0;
stop if i > 7;
write i;
repeat;
print;
return;
1357
rule main:
cycle outer:
new i ∈ Z;
for i ∈ (1..3) do
for j ∈ (1..3) do
stop outer if i * j > 4;
write i * j;
repeat;
repeat;
print;
return;
12324
rule main:
match 2:
when 1 do
print "one";
when 2, 3 do
print "two or three";
other
print "other";
done;
return;
two or three
rule main:
match all 4:
when 4 do
print "exactly four";
when (0..9) do
print "a digit";
done;
return;
exactly four
a digit
type Small: (0..3) <: Z;
rule main:
new v: 2 ∈ Small;
match v:
when 0, 1 do
print "low";
when (2..3) do
print "high";
done;
return;
high
rule main:
new n := 4;
expect n > 0;
print "held";
return;
held
rule main:
trial:
try:
print "first";
try:
print "second";
final
print "always";
done;
return;
first
second
always
rule main:
trial:
try:
print "a";
try:
raise 300, "boom";
try:
print "c";
case $error.code = 300 do
print "handled " + $error.message;
resume;
done;
return;
a
handled boom
c
rule main:
trial:
new tries: 0 ∈ Z;
try:
let tries += 1;
raise 400, "flaky" if tries < 3;
print "ok after " + tries;
case $error.code = 400 do
retry;
done;
return;
ok after 3
rule main:
trial:
try:
raise 999, "unknown";
case $error.code = 1 do
print "wrong";
miss
print "missed " + $error.code;
done;
return;
missed 999
rule main:
trial:
try:
print "a";
pass;
print "skipped";
try:
fail 500, "noted";
try:
print "code is " + $error.code;
final
print "done";
done;
return;
a
code is 500
done
rule first_of[T](items ∈ [T]) => (r ∈ T):
let r := items[0];
return;
rule main:
print first_of([1,2,3]);
print first_of(["alpha","beta"]);
print first_of([1.5, 2.5]);
return;
1
alpha
1.5
rule first_of[T](items ∈ [T]) => (r ∈ T):
let r := items[0];
return;
rule main:
new n := first_of([10,20]);
new s := first_of(["x"]);
print (kind(n), kind(s));
return;
Z,S
rule same[T](a, b ∈ T) => (r ∈ B):
let r := a = b;
return;
rule main:
print same(1, 1);
print same("x", "y");
print same(1.5, 1.5);
return;
0B1
0B0
0B1
rule pair[T](a, b ∈ T) => (r ∈ [T]):
let r := [a, b];
return;
rule main:
print pair(7, 8);
print pair("l", "r");
return;
[7,8]
[l,r]
rule label[K, V](key ∈ K, value ∈ V) => (r ∈ S):
let r := key + "=" + value;
return;
rule main:
print label("count", 3);
print label(1, "one");
return;
count=3
1=one
rule occurrences[T](items ∈ [T], wanted ∈ T) => (n ∈ Z):
cycle:
new item ∈ T;
for item ∈ items do
let n += 1 if item = wanted;
repeat;
return;
rule main:
print occurrences([1,2,2,3], 2);
print occurrences(["a","b","a"], "a");
return;
2
2
rule head_of[T](items ∈ (T)) => (r ∈ T):
let r := items.head;
return;
rule main:
print head_of((1,2,3));
print head_of(("a","b"));
return;
1
a
rule first_of[T](items ∈ [T]) => (r ∈ T):
let r := items[0];
return;
rule twice[T](items ∈ [T]) => (r ∈ [T]):
let r := [first_of(items), first_of(items)];
return;
rule main:
print twice([9,8]);
print twice(["q"]);
return;
[9,9]
[q,q]
trait Sized:
rule size() => (n ∈ Z);
done;
rule Box(width ∈ Z) => (self ∈ Box <: Sized):
new self.width := width;
rule .size() => (n ∈ Z):
let n := self.width;
return;
return;
rule bigger[T <: Sized](thing ∈ T) => (n ∈ Z):
let n := thing.size() * 2;
return;
rule main:
print bigger(Box(21));
return;
42
rule swapped[T](a, b ∈ T) => (x, y ∈ T):
let x := b;
let y := a;
return;
rule main:
new p, q := swapped(1, 2);
print (p, q);
new r, s := swapped("left", "right");
print (r, s);
return;
2,1
right,left
rule main:
print (abs(-3), abs(3), abs(-2.5));
return;
3,3,2.5
rule main:
print (min(4, 2), max(4, 2));
print min(9, 3, 7, 1);
print max(1.5, 2.5);
return;
2,4
1
2.5
rule main:
print (clamp(-5, 0, 10), clamp(5, 0, 10), clamp(15, 0, 10));
return;
0,5,10
rule main:
print (floor(3.7), ceil(3.2), round(3.5));
print (floor(-3.2), ceil(-3.7), round(-3.5));
return;
3,4,4
-4,-3,-4
rule main:
print (sign(-7), sign(0), sign(7));
print (gcd(12, 18), gcd(35, 64));
return;
-1,0,1
6,1
rule reduce(top, bottom ∈ Z) => (a, b ∈ Z):
new by := gcd(top, bottom);
let a := top / by;
let b := bottom / by;
return;
rule main:
new a, b := reduce(84, 132);
print a + "/" + b;
return;
7/11
rule main:
print (ord('A'), chr(66));
cycle:
new i ∈ Z;
for i ∈ (0..5) do
write chr(ord('a') + i);
repeat;
print;
return;
65,B
abcdef
rule main:
print upper("bee");
print lower("BEE");
print "[" + trim(" spaced ") + "]";
return;
BEE
bee
[spaced]
rule main:
print find("hello world", "world");
print find("hello", "z");
print contains("hello", "ell");
return;
6
-1
0B1
rule main:
print replace("2026-08-18", "-", "/");
print reverse("stressed");
return;
2026/08/18
desserts
rule main:
new parts := split("alpha,beta,gamma", ",");
print parts;
print parts.length;
print join(parts, " -> ");
return;
(alpha,beta,gamma)
3
alpha -> beta -> gamma
rule main:
print split("bee", "");
return;
(b,e,e)
rule main:
print parse_z("42") + 1;
print parse_r("2.5") * 2.0;
new fields := split("3,4", ",");
print parse_z(fields.head) + parse_z(fields.tail);
return;
43
5.0
7
rule main:
new xs := [1,2,3,4,5];
print sum(xs);
print sum(xs) / xs.length;
return;
15
3
rule main:
print sorted([3,1,2]);
print sorted(["pear","apple","fig"]);
print reverse(sorted([3,1,2]));
return;
[1,2,3]
[apple,fig,pear]
[3,2,1]
rule main:
new xs := [9,8,7];
print (first(xs), last(xs), empty(xs));
new nothing ∈ (Z);
print empty(nothing);
return;
9,7,0B0
0B1
rule main:
new text := "the bee flies the field";
new words := split(text, " ");
print words.length;
print sorted(words);
return;
5
(bee,field,flies,the,the)
-- a declared name shadows a library one, so adding to the library
-- cannot break a program that already used that name
rule sum(a, b ∈ Z) => (r ∈ Z):
let r := a + b;
return;
rule main:
print sum(2, 3);
return;
5
rule main:
new t := True;
new f := False;
print (t, f);
return;
0B1,0B0
rule main:
print (True ∧ False, True ∨ False, ¬True, True ⊕ True);
return;
0B0,0B1,0B0,0B0
rule main:
print (True and False, True or False, not True);
return;
0B0,0B1,0B0
rule main:
new a: 1, b: 2 ∈ Z;
print a = 1 ∧ b = 2;
return;
0B1
rule main:
new a: 1, b: 2, c: 3 ∈ Z;
print a < b < c;
print a < c < b;
return;
0B1
0B0
rule main:
print 1 = 1;
print 1 ≡ 1;
print 1 ≠ 2;
return;
0B1
0B1
0B1
rule main:
new a := 10;
print a ∈ Z;
print a ∈ R;
return;
0B1
0B0
rule main:
new n := 5;
print "big" if n > 3;
print "small" if n ≤ 3;
return;
big
rule main:
new z: -5 ∈ Z;
new n: 5 ∈ N;
print (z, n);
return;
-5,5
rule main:
print (7 + 2, 7 - 2, 7 * 2);
return;
9,5,14
rule main:
print 7 / 2;
print -7 / 2;
return;
3
-3
rule main:
print 7 % 3;
print -7 % 3;
return;
1
-1
rule main:
new a: 7 ∈ Z;
print (a :> R) / 2.0;
return;
3.5
rule main:
new x := 2;
print x ^ 10;
print x²;
new n := 3;
print xⁿ;
return;
1024
4
8
rule main:
print 9 √ 2;
print 27 root 3;
return;
3.0
3.0
rule main:
new n: 5 ∈ N;
new z ∈ Z;
let z := n;
new r ∈ R;
let r := z;
print r;
return;
5.0
rule main:
new r: 9.7 ∈ R;
print r :> Z;
return;
9
rule main:
print 3 ÷ 9;
print 4 divides 9;
return;
0B1
0B0
rule Point(x, y ∈ Z) => (self ∈ Point):
new self.x := x;
new self.y := y;
return;
rule main:
new p := Point(3,4);
print (p.x, p.y);
print kind(p);
return;
3,4
Point
rule Base(tag ∈ S) => (self ∈ Base):
new self.tag := tag;
new self.level := 1;
return;
rule Derived() => (self ∈ Derived <: Base):
let self := super("child");
let self.level := 2;
return;
rule main:
new d := Derived();
print (d.tag, d.level);
return;
child,2
rule Counter() => (self ∈ Counter):
new self.n := 0;
rule .bump():
let self.n += 1;
return;
rule .value() => (v ∈ Z):
let v := self.n;
return;
return;
rule main:
new c := Counter();
apply c.bump();
apply c.bump();
print c.value();
return;
2
trait Named:
rule name() => (n ∈ S);
done;
rule Dog() => (self ∈ Dog <: Named):
new self.legs := 4;
rule .name() => (n ∈ S):
let n := "dog";
return;
return;
rule main:
print Dog().name();
return;
dog
trait Named:
rule name() => (n ∈ S);
done;
rule Dog() => (self ∈ Dog <: Named):
new self.legs := 4;
rule .name() => (n ∈ S):
let n := "dog";
return;
return;
rule Bird() => (self ∈ Bird <: Named):
new self.legs := 2;
rule .name() => (n ∈ S):
let n := "bird";
return;
return;
rule announce(x ∈ Named):
print x.name();
return;
rule main:
apply announce(Dog());
apply announce(Bird());
return;
dog
bird
rule main:
new a := {v: 1};
new shared := a;
new copied :: a;
let a.v := 9;
print (shared.v, copied.v);
return;
9,1
rule main:
for i ∈ (1..5) do
write i;
repeat;
print;
return;
12345
rule main:
for i ∈ (1.!5) do
write i;
repeat;
print;
for i ∈ (1!.5) do
write i;
repeat;
print;
return;
1234
2345
rule main:
for i ∈ (1!!5) do
write i;
repeat;
print;
return;
234
rule main:
for i ∈ (0..10:2) do
write i;
write ",";
repeat;
print;
return;
0,2,4,6,8,10,
rule main:
print 5 ∈ (1..9);
print 5 in (1..4);
return;
0B1
0B0
rule main:
for c ∈ ('a'..'e') do
write c;
repeat;
print;
return;
abcde
rule main:
print (1\2, 1\4, 1\8);
return;
0.5,0.25,0.125
rule main:
print 1\4 + 1\8;
print 1\4 * 1\2;
print 1\4 / 1\8;
return;
0.375
0.125
2
rule main:
new total ∈ Q;
cycle:
new i ∈ Z;
for i ∈ (1..8) do
let total += 1\8;
repeat;
print total;
expect total = 1;
return;
1
rule main:
new tiny: 31.75 ∈ Q(5,2);
print (tiny, kind(tiny));
return;
31.75,Q5.2
rule main:
print (0.33333 ≈ 1\3);
print (0.25 ≈ 1\3);
print (0.25 ≈ 1\3 ± 0.1);
return;
0B1
0B0
0B1
rule main:
print 1\10;
print exact(1\10);
return;
0.1
0.09999847412109375
rule main:
new r ∈ R;
let r := 1\2;
print r;
print 0.75 :> Q;
return;
0.5
0.75
rule main:
new lon: 2.3522 ∈ Λ;
new lat: 48.8566 ∈ Φ;
print (lat, lon);
print kind(lat);
return;
48.8566,2.3522
Φ
rule double(n ∈ Z) => (r ∈ Z):
let r := n * 2;
return;
rule main:
print double(21);
return;
42
rule split(n ∈ Z) => (lo, hi ∈ Z):
let lo := n / 2;
let hi := n - lo;
return;
rule main:
new a, b := split(9);
print (a, b);
return;
4,5
rule split(n ∈ Z) => (lo, hi ∈ Z):
let lo := n / 2;
let hi := n - lo;
return;
rule main:
new both := split(9);
print both;
return;
(4,5)
rule greet(name ∈ S, times: 1 ∈ Z):
for i ∈ (1..times) do
write name;
repeat;
print;
return;
rule main:
apply greet("hi");
apply greet("ho", 3);
return;
hi
hohoho
rule box(width: 1, height: 1 ∈ Z) => (area ∈ Z):
let area := width * height;
return;
rule main:
print box(height: 5);
print box(width: 2, height: 3);
return;
5
6
rule fact(n ∈ N) => (r ∈ N):
if n ≤ 1 do
let r := 1;
else
let r := n * fact(n - 1);
done;
return;
rule main:
print fact(6);
return;
720
rule odd(n ∈ Z) => (r ∈ B);
rule even(n ∈ Z) => (r ∈ B):
if n = 0 do
let r := True;
else
let r := odd(n - 1);
done;
return;
rule odd(n ∈ Z) => (r ∈ B):
if n = 0 do
let r := False;
else
let r := even(n - 1);
done;
return;
rule main:
print (even(10), odd(10));
return;
0B1,0B0
rule bump(n ∈ [Z]):
let n += 1;
return;
rule main:
new count := 0;
apply bump(@count);
print count;
return;
1
rule total(xs ∈ [Z]) => (sum ∈ Z):
for x ∈ xs do
let sum += x;
repeat;
return;
rule main:
print total([1,2,3,4]);
return;
10
rule main:
new square := λ(x ∈ Z) => x² ∈ Z;
print square(7);
return;
49
rule twice(x ∈ Z, f: λ(v ∈ Z) => Z) => (r ∈ Z):
let r := f(f(x));
return;
rule main:
print twice(3, λ(v ∈ Z) => v + 1 ∈ Z);
return;
5
rule main:
new ops := {"inc": λ(x ∈ Z) => x + 1 ∈ Z};
print ops["inc"](41);
return;
42
rule value() => (r ∈ Z):
let r := 7;
return;
rule main:
apply _ := value();
print "discarded";
return;
discarded
rule main:
new big: 9223372036854775806 ∈ Z;
let big += 1;
print big;
print "one more would trap, not wrap";
return;
9223372036854775807
one more would trap, not wrap
type Digit: (0..9) <: Z;
rule main:
new d: 9 ∈ Digit;
print d;
return;
9
rule consume(xs ∈ [Z]) => (total ∈ Z):
for x ∈ xs do
let total += x;
repeat;
return;
rule main:
new numbers := [1,2,3,4];
print consume(numbers!);
let numbers := [10,20];
print consume(numbers!);
return;
10
30
rule main:
new a: 1, b: 2 ∈ Z;
print a = 1 and b = 2;
print 2 in (1..3);
print forall (i in {2,4}) and (i % 2 = 0);
print {1} union {2};
return;
0B1
0B1
0B1
{1,2}
rule consume(data ∈ [Z]) => (total ∈ Z):
cycle:
new i ∈ Z;
for i ∈ data do
let total += i;
repeat;
return;
rule main:
new numbers := [1,2,3,4];
print consume(numbers!);
-- the name holds nothing until it is given a new value
let numbers := [10,20];
print consume(numbers!);
return;
10
30
rule main:
new s := "text";
new c := 'x';
print (s, c);
return;
text,x
rule main:
print "n = " + 42;
print "r = " + 0.5;
return;
n = 42
r = 0.5
rule main:
print '-' * 20;
print "ab" * 3;
return;
--------------------
ababab
rule main:
new s := "hello";
print s.length;
print s[0];
print s[-1];
return;
5
h
o
rule main:
new s := "abcdef";
print s[0..2];
print s[2..5];
return;
abc
cdef
rule main:
print "n=#(z) s=#(s)" ? (5, "hi");
return;
n=5 s='hi'
rule main:
print "#(r:0.3)" ? (3.14159);
print "#(>0:6)" ? (42);
print "#(<_:6)|" ? (42);
return;
3.142
000042
42 |
rule main:
print "#(b)" ? (10);
print "#(h)" ? (255);
print "#(q)" ? ("q");
return;
1010
ff
"q"
rule main:
print "all: #[*]" ? ([1,2,3]);
print "one: #[1]" ? ([1,2,3]);
return;
all: 1,2,3
one: 2
rule main:
new a := "x";
new b := a;
let a += "y";
print b;
return;
xy
type Row: [Z](3);
rule main:
new r ∈ Row;
let r[*] := 1;
print r;
return;
[1,1,1]
type Digit: (0..9) <: Z;
rule main:
new d: 7 ∈ Digit;
print d;
print kind(d);
return;
7
Digit
type Point: {x ∈ Z, y ∈ Z} <: Object;
rule main:
new p ∈ Point;
let p.x := 3;
let p.y := 4;
print p;
return;
{x: 3, y: 4}
rule main:
new p := {x: 1, y: 2};
print p;
print p.x;
return;
{x: 1, y: 2}
1
rule main:
new o := {inner: {v: 7}};
print o.inner.v;
return;
7
rule main:
new n := 1;
new m := 1;
-- a label, for reading
print kind(n);
-- a checked question
print n ∈ Z;
-- value and type together
print n ≡ m;
return;
Z
0B1
0B1
The conformance demos: complete programs with recorded output, run by
run_tests.py on every change. Sources are in tests/demos/.
tests/demos/bee3.bee
+-------------------------------------------
| what Bee-3 changed, and why |
-------------------------------------------+
-- Every line here is either impossible or wrong in Bee-2.
-- D71: mutual recursion, which Bee-2 could not express at all
rule odd(n ∈ Z) => (r ∈ B);
rule even(n ∈ Z) => (r ∈ B):
if n = 0 do
let r := True;
else
let r := odd(n - 1);
done;
return;
rule odd(n ∈ Z) => (r ∈ B):
if n = 0 do
let r := False;
else
let r := even(n - 1);
done;
return;
rule main:
-- D66: a compound condition means what it looks like
new a: 1, b: 2 ∈ Z;
print a = 1 ∧ b = 2;
print a > 0 ∨ b > 9;
-- D68: the same program, typed on an ordinary keyboard
print a = 1 and b = 2;
print 2 in (1..3);
print forall (i in {2,4}) and (i % 2 = 0);
print {1,2} union {3};
-- D69: == compares values, as everywhere else
new x := "abc";
new y := "abc";
print x == y;
-- D71 again
print even(10);
print odd(10);
-- D72: a match covers every selector
match 99:
when 1 do
print "one";
other
print "anything else";
done;
return;
0B1
0B1
0B1
0B1
0B1
{1,2,3}
0B1
0B1
0B0
anything else
tests/demos/contracts.bee
+-------------------------------------------
| contracts: what a rule promises |
-------------------------------------------+
-- A precondition is the caller's obligation, a postcondition the rule's.
-- Both sit in the signature, where a reader looking only at the interface
-- still sees them, and both must be free of side effects (D75).
-- A pure helper, so it may be used in a contract.
rule sorted_pair(lo, hi ∈ Z) => (r ∈ B):
let r := lo ≤ hi;
return;
-- The caller must pass an even, non-negative number; the rule promises
-- the result doubles back to it.
rule half(n ∈ Z) => (r ∈ Z):
require n ≥ 0;
require n % 2 = 0;
ensure r * 2 = n;
let r := n / 2;
return;
-- A contract may name the results and the parameters together.
rule clamp(v, lo, hi ∈ Z) => (r ∈ Z):
require sorted_pair(lo, hi);
ensure lo ≤ r ≤ hi;
let r := v;
if v < lo do
let r := lo;
else if v > hi do
let r := hi;
done;
return;
rule main:
print half(8);
print half(0);
print clamp(5, 1, 10);
print clamp(-3, 1, 10);
print clamp(99, 1, 10);
-- the postcondition of clamp uses a chained comparison (D74)
expect clamp(7, 1, 10) = 7;
return;
4
0
5
1
10
tests/demos/safety.bee
+-------------------------------------------
| three safety features Bee-2 lacked |
-------------------------------------------+
-- D80: a rule with results cannot be called for effect alone, unless the
-- discard is written down.
rule checked(n ∈ Z) => (ok ∈ B):
let ok := n > 0;
return;
rule announce(n ∈ Z):
print n;
return;
-- D81: taking ownership. The caller cannot touch `data` afterwards, so a
-- job may mutate it with nothing to race against and no lock to forget.
rule consume(data ∈ [Z]) => (total ∈ Z):
cycle:
new i ∈ Z;
for i ∈ data do
let total += i;
repeat;
return;
rule main:
-- D79: an accumulator relies on the zero value, and stays legal
new total ∈ Z;
cycle:
new i ∈ Z;
for i ∈ (1..4) do
let total += i;
repeat;
print total;
-- D80: results are bound, or discarded on purpose
new ok := checked(5);
print ok;
apply announce(7);
apply _ := checked(-1);
-- D81: ownership moves out of `numbers`
new numbers := [1,2,3,4];
print consume(numbers!);
-- and a new value revives the name
let numbers := [10,20];
print consume(numbers!);
return;
10
0B1
7
10
30
tests/demos/parallel.bee
+-------------------------------------------
| ∀ means the iterations are independent |
-------------------------------------------+
-- Bee-2 treated ∀ in a for header as decoration (D20). Bee-3 makes it a
-- claim the compiler checks (D82): an iteration may write only what it
-- owns — its own locals, and the element its control variable selects.
-- -- Nothing runs in parallel yet. The claim is checked, which is the part
-- that has to be true before the rest is worth building.
-- Λ and Φ are constrained Q domains, not a new numeric kind (D83).
rule east_of(here, there ∈ Λ) => (r ∈ B):
let r := here > there;
return;
rule main:
-- data-parallel: each iteration writes a different element
new squares ∈ [Z](6);
for ∀ i ∈ (0.!6) do
let squares[i] := i * i;
repeat;
print squares;
-- a plain for has no such restriction, and may accumulate
new total ∈ Z;
for n ∈ squares do
let total += n;
repeat;
print total;
-- geospatial: about 0.85 m of resolution at the equator
new paris_lon: 2.3522 ∈ Λ;
new paris_lat: 48.8566 ∈ Φ;
print (paris_lat, paris_lon);
print exact(paris_lon);
new london_lon: -0.1276 ∈ Λ;
print east_of(paris_lon, london_lon);
print kind(paris_lat);
return;
[0,1,4,9,16,25]
55
48.8566,2.3522
2.352203369140625
0B1
Φ
tests/demos/traits.bee
+-------------------------------------------
| traits: a promise, not just a shape |
-------------------------------------------+
-- A trait names the methods a type must provide, and may carry the
-- contracts every implementation inherits (D84). A type declares which
-- trait it satisfies on its constructor's result, and the compiler checks
-- it — nothing is satisfied by accident.
-- -- Methods live inside the constructor, which is where upstream's own
-- generator demo writes them.
trait Shape:
rule area() => (a ∈ R)
ensure a > 0;
rule name() => (n ∈ S);
done;
rule Circle(radius ∈ R) => (self ∈ Circle <: Shape):
new self.radius := radius;
rule .area() => (a ∈ R):
let a := 3.14159 * self.radius * self.radius;
return;
rule .name() => (n ∈ S):
let n := "circle";
return;
return;
rule Square(side ∈ R) => (self ∈ Square <: Shape):
new self.side := side;
rule .area() => (a ∈ R):
let a := self.side * self.side;
return;
rule .name() => (n ∈ S):
let n := "square";
return;
return;
-- one rule, any Shape
rule describe(s ∈ Shape):
print s.name() + " has area " + s.area();
return;
rule main:
apply describe(Circle(1.0));
apply describe(Square(3.0));
return;
circle has area 3.14159
square has area 9.0
tests/demos/generics.bee
+-------------------------------------------
| generics: type parameters on rules |
-------------------------------------------+
-- Deliberately small (D86): parameters on rules only, no variance, no
-- higher kinds, bounds through the existing traits, and monomorphised —
-- one compiled function per set of type arguments.
-- -- This is what the standard library wanted: 17 of its 27 rules are
-- built-ins purely because `rule abs(n ∈ Z)` could not also serve R.
trait Sized:
rule size() => (n ∈ Z);
done;
rule Box(width ∈ Z) => (self ∈ Box <: Sized):
new self.width := width;
rule .size() => (n ∈ Z):
let n := self.width;
return;
return;
-- one rule, any element type
rule first_of[T](items ∈ [T]) => (r ∈ T):
let r := items[0];
return;
-- the variable may appear more than once
rule occurrences[T](items ∈ [T], wanted ∈ T) => (n ∈ Z):
cycle:
new item ∈ T;
for item ∈ items do
let n += 1 if item = wanted;
repeat;
return;
-- and in the result
rule pair[T](a, b ∈ T) => (r ∈ [T]):
let r := [a, b];
return;
-- a bound is a promise: T must satisfy Sized
rule doubled[T <: Sized](thing ∈ T) => (n ∈ Z):
let n := thing.size() * 2;
return;
rule main:
-- the same rule, three element types
print first_of([1,2,3]);
print first_of(["alpha","beta"]);
print first_of([1.5, 2.5]);
-- and the result keeps that type
new n := first_of([10,20]);
new s := first_of(["x"]);
print (kind(n), kind(s));
print occurrences([1,2,2,3], 2);
print occurrences(["a","b","a"], "a");
print pair(7, 8);
print pair("l", "r");
print doubled(Box(21));
return;
1
alpha
1.5
Z,S
2
2
[7,8]
[l,r]
42
tests/demos/library.bee
+-------------------------------------------
| the standard library |
-------------------------------------------+
-- Bee-3 had five built-ins, so every program began by rebuilding abs and
-- min. These are built-ins rather than a library written in Bee because
-- Bee has no generics: `rule abs(n ∈ Z)` could not also serve R or Q, and
-- a library would need a copy per type (D85).
rule main:
-- numbers, whatever their type
print (abs(-3), abs(-3.5), min(4,2,9), max(4,2,9));
print (sign(-7), floor(3.7), ceil(3.2), round(3.5), round(-3.5));
print (clamp(15, 1, 10), gcd(12, 18));
-- characters
print (ord('A'), chr(66));
-- text
print (upper("bee"), lower("BEE"), trim(" spaced "));
print (find("hello", "ll"), contains("hello", "ell"));
print replace("a-b-c", "-", "+");
print reverse("stressed");
-- text into numbers
print parse_z("42") + 1;
print parse_r("2.5") * 2.0;
-- collections
new xs := [5,3,9,1];
print (sum(xs), first(xs), last(xs), empty(xs));
print sorted(xs);
print reverse(xs);
-- splitting and joining
new parts := split("alpha,beta,gamma", ",");
print parts;
print join(parts, " -> ");
print parts.length;
return;
3,3.5,2,9
-1,3,4,4,-4
10,6
65,B
BEE,bee,spaced
2,0B1
a+b+c
desserts
43
5.0
18,5,1,0B0
[1,3,5,9]
[1,9,3,5]
(alpha,beta,gamma)
alpha -> beta -> gamma
3
tests/demos/oldvalue.bee
+-------------------------------------------
| contracts about change |
-------------------------------------------+
-- `@T` marks a parameter the rule may write through (D88). Bee-2 spelled
-- this `[T]` — the same as an array — so `let a += 1` incremented a boxed
-- scalar but appended to an array, and a contract could say nothing about
-- either.
-- -- `old n` is what a parameter held at entry (D89), so a postcondition can
-- describe the change rather than only the result.
rule bump(n ∈ @Z):
ensure n = old n + 1;
let n += 1;
return;
rule grow(items ∈ [Z], by ∈ Z):
require by ≥ 0;
ensure items.length = old items.length + by;
let items ++ by;
return;
rule deposit(balance ∈ @Q, amount ∈ Q):
require amount > 0;
ensure balance > old balance;
let balance += amount;
return;
rule main:
-- a scalar the rule writes through
new counter: 10 ∈ Z;
apply bump(@counter);
print counter;
-- a collection: old deep-copies, so the length before is knowable
new xs ∈ [Z](2);
print xs.length;
apply grow(xs, 3);
print xs.length;
-- exact money, with a promise it went up
new balance: 10 ∈ Q;
apply deposit(@balance, 1\4);
print balance;
return;
11
2
5
10.25
tests/demos/hello_world.bee
-- hello world demo
rule main:
print "Hello World";
return;
Hello World
tests/demos/fibonacci.bee
+----------------------------
| Demo Fibonacci rule |
----------------------------+
-- Ported from demo/fibonacci.bee
-- Note: fib(0) = fib(1) = 1, so the sequence is offset by one
-- from the conventional Fibonacci numbering. fib(5) = 8.
rule fib(n ∈ N) => (y ∈ N):
if (n = 1) ∨ (n = 0) do
let y := 1; -- first value
else
let y := fib(n-1) + fib(n-2);
done;
return;
rule main:
-- call fib rule using a named argument
new r := fib(n: 5);
print r;
return;
8
tests/demos/bubble_sort.bee
+--------------------------------------
| Bubble sort with Array of integers |
--------------------------------------+
-- Ported from demo/bubble_sort.bee
-- Two bugs fixed: comparison direction (was descending) and
-- an off-by-one that read this[n] past the end of the array.
rule sort(this ∈ [Z]):
new n := length(this);
new swap := True; -- inferred B
cycle:
do
let swap := False; -- reset flag
for i ∈ (0 .! n-1) do
if this[i] > this[i+1] do
let (this[i], this[i+1]) := (this[i+1], this[i]); -- swap
let swap := True;
done;
repeat;
repeat if swap;
return;
rule main:
new test := [1,4,1,5,9,2,6,5,3,5];
new result := [1,1,2,3,4,5,5,5,6,9];
apply sort(test);
print test;
expect test = result;
return;
[1,1,2,3,4,5,5,5,6,9]
tests/demos/rationals.bee
+-----------------------------------
| fixed point, compiled |
-----------------------------------+
-- Kept inside the C backend's subset so both implementations run it.
rule payment(total ∈ Q, parts ∈ Z) => (each ∈ Q):
let each := total / parts;
return;
rule main:
-- the inch divisions: all exact in binary fixed point
print 1\2;
print 1\4;
print 1\8;
print 1\16;
print 1\32;
-- arithmetic does not drift
new total: 0 ∈ Q;
new step: 1\8 ∈ Q;
cycle:
new i ∈ Z;
for i ∈ (1..8) do
let total += step;
repeat;
print total;
expect total = 1;
-- mixed with integers, and division
print 1\4 + 1\8;
print 1\4 * 2;
print payment(3\4, 3);
-- conversions both ways
new r ∈ R;
let r := 1\2;
print r;
new back := 0.75 :> Q;
print back;
print (1\2 + 1) :> Z;
-- a narrower container
new tiny: 31.75 ∈ Q(5,2);
print tiny;
return;
0.5
0.25
0.125
0.0625
0.03125
1
0.375
0.5
0.25
0.5
0.75
1
31.75
tests/demos/lists.bee
+-----------------------------------
| lists, in both implementations |
-----------------------------------+
-- Kept inside the C backend's subset, so the differential harness compares
-- the interpreter against a native binary on every line of this.
rule drain(queue ∈ (Z)) => (total ∈ Z):
cycle:
while queue.length > 0 do
let total += queue.head;
let queue << 1;
repeat;
return;
rule main:
new l := (1,2,3);
print l;
print (l.head, l.tail, l.length);
print l[1];
print l[-1];
-- the ends grow and shrink independently
let l <+ 4;
let l +> 0;
print l;
let l << 2;
let l >> 1;
print l;
-- concatenation and equality are by value
new m := (9,8);
print l + m;
new a := (1,2);
new b := (1,2);
print a = b;
-- a list is shared by :=, copied by ::
new shared := a;
new copied :: a;
let a <+ 3;
print (shared.length, copied.length);
-- iteration walks the live window, not the buffer
new sum ∈ Z;
for x ∈ m do
let sum += x;
repeat;
print sum;
-- passed by reference, so the rule consumes the caller's list
new queue := (5,10,15);
print drain(queue);
print queue.length;
return;
(1,2,3)
1,3,3
2
3
(0,1,2,3,4)
(2,3)
(2,3,9,8)
0B1
3,2
17
30
0
tests/demos/collections.bee
+-----------------------------------
| sets, maps and builders |
-----------------------------------+
-- New in Bee-1a. Nothing in this file exists in Bee-0.
rule main:
-- sets are sorted, unique and unindexed
new small := {3,1,2,1};
print small; -- duplicates collapse
new bigger := {2,3,4};
print small ∪ bigger;
print small ∩ bigger;
print small Δ bigger;
print {1,2} ⊂ small;
let small += 9;
let small -= 1;
print small;
print 9 ∈ small;
-- maps are keyed and kept in key order
new roman := {1:"I", 2:"II"};
let roman[3] := "III";
print roman[3];
scrap roman[1];
for key, value ∈ roman do
write key + "=" + value + " ";
repeat;
print;
-- builders draw from a source and may filter
print { x | x ∈ (1..5) ∧ (x % 2 = 1) };
print { x² | x ∈ (1..3) };
print [ x | x ∈ (1..9:2) ];
print { (x:x²) | x ∈ (0.!10) ∧ (x % 2 = 0) };
-- logic quantifiers over a collection
print ∀ (i ∈ {2,4,6}) ∧ (i % 2 = 0);
print ∃ (i ∈ {1,3,5}) ∧ (i = 3);
return;
{1,2,3}
{1,2,3,4}
{2,3}
{1,4}
0B1
{2,3,9}
0B1
III
2=II 3=III
{1,3,5}
{1,4,9}
[1,3,5,7,9]
{(0:0),(2:4),(4:16),(6:36),(8:64)}
0B1
0B1
tests/demos/advanced.bee
+-----------------------------------------
| lambdas, templates, match, trial, |
| objects — everything added in Bee-1b |
-----------------------------------------+
type Point: {x ∈ Z, y ∈ Z} <: Object;
-- a lambda passed as a callback
rule combine(a, b ∈ Z, op: λ(p, q ∈ Z) => Z) => (r ∈ Z):
let r := op(a, b);
return;
-- a rule that fails on bad input, for the trial below
rule halve(n ∈ Z) => (r ∈ Z):
let r := n / 2;
return;
rule main:
-- lambdas are values
new square := λ(v ∈ Z) => v² ∈ Z;
print square(7);
print combine(3, 4, λ(p, q ∈ Z) => p * q ∈ Z);
-- string templates
print "#(z) and #(z) make #(z)" ? (2, 3, 5);
print "pi is about #(r:0.3)" ? (3.14159);
print "padded:#(>0:5)" ? (42);
print "everything: #[*]" ? ([1,2,3]);
-- match, one variant: the first hit wins
new grade := 87;
match grade:
when (90..100) do
print "A";
when (80.!90) do
print "B";
other
print "C or below";
done;
-- match, all variant: every hit runs
match all 4:
when 4 do
print "exactly four";
when (0..9) do
print "a single digit";
done;
-- objects are records with named fields
new here ∈ Point;
let here.x := 3;
let here.y := 4;
print here;
print here.x + here.y;
new there := {x: 10, y: 20};
print there.y;
-- a trial: one job fails, a case resolves it, the rest continue
trial:
new done_jobs: 0 ∈ Z;
try:
let done_jobs += 1;
print "checked input";
try:
let done_jobs += 1;
raise 300, "value rejected";
try:
let done_jobs += 1;
print "finished work";
case $error.code = 300 do
print "recovered from: " + $error.message;
resume;
miss
print "no handler matched";
final
print "jobs run: " + done_jobs;
done;
return;
49
12
2 and 3 make 5
pi is about 3.142
padded:00042
everything: 1,2,3
B
exactly four
a single digit
{x: 3, y: 4}
7
20
checked input
recovered from: value rejected
finished work
jobs run: 3
tests/demos/producer_consumer.bee
+-------------------------------------------
| producer and consumer, two coroutines |
| taking turns over one channel |
-------------------------------------------+
-- Ported from demo/producer_consumer.bee, which is written in the legacy
-- dialect and uses an operator (`-?`) that appears in no upstream table.
-- The shape is kept: a producer fills a bounded channel, a consumer drains
-- it, and neither runs while the other does.
-- The producer stops filling once the channel reaches its batch size.
rule produce(channel ∈ (N), last, batch ∈ N) => (made ∈ N):
cycle:
new mark: 1 ∈ N;
do
-- fill until the channel is full or the numbers run out
cycle:
while (channel.length < batch) ∧ (mark ≤ last) do
let channel <+ mark;
let made += 1;
let mark += 1;
repeat;
yield;
repeat if mark ≤ last;
let made := 0;
return;
-- The consumer drains whatever is waiting, then hands control back.
rule consume(channel ∈ (N)) => (taken ∈ N):
cycle:
do
cycle:
while channel.length > 0 do
write channel.head + " ";
let channel << 1;
let taken += 1;
repeat;
yield;
repeat;
return;
rule main:
new channel ∈ (N);
begin produce(channel, 9, 4);
begin consume(channel);
-- declared out here so the totals survive the cycle
new made ∈ N;
new taken ∈ N;
cycle:
do
yield made << produce;
yield taken << consume;
repeat if made > 0;
print;
print "consumed " + taken;
expect channel.length = 0;
return;
1 2 3 4 5 6 7 8 9
consumed 9
tests/demos/map_reduce.bee
+-------------------------------------------
| map-reduce: four jobs, then a fold |
-------------------------------------------+
-- Ported from the concurrency chapter. Every job here is isolated (D64):
-- `sum` reads only its arguments and writes only its own result, so the
-- four could run in parallel with identical results.
-- -- python3 -m bee --isolation tests/demos/map_reduce.bee
rule sum(a, b ∈ Z) => (r ∈ Z):
cycle:
new i ∈ Z;
for i ∈ (a..b) do
let r += i;
repeat;
return;
rule main:
new partials ∈ (Z);
cycle:
new lo ∈ Z;
for lo ∈ (1..76:25) do
begin partials <+ sum(lo, lo + 24);
repeat;
wait;
new total ∈ Z;
for part ∈ partials do
let total += part;
repeat;
print total;
expect total = 5050;
return;
5050
tests/demos/complete.bee
+-------------------------------------------
| rationals, constructors, inheritance, |
| coroutines and deferred jobs |
-------------------------------------------+
set $precision: 0.001;
type Digit: (0..9) <: Z;
-- a constructor: its single result is named self, and its name is its type
rule Shape(name ∈ S) => (self ∈ Shape):
new self.name := name;
new self.sides := 0;
return;
-- a child constructor chains through super
rule Square(size ∈ Q) => (self ∈ Square <: Shape):
let self := super("square");
let self.sides := 4;
let self.area := size * size;
return;
-- a bare yield makes this a coroutine
rule halves(n ∈ N) => (part ∈ Q):
cycle:
new i ∈ N;
for i ∈ (1..n) do
let part := 1\2 ^ i;
yield;
repeat;
let part := 0;
return;
rule scaled(x ∈ Z) => (r ∈ Z):
let r := x * 10;
return;
rule main:
-- fixed point is exact, and p\q is the literal notation
print (1\2, 1\4, 1\8);
print 1\4 + 1\8;
print 1\4 * 1\2;
print 1\3;
-- a sized container states its own range
new tiny: 31.75 ∈ Q(5,2);
print (tiny, kind(tiny));
-- ≈ uses $precision unless a tolerance is given
print (0.333 ≈ 1\3);
print (0.25 ≈ 1\3);
print (0.25 ≈ 1\3 ± 0.1);
-- a range subtype constrains its values
new d: 7 ∈ Digit;
print d;
-- constructors and inheritance
new blob := Shape("blob");
print (blob.name, blob.sides);
new sq := Square(1\2);
print (sq.name, sq.sides, sq.area);
-- a coroutine keeps its state between resumes
begin halves(4);
cycle:
new v ∈ Q;
do
yield v << halves;
write v + " ";
repeat if v > 0;
print;
-- begin defers, wait joins in start order
new results ∈ (Z);
begin results <+ scaled(1);
begin results <+ scaled(2);
begin results <+ scaled(3);
wait;
print results;
return;
0.5,0.25,0.125
0.375
0.125
0.33334
31.75,Q5.2
0B1
0B0
0B1
7
blob,0
square,4,0.25
0.5 0.25 0.125 0.0625 0
(10,20,30)
Each of these fails on purpose. A language whose argument is that it catches mistakes should let you watch it catch them, so every guarantee has a program here that trips it.
rule main:
new count := 1;
start:
new count := 2;
do
print count;
done;
return;
error[E248]: "count" shadows an outer declaration
= help: rename one of them; a reader should not have to work out which is meant (D70)
rule main:
match 99:
when 1 do
print "one";
done;
return;
error[E250]: this match has no `other` branch
= help: the branches cannot be shown to cover every value of Z; add `other` (D72)
rule main:
new a := [1,2,3,4,5];
new window := a[0..2];
let a ++ 3;
print window;
return;
runtime error: this slice was taken before the array was resized
rule main:
new a := 2;
new b := 3;
print a ** b;
return;
error[E032]: "**" mid-line is neither a comment nor a power
= help: a `**` comment must start a line; for exponentiation write ^ or a superscript (D67)
rule main:
new n := 1;
if n do
print 1;
done;
return;
error[E010]: the if condition must be B, found Z
= help: Bee has no truthiness; compare explicitly, as in `x ≠ 0` (§7.4)
rule main:
new n ∈ Z;
let n := 10.5;
print n;
return;
error[E012]: cannot assign R to Z
= help: narrowing is never implicit; write `... :> Z` (§4.5)
rule main:
print total;
return;
error[E013]: undeclared identifier "total"
= help: Bee has no hoisting: declare it before use (§3)
rule main:
new n: 1 ∈ Z;
new s := "two";
print n < s < n;
return;
error[E219]: cannot compare Z with S
rule main:
new big: 9223372036854775807 ∈ Z;
let big += 1;
print big;
return;
runtime error: + overflowed a 64-bit integer
type Digit: (0..9) <: Z;
rule main:
new d: 99 ∈ Digit;
print d;
return;
runtime error: 99 is above the domain of Digit
rule main:
new a := [1,2,3];
print a[9];
return;
runtime error: index 9 is outside 0..2
rule half(n ∈ Z) => (r ∈ Z):
require n % 2 = 0;
let r := n / 2;
return;
rule main:
print half(7);
return;
runtime error: "half" requires condition 1
new log: 0 ∈ Z;
rule noisy(n ∈ Z) => (r ∈ B):
let log += 1;
let r := n > 0;
return;
rule bad(n ∈ Z) => (r ∈ Z):
require noisy(n);
let r := n;
return;
rule main:
print bad(1);
return;
error[E252]: a require condition cannot call "noisy"
= help: it is not isolated: writes the module variable "log" (D75)
rule shrink(n ∈ @Z):
ensure n > old n;
let n -= 1;
return;
rule main:
new x: 5 ∈ Z;
apply shrink(@x);
print x;
return;
runtime error: "shrink" fails to ensure condition 1
rule f(n ∈ @Z):
require n > old n;
let n += 1;
return;
rule main:
new x: 1 ∈ Z;
apply f(@x);
return;
error[E264]: "old" belongs in an ensure condition
= help: in a require nothing has happened yet (D89)
rule main:
new n := 1;
print type(n);
return;
error[E263]: the built-in is "kind", not "type"
= help: write `kind(x)`; `type` declares a type (D87)
trait Sized:
rule size() => (n ∈ Z);
done;
rule doubled[T <: Sized](thing ∈ T) => (n ∈ Z):
let n := thing.size() * 2;
return;
rule main:
print doubled(42);
return;
error[E261]: Z does not satisfy Sized
= help: the type parameter T is bounded (D86)
rule same[T](a, b ∈ T) => (r ∈ T):
let r := a;
return;
rule main:
print same(1, "x");
return;
error[E261]: "same" cannot take S where its b is T
= help: the type parameter is already fixed by an earlier argument (D86)
trait Shape:
rule area() => (a ∈ R)
ensure a > 0;
done;
rule Bad() => (self ∈ Bad <: Shape):
new self.x := 0;
rule .area() => (a ∈ R):
let a := -1.0;
return;
return;
rule main:
print Bad().area();
return;
runtime error: "area" fails to ensure condition 1
trait Shape:
rule area() => (a ∈ R);
rule name() => (n ∈ S);
done;
rule Dot() => (self ∈ Dot <: Shape):
new self.x := 0;
rule .area() => (a ∈ R):
let a := 1.0;
return;
return;
rule main:
print Dot().area();
return;
error[E259]: "Dot" does not provide "name", which trait Shape requires
= help: declare `rule .name(...)` inside the constructor (§16.3)
rule main:
new total ∈ Z;
for ∀ i ∈ (1..4) do
let total += i;
repeat;
print total;
return;
error[E258]: a ∀ loop cannot write "total", which it does not own
= help: write only locals, or an element selected by the loop variable (D82)
rule main:
new bad: 200 ∈ Λ;
print bad;
return;
runtime error: 200 is above the domain of Λ
rule main:
new forgotten ∈ Z;
print forgotten;
return;
error[E254]: "forgotten" is read but never given a value
= help: it holds its type's zero; assign it, or give it an initial value at the declaration (D79)
rule value() => (r ∈ Z):
let r := 7;
return;
rule main:
apply value();
return;
error[E255]: "value" returns r, which this discards
= help: bind the results, or write `apply _ := value(...)` to discard them on purpose (D80)
rule main:
new a := [1,2];
new b := a!;
print b;
print a;
return;
error[E257]: "a" was moved and no longer holds a value
= help: give it a new value before reading it again (D81)
rule ghost(x ∈ Z) => (y ∈ Z);
rule main:
print 1;
return;
error[E249]: "ghost" is declared but never defined
= help: a forward declaration needs a matching rule body (§9)