Examples

The examples/ folder of the compiler repository has complete programs. This page walks through each one: what it does, what it shows, and what it prints. Every program runs as is:

cryn run examples/fib.cryn

The same programs run through any of the three build paths (cryn run on its own, --release, or --native) and print the same bytes.

hello

The whole program:

define main

set 10
push

set 20
add
output
return
end

This prints 30. It is the smallest honest tour of the machine: a value in hand, a value on the pile, one arithmetic word, one output. If this is your first hour with Cryn, the Learning Cryn tutorial starts from here and goes slower.

fib

Iterative fibonacci, printing fib(1) through fib(12):

1 1 2 3 5 8 13 21 34 55 89 144

Two cells hold the sliding window, a and b, and a third counts down. The heart of the loop is the stack work:

move b
read
push
move a
read
push
move b
read
add
push
move b
write
pop
pop
move a
write

Walk the pile: push the old b, push the old a, put the old b back in hand, add pops the old a, so the working value is a + b. Push that sum, write it into b, then pop twice: the sum is discarded, the old b comes off the pile and lands in a. The window slides one step. This is the replacement for a, b = b, a + b, and reading it as a pile drill is good practice.

fizzbuzz

The classic, from 1 to 30, with one marker per line:

1 2 F 4 B F 7 8 F B 11 F 13 14 FB 16 17 F 19 B F 22 23 F B 26 F 28 29 FB

Two details are worth stealing. First, no division by 15 exists in the program. Each pass stores remainder 3 and remainder 5 into the cells fizz and buzz, and the branches test those cells against 0. Two remainders answer all three questions.

Second, the markers are printed as single characters, set 'F' and set 'B', not as strings. When a marker is one byte long, a byte is the honest data type for it.

wordcount

A tiny wc. It reads the input stream to the end and prints lines words chars:

printf 'one two three\nfour\n' | cryn run examples/wordcount.cryn
2 4 19

The four counters are world cells. A transformation named bump does the counting, and it takes the counter as an address, so one word of code increments any of the four:

define bump address int64 cell result nothing
  move cell
  read
  move at
  read
  add 1
  write
  set nothing
  return
end

That shape, address parameter, move at, read, add 1, write, is the standard way to let one transformation touch a cell chosen by the caller. The main loop reads one byte at a time with input, classifies it, and calls bump through the address of the right counter.

sorting

Bubble sort over a heap block of eight numbers:

3 7 17 21 42 58 65 99

The block is one make 8 of int64, and the program never touches it except through two helpers:

define getelem address array of int64 blk int64 idx result int64
  move idx
  read
  push
  move blk
  read
  move at
  pop
  move index
  read
  return
end

getelem and its twin setelem are the whole idea. A run time sized block has the type address array of int64, which passes to transformations like any value, so element access becomes two reusable words instead of eight lines of focus work repeated at every touch point. The same pair reappears in the allocator below. When a program indexes one block from many places, write the pair once.

linkedlist

Three nodes in heap blocks, walked and summed:

10
20
30
60

A node is make 2 of int64: element 0 holds the value, element 1 holds the address of the next node, 0 for the last one. Linking a node puts an address into element 1, and addresses convert to and from integers, so the link slot is a plain int64 cell:

move n3
read
convert int64
push
move n2
read
move at
set 20
move 0
write
back
move 1
pop
write
back

That block builds node two: the address of node three is pushed as an integer, the value 20 is written, back steps out to the block root, and the saved address is popped into element 1. Walking the list is a move at loop until the link reads 0.

This program is the reference for building structures that outlive the frame: blocks from make <size> of, addresses inside them, free at the end.

allocator

A free-list allocator with 16 slots over one 17-element pool:

1
2
3
2

Slot 0 is not data. It holds the head of the free list, and each free slot holds the index of the next free slot. alloc pops the head and publishes the next index; dealloc pushes a slot back by writing the old head into it and moving the head. The fourth line printing 2 is the point of the demo: slot 2 was freed, and the next alloc hands it out again.

The pool is built with a loop that chains every slot to its neighbor, then the last slot is capped with 0. Two helpers, getslot and setslot, are the sorting example's getelem and setelem under different names, which is the strongest argument for writing that pair once and reusing it.