Overview
The .krb format is a compact bytecode representation of a Kryon UI. Compiled from .kry source by the kry2krb compiler, it is executed by the krbdraw runtime on any supported platform.
Design Goals
- Compact: Typical UIs under 1KB
- Platform-independent: Same file runs everywhere
- Sequential: Linear bytecode stream, simple execution model
Tools
kry2krb— Compiler (.kry → .krb), outputs "KRY1" magickrbdraw— Runtime engine for drawing and interactionkrbdump— Debug tool for inspecting .krb bytecode
File Header
Every .krb file begins with a 4-byte magic number:
| Offset | Bytes | Value |
|---|---|---|
| 0x00 | 4 | "KRY1" (ASCII: 0x4B 0x52 0x59 0x31) |
Following the header is the bytecode stream.
Data Types
| Type | Size | Encoding |
|---|---|---|
| u8 | 1 byte | Unsigned 8-bit integer |
| u16 | 2 bytes | Little-endian unsigned 16-bit |
| u32 | 4 bytes | Little-endian unsigned 32-bit |
| string | variable | u16 length + UTF-8 bytes |
Note: Multi-byte integers are little-endian (LSB first).
VM Operations
These opcodes define the operations in the bytecode stream.
Operation Opcodes
| Opcode | Name | Description |
|---|---|---|
| 0x02 | OP_WRITE | Write to a device |
| 0x03 | OP_LISTEN | Listen for device events |
| 0x04 | OP_STORE_INT | Store computed value to local slot |
| 0x05 | OP_IF | Conditional execution |
| 0x06 | OP_STORE_VALUE | Store static value to local slot |
OP_WRITE (0x02)
Write to a device. Format:
[OP_WRITE][device_id][window_id][cmd_id][argc][args...]
OP_LISTEN (0x03)
Listen for device events. Format:
[OP_LISTEN][device_id][window_id][cmd_id][argc][args...][body_len][body...]
OP_STORE_INT (0x04)
Store a computed value to a local slot. Format:
[OP_STORE_INT][slot_u16][expr...]
OP_IF (0x05)
Conditional execution. Format:
[OP_IF][cond_expr][then_len_u16][then_bytes...][else_len_u16][else_bytes...]
OP_STORE_VALUE (0x06)
Store a static value to a local slot. Format:
[OP_STORE_VALUE][slot_u16][arg...]
Device IDs
| ID | Name | Description |
|---|---|---|
| 0x01 | DEV_DRAW | Drawing commands |
| 0x03 | DEV_CONS | Console output |
| 0x04 | DEV_WCTL | Window control |
| 0x05 | DEV_MOUSE | Mouse/touch input |
| 0x06 | DEV_CURSOR | Cursor control |
| 0x07 | DEV_TIMER | Timer events |
Command IDs
| Device | Command | ID | Description |
|---|---|---|---|
| DEV_DRAW | CMD_RECT | 0x10 | Draw rectangle |
| DEV_DRAW | CMD_TEXT | 0x11 | Draw text |
| DEV_DRAW | CMD_LINE | 0x12 | Draw line |
| DEV_DRAW | CMD_CIRC | 0x13 | Draw circle |
| DEV_DRAW | CMD_MASK | 0x14 | Draw glyph mask |
| DEV_MOUSE | CMD_BOUNDS | 0x20 | Mouse bounds |
| DEV_WCTL | CMD_NEW | 0x30 | Create new window |
| DEV_TIMER | CMD_TICK | 0x40 | Timer tick event |
Argument Tags
Arguments to commands and expressions are tagged with their type.
| Tag | Value | Format |
|---|---|---|
| ARG_INT | 0x01 | u32 little-endian integer |
| ARG_STR | 0x02 | u16 length + UTF-8 bytes |
| ARG_PATH | 0x03 | u16 length + UTF-8 path string |
| ARG_EXPR | 0x04 | Embedded expression (see below) |
| ARG_MASK | 0x05 | 8 bytes (8x8 glyph/sprite data) |
Example Arguments
// Integer value 100
[ARG_INT][0x64][0x00][0x00][0x00]
// String "Hello"
[ARG_STR][0x05][0x00]['H']['e']['l']['l']['o']
// Path reference
[ARG_PATH][0x03][0x00]['.']['/']['v']['a']['l'] // ./val
Expression Tags
Runtime expressions embedded in ARG_EXPR.
| Tag | Value | Format |
|---|---|---|
| EX_INT | 0x01 | u32 little-endian |
| EX_PATH | 0x02 | u16 length + UTF-8 path string |
| EX_ADD | 0x03 | [left_expr][right_expr] |
| EX_GE | 0x04 | [left_expr][right_expr] |
| EX_LE | 0x05 | [left_expr][right_expr] |
| EX_SUB | 0x06 | [left_expr][right_expr] |
| EX_MUL | 0x07 | [left_expr][right_expr] |
| EX_DIV | 0x08 | [left_expr][right_expr] |
| EX_EQ | 0x09 | [left_arg][right_arg] |
| EX_MOD | 0x0A | [left_expr][right_expr] — Modulo |
| EX_NE | 0x0B | [left_expr][right_expr] — Not equal |
| EX_LT | 0x0C | [left_expr][right_expr] — Less than |
| EX_GT | 0x0D | [left_expr][right_expr] — Greater than |
| EX_AND | 0x0E | [left_expr][right_expr] — Logical AND |
| EX_OR | 0x0F | [left_expr][right_expr] — Logical OR |
| EX_NOT | 0x10 | [expr] — Logical NOT |
| EX_MIN | 0x11 | [left_expr][right_expr] — Minimum |
| EX_MAX | 0x12 | [left_expr][right_expr] — Maximum |
| EX_ABS | 0x13 | [expr] — Absolute value |
Expression Example
// [ + ./radius 1 ]
[ARG_EXPR][EX_ADD][EX_PATH][0x07][0x00]['.']['/']['r']['a']['d']['i']['u']['s'][EX_INT][1][0][0][0]
Complete Examples
Source (.kry)
const meta { title "Demo" }
var env { w 200 }
def window {
write /dev/wctl [ new 0 0 %size[0] %size[1] %title ]
}
window {
title /meta/title
size [ /env/w 300 ]
}
Bytecode Structure (simplified)
Header: "KRY1"
// Initialize var lib slot /env/w with 200
[OP_STORE_LOCAL][slot][EX_INT][200][0x00][0x00][0x00]
// Create window (CMD_NEW returns window ID 0)
[OP_WRITE][DEV_WCTL][0][CMD_NEW][argc=5]
[ARG_LOCAL][title_slot]
[ARG_LOCAL][size_0_slot]
[ARG_LOCAL][size_1_slot]
[ARG_INT][0][0][0][0]
[ARG_INT][0][0][0][0]
Circle Drawing
def circle {
write /dev/draw [ circ %center[0] %center[1] ./radius %color ]
}
circle {
center [ 100 150 ]
radius 50
color 0xFF0000
}
Compiles to:
// Parameters are stored in slots first
[OP_STORE_VALUE][center_0_slot][ARG_INT][100][0][0][0]
[OP_STORE_VALUE][center_1_slot][ARG_INT][150][0][0][0]
[OP_STORE_VALUE][radius_slot][ARG_INT][50][0][0][0]
[OP_STORE_VALUE][color_slot][ARG_INT][0x00][0x00][0xF0][0x00]
// Draw circle
[OP_WRITE][DEV_DRAW][0][CMD_CIRC][argc=4]
[ARG_LOCAL][center_0_slot]
[ARG_LOCAL][center_1_slot]
[ARG_LOCAL][radius_slot]
[ARG_LOCAL][color_slot]
OP_IF Detail
Conditional statements compile to OP_IF with embedded lengths.
Source
if [ >= ./radius 60 ] {
write ./dir -1
} else {
write ./dir 1
}
Compiles to:
[OP_IF]
[EX_GE][EX_LOCAL][radius_slot][EX_INT][60][0][0][0] // condition
[then_len_u16] // then block length
[OP_STORE_VALUE][dir_slot][ARG_INT][0xFF][0xFF][0xFF][0xFF]
[else_len_u16] // else block length
[OP_STORE_VALUE][dir_slot][ARG_INT][1][0][0][0]
OP_LISTEN Detail
Event listeners compile to OP_LISTEN with handler bodies.
Timer Listen
listen /dev/timer {
tick 50 {
write ./radius [ + ./radius ./dir ]
}
}
Compiles to:
[OP_LISTEN][DEV_TIMER][0][CMD_TICK][argc=1]
[ARG_INT][50][0][0][0]
[body_len_u16]
[OP_STORE_LOCAL][radius_slot]
[ARG_EXPR]
[EX_ADD]
[EX_LOCAL][radius_slot]
[EX_LOCAL][dir_slot]
Mouse Listen
listen /dev/mouse {
bounds [ %pos[0] %pos[1] %size[0] %size[1] ]
down { %action }
}
Compiles to:
[OP_LISTEN][DEV_MOUSE][0][CMD_BOUNDS][argc=4]
[ARG_LOCAL][pos_0_slot][ARG_LOCAL][pos_1_slot]
[ARG_LOCAL][size_0_slot][ARG_LOCAL][size_1_slot]
[enter_len_u16][enter_bytes...]
[exit_len_u16][exit_bytes...]
[down_len_u16][down_bytes...]
[up_len_u16][up_bytes...]
Map Format (.kmap)
Optionally generate a map file alongside the bytecode with "KMAP1" magic. This contains a serialized AST for debugging and reflection.
Note: The runtime now maintains VFS structures internally, so map files are only needed for debugging purposes.
kry2krb -m input.kry output.krb output.kmap
The map format is a tree structure with node types, names, and values.
Notes
- All multi-byte integers are little-endian
- Bytecode is sequential — no jumps or branches (except via OP_IF conditional sections)
- Window IDs are assigned at runtime starting from 0
- Slots are assigned during compilation for all local variables
- const values are inlined at compile time
- var values get slots initialized via OP_STORE_LOCAL at startup