Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
c41af86
chore: Cargo.toml/lock 更新
miaobyte Aug 11, 2026
0317023
refactor: keytree/kvcpu rust 修复
miaobyte Aug 11, 2026
e135070
refactor: rwir rust 修复
miaobyte Aug 11, 2026
4fd4c87
refactor: logx/vthread/symbol rust 修复
miaobyte Aug 11, 2026
e244b5e
chore: go.mod + test.py 更新
miaobyte Aug 11, 2026
db234fa
refactor: kvcpu/rwir rust 修复
miaobyte Aug 11, 2026
eff9f81
refactor: 删除旧 check_hardcoded.py + test.py 修复
miaobyte Aug 11, 2026
270e5e9
feat: 新增 cargo/claude/build 配置
miaobyte Aug 11, 2026
5781730
refactor: keytree/layout/rwir Go 修复
miaobyte Aug 11, 2026
fb27770
chore: 子模块更新 + 删除 rust plan + go.mod
miaobyte Aug 11, 2026
99c6ace
refactor: Go runtime 修复
miaobyte Aug 11, 2026
235579a
refactor: rust runtime 修复
miaobyte Aug 11, 2026
a706d4e
chore: 更新 deepx-design 子模块
miaobyte Aug 11, 2026
2ae761f
refactor: layout/coerce/helper 修复
miaobyte Aug 12, 2026
818f238
chore: 更新 deepx-design 子模块
miaobyte Aug 12, 2026
5df803c
fix: CLI main + go.mod 更新
miaobyte Aug 12, 2026
a372a19
refactor: runtime 全局修复
miaobyte Aug 12, 2026
ccd7456
refactor: rwir/builtin 全局修复
miaobyte Aug 12, 2026
26e1e9d
refactor: rwir/dispatch + rwir + go.mod 修复
miaobyte Aug 12, 2026
e66bb54
chore: CLAUDE.md 迁移到 .claude/
miaobyte Aug 12, 2026
597683f
chore: 更新 deepx-design 子模块
miaobyte Aug 12, 2026
bf4740f
refactor: runtime 全局修复
miaobyte Aug 12, 2026
7bbb3da
refactor: layout/rwir 全局修复
miaobyte Aug 12, 2026
e19adcc
chore: 更新 deepx-design 子模块
miaobyte Aug 12, 2026
16d4c90
refactor: runtime 全局修复
miaobyte Aug 12, 2026
a58ee05
refactor: layout/rwir 全局修复
miaobyte Aug 12, 2026
656cb6c
feat: 新增 rwir/builtin byte/utf8 + go.mod
miaobyte Aug 12, 2026
ffa368a
fix: rwir debugger/dispatch + go.mod
miaobyte Aug 12, 2026
d665347
fix: test.py 修复
miaobyte Aug 12, 2026
24998b1
refactor: ast/parser/scanner 修复
miaobyte Aug 12, 2026
91cb2b1
refactor: cmd/layout/keytree 修复
miaobyte Aug 12, 2026
b1a7e22
refactor: rwir builtin/dispatch + go.mod
miaobyte Aug 12, 2026
43c077c
feat: 新增 rwir/builtin/random + tutorial
miaobyte Aug 12, 2026
2baf781
chore: 更新 deepx-design 子模块
miaobyte Aug 12, 2026
39bec68
refactor: array key
miaobyte Aug 13, 2026
2389036
feat: 类型系统引入 kindexp(数组类型)+ string→stringbyte 重命名
miaobyte Aug 14, 2026
d7111c1
chore: 更新 deepx-design 子模块
miaobyte Aug 14, 2026
9eb35aa
feat: 写槽类型标注校验(标量/数组标注与表达式数组性一致)
miaobyte Aug 14, 2026
f919552
fix: 有符号/无符号整数比较正确处理(cmpInt)
miaobyte Aug 14, 2026
563a379
refactor: time.duration.* 重命名为 time/duration.*
miaobyte Aug 14, 2026
813c9e6
feat: 新增 random.uint64/int63/intn 内建
miaobyte Aug 14, 2026
33802cd
refactor: 符号 * 由 star 重命名为 pointer
miaobyte Aug 14, 2026
97982d2
chore: tutorial 目录重组(插入 array/dict 分类并重编号)
miaobyte Aug 14, 2026
47fad2b
chore: 更新 deepx-design 子模块
miaobyte Aug 14, 2026
cee9772
feat: 分离数组 a<i> 索引语法 + scatter/compact 读写分离
miaobyte Aug 14, 2026
c360212
feat: rwir 注册表重构 + lib 数据(sys rwir runtime 命名空间 + math 常量)
miaobyte Aug 14, 2026
7736cd5
fix: .gitignore kvlang 规则锚定到根(/kvlang),不再误忽略 cmd/kvlang/ 源码
miaobyte Aug 14, 2026
2d919de
feat: 内置 stdlib 源码(go:embed .kv)+ lib 隐式 init() 封装
miaobyte Aug 14, 2026
54ca85e
feat: Rust runtime CLI 入口(main.rs)
miaobyte Aug 14, 2026
5bbb63f
refactor: stringbyte → charbyte 类型重命名
miaobyte Aug 14, 2026
48d4b56
feat: rwirext 外部 rwir 执行器 + terminal I/O 迁移 device → rwirext/term
miaobyte Aug 14, 2026
6a0c82b
chore: 更新 deepx-design 子模块
miaobyte Aug 14, 2026
0f9c87c
chore: .gitignore 忽略 rwirext/json 构建产物
miaobyte Aug 14, 2026
4222def
refactor: 移除分离数组 <> 语法,数组统一 [] + array.* 命名空间算子
miaobyte Aug 14, 2026
7d320d8
refactor: rwir 命名空间 /sys/rwir → /rwir
miaobyte Aug 15, 2026
c11cbc2
chore: 更新 deepx-design 子模块
miaobyte Aug 15, 2026
03c47ca
feat: char 类型系统三编码 char/{utf32,utf8,ascii}
miaobyte Aug 15, 2026
852366f
chore: 更新 deepx-design 子模块
miaobyte Aug 15, 2026
6b4629e
feat: parser 支持 num/any 类型类
miaobyte Aug 15, 2026
63ba373
refactor: abs/min/max/sign 下沉 stdlib/math.kv
miaobyte Aug 15, 2026
87b206c
refactor: rwirext 批量执行,移除 rwir/dispatch 与 /sys 命名空间
miaobyte Aug 15, 2026
dc95ee4
refactor: 移除终端发现层,term 直接读写 /dev/stdout|stderr|stdin
miaobyte Aug 15, 2026
b9c5895
refactor: 抽取 rwirext 扩展运行时框架到 rwir/ext
miaobyte Aug 15, 2026
f93151d
chore: 更新 deepx-design 子模块指针
miaobyte Aug 16, 2026
7cc6cb0
refactor: ext.RunBatch/FinishBatch 更名 RunSeq/WriteFinalPC
miaobyte Aug 16, 2026
22abd5e
feat: 新增 12-struct wip 教程,test.py 支持 # wip 跳过
miaobyte Aug 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build]
rustflags = ["-L", "/home/peng.li24/github.com/array2d/kvspace-c/build"]

File renamed without changes.
116 changes: 116 additions & 0 deletions .claude/runtime-rust.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# kvlang Rust Runtime 开发原则

## 零、总体原则

**kvlang Rust runtime 是 Go kvlang runtime 的像素级 C ABI 移植。**

Go 负责 toolchain(parse → lower → layout → 写入 kvspace),Rust/C++ 负责 runtime(从 kvspace 读取指令 → kvcpu 执行)。

## 一、零拷贝原则

XValue 的 kind 解析后,body 字节直接 reinterpret_cast,不做任何拷贝或中间类型转换。

```
SHM sbo_data 指针 → read_tlv() 返回直接指针(无 malloc)
Rust: *const u8 → *(ptr as *const i64).read_unaligned() → i64
C++: const uint8_t* → *reinterpret_cast<const int64_t*>(ptr)
```

- 禁止 `to_vec()`, `memcpy`, `copy_from_slice`, `malloc` 在 hot path
- 禁止创建中间 Vec/u8 对象装载 body 字节
- `display()` 做格式化输出时从 raw pointer 直接读,不拷
- 只有 kind 字符串(<16 bytes)允许拷贝

## 二、先读 Go 代码原则

实现任何 runtime 功能前,必须先读 Go 对应文件理解逻辑:

| 功能 | Go 文件 |
|------|--------|
| 执行循环 | `kvcpu/execute.go` |
| 控制流 | `kvcpu/controlflow.go` |
| 算术 | `rwir/builtin/arith.go` |
| 比较 | `rwir/builtin/cmp.go` |
| IO | `rwir/builtin/io.go` |
| 时间 | `rwir/builtin/time.go` |
| 分发 | `rwir/builtin/ops.go` |
| 虚线程 | `vthread/vthread.go` |
| 路径生成 | `keytree/const.go` + `keytree/vthread.go` |

禁止不读 Go 代码直接凭想象写 Rust 实现。

## 三、禁止 hardcode 原则

所有路径常量、kind 字符串、opcode 字符串必须引用模块常量,禁止裸字符串。

- 路径 → `keytree/const.rs`(对齐 `keytree/const.go`)
- kind → 引用 XValue kind 常量
- opcode → `rwir/builtin/ops.rs` dispatch table 中定义

禁止在 execute.rs / controlflow.rs 等文件中出现 `"/lib/"`, `"/vthread/"`, `".pc"`, `"main"` 等裸字符串。

## 四、像素级对齐 Go 原则

Rust 项目的文件路径、文件名、函数名、模块名必须与 Go 源码一对一对应:

```
Go: kvlang/kvcpu/execute.go → Rust: kvlang/kvcpu/execute.rs
Go: kvlang/kvcpu/controlflow.go → Rust: kvlang/kvcpu/controlflow.rs
Go: kvlang/kvcpu/cpu.go → Rust: kvlang/kvcpu/cpu.rs
Go: kvlang/rwir/rwir.go → Rust: kvlang/rwir/rwir.rs
Go: kvlang/rwir/builtin/arith.go → Rust: kvlang/rwir/builtin/arith.rs
Go: kvlang/rwir/builtin/cmp.go → Rust: kvlang/rwir/builtin/cmp.rs
Go: kvlang/rwir/builtin/io.go → Rust: kvlang/rwir/builtin/io.rs
Go: kvlang/rwir/builtin/time.go → Rust: kvlang/rwir/builtin/time.rs
Go: kvlang/rwir/builtin/ops.go → Rust: kvlang/rwir/builtin/ops.rs
Go: kvlang/rwir/builtin/logic.go → Rust: kvlang/rwir/builtin/logic.rs
Go: kvlang/rwir/builtin/math.go → Rust: kvlang/rwir/builtin/math.rs
Go: kvlang/rwir/builtin/string.go → Rust: kvlang/rwir/builtin/string.rs
Go: kvlang/vthread/vthread.go → Rust: kvlang/vthread/vthread.rs
Go: kvlang/keytree/const.go → Rust: kvlang/keytree/const.rs
Go: kvlang/logx/logx.go → Rust: kvlang/logx/logx.rs
```

Go 中的公开函数名在 Rust 中保持一致。例如 Go 的 `handle_goto` → Rust 的 `handle_goto`,Go 的 `exec_add` → Rust 的 `exec_add`。

## 五、模块结构

```rust
// lib.rs
pub mod kvcpu;
pub mod rwir;
pub mod keytree;
pub mod logx;
pub mod vthread;

// kvcpu/mod.rs
pub mod cpu;
pub mod execute;
pub mod controlflow;

// rwir/mod.rs
pub mod rwir;
pub mod builtin;

// rwir/builtin/mod.rs
pub mod ops; pub mod arith; pub mod cmp; pub mod io;
pub mod time; pub mod logic; pub mod math; pub mod bit;
pub mod cast; pub mod string; pub mod kvop;
```

## 六、编译与测试

```bash
# C 构建
make -C kvspace-c/build -j4

# Rust 构建
cargo build --manifest-path kvlang/Cargo.toml

# 单文件测试
KVSPACE_SHM=/tmp/t kvlang-rust main

# 全量测试
python3 kvlang/tutorial/test.py --runtime=rust
```
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ appendonly.aof
# ── Project-specific ─────────────────────────────────
/tmp/
/post/
kvlang
/kvlang
/json

# Tool config
.omc/
Expand Down
9 changes: 9 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 2 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "kvlang"
version = "0.1.0"
edition = "2024"
edition = "2021"
description = "kvlang VM — Rust runtime (kvcpu executor)"
license = "MIT"

Expand All @@ -13,5 +13,4 @@ name = "kvlang"
path = "cmd/kvlang/main.rs"

[dependencies]
# kvspace-rdma client (future)
# serde = { version = "1", features = ["derive"] }
libc = "0.2"
9 changes: 8 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: build test vet clean kvspace install
.PHONY: build test vet clean kvspace install rust rust-test

export GOPROXY ?= https://goproxy.cn,direct
PREFIX ?= ~/.local
Expand All @@ -9,9 +9,16 @@ build:
install -d $(PREFIX)/bin
install kvlang $(PREFIX)/bin/kvlang

rust:
cargo build --manifest-path $(CURDIR)/Cargo.toml

rust-test:
python3 tutorial/test.py --runtime=rust

vet:
go vet ./...

clean:
go clean
cargo clean --manifest-path $(CURDIR)/Cargo.toml
rm -f kvlang
7 changes: 0 additions & 7 deletions ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,6 @@ func (s FuncSig) NumReads() int32 { return int32(len(s.Params)) }
func (s FuncSig) NumWrites() int32 { return int32(len(s.Returns)) }

// ReturnNames 返回输出参数名列表。
func (s FuncSig) ReturnNames() []string {
names := make([]string, len(s.Returns))
for i, p := range s.Returns {
names[i] = p.Name
}
return names
}

// ── 函数 ──────────────────────────────────────────────────────

Expand Down
1 change: 1 addition & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fn main() { println!("cargo:rustc-link-search=native=/home/peng.li24/github.com/array2d/kvspace-c/build"); println!("cargo:rustc-link-lib=kvspace-c"); }
14 changes: 6 additions & 8 deletions cmd/kvlang/layout.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ func cmdLayout(args []string) {
layout.WriteFunc(kv, fpkg, lower.Func(&df.Funcs[i]))
anyCode = true
}
for i := range df.RwirDecls {
layout.WriteRwirDecl(kv, &df.RwirDecls[i])
}
body := df.InitBody
for _, c := range df.TopLevelCalls { body = append(body, c) }
if len(body) > 0 {
Expand Down Expand Up @@ -121,16 +124,11 @@ func _loadFile(kv kvspace.KVSpace, f string, anyCode *bool, loaded map[string]bo
layout.WriteFunc(kv, fpkg, lower.Func(&df.Funcs[i]))
*anyCode = true
}
for i := range df.RwirDecls {
layout.WriteRwirDecl(kv, &df.RwirDecls[i])
}
for _, st := range df.InitBody { *initBody = append(*initBody, st) }
for _, c := range df.TopLevelCalls { *initBody = append(*initBody, c) }
if len(df.InitBody) > 0 || len(df.TopLevelCalls) > 0 { *anyCode = true }
}

func makeInitFunc(calls []*ast.Instruction) *ast.Func {
body := make([]ast.Stmt, len(calls))
for i, inst := range calls {
body[i] = inst
}
initFn := ast.Func{Sig: ast.FuncSig{Name: "init"}, Body: body}
return lower.Func(&initFn)
}
9 changes: 7 additions & 2 deletions cmd/kvlang/layoutandrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func findEntryPrefix(kv kvspace.KVSpace, prefix string) string {
func runFiles(dsn string, paths []string, debug bool) {
kv := kvspace.Conn(dsn)
defer kv.DisConn()
registerDefaultTerm(kv)
initDirs(kv)

var files []string
for _, p := range paths {
Expand All @@ -59,14 +59,16 @@ func runFiles(dsn string, paths []string, debug bool) {
}
if len(files) == 0 { logx.Fatal("no .kv files found") }

layoutAndRunStdlib(kv)
if !loadFunctions(kv, files) { return }
executeEntry(kv, findEntry(dsn), debug)
}

func runCode(name string, rc io.Reader, dsn string, debug bool) {
kv := kvspace.Conn(dsn)
defer kv.DisConn()
registerDefaultTerm(kv)
initDirs(kv)
layoutAndRunStdlib(kv)

df, diags, err := parser.ParseCode(rc)
if err != nil { logx.Fatal("parse: %v", err) }
Expand All @@ -78,6 +80,9 @@ func runCode(name string, rc io.Reader, dsn string, debug bool) {
if fpkg == "" { fpkg = df.Package }
layout.WriteFunc(kv, fpkg, lower.Func(&df.Funcs[i]))
}
for i := range df.RwirDecls {
layout.WriteRwirDecl(kv, &df.RwirDecls[i])
}
body := df.InitBody
for _, c := range df.TopLevelCalls { body = append(body, c) }
if len(body) > 0 {
Expand Down
2 changes: 1 addition & 1 deletion cmd/kvlang/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
// 注册 KVSpace 实现;--kvspace DSN 的 scheme 选择后端(默认 shm://)。
_ "github.com/array2d/kvspace-go/redis"
_ "github.com/array2d/kvspace-go/goheap"
_ "github.com/array2d/kvspace-go/shm"
// _ "github.com/array2d/kvspace-go/shm" // requires libkvspace-c.so
)

func main() {
Expand Down
15 changes: 15 additions & 0 deletions cmd/kvlang/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use std::env;
use kvlang::kvcpu::cpu::KVCpu;
use kvlang::kvcpu::execute;

fn main() {
let func = env::args().nth(1).unwrap_or_else(|| "main".into());
let shm = env::var("KVSPACE_SHM").expect("KVSPACE_SHM not set");
let kv_ptr = KVCpu::open(&shm).expect("open shm");
let cpu = KVCpu::new(kv_ptr, "rust");
if let Err(e) = execute::execute(&cpu, &func) {
kvlang::logx::logx::error(format_args!("{}", e));
std::process::exit(1);
}
KVCpu::close(kv_ptr);
}
25 changes: 17 additions & 8 deletions cmd/kvlang/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import (
"flag"
"fmt"
"os"
"path/filepath"
"strings"
"time"

"kvlang/rwirext/term"
"kvlang/keytree"
"kvlang/kvcpu"
"github.com/array2d/kvspace-go"
Expand All @@ -18,11 +20,14 @@ import (
)

// cmdRun 解析参数并路由:内联 / {lib}.{func} / 文件 / 管道。
var noterm bool

func cmdRun(args []string) {
fs := flag.NewFlagSet("run", flag.ExitOnError)
dsn := fs.String("kvspace", defaultKVSpace(), kvspaceFlagDesc)
code := fs.String("c", "", "内联代码(直接执行字符串)")
debug := fs.Bool("debug", false, "单步调试模式(交互式,每条指令暂停)")
fs.BoolVar(&noterm, "noterm", false, "禁用内置终端 daemon(print/input 不再可用)")
fs.Usage = func() {
fmt.Fprintln(os.Stderr, "usage: kvlang run [--debug] [-c code | {lib}.{func} | <file.kv|dir>]")
fs.PrintDefaults()
Expand Down Expand Up @@ -56,7 +61,8 @@ func runLib(lib, fn string, debug bool) {
if lib == "" { name = fn }
kv := kvspace.Conn(defaultKVSpace())
defer kv.DisConn()
registerDefaultTerm(kv)
initDirs(kv)
layoutAndRunStdlib(kv)
executeEntry(kv, name, debug)
}

Expand All @@ -66,28 +72,31 @@ func executeEntry(kv kvspace.KVSpace, entryName string, debug bool) {
vtid := vthread.AllocVtid(kv)
kv.DelTree(keytree.VThread(vtid))
kvspace.MkIndexRecursive(kv, keytree.VThread(vtid)+"/")
builtin.WriteSysRwir(kv)
builtin.WriteRwir(kv, filepath.Base(os.Args[0]))
if !noterm {
term.Register(kv)
go term.Serve(kv)
}
firstPC := layout.Bootstrap(ctx, kv, vtid, entryName, nil)
if firstPC == "" {
logx.Fatal("[single] Bootstrap %s failed", entryName)
}
vthread.Set(ctx, kv, vtid, firstPC, "init")
kv.Set([]kvspace.KVPair{
{keytree.VThreadCtime(vtid), kvspace.NewTime(time.Now().UnixNano())},
{keytree.VThreadTerm(vtid), kvspace.NewChar("kvlangrun")},
{Key: keytree.VThreadCtime(vtid), Val: kvspace.NewTime(time.Now().UnixNano())},
})

if debug {
kv.Set([]kvspace.KVPair{{keytree.VThreadDebugger(vtid), kvspace.NewChar("break")}})
kv.Set([]kvspace.KVPair{{Key: keytree.VThreadDebugger(vtid), Val: kvspace.NewCharByte([]byte("break")...)}})
logx.Info("[single] debug mode: executing %s", firstPC)
cpu := kvcpu.New(kv, "single")
cpu := kvcpu.New(kv)
cpu.Execute(firstPC)
logx.Info("[dbg] execution finished")
return
}

logx.Info("[single] executing %s", firstPC)
cpu := kvcpu.New(kv, "single")
cpu := kvcpu.New(kv)
cpu.Execute(firstPC)
reportRunError(kv, vtid)
}
Expand All @@ -96,7 +105,7 @@ func reportRunError(kv kvspace.KVSpace, vtid string) {
msgVal := kvspace.GetOne(kv, keytree.VThreadStatusMsg(vtid, "error"))
if !kvspace.IsNone(msgVal) {
pcVal := kvspace.GetOne(kv, keytree.VThreadPC(vtid))
logx.Error("%s at %s", msgVal.String(), pcVal.String())
logx.Error("%s at %s", msgVal.ValueString(), pcVal.ValueString())
os.Exit(1)
}
}
Loading
Loading