Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

633 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

kvlang

CI Go Version License: MIT Tutorial Examples

The VM of deepx (formerly dxlang) — an agent-native, train-inference-unified, self-iterating AI compute architecture. kvspace tree paths form a single unified address space; one syntax simultaneously serves as VM instructions, high-level language, compiler IR, and human-readable source.

中文文档: README_CN.md | Design: deep-dive — root design doc; README is the teaching derivative. All behavior norms (p0–p7), instruction model (§2), Link call mechanism (§6), type system (§9), diagnostics (§12) live there.

Design docs (CN): deepx-design/doc/kvlang-design-and-implementation · (EN): deepx-design/doc-en/kvlang-design-and-implementation — 19 chapters covering architecture, parser, runtime, kvspace, and language design reference.


Core Model in One Screen

No IR layers — source IS the IR. The program counter is a kvspace path string; call-stack depth equals path depth:

PC    = "/vthread/tid/[0,0]/[0,0]/[1,0]"   the program counter is a KV path
fetch = kv.Get(PC)                           instruction fetch is one KV read
call  = create subtree; return = clean it    crash? restart and resume from PC

Every instruction occupies a 2-D coordinate [s0, s1]: [s0,0] is always the opcode, [s0,-j] read params, [s0,+j] write params.

lib main {
    rwfunc add(A:int64, B:int64) -> (C:int64) { A + B -> C }
}
/lib/main.add/[0,0]  = "+"     /lib/main.add/[0,-1] = "A"
/lib/main.add/[0,-2] = "B"     /lib/main.add/[0,1]  = "C"

Four address-space domains: /lib (function library) /vthread (runtime frames) /sys (infrastructure) /dev (I/O).


Quick Start

# Requirements: Go 1.24+, Redis
make build

./kvlang tutorial/01-basics/hello.kv         # run a file
./kvlang -c 'print("hello, world")'          # inline mode
echo '40 + 2 -> x; print(x)' | ./kvlang      # pipe mode (; separates statements on one line)
./kvlang vet my.kv                           # syntax check
./kvlang format my.kv                        # format

Language Guide

Program Structure (read this first)

Top level: lib name { }, rwfunc, and single instructions. Always wrap code in rwfunc main() -> () { … }; main(). Bare if / while / for at top level may auto-wrap into implicit init() but this is unreliable — explicitly wrapping in main() is the only guaranteed pattern. Never name your function init to avoid conflicts with implicit wrapping.

rwfunc main() -> () {
    total = 0  # = is equivalent to <-
    1 -> i
    while (i <= 5) {
        total <- total + i
        i + 1 -> i
    }
    println(total)
}

main()

rwir(Read-Write IR):Three Assignment Forms

x = 40 + 2            # = : write slot on the left (≡ <-); = is NOT an expression, cannot nest in conditions
y <- x                # left arrow: write slot on the left
x × y -> z            # right arrow: write slot on the right
f(a, b) -> r          # write-param mapping for calls; multiple: -> x, y; discard: -> _

A write slot must be a location: a bare name (frame-local), /abs/path (global key), or base.name (member). Literals are not locations.

rwfunc func(ra,rb) -> (wa,wb) { … } = composite rwir, the named form. Single-line rwir like A + B -> C is atomic (one opcode + reads + writes); rwfunc packs multiple rwir into a named unit with the same arrow interface — (ra,rb) declare read params, -> (wa,wb) declare write params. Calling add(3,4) -> s binds arguments to read slots, maps write slots back to the caller frame. No return values, only write-param mapping.

-> (C:int64) in a rwfunc signature is a write-param declaration. The function writes results into its write-param slots; the caller maps them with -> r. Read params are read-only: the body may not place a read param in a write slot (e.g. A = A + 1). This includes array element writes — a[i] <- v writes through a, so a must be a write param if you need to modify it. Array/dict to mutate → write param; array/dict to read only → read param.

# ❌ wrong: array as read param, a[i] <- v writes through read-param slot → parser rejects
rwfunc bad(a:int64) -> () { 99 -> a[0] }

# ✅ correct: array as write param, readable and writable inside the body
rwfunc good() -> (a:int64) { a:int64 = [10, 20]; 99 -> a[0]; a }

Decide the role first — an accumulator is an output, so declare it as a write param (write params start at zero, are readable and writable in the body — like Go named return values): rwfunc sum(arr:int64) -> (acc:int64) { acc + arr[i] -> acc }. A pure working variable is copied to a local first (A -> a, then use a):

lib mylib {
    rwfunc add(A:int64, B:int64) -> (C:int64) {
        A + B -> C
    }
}

rwfunc main() -> () {
    mylib.add(3, 4) -> s
    println(s)          # 7
}

main()

dict, Member Access, and Linked Lists

d = { name="kv"; ver=1 }    # dict literal: members are the flat key-family d.name, d.ver
println(d.name)               # member read
d.ver = 2                   # member write
k = "name"; d.*k -> v       # dynamic key: reads d.name (k's value becomes the key)

Pointer via path string: store an absolute path in a variable, then use .member to read/write at that path — the variable's string value becomes the path prefix.

/node = { val=42 }       # dict at absolute path
"/node" -> p             # p holds the path string
p.val -> v               # reads /node.val → 42

Data structures shared across functions (e.g. linked lists) create nodes at absolute paths (frame-locals die when the frame returns):

rwfunc build() -> () {
    /n1 = { val=1; next="/n2" }  # = is equivalent to <-
    /n2 <- { val=2; next="/n3" }
    { val=3; next="" } -> /n3
}

rwfunc main() -> () {
    build()
    "/n1" -> p                   # p holds a path string (a pointer)
    while (p != "") {
        p.val -> v               # pointer deref: reads /n1.val
        println(v)
        p.next -> p
    }
}

main()

Numeric Types (exact-width only — no int or float)

f = float32(3)        # ten constructors: int8/16/32/64 uint8/16/32/64 float32/64 — they construct AND convert
w = int8(300)         # 44: narrowing wraps (two's complement); float→int truncates toward zero; arithmetic domain is int64/float64
x:int64 = 42          # type-annotated variable declaration

int and float are rejected by the parser — use exact-width types only. The ten precision operators are both constructors and converters.

Control Flow (inside rwfunc bodies only)

i = 1; sum = 0
while (i <= 10) { sum + i -> sum; i + 1 -> i }
if (sum > 50) { println("big") } else { println("small") }   # sum=55 → big
for (x in [7, 2, 9, 4]) { println(x) }

Conditions may be compound expressions: if (7 % 2 != 0) and while (i < string.len(s)) both work (auto-flattened to temp slots at compile time).

Operators

Category Symbols
Arithmetic + - × ÷ %
Comparison == != < > <= >=
Logic && || !
Bitwise & | ^ << >>

÷: both ints → integer division (C-style, 7÷2=3, -9÷2=-4); either side float → float division (7.0÷2=3.5). / is reserved for paths and path separators. * is reserved for future pointer dereference.

Builtins

Scalar: abs neg sign pow sqrt exp log min max (variadic, e.g. max(a,b,c)) println (auto-newline) print (no newline) cerr input debugger
Types: bool int8 int16 int32 int64 uint8 uint16 uint32 uint64 float32 float64
Collections: array len at set has sort dict kvat kvhas
Strings: string.char string.ord string.len string.cmp string.find string.slice string.concat string.set
Time: time.now time.sub time.add time.duration.nanos time.duration.millis time.duration.seconds time.before time.after

a:int64 = [7, 2, 9, 4]     # typed 1D array, = ≡ <-
len(a) -> n              # 4
at(a, 2) -> e            # 9 (0-indexed)
set(a, 1, 99) -> a       # modify element: a becomes [7, 99, 9, 4]
sort(a) -> sorted         # sorted copy: [2, 4, 7, 9]
s = "hello"
string.char(s, 1) = "a"     # replace char at index 1 → "hallo"
s + " world" -> t           # concatenation → "hallo world"
string.len(s) -> n          # 5
string.find(s, "ll") -> i   # 2 (first index of substring, -1 if absent)
string.slice(s, 0, 2) -> p  # "he"

Strings support indexing and concatenation with +; at(s, i) reads the i-th char, string.char(s, i) reads it, string.char(s, i) = "X" replaces one char.


Tutorial

140 self-contained examples (129 with expected output, fully CI-verified), organized by topic:

01-basics/        hello, arith, precision, numtypes, strings, …  (14 files)
02-func/          rwfunc, call, accumulator                       (2 files)
03-control/       if, while, for, guess                           (5 files)
03-debugger/      chain_array, debugger builtin                   (4 files)
04-algo/          fibonacci, gcd, collatz, …                      (13 files)
06-lib/           lib block, nested, cross-lib, anon              (11 files)
07-leetcode/      LeetCode solutions                              (90 files)
builtin/          kvhas_string_key                                (1 file)
error_cases/      type_error, index_error, zero_division, …       (36 files)
./kvlang tutorial/01-basics/hello.kv         # hello kvlang
./kvlang tutorial/04-algo/fibonacci.kv       # fib = 55
./kvlang tutorial/07-leetcode/001_two_sum.kv # LeetCode

python3 tutorial/test.py                     # all positive examples — CI verification
python3 tutorial/error_test.py               # all negative tests

Design Documentation

In-depth design and implementation docs covering the full architecture:

Chapter EN CN
Architecture — storage/compute/control separation en cn
Architecture — everything is plaintext en cn
Architecture — program as data + functions en cn
Architecture — four-level code hierarchy en cn
Parser — instruction architecture en cn
Parser — functions en cn
Parser — compiler pipeline en cn
Parser — diagnostics en cn
Parser — layoutrwir en cn
Parser & Runtime — control flow en cn
Runtime — type system en cn
Runtime — member access & data structures en cn
Runtime — debugging & observability en cn
Runtime — function calls & builtins en cn
KVSpace — address space en cn
KVSpace — addressing & naming en cn
KVSpace — code instruction layout en cn
KVSpace — system variables en cn
Reference — how to design a programming language en cn

Each English translation includes Implementation Consistency Notes cross-checked against the Go source.

License

MIT — see LICENSE

About

Agent-native 训推一体自迭代强人工智能计算架构 — kvspace 树形路径统一地址空间,单层 IR(源码即指令),读写码显式数据流

Resources

Contributing

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages