Kryon / Documentation / .kry Language

.kry Language Reference

Path-based VFS-oriented language for Kryon UIs

Overview

The .kry language is a path-based, virtual filesystem language. Every value is accessed through a path, and operations are performed by writing to device files. It compiles to compact .krb bytecode.

Example

const meta {
    title "Inner Breeze"
    ver   "alpha"
    by    "waozi"
    id    "xyz.waozi.inbe"
}

var env {
    w       200
    h       400
    pause   0
}

def window {
    write /dev/wctl [ new 0 0 %size[0] %size[1] %title ]
}

def button {
    write /dev/draw [ rect %pos[0] %pos[1] %size[0] %size[1] 0xCCCCCC ]

    fn center {
        if %value {
            write /dev/draw [
                %cmd
                [ + %pos[0] [ / %size[0] 2 ] ]
                [ + %pos[1] [ / %size[1] 2 ] ]
                50 50
                %value
                %color
            ]
        }
    }

    center {
        cmd text
        pos %pos
        size %size
        value %label
        color 0x000000
    }

    listen /dev/mouse {
        bounds [ %pos[0] %pos[1] %size[0] %size[1] ]
        enter { write /dev/cursor 2 }
        exit  { write /dev/cursor 1 }
        down  { %action }
    }
}

window {
    title /meta/title
    size [ /env/w /env/h ]

    button {
        pos [ 50 250 ]
        size [ 80 30 ]
        label "Click Me"
        action {
            write /dev/cons "Button clicked!\n"
        }
    }
}

Syntax Rules

  • Whitespace: Spaces, tabs, and newlines are insignificant
  • Strings: Double-quoted: "hello" — Strings are only for literal text, not paths
  • Numbers: Decimal integers: 50, -1, hex colors: 0xFF0000
  • Blocks: Defined with curly braces: { ... }
  • Arrays: Bracketed lists: [ 1 2 3 ]
  • Paths: Not strings — use paths directly: /dev/draw, ./radius

Paths

Paths are the primary way to access data in Kryon. Paths are not strings.

Absolute Paths

Root-level paths start with /:

/dev/draw
/dev/wctl
/dev/mouse
/dev/timer
/dev/cons
/meta/title
/env/w

Relative Paths

Paths starting with ./ refer to the current VFS node:

./radius
./dir
./color

Parent Paths

Paths starting with ../ refer to the parent VFS node:

../speed
../size
../title

Path Context

The command position determines whether a path is read or written:

write /dev/draw [ text 5 5 /meta/title 0x000000 ]  // write to /dev/draw
write ./radius [ + ./radius ./dir ]                  // write to ./radius
listen /dev/mouse { ... }                             // read from /dev/mouse

Root Blocks

Top-level blocks define the structure of your program.

const

Compile-time constants. Creates a read-only VFS folder.

const meta {
    title "Inner Breeze"
    ver   "alpha"
    by    "waozi"
    id    "xyz.waozi.inbe"
}

Accessible at: /meta/title, /meta/ver, etc.

var

Mutable runtime variables. Creates a read-write VFS folder.

var env {
    w       200
    h       400
    breaths 30
    rounds  3
    pause   0
}

Accessible at: /env/w, /env/h, etc.

const for Data Structures

You can define complex data structures like sprites/glyphs:

const glyph {
    play [
        [ . . . . . . . . ]
        [ . # . . . . . . ]
        [ . # # . . . . . ]
        [ . # # # . . . . ]
        [ . # # # # . . . ]
        [ . # # # . . . . ]
        [ . # # . . . . . ]
        [ . # . . . . . . ]
    ]

    pause [
        [ . . . . . . . . ]
        [ . # # . . # # . ]
        [ . # # . . # # . ]
        [ . # # . . # # . ]
        [ . # # . . # # . ]
        [ . # # . . # # . ]
        [ . # # . . # # . ]
        [ . . . . . . . . ]
    ]
}

Accessible at: /glyph/play, /glyph/pause.

Definitions and Functions

def

Creates a real VFS instance folder when called. Each invocation creates a new numbered instance.

def button {
    write /dev/draw [ rect %pos[0] %pos[1] %size[0] %size[1] 0xCCCCCC ]
}

Calling it creates numbered instances:

button { pos [ 10 10 ] size [ 80 30 ] }  // Creates /0
button { pos [ 10 50 ] size [ 80 30 ] }  // Creates /1

fn

Expands inline and does not create a VFS folder. Use for helper code.

fn center {
    if %value {
        write /dev/draw [
            %cmd
            [ + %pos[0] [ / %size[0] 2 ] ]
            [ + %pos[1] [ / %size[1] 2 ] ]
            50 50
            %value
            %color
        ]
    }
}

Parameters

Parameters use the %name syntax and are passed into def and fn blocks.

Common Parameters

%pos      // Position [x y]
%size     // Size [w h] or single value
%label    // Text label
%icon     // Glyph/sprite reference
%action   // Action block
%value    // Generic value
%color    // Color value

Nil Handling

Missing parameters default to nil. Use if to check:

if %icon {
    write /dev/draw [ mask ... %icon ... ]
}

Current and Parent Paths

Use relative paths within definitions to access local state.

def circle {
    write /dev/draw [ circ %center[0] %center[1] ./radius %color ]

    %logic
}

circle {
    center [ 100 100 ]
    radius 40
    color 0xFF0000
    dir 1

    logic {
        listen /dev/timer {
            tick ../speed {
                write ./radius [ + ./radius ./dir ]

                if [ >= ./radius 60 ] {
                    write ./dir -1
                }

                if [ <= ./radius 40 ] {
                    write ./dir 1
                }
            }
        }
    }
}

Control blocks like action, logic, tick, enter, exit, down do not create folders, so ./radius inside an action still refers to the parent circle.

Device Files

Device files provide I/O operations. Write to them to perform actions.

DevicePurposeOperations
/dev/wctlWindow controlnew, size, title
/dev/drawDrawing commandsrect, circ, text, mask
/dev/mouseMouse/touch inputlisten with bounds, enter, exit, down
/dev/timerTimer eventslisten with tick
/dev/consConsole outputwrite for debug output
/dev/cursorCursor controlwrite cursor ID

/dev/wctl - Window Control

write /dev/wctl [ new 0 0 200 400 "My Window" ]

/dev/draw - Drawing

// Draw rectangle
write /dev/draw [ rect x y w h color ]

// Draw circle
write /dev/draw [ circ center_x center_y radius color ]

// Draw text
write /dev/draw [ text x y string color ]

// Draw glyph mask
write /dev/draw [ mask x y 50 50 glyph_ref color ]

/dev/mouse - Mouse/Touch Input

listen /dev/mouse {
    bounds [ x y w h ]
    enter { write /dev/cursor 2 }  // hand cursor
    exit  { write /dev/cursor 1 }  // arrow cursor
    down  { %action }
}

/dev/timer - Timer Events

listen /dev/timer {
    tick 100 {       // every 100ms
        write ./radius [ + ./radius 1 ]
    }
}

Commands

write

Write data to a path.

write /dev/draw [ rect 10 10 50 50 0xFF0000 ]
write ./radius [ + ./radius 1 ]
write /dev/cons "Debug output\n"

listen

Listen for events on a device.

listen /dev/mouse {
    bounds [ %pos[0] %pos[1] %size[0] %size[1] ]
    down { %action }
}

listen /dev/timer {
    tick 50 { ... }
}

if

Conditional execution.

if [ >= ./radius 60 ] {
    write ./dir -1
}

if %value {
    write /dev/draw [ ... ]
}

Operations and Expressions

Operations are written in bracketed prefix notation.

Arithmetic

[ + a b ]       // Addition
[ - a b ]       // Subtraction
[ * a b ]       // Multiplication
[ / a b ]       // Division

Comparison

[ >= a b ]      // Greater than or equal
[ <= a b ]      // Less than or equal
[ == a b ]      // Equal
[ != a b ]      // Not equal

Nested Operations

[ + %pos[0] [ / %size[0] 2 ] ]   // pos[0] + (size[0] / 2)
write ./radius [ + ./radius ./dir ]

Array Indexing

%pos[0]         // First element of pos array
%size[1]        // Second element of size array
/env/w          // Access const/var value

Colors

Colors are specified as hexadecimal values.

0xFF0000    // Red
0x00FF00    // Green
0x0000FF    // Blue
0xFFFFFF    // White
0x000000    // Black
0xCCCCCC    // Gray

Animations with Timers

Animations are created by listening to timer events and updating values.

Pulsing Circle

def circle {
    write /dev/draw [ circ %center[0] %center[1] ./radius %color ]
    %logic
}

circle {
    center [ 100 100 ]
    radius 40
    color 0xFF0000
    dir 1

    logic {
        listen /dev/timer {
            tick 50 {
                write ./radius [ + ./radius ./dir ]

                if [ >= ./radius 60 ] {
                    write ./dir -1
                }

                if [ <= ./radius 40 ] {
                    write ./dir 1
                }
            }
        }
    }
}

Multi-Property Animation

var env {
    w 200
    h 400
}

window {
    speed 50
    size [ /env/w /env/h ]

    circle {
        center [ 100 100 ]
        radius 30
        color 0xFF0000
        red_dir 1
        green_dir 0
        blue_dir 0

        logic {
            listen /dev/timer {
                tick ../speed {
                    // Animate through colors
                    if [ == ./red_dir 1 ] {
                        write ./color [ + ./color 0x000100 ]
                        if [ >= ./color 0x00FF00 ] { write ./red_dir 0; write ./green_dir 1 }
                    }
                    if [ == ./green_dir 1 ] {
                        write ./color [ + ./color 0x000001 ]
                        if [ >= ./color 0x0000FF ] { write ./green_dir 0; write ./blue_dir 1 }
                    }
                }
            }
        }
    }
}

Complete Grammar

file       ::= (root_block | def | fn)*

root_block ::= 'const' identifier block
            | 'var' identifier block

def        ::= 'def' identifier block

fn         ::= 'fn' identifier block

block      ::= '{' stmt* '}'

stmt       ::= path value?              // property assignment
            | 'def' identifier block     // nested definition
            | 'fn' identifier block      // nested function
            | 'write' path array         // write command
            | 'listen' path block        // event listener
            | 'if' path block            // conditional
            | control_block              // action, logic, tick, etc.

path       ::= '/' path_segment+
            | './' path_segment+
            | '../' path_segment+

path_segment ::= identifier
               | '[' expression ']'    // array index

expression  ::= path
            | number
            | string
            | '[' op expression+ ']'   // operation

op         ::= '+' | '-' | '*' | '/' | '>=' | '<=' | '==' | '!='

array      ::= '[' (expression|array)* ']'

control_block ::= 'action' block
               | 'logic' block
               | 'tick' number block
               | 'enter' block
               | 'exit' block
               | 'down' block

number     ::= [0-9]+ | '0x' [0-9A-Fa-f]+

string     ::= '"' [^"]* '"'

identifier ::= [a-zA-Z_][a-zA-Z0-9_]*

Complete Example: Breathing App

const meta {
    title "Inner Breeze"
    ver   "alpha"
    by    "waozi"
    id    "xyz.waozi.inbe"
}

const glyph {
    play [
        [ . . . . . . . . ]
        [ . # . . . . . . ]
        [ . # # . . . . . ]
        [ . # # # . . . . ]
        [ . # # # # . . . ]
        [ . # # # . . . . ]
        [ . # # . . . . . ]
        [ . # . . . . . . ]
    ]

    pause [
        [ . . . . . . . . ]
        [ . # # . . # # . ]
        [ . # # . . # # . ]
        [ . # # . . # # . ]
        [ . # # . . # # . ]
        [ . # # . . # # . ]
        [ . # # . . # # . ]
        [ . . . . . . . . ]
    ]
}

var env {
    w       200
    h       400
    breaths 30
    rounds  3
    pause   0
}

def window {
    write /dev/wctl [ new 0 0 %size[0] %size[1] %title ]
}

def center {
    if %value {
        write /dev/draw [
            %cmd
            [ + %pos[0] [ / %size[0] 2 ] ]
            [ + %pos[1] [ / %size[1] 2 ] ]
            50 50
            %value
            %color
        ]
    }
}

def button {
    write /dev/draw [ rect %pos[0] %pos[1] %size[0] %size[1] 0xCCCCCC ]

    center {
        cmd text
        pos %pos
        size %size
        value %label
        color 0x000000
    }

    center {
        cmd mask
        pos %pos
        size %size
        value %icon
        color 0x000000
    }

    listen /dev/mouse {
        bounds [ %pos[0] %pos[1] %size[0] %size[1] ]
        enter { write /dev/cursor 2 }
        exit  { write /dev/cursor 1 }
        down  { %action }
    }
}

def circle {
    write /dev/draw [ circ %center[0] %center[1] ./radius %color ]
    %logic
}

window {
    title /meta/title
    speed 50
    size [ /env/w /env/h ]

    circle {
        center [ 100 100 ]
        radius 40
        color 0xFF0000
        dir 1

        logic {
            listen /dev/timer {
                tick ../speed {
                    write ./radius [ + ./radius ./dir ]

                    if [ >= ./radius 60 ] {
                        write ./dir -1
                    }

                    if [ <= ./radius 40 ] {
                        write ./dir 1
                    }
                }
            }
        }
    }

    cent_x [ / /env/w 2 ]

    button {
        pos [ [ - ../cent_x 40 ] 250 ]
        size [ 20 20 ]
        action {
            write /dev/cons "hello world\n"
        }
        icon /glyph/play
    }

    button {
        pos [ [ - ../cent_x 10 ] 250 ]
        size [ 20 20 ]

        action {
            if [ == /env/pause 0 ] {
                write /env/pause 1
                write ./icon /glyph/play
            } else {
                write /env/pause 0
                write ./icon /glyph/pause
            }
        }

        icon /glyph/pause
    }
}