Kryon / Documentation / .krb Format

.krb Binary Format

Kryon bytecode format specification

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" magic
  • krbdraw — Runtime engine for drawing and interaction
  • krbdump — Debug tool for inspecting .krb bytecode

File Header

Every .krb file begins with a 4-byte magic number:

OffsetBytesValue
0x004"KRY1" (ASCII: 0x4B 0x52 0x59 0x31)

Following the header is the bytecode stream.

Data Types

TypeSizeEncoding
u81 byteUnsigned 8-bit integer
u162 bytesLittle-endian unsigned 16-bit
u324 bytesLittle-endian unsigned 32-bit
stringvariableu16 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

OpcodeNameDescription
0x02OP_WRITEWrite to a device
0x03OP_LISTENListen for device events
0x04OP_STORE_INTStore computed value to local slot
0x05OP_IFConditional execution
0x06OP_STORE_VALUEStore 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

IDNameDescription
0x01DEV_DRAWDrawing commands
0x03DEV_CONSConsole output
0x04DEV_WCTLWindow control
0x05DEV_MOUSEMouse/touch input
0x06DEV_CURSORCursor control
0x07DEV_TIMERTimer events

Command IDs

DeviceCommandIDDescription
DEV_DRAWCMD_RECT0x10Draw rectangle
DEV_DRAWCMD_TEXT0x11Draw text
DEV_DRAWCMD_LINE0x12Draw line
DEV_DRAWCMD_CIRC0x13Draw circle
DEV_DRAWCMD_MASK0x14Draw glyph mask
DEV_MOUSECMD_BOUNDS0x20Mouse bounds
DEV_WCTLCMD_NEW0x30Create new window
DEV_TIMERCMD_TICK0x40Timer tick event

Argument Tags

Arguments to commands and expressions are tagged with their type.

TagValueFormat
ARG_INT0x01u32 little-endian integer
ARG_STR0x02u16 length + UTF-8 bytes
ARG_PATH0x03u16 length + UTF-8 path string
ARG_EXPR0x04Embedded expression (see below)
ARG_MASK0x058 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.

TagValueFormat
EX_INT0x01u32 little-endian
EX_PATH0x02u16 length + UTF-8 path string
EX_ADD0x03[left_expr][right_expr]
EX_GE0x04[left_expr][right_expr]
EX_LE0x05[left_expr][right_expr]
EX_SUB0x06[left_expr][right_expr]
EX_MUL0x07[left_expr][right_expr]
EX_DIV0x08[left_expr][right_expr]
EX_EQ0x09[left_arg][right_arg]
EX_MOD0x0A[left_expr][right_expr] — Modulo
EX_NE0x0B[left_expr][right_expr] — Not equal
EX_LT0x0C[left_expr][right_expr] — Less than
EX_GT0x0D[left_expr][right_expr] — Greater than
EX_AND0x0E[left_expr][right_expr] — Logical AND
EX_OR0x0F[left_expr][right_expr] — Logical OR
EX_NOT0x10[expr] — Logical NOT
EX_MIN0x11[left_expr][right_expr] — Minimum
EX_MAX0x12[left_expr][right_expr] — Maximum
EX_ABS0x13[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