diff --git a/.gitignore b/.gitignore
index 17da4106..9fddc79c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -72,3 +72,6 @@ kvlanglayout
silent*
dumptest*
d[0-9][0-9][0-9][0-9][0-9][0-9][0-9]
+
+# 五语言对齐 reference 材料(本地查阅用,不入库)
+stdlib/kvlang/reference/
diff --git a/README_CN.md b/README_CN.md
index 6a9898c6..7234c8ac 100644
--- a/README_CN.md
+++ b/README_CN.md
@@ -55,7 +55,7 @@ kvspace 是核心的寻址空间与内存空间;语言本体是小核心 runti

- **kvspace** — 一套 C ABI(`kvspace_*`,24 符号),由 DSN 选择两种实现:`kvspace-c`(C,`shm://`,链接 `blockmalloc` + `slotsboxmalloc`)与 `kvspace-durable`(Rust,`redis://` / `fs://`,s3/tikv 规划中)。
-- **kvlang** — `layout`(Rust,编译)与 `runtime`(C,执行),二者都只依赖 `kvspace_*` C ABI。
+- **kvlang** — `layout`(Rust,语法检查+布局)与 `runtime`(C,执行),二者都只依赖 `kvspace_*` C ABI。
- **rwirext** — 构建在 runtime 之上的扩展。嵌入式(Rust `term`,经 `kvlang_rwirext.h` 链接 `libkvlang_runtime`)或独立进程 handoff(Go `json`、Python `numpy`)。`term` / `json` 只是基础示例扩展,不是招牌能力。
---
@@ -191,7 +191,7 @@ if (sum > 50) { println("big") } else { println("small") }
for (x in [7, 2, 9, 4]) { println(x) }
```
-条件支持复合表达式:`if (7 % 2 != 0)`、`while (i < string.len(s))` 均可(编译期自动展平为临时槽)。
+条件支持复合表达式:`if (7 % 2 != 0)`、`while (i < string.len(s))` 均可(布局期自动展平为临时槽)。
### 操作符
diff --git a/docs/kvlang-ecosystem-architecture.drawio b/docs/kvlang-ecosystem-architecture.drawio
new file mode 100644
index 00000000..8a905729
--- /dev/null
+++ b/docs/kvlang-ecosystem-architecture.drawio
@@ -0,0 +1,169 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tutorial/error_cases/array_param/mutate_correct.kv b/error_cases/array_param/mutate_correct.kv
similarity index 100%
rename from tutorial/error_cases/array_param/mutate_correct.kv
rename to error_cases/array_param/mutate_correct.kv
diff --git a/tutorial/error_cases/array_param/mutate_literal.kv b/error_cases/array_param/mutate_literal.kv
similarity index 100%
rename from tutorial/error_cases/array_param/mutate_literal.kv
rename to error_cases/array_param/mutate_literal.kv
diff --git a/tutorial/error_test.py b/error_cases/error_test.py
similarity index 93%
rename from tutorial/error_test.py
rename to error_cases/error_test.py
index c7b44762..11735a86 100644
--- a/tutorial/error_test.py
+++ b/error_cases/error_test.py
@@ -5,7 +5,7 @@
用法: python3 tutorial/error_test.py
"""
from __future__ import annotations
-import os, re, subprocess, sys
+import os, subprocess, sys
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
@@ -44,11 +44,6 @@ def _unescape_logx(stderr: str) -> str:
"""logx msg= 域为 JSON-style 引号串,\" → " 以利子串匹配。"""
return stderr.replace('\\"', '"')
-def _detect_entry(out: str) -> str:
- m = re.search(r"ENTRY=(\S+)", out)
- return m.group(1) if m else "init"
-
-
def collect_errors(rel: str) -> str:
"""layout(编译期诊断)+ run(运行时诊断),收集 stderr 合并。"""
# 用 kvspace clear 隔离各 case
@@ -58,8 +53,7 @@ def collect_errors(rel: str) -> str:
text=True, timeout=60, cwd=str(ROOT))
stderr += _unescape_logx(layout.stderr)
if layout.returncode == 0:
- entry = _detect_entry(layout.stdout)
- crun = subprocess.run([TERM_BIN, entry], capture_output=True,
+ crun = subprocess.run([TERM_BIN, "test"], capture_output=True,
text=True, timeout=120, cwd=str(ROOT),
env={**os.environ, "KVSPACE": _C_DSN})
stderr += "\n" + _unescape_logx(crun.stderr)
diff --git a/tutorial/error_cases/index_error/at_oob.kv b/error_cases/index_error/at_oob.kv
similarity index 100%
rename from tutorial/error_cases/index_error/at_oob.kv
rename to error_cases/index_error/at_oob.kv
diff --git a/tutorial/error_cases/index_error/char_oob.kv b/error_cases/index_error/char_oob.kv
similarity index 100%
rename from tutorial/error_cases/index_error/char_oob.kv
rename to error_cases/index_error/char_oob.kv
diff --git a/tutorial/error_cases/index_error/slice_oob.kv b/error_cases/index_error/slice_oob.kv
similarity index 100%
rename from tutorial/error_cases/index_error/slice_oob.kv
rename to error_cases/index_error/slice_oob.kv
diff --git a/tutorial/error_cases/index_error/typed_array_string_key.kv b/error_cases/index_error/typed_array_string_key.kv
similarity index 100%
rename from tutorial/error_cases/index_error/typed_array_string_key.kv
rename to error_cases/index_error/typed_array_string_key.kv
diff --git a/tutorial/error_cases/key_error/kv_at_missing.kv b/error_cases/key_error/kv_at_missing.kv
similarity index 100%
rename from tutorial/error_cases/key_error/kv_at_missing.kv
rename to error_cases/key_error/kv_at_missing.kv
diff --git a/tutorial/error_cases/name_error/nosuch_func.kv b/error_cases/name_error/nosuch_func.kv
similarity index 100%
rename from tutorial/error_cases/name_error/nosuch_func.kv
rename to error_cases/name_error/nosuch_func.kv
diff --git a/tutorial/error_cases/none_type_error/none_arith.kv b/error_cases/none_type_error/none_arith.kv
similarity index 100%
rename from tutorial/error_cases/none_type_error/none_arith.kv
rename to error_cases/none_type_error/none_arith.kv
diff --git a/tutorial/error_cases/none_type_error/none_bool.kv b/error_cases/none_type_error/none_bool.kv
similarity index 100%
rename from tutorial/error_cases/none_type_error/none_bool.kv
rename to error_cases/none_type_error/none_bool.kv
diff --git a/tutorial/error_cases/none_type_error/none_cast.kv b/error_cases/none_type_error/none_cast.kv
similarity index 100%
rename from tutorial/error_cases/none_type_error/none_cast.kv
rename to error_cases/none_type_error/none_cast.kv
diff --git a/tutorial/error_cases/none_type_error/none_cmp.kv b/error_cases/none_type_error/none_cmp.kv
similarity index 100%
rename from tutorial/error_cases/none_type_error/none_cmp.kv
rename to error_cases/none_type_error/none_cmp.kv
diff --git a/tutorial/error_cases/read_only/dup_param.kv b/error_cases/read_only/dup_param.kv
similarity index 100%
rename from tutorial/error_cases/read_only/dup_param.kv
rename to error_cases/read_only/dup_param.kv
diff --git a/tutorial/error_cases/read_only/write_param.kv b/error_cases/read_only/write_param.kv
similarity index 100%
rename from tutorial/error_cases/read_only/write_param.kv
rename to error_cases/read_only/write_param.kv
diff --git a/tutorial/error_cases/recursion_error/stack_overflow.kv b/error_cases/recursion_error/stack_overflow.kv
similarity index 100%
rename from tutorial/error_cases/recursion_error/stack_overflow.kv
rename to error_cases/recursion_error/stack_overflow.kv
diff --git a/tutorial/error_cases/runtime_error/bootstrap_missing.kv b/error_cases/runtime_error/bootstrap_missing.kv
similarity index 100%
rename from tutorial/error_cases/runtime_error/bootstrap_missing.kv
rename to error_cases/runtime_error/bootstrap_missing.kv
diff --git a/tutorial/error_cases/syntax_error/break_outside_loop.kv b/error_cases/syntax_error/break_outside_loop.kv
similarity index 100%
rename from tutorial/error_cases/syntax_error/break_outside_loop.kv
rename to error_cases/syntax_error/break_outside_loop.kv
diff --git a/tutorial/error_cases/syntax_error/return_with_value.kv b/error_cases/syntax_error/return_with_value.kv
similarity index 100%
rename from tutorial/error_cases/syntax_error/return_with_value.kv
rename to error_cases/syntax_error/return_with_value.kv
diff --git a/tutorial/error_cases/syntax_error/sparse_literal_position.kv b/error_cases/syntax_error/sparse_literal_position.kv
similarity index 100%
rename from tutorial/error_cases/syntax_error/sparse_literal_position.kv
rename to error_cases/syntax_error/sparse_literal_position.kv
diff --git a/tutorial/error_cases/syntax_error/top_level_if.kv b/error_cases/syntax_error/top_level_if.kv
similarity index 100%
rename from tutorial/error_cases/syntax_error/top_level_if.kv
rename to error_cases/syntax_error/top_level_if.kv
diff --git a/tutorial/error_cases/syntax_error/unclosed_block.kv b/error_cases/syntax_error/unclosed_block.kv
similarity index 100%
rename from tutorial/error_cases/syntax_error/unclosed_block.kv
rename to error_cases/syntax_error/unclosed_block.kv
diff --git a/tutorial/error_cases/type_error/arith_bool.kv b/error_cases/type_error/arith_bool.kv
similarity index 100%
rename from tutorial/error_cases/type_error/arith_bool.kv
rename to error_cases/type_error/arith_bool.kv
diff --git a/tutorial/error_cases/type_error/arith_string.kv b/error_cases/type_error/arith_string.kv
similarity index 100%
rename from tutorial/error_cases/type_error/arith_string.kv
rename to error_cases/type_error/arith_string.kv
diff --git a/tutorial/error_cases/type_error/bitwise_bool.kv b/error_cases/type_error/bitwise_bool.kv
similarity index 100%
rename from tutorial/error_cases/type_error/bitwise_bool.kv
rename to error_cases/type_error/bitwise_bool.kv
diff --git a/tutorial/error_cases/type_error/bitwise_float.kv b/error_cases/type_error/bitwise_float.kv
similarity index 100%
rename from tutorial/error_cases/type_error/bitwise_float.kv
rename to error_cases/type_error/bitwise_float.kv
diff --git a/error_cases/type_error/bool_branch.kv b/error_cases/type_error/bool_branch.kv
new file mode 100644
index 00000000..6e9eb511
--- /dev/null
+++ b/error_cases/type_error/bool_branch.kv
@@ -0,0 +1,6 @@
+// expected
+// TypeError: branch condition must be bool, got int64
+// 修复: B2 铁律 — 分支条件必须是 bool,禁止 int 隐式真值化(用 != 0)
+rwfunc test() -> () {
+ if (int64(1)) { }
+}
diff --git a/error_cases/type_error/bool_logic.kv b/error_cases/type_error/bool_logic.kv
new file mode 100644
index 00000000..16f84ec5
--- /dev/null
+++ b/error_cases/type_error/bool_logic.kv
@@ -0,0 +1,6 @@
+// expected
+// TypeError: && requires bool, got int64
+// 修复: B2 铁律 — 逻辑运算只接受 bool,禁止 int 隐式真值化(用 != 0)
+rwfunc test() -> () {
+ int64(1) && true -> x
+}
diff --git a/tutorial/error_cases/type_error/char_bad_args.kv b/error_cases/type_error/char_bad_args.kv
similarity index 100%
rename from tutorial/error_cases/type_error/char_bad_args.kv
rename to error_cases/type_error/char_bad_args.kv
diff --git a/tutorial/error_cases/type_error/cmp_int_bool.kv b/error_cases/type_error/cmp_int_bool.kv
similarity index 100%
rename from tutorial/error_cases/type_error/cmp_int_bool.kv
rename to error_cases/type_error/cmp_int_bool.kv
diff --git a/tutorial/error_cases/type_error/cmp_mixed.kv b/error_cases/type_error/cmp_mixed.kv
similarity index 100%
rename from tutorial/error_cases/type_error/cmp_mixed.kv
rename to error_cases/type_error/cmp_mixed.kv
diff --git a/tutorial/error_cases/type_error/compact_string_array.kv b/error_cases/type_error/compact_string_array.kv
similarity index 100%
rename from tutorial/error_cases/type_error/compact_string_array.kv
rename to error_cases/type_error/compact_string_array.kv
diff --git a/tutorial/error_cases/type_error/concat_non_string.kv b/error_cases/type_error/concat_non_string.kv
similarity index 100%
rename from tutorial/error_cases/type_error/concat_non_string.kv
rename to error_cases/type_error/concat_non_string.kv
diff --git a/tutorial/error_cases/type_error/minmax_mixed.kv b/error_cases/type_error/minmax_mixed.kv
similarity index 100%
rename from tutorial/error_cases/type_error/minmax_mixed.kv
rename to error_cases/type_error/minmax_mixed.kv
diff --git a/tutorial/error_cases/type_error/mod_float.kv b/error_cases/type_error/mod_float.kv
similarity index 100%
rename from tutorial/error_cases/type_error/mod_float.kv
rename to error_cases/type_error/mod_float.kv
diff --git a/tutorial/error_cases/type_error/neg_unsigned.kv b/error_cases/type_error/neg_unsigned.kv
similarity index 100%
rename from tutorial/error_cases/type_error/neg_unsigned.kv
rename to error_cases/type_error/neg_unsigned.kv
diff --git a/tutorial/error_cases/type_error/sqrt_string.kv b/error_cases/type_error/sqrt_string.kv
similarity index 100%
rename from tutorial/error_cases/type_error/sqrt_string.kv
rename to error_cases/type_error/sqrt_string.kv
diff --git a/tutorial/error_cases/value_error/log_range.kv b/error_cases/value_error/log_range.kv
similarity index 100%
rename from tutorial/error_cases/value_error/log_range.kv
rename to error_cases/value_error/log_range.kv
diff --git a/tutorial/error_cases/zero_division/div_zero.kv b/error_cases/zero_division/div_zero.kv
similarity index 100%
rename from tutorial/error_cases/zero_division/div_zero.kv
rename to error_cases/zero_division/div_zero.kv
diff --git a/tutorial/error_cases/zero_division/float_underflow_div.kv b/error_cases/zero_division/float_underflow_div.kv
similarity index 100%
rename from tutorial/error_cases/zero_division/float_underflow_div.kv
rename to error_cases/zero_division/float_underflow_div.kv
diff --git a/tutorial/error_cases/zero_division/mod_zero.kv b/error_cases/zero_division/mod_zero.kv
similarity index 100%
rename from tutorial/error_cases/zero_division/mod_zero.kv
rename to error_cases/zero_division/mod_zero.kv
diff --git a/layout/Cargo.toml b/layout/Cargo.toml
index 70018221..afe884ac 100644
--- a/layout/Cargo.toml
+++ b/layout/Cargo.toml
@@ -3,7 +3,7 @@ name = "kvlang-layout"
version = "0.1.0"
edition = "2021"
license = "MIT"
-description = "kvlang 编译期(parser/lower/layoutcode),只依赖 kvspace-durable 的 C ABI"
+description = "kvlang 语法检查 + 布局工具(parser/lower/layoutcode),只依赖 kvspace-durable 的 C ABI"
[lib]
name = "kvlanglayout"
diff --git a/layout/src/ast.rs b/layout/src/ast.rs
index fdcaa317..e5e829a5 100644
--- a/layout/src/ast.rs
+++ b/layout/src/ast.rs
@@ -180,6 +180,43 @@ impl RwirDecl {
}
}
+// ── struct ───────────────────────────────────────────────────────────
+
+#[derive(Clone)]
+pub struct Field {
+ pub name: String,
+ pub ty: String, // kindexpr(字段类型)
+ pub default: Option, // 默认值字面量(None = 未给)
+}
+
+#[derive(Clone)]
+pub struct StructDecl {
+ pub comments: Vec,
+ pub name: String,
+ pub pkg: String,
+ pub fields: Vec,
+}
+
+impl StructDecl {
+ pub fn sig_string(&self) -> String {
+ let mut sb = format!("struct {} {{", self.name);
+ for (i, fld) in self.fields.iter().enumerate() {
+ sb.push_str(if i > 0 { "; " } else { " " });
+ sb.push_str(&fld.name);
+ if !fld.ty.is_empty() {
+ sb.push(':');
+ sb.push_str(&fld.ty);
+ }
+ if let Some(d) = &fld.default {
+ sb.push('=');
+ sb.push_str(&d.to_string());
+ }
+ }
+ sb.push_str(" }");
+ sb
+ }
+}
+
// ── Expr ─────────────────────────────────────────────────────────────
#[derive(Clone, Copy, PartialEq, Eq)]
@@ -608,6 +645,7 @@ impl fmt::Display for ScopeStmt {
pub struct File {
pub package: String,
pub rwir_decls: Vec,
+ pub structs: Vec,
pub funcs: Vec,
pub top_level_calls: Vec,
pub init_body: Vec,
@@ -617,6 +655,7 @@ pub struct File {
#[derive(Default)]
struct PkgNode {
rwirs: Vec,
+ structs: Vec,
funcs: Vec,
body: Vec,
children: std::collections::BTreeMap,
@@ -635,6 +674,17 @@ fn pkg_node<'a>(root: &'a mut PkgNode, pkg: &str) -> &'a mut PkgNode {
fn emit_node(sb: &mut String, node: &PkgNode, indent: &str) {
let mut items: Vec = Vec::new();
+ for d in &node.structs {
+ let mut s = String::new();
+ for c in &d.comments {
+ s.push_str(indent);
+ s.push_str(c);
+ s.push('\n');
+ }
+ s.push_str(indent);
+ s.push_str(&d.sig_string());
+ items.push(s);
+ }
for d in &node.rwirs {
let mut s = String::new();
for c in &d.comments {
@@ -684,6 +734,9 @@ impl File {
/// 格式化为规范 kvlang 源码(重建 lib 分组,保留包名,round-trip 语义等价)。
pub fn format(&self) -> String {
let mut root = PkgNode::default();
+ for d in &self.structs {
+ pkg_node(&mut root, &d.pkg).structs.push(d.clone());
+ }
for d in &self.rwir_decls {
pkg_node(&mut root, &d.pkg).rwirs.push(d.clone());
}
diff --git a/layout/src/bin/kvlanglayout.rs b/layout/src/bin/kvlanglayout.rs
index 03475079..a4134eb2 100644
--- a/layout/src/bin/kvlanglayout.rs
+++ b/layout/src/bin/kvlanglayout.rs
@@ -1,4 +1,4 @@
-//! 读 .kv 文件,用 Rust layout 编译进 kvspace(默认 redis),并输出入口(ENTRY=...),
+//! 读 .kv 文件,用 Rust layout 检查语法并布局进 kvspace(默认 redis),并输出入口(ENTRY=...),
//! 供 Go runtime 执行验证。
//! 用法:
//! kvlanglayout [dsn] 仅 layout,打印 ENTRY=(默认子命令)
diff --git a/layout/src/capi.rs b/layout/src/capi.rs
index 249fb5ca..dda220d6 100644
--- a/layout/src/capi.rs
+++ b/layout/src/capi.rs
@@ -209,9 +209,9 @@ pub extern "C" fn kvlangKindexprParse(kindexpr: *const c_char, out: *mut kvlangK
if s.is_empty() {
return -1;
}
- let (r, dims, kind) = kvkind::parse_kindexpr(s);
+ let (dims, kind) = kvkind::parse_kindexpr(s);
let out = unsafe { &mut *out };
- out.ref_ = r;
+ out.ref_ = 0;
out.ndim = dims.len() as i32;
for (i, d) in dims.iter().enumerate() {
if i < 8 {
diff --git a/layout/src/code.rs b/layout/src/code.rs
index 0c2d7647..8ee8d79b 100644
--- a/layout/src/code.rs
+++ b/layout/src/code.rs
@@ -1,7 +1,7 @@
-//! layoutcode(对齐 layout/layout.go 的编译期部分):把 AST 写到 /lib/ 下的结构化 KV。
+//! layoutcode(对齐 layout/layout.go):检查 AST 并把结果布局写到 /lib/ 下的结构化 KV。
//!
//! 存储约定:
-//! /lib/·/[0,0] 编译后签名(kind=rwfunc)
+//! /lib/·/[0,0] 布局后签名(kind=rwfunc)
//! /lib/·/ 命名参数→slot 指针(kind=char, isptr=1)
//! /lib/·/[i,j] 编译后指令(kind=rwir),i 从 1 开始
//! /lib/·/‥labels/ label → irseq
@@ -11,7 +11,7 @@
use std::collections::HashMap;
-use super::ast::{Func, Instruction, RwirDecl, Stmt};
+use super::ast::{Expr, Func, Instruction, RwirDecl, Stmt, StructDecl};
use super::ffi::Kv;
use super::{builtin, ffi, keytree, kvkind, lower, parser};
@@ -39,6 +39,10 @@ pub fn compile(kv: &mut Kv, src: &str) -> Result, String> {
let mut any_code = false;
let mut inits: Vec = Vec::new();
+ for decl in &file.structs {
+ write_struct_decl(kv, decl);
+ any_code = true;
+ }
for func in &file.funcs {
let pkg = if func.pkg.is_empty() {
file.package.clone()
@@ -144,7 +148,7 @@ pub fn vet(src: &str) -> Result<(), String> {
let _ = lower::lower_func(func);
any_code = true;
}
- if !file.init_body.is_empty() || !file.top_level_calls.is_empty() {
+ if !file.init_body.is_empty() || !file.top_level_calls.is_empty() || !file.structs.is_empty() {
any_code = true;
}
if !any_code {
@@ -315,7 +319,7 @@ fn collect_slots(kv: &mut Kv, prefix: &str, out: &mut Vec) {
}
}
-/// 注释不允许换行:defrwfunc 的参数类型以 \n 连接,改 " | " 呈现。
+/// 注释不允许换行:rwfunc 签名的参数类型以 \n 连接,改 " | " 呈现。
fn sanitize(s: &str) -> String {
s.replace('\n', " | ")
}
@@ -431,6 +435,63 @@ pub fn write_func(kv: &mut Kv, pkg: &str, fn_: &mut Func) {
}
}
+/// 写 struct 原型到 /lib/:基节点(kind=struct) + memindex(/lib/Name·) + 各字段默认值。
+/// 运行时 struct·new 以此为原型 cplist 克隆,故字段默认值即实例初值。
+pub fn write_struct_decl(kv: &mut Kv, decl: &StructDecl) {
+ let mut name = decl.name.clone();
+ if !decl.pkg.is_empty() {
+ name = format!("{}{}{name}", decl.pkg, keytree::MEMBER_SEP);
+ }
+ let base = keytree::rwir(&name);
+ let _ = kv.del_tree(&base);
+ let fnames: Vec = decl.fields.iter().map(|f| f.name.clone()).collect();
+ let ftypes: Vec<(String, String)> = decl
+ .fields
+ .iter()
+ .map(|f| (f.name.clone(), f.ty.clone()))
+ .collect();
+ let mut pairs: Vec<(String, Vec)> = Vec::new();
+ pairs.push((base.clone(), kvkind::new_struct(&ftypes)));
+ pairs.push((keytree::member(&base, ""), kvkind::new_memindex(&fnames)));
+ for fld in &decl.fields {
+ pairs.push((
+ keytree::member(&base, &fld.name),
+ field_default(&fld.ty, fld.default.as_ref()),
+ ));
+ }
+ let _ = kv.set(&pairs);
+}
+
+/// 字段默认值 XValue:head kind = 字段类型,body = 默认字面量(未给则零值)。
+/// 标量+char 直接编码;带 dims / structref 仅记录类型(空 body),嵌套 struct 待定。
+fn field_default(ty: &str, default: Option<&Expr>) -> Vec {
+ let (dims, base) = kvkind::parse_kindexpr(ty);
+ let s = default.map(|e| e.val.clone()).unwrap_or_default();
+ if base.starts_with("char/") {
+ return ffi::new_char(&base, &s);
+ }
+ if !dims.is_empty() {
+ return ffi::tlv_encode(&base, &[], dims.iter().product());
+ }
+ let i = || s.parse::().unwrap_or(0);
+ let u = || s.parse::().unwrap_or(0);
+ let f = || s.parse::().unwrap_or(0.0);
+ match base.as_str() {
+ "bool" => ffi::new_bool(s == "true"),
+ "int8" => ffi::tlv_encode("int8", &(i() as i8).to_le_bytes(), 1),
+ "int16" => ffi::tlv_encode("int16", &(i() as i16).to_le_bytes(), 1),
+ "int32" => ffi::tlv_encode("int32", &(i() as i32).to_le_bytes(), 1),
+ "int64" => ffi::new_int64(i()),
+ "uint8" => ffi::tlv_encode("uint8", &[u() as u8], 1),
+ "uint16" => ffi::tlv_encode("uint16", &(u() as u16).to_le_bytes(), 1),
+ "uint32" => ffi::tlv_encode("uint32", &(u() as u32).to_le_bytes(), 1),
+ "uint64" => ffi::tlv_encode("uint64", &u().to_le_bytes(), 1),
+ "float32" => ffi::tlv_encode("float32", &(f() as f32).to_le_bytes(), 1),
+ "float64" => ffi::new_float64(f()),
+ _ => ffi::tlv_encode(&base, &[], 1),
+ }
+}
+
/// 写用户声明的 rwir(无体)到 /lib/。
pub fn write_rwir_decl(kv: &mut Kv, decl: &RwirDecl) {
let mut opcode = decl.sig.name.clone();
@@ -593,7 +654,6 @@ fn is_literal(s: &str) -> bool {
|| b[0] == b'/'
|| s == "true"
|| s == "false"
- || s == "null"
|| b[0].is_ascii_digit()
|| (b[0] == b'-' && s.len() > 1)
}
@@ -614,6 +674,16 @@ mod tests {
roundtrip("lib byteseek {\nlib session {\nlib s1 {\nrwfunc main() -> () {\n3 + 4 -> s\nprintln(s)\n}\n}\n}\n}\nmain()\n");
}
+ #[test]
+ fn null_literal_rejected() {
+ // 空值只有 None;书写 null 是错误,layout 必须显式拒绝。
+ assert!(vet("lib t {\nrwfunc main() -> () {\nnull -> x\n}\n}\n").is_err());
+ assert!(vet("lib t {\nrwfunc main() -> () {\nprintln(null)\n}\n}\n").is_err());
+ // None、字符串 "null"、含 null 的路径不受影响。
+ assert!(vet("lib t {\nrwfunc main() -> () {\nNone -> x\n}\n}\n").is_ok());
+ assert!(vet("lib t {\nrwfunc main() -> () {\n\"null\" -> x\n}\n}\n").is_ok());
+ }
+
#[test]
fn nested_lib_layout_and_merge() {
let mut kv = Kv::conn(&format!(
@@ -627,7 +697,7 @@ mod tests {
"lib a {\nlib b {\nrwfunc f() -> (r:int64) {\n1 -> r\n}\n}\n}\n",
)
.unwrap();
- assert_eq!(kvkind::kind(&kv.get_one("/lib/a/b·f/[0,0]")), "defrwfunc");
+ assert_eq!(kvkind::kind(&kv.get_one("/lib/a/b·f/[0,0]")), "rwfunc");
// 同 lib a 下再 layout 另一嵌套 lib c,验证 b·f 未被整库删除(增量合并)
compile(
@@ -637,10 +707,10 @@ mod tests {
.unwrap();
assert_eq!(
kvkind::kind(&kv.get_one("/lib/a/b·f/[0,0]")),
- "defrwfunc",
+ "rwfunc",
"b·f 应保留"
);
- assert_eq!(kvkind::kind(&kv.get_one("/lib/a/c·g/[0,0]")), "defrwfunc");
+ assert_eq!(kvkind::kind(&kv.get_one("/lib/a/c·g/[0,0]")), "rwfunc");
}
#[test]
@@ -658,7 +728,7 @@ mod tests {
"lib t {\nrwfunc main() -> () {\nfoo.bar(\"x\") -> y\nbaz(\"z\") -> w\n}\n}\n",
)
.unwrap();
- assert_eq!(kvkind::kind(&kv.get_one("/lib/t·main/[0,0]")), "defrwfunc");
+ assert_eq!(kvkind::kind(&kv.get_one("/lib/t·main/[0,0]")), "rwfunc");
assert!(
kvkind::value_string(&kv.get_one("/lib/t·main/[1,0]")).contains("foo.bar"),
"'.' 应作普通字符保留在 opcode 内(单一 token foo.bar)"
diff --git a/layout/src/ffi.rs b/layout/src/ffi.rs
index 10236a17..79b24df3 100644
--- a/layout/src/ffi.rs
+++ b/layout/src/ffi.rs
@@ -38,10 +38,11 @@ extern "C" {
err: *mut c_char,
err_cap: u32,
) -> c_int;
- /// 新位置写:按 (kindexpr, body_len) 分配新 box、写 head,返回 body 偏移指针。
+ /// 新位置写:按 (xkind, kindexpr, body_len) 分配新 box、写 head,返回 body 偏移指针。
fn kvspaceWriteNewPlace(
h: Handle,
key: *const c_char,
+ xkind: u8,
kindexpr: *const c_char,
body_len: u32,
body: *mut *mut u8,
@@ -62,7 +63,8 @@ extern "C" {
expand_ext: c_int,
resolve: c_int,
idx: i32,
- out: *mut *mut u8,
+ buf: *mut u8,
+ buf_cap: u32,
out_len: *mut u32,
) -> c_int;
fn kvspaceDel(
@@ -73,7 +75,13 @@ extern "C" {
err_cap: u32,
) -> c_int;
fn kvspaceDelTree(h: Handle, prefix: *const c_char, err: *mut c_char, err_cap: u32) -> c_int;
- fn kvspaceMkindex(h: Handle, path: *const c_char, err: *mut c_char, err_cap: u32) -> c_int;
+ fn kvspaceMkindex(
+ h: Handle,
+ path: *const c_char,
+ capacity: u32,
+ err: *mut c_char,
+ err_cap: u32,
+ ) -> c_int;
fn kvspaceMkindexExt(
h: Handle,
path: *const c_char,
@@ -111,7 +119,11 @@ extern "C" {
/// XValueHead 解码结果(与 kvspace-durable 的 kvspaceHead_t 布局一致)。kindexpr 为唯一类型真相。
#[repr(C)]
pub struct kvspaceHead_t {
+ pub xkind: u8,
pub kindexpr: [u8; 256],
+ pub kind_off: i32,
+ pub ndim: i32,
+ pub dims: [i32; 8],
pub ro: u8,
pub vid: u32,
pub body_len: i32,
@@ -194,6 +206,7 @@ impl Kv {
kvspaceWriteNewPlace(
self.h,
ck.as_ptr(),
+ h.xkind,
kindexpr.as_ptr(),
body_len as u32,
&mut body,
@@ -237,19 +250,22 @@ impl Kv {
}
let mut v = Vec::with_capacity(count as usize);
for i in 0..count {
- let bytes = call_borrow(|out, out_len| unsafe {
+ let mut buf = [0u8; 1024];
+ let mut out_len: u32 = 0;
+ let ok = unsafe {
kvspaceListAt(
self.h,
c.as_ptr(),
expand_ext as c_int,
resolve as c_int,
i,
- out,
- out_len,
+ buf.as_mut_ptr(),
+ buf.len() as u32,
+ &mut out_len,
)
- });
- if !bytes.is_empty() {
- v.push(String::from_utf8_lossy(&bytes).into_owned());
+ } == 0;
+ if ok && out_len > 0 {
+ v.push(String::from_utf8_lossy(&buf[..out_len as usize]).into_owned());
}
}
v
@@ -265,7 +281,8 @@ impl Kv {
pub fn mkindex(&mut self, path: &str) -> Result<(), String> {
let c = CString::new(path).expect("no NUL");
let mut err: [c_char; 256] = [0; 256];
- let ret = unsafe { kvspaceMkindex(self.h, c.as_ptr(), err.as_mut_ptr(), err.len() as u32) };
+ let ret =
+ unsafe { kvspaceMkindex(self.h, c.as_ptr(), 0, err.as_mut_ptr(), err.len() as u32) };
err_ret(&mut err, ret)
}
@@ -333,7 +350,11 @@ pub fn tlv_encode(kind: &str, raw: &[u8], array_len: i32) -> Vec {
/// 解码 XValueHead。
pub fn decode_head(data: &[u8]) -> kvspaceHead_t {
let mut h = kvspaceHead_t {
+ xkind: 0,
kindexpr: [0u8; 256],
+ kind_off: 0,
+ ndim: 0,
+ dims: [0i32; 8],
ro: 0,
vid: 0,
body_len: 0,
diff --git a/layout/src/kindexpr.rs b/layout/src/kindexpr.rs
index a9e274e3..d6e28b46 100644
--- a/layout/src/kindexpr.rs
+++ b/layout/src/kindexpr.rs
@@ -39,11 +39,25 @@ fn known_kind(k: &str) -> bool {
| "rwir"
| "rwfunc"
| "scope"
+ | "struct"
| "time"
| "duration"
)
}
+/// structref = "/" path:指向 /lib 下类型定义节点的完整路径(实例 kindexpr、struct 字段类型)。
+/// 仅做语法承认(`/` + 合法路径段),不解析 /lib 是否存在该类型 —— 存在性/字段一致性留给 runtime。
+fn valid_structref(s: &str) -> bool {
+ let rest = match s.strip_prefix('/') {
+ Some(r) => r,
+ None => return false,
+ };
+ !rest.is_empty()
+ && rest.split('/').all(|seg| {
+ !seg.is_empty() && seg.bytes().all(|b| b.is_ascii_alphanumeric() || b == b'_')
+ })
+}
+
fn valid_base(s: &str) -> bool {
if s.is_empty() {
return false;
@@ -118,8 +132,11 @@ fn valid_key(s: &str) -> bool {
tail.is_empty() && inner.split(',').all(valid_scalar)
}
-/// atom = shape | mapexpr;mapexpr = key "·" type(value 可递归含容器,故支持嵌套 map)。
+/// atom = shape | mapexpr | structref;mapexpr = key "·" type;structref = "/" path。
fn valid_atom(s: &str) -> bool {
+ if s.starts_with('/') {
+ return valid_structref(s);
+ }
if let Some(i) = s.find('·') {
return valid_key(&s[..i]) && valid_kindexpr(&s[i + '·'.len_utf8()..]);
}
@@ -151,7 +168,7 @@ fn base_match(s: &str, kind: &str) -> bool {
fn match_shape(s: &str, ndim: i32, dims: &[i32]) -> bool {
if s.is_empty() {
- return ndim >= 1;
+ return ndim == 1;
}
let parts: Vec<&str> = s.split(',').collect();
if parts.len() as i32 != ndim {
@@ -235,6 +252,11 @@ mod tests {
"[int32,int32]·[]char/utf8",
"[float32,float32]·[]char/utf8",
"[float32,int8,uint32]·int64",
+ "struct",
+ "/lib/Point",
+ "/lib/geom/Point",
+ "/lib/Node",
+ "/lib/Point|/lib/Node",
] {
assert!(valid_kindexpr(e), "{e} should be valid");
}
@@ -248,9 +270,16 @@ mod tests {
"[?]·int64",
"[int32,]·int64",
"[foo,int32]·int64",
+ "/",
+ "/lib/",
+ "/lib//Point",
+ "lib/Point",
+ "/lib/Po int",
] {
assert!(!valid_kindexpr(e), "{e} should be invalid");
}
+ assert!(match_kindexpr("/lib/Point", "/lib/Point", 0, &[]));
+ assert!(!match_kindexpr("/lib/Point", "/lib/Node", 0, &[]));
assert!(match_kindexpr("[]char/utf8·int64", "stringkeymap", 1, &[3]));
assert!(!match_kindexpr("[]char/utf8·int64", "object", 0, &[]));
}
@@ -315,6 +344,8 @@ mod tests {
("int64|float64", "float64", 0, &[], true),
("int64|float64", "bool", 0, &[], false),
("[]float32", "float32", 1, &[5], true),
+ ("[]float32", "float32", 2, &[2, 3], false),
+ ("[]float32", "float32", 0, &[], false),
("[2,3]float32", "float32", 2, &[2, 3], true),
("[2,3]float32", "float32", 2, &[2, 4], false),
("[?,768]float32", "float32", 2, &[100, 768], true),
diff --git a/layout/src/kvkind.rs b/layout/src/kvkind.rs
index 01889402..bac60325 100644
--- a/layout/src/kvkind.rs
+++ b/layout/src/kvkind.rs
@@ -18,12 +18,12 @@ pub const KIND_OBJ: &str = "object";
pub const KIND_MAP: &str = "stringkeymap";
pub const KIND_INDEX: &str = "index";
pub const KIND_EXT_INDEX: &str = "extindex";
+pub const KIND_STRUCT: &str = "struct";
// kvlang 自有 kind
pub const KIND_RWIR: &str = "rwir";
pub const KIND_RWFUNC: &str = "rwfunc";
pub const KIND_DEF_RWIR: &str = "defrwir";
-pub const KIND_DEF_RWFUNC: &str = "defrwfunc";
pub const KIND_RWIR_OR_RWFUNC: &str = "rwir|rwfunc";
pub const KIND_SCOPE: &str = "scope";
@@ -38,28 +38,22 @@ pub fn head(data: &[u8]) -> ffi::kvspaceHead_t {
ffi::decode_head(data)
}
-/// 解析 head 的 kindexpr 内容 → (ref, dims, base kind)。
-pub fn parse_kindexpr(kx: &str) -> (i32, Vec, String) {
- let (r, rest) = match kx.as_bytes().first() {
- Some(b'*') => (1, &kx[1..]),
- Some(b'@') => (2, &kx[1..]),
- _ => (0, kx),
- };
- if rest.starts_with('[') {
- match rest.find(']') {
+/// 解析 kindexpr 内容 → (dims, base kind)。kindexpr 无前缀(ref/ptr 归 head.xkind)。
+pub fn parse_kindexpr(kx: &str) -> (Vec, String) {
+ if kx.starts_with('[') {
+ match kx.find(']') {
Some(end) => (
- r,
- rest[1..end]
+ kx[1..end]
.split(',')
.filter(|d| !d.is_empty())
.map(|d| d.parse().unwrap_or(0))
.collect(),
- rest[end + 1..].to_string(),
+ kx[end + 1..].to_string(),
),
- None => (r, Vec::new(), rest.to_string()),
+ None => (Vec::new(), kx.to_string()),
}
} else {
- (r, Vec::new(), rest.to_string())
+ (Vec::new(), kx.to_string())
}
}
@@ -81,18 +75,18 @@ pub fn kind(data: &[u8]) -> String {
if data.is_empty() {
return String::new();
}
- parse_kindexpr(&kindexpr(data)).2
+ parse_kindexpr(&kindexpr(data)).1
}
pub fn is_ptr(data: &[u8]) -> bool {
- !data.is_empty() && parse_kindexpr(&kindexpr(data)).0 == 1
+ !data.is_empty() && ffi::decode_head(data).xkind == 1
}
pub fn array_len(data: &[u8]) -> i32 {
if data.is_empty() {
return 0;
}
- let dims = parse_kindexpr(&kindexpr(data)).1;
+ let dims = parse_kindexpr(&kindexpr(data)).0;
if dims.is_empty() {
1
} else {
@@ -128,13 +122,13 @@ pub fn display(data: &[u8]) -> String {
if data.is_empty() {
return "None".to_string();
}
- let (r, _, k) = parse_kindexpr(&kindexpr(data));
+ let (_, k) = parse_kindexpr(&kindexpr(data));
if k.is_empty() {
return "None".to_string();
}
let h = ffi::decode_head(data);
let b = body(data, &h);
- if r == 1 {
+ if h.xkind == 1 {
return format!("→{}:{}", String::from_utf8_lossy(b), k);
}
format!("{}:{}", k, plain_value(&k, b))
@@ -194,7 +188,7 @@ fn plain_value(k: &str, b: &[u8]) -> String {
.collect(),
"index" => format!("({})", count_names(b)),
// kvlang 自有 kind:body = [2B nr][2B nw][sig];槽值/调用目标 nr=nw=0,取 sig 即可。
- "rwir" | "rwir|rwfunc" | "defrwir" | "defrwfunc" => {
+ "rwir" | "rwir|rwfunc" | "rwfunc" | "defrwir" => {
let (nr, nw) = if b.len() >= 4 {
(
u16::from_le_bytes([b[0], b[1]]),
@@ -245,6 +239,26 @@ pub fn new_defrwir(nr: i32, nw: i32, sig: &str) -> Vec {
ffi::tlv_encode(KIND_DEF_RWIR, &rwir_body(nr, nw, sig), 1)
}
+// ── struct 原型(对齐 runtime kvlangBuiltinMemindex)─────────────────
+//
+// /lib/Name kind=struct,body="name:kindexpr\n..."(字段声明类型,供实例化类型校验)
+// /lib/Name· kind=index,body=[4B count LE][name\n...](字段名唯一权威)
+
+pub fn new_struct(fields: &[(String, String)]) -> Vec {
+ let body = fields
+ .iter()
+ .map(|(n, t)| format!("{n}:{t}"))
+ .collect::>()
+ .join("\n");
+ ffi::tlv_encode(KIND_STRUCT, body.as_bytes(), 1)
+}
+
+pub fn new_memindex(names: &[String]) -> Vec {
+ let mut raw = (names.len() as u32).to_le_bytes().to_vec();
+ raw.extend_from_slice(names.join("\n").as_bytes());
+ ffi::tlv_encode(KIND_INDEX, &raw, 1)
+}
+
// ── kvlang 自有 kind:rwfunc ────────────────────────────────────────
//
// body = [2B nr LE][2B nw LE][param_types 以 \n 连接],array_len=num_insts。
@@ -254,7 +268,7 @@ pub fn new_rwfunc(num_insts: i32, nr: i32, nw: i32, param_types: &[String]) -> V
raw.extend_from_slice(&(nr as u16).to_le_bytes());
raw.extend_from_slice(&(nw as u16).to_le_bytes());
raw.extend_from_slice(param_types.join("\n").as_bytes());
- ffi::tlv_encode(KIND_DEF_RWFUNC, &raw, num_insts)
+ ffi::tlv_encode(KIND_RWFUNC, &raw, num_insts)
}
/// rwfunc body 访问器(layout 读回签名时用)。
diff --git a/layout/src/lib.rs b/layout/src/lib.rs
index e80e6513..93089b17 100644
--- a/layout/src/lib.rs
+++ b/layout/src/lib.rs
@@ -1,5 +1,5 @@
#![allow(non_snake_case)]
-//! kvlang-layout — 编译期:parse → lower → layoutcode。
+//! kvlang-layout — 语法检查 + 布局工具:parse → lower → layoutcode(把 AST 检查后布局写入 /lib/)。
//! 只依赖 kvspace-durable 的 C ABI(见 [`ffi`]),不依赖其 Rust 类型。
//! 翻译自 kvlang 的 Go 源码:parser/ lower/ layout/ ast/ symbol/ keytree/。
diff --git a/layout/src/parser.rs b/layout/src/parser.rs
index 96723b86..6d311b57 100644
--- a/layout/src/parser.rs
+++ b/layout/src/parser.rs
@@ -2,7 +2,9 @@
//!
//! 入口:`parse_code(src) → Result<(File, Vec), String>`。
-use super::ast::{self, Expr, Func, FuncSig, Instruction, Param, RwirDecl, Stmt};
+use super::ast::{
+ self, Expr, Field, Func, FuncSig, Instruction, Param, RwirDecl, Stmt, StructDecl,
+};
use super::keytree;
use super::scanner::{scan, Diagnostic, Kind, Pos, Token};
use super::symbol;
@@ -144,6 +146,17 @@ impl Parser {
continue;
}
+ let is_struct = self.peek().kind == Kind::Ident
+ && self.peek().value == "struct"
+ && self.peek_at(1).kind == Kind::Ident
+ && self.peek_at(2).kind == Kind::LBrace;
+ if is_struct {
+ let mut decl = self.parse_struct_decl();
+ decl.comments = comments;
+ f.structs.push(decl);
+ continue;
+ }
+
if self.peek().kind == Kind::Ident && self.peek().value == "rwir" {
let decl = self.parse_rwir_decl();
f.rwir_decls.push(decl);
@@ -258,6 +271,17 @@ impl Parser {
self.parse_lib_body(f, &pkg);
continue;
}
+ let is_struct = self.peek().kind == Kind::Ident
+ && self.peek().value == "struct"
+ && self.peek_at(1).kind == Kind::Ident
+ && self.peek_at(2).kind == Kind::LBrace;
+ if is_struct {
+ let mut decl = self.parse_struct_decl();
+ decl.pkg = pkg.clone();
+ decl.comments = comments;
+ f.structs.push(decl);
+ continue;
+ }
if self.peek().kind == Kind::Ident && self.peek().value == "rwir" {
let mut decl = self.parse_rwir_decl();
decl.pkg = pkg.clone();
@@ -351,6 +375,60 @@ impl Parser {
decl
}
+ fn parse_struct_decl(&mut self) -> StructDecl {
+ self.advance(); // consume 'struct'
+ let name = self.advance().value; // struct 名
+ self.expect(Kind::LBrace);
+ let mut fields = Vec::new();
+ loop {
+ while matches!(
+ self.peek().kind,
+ Kind::Newline | Kind::Comma | Kind::Comment
+ ) {
+ self.advance();
+ }
+ if self.peek().kind == Kind::RBrace || self.peek().kind == Kind::EOF {
+ break;
+ }
+ if self.peek().kind != Kind::Ident {
+ let t = self.peek();
+ self.errors.push(Diagnostic {
+ pos: t.pos,
+ message: format!("struct {name:?}: expected field name, got {:?}", t.value),
+ warn: false,
+ info: false,
+ source: String::new(),
+ src_file: String::new(),
+ src_name: String::new(),
+ });
+ break;
+ }
+ let fname = self.advance().value;
+ let mut ty = String::new();
+ if self.peek().kind == Kind::Colon {
+ self.advance();
+ ty = self.parse_type();
+ }
+ let mut default = None;
+ if self.peek().kind == Kind::Arrow && self.peek().value == "=" {
+ self.advance();
+ default = self.parse_pratt(0);
+ }
+ fields.push(Field {
+ name: fname,
+ ty,
+ default,
+ });
+ }
+ self.expect(Kind::RBrace);
+ StructDecl {
+ comments: Vec::new(),
+ name,
+ pkg: String::new(),
+ fields,
+ }
+ }
+
fn parse_func_sig(&mut self) -> FuncSig {
self.advance(); // consume 'rwfunc'
let mut sig = FuncSig {
@@ -1163,6 +1241,76 @@ impl Parser {
return Some(ast::call("array", elems));
}
+ // struct 字面量 Name{...} 或 pkg.Name{...} → struct·new("/lib/…", "f", v, …)
+ let struct_lit = t.kind == Kind::Ident
+ && (self.peek_at(1).kind == Kind::LBrace || {
+ let mut j = 1isize;
+ while self.peek_at(j).kind == Kind::Dot && self.peek_at(j + 1).kind == Kind::Ident {
+ j += 2;
+ }
+ j > 1 && self.peek_at(j).kind == Kind::LBrace
+ });
+ if struct_lit {
+ let mut path = format!("{}/{}", keytree::LIB_ROOT, self.advance().value);
+ while self.peek().kind == Kind::Dot && self.peek_at(1).kind == Kind::Ident {
+ self.advance(); // skip Dot
+ path.push_str(keytree::MEMBER_SEP);
+ path.push_str(&self.advance().value);
+ }
+ let mut args = vec![ast::str_lit(&path)];
+ self.advance(); // consume {
+ loop {
+ while matches!(
+ self.peek().kind,
+ Kind::Newline | Kind::Comma | Kind::Comment
+ ) {
+ self.advance();
+ }
+ if self.peek().kind == Kind::RBrace || self.peek().kind == Kind::EOF {
+ break;
+ }
+ if self.peek().kind != Kind::Ident {
+ let bt = self.peek();
+ self.errors.push(Diagnostic {
+ pos: bt.pos,
+ warn: false,
+ info: false,
+ message: format!("struct literal: expected field name, got {:?}", bt.value),
+ source: String::new(),
+ src_file: String::new(),
+ src_name: String::new(),
+ });
+ break;
+ }
+ let key = self.advance().value;
+ if !(self.peek().kind == Kind::Arrow && self.peek().value == "=") {
+ let bt = self.peek();
+ self.errors.push(Diagnostic {
+ pos: bt.pos,
+ warn: false,
+ info: false,
+ message: format!("struct literal: expected '=' after {key:?}"),
+ source: String::new(),
+ src_file: String::new(),
+ src_name: String::new(),
+ });
+ break;
+ }
+ self.advance(); // consume =
+ let val = match self.parse_pratt(0) {
+ Some(v) => v,
+ None => break,
+ };
+ args.push(ast::str_lit(&key));
+ args.push(val);
+ }
+ self.expect(Kind::RBrace);
+ return Some(ast::call(
+ &format!("struct{}new", keytree::MEMBER_SEP),
+ args,
+ ));
+ }
+
// dict 字面量
if t.kind == Kind::LBrace {
let mut j = 1isize;
@@ -1407,6 +1555,17 @@ impl Parser {
}
}
}
+ if t.kind == Kind::Ident && t.value == "null" {
+ self.errors.push(Diagnostic {
+ pos: t.pos,
+ message: "null 不是合法字面量;空值只有 None".to_string(),
+ warn: false,
+ info: false,
+ source: String::new(),
+ src_file: String::new(),
+ src_name: String::new(),
+ });
+ }
Some(ast::leaf(&t.value))
}
@@ -1703,6 +1862,21 @@ impl Parser {
if s.starts_with('/') {
return;
}
+ // struct 赋值(RHS = struct·new):浅拷 base+一层成员,lower 为 kv·cplist(struct·new→temp, dst)。
+ // 不走 kv·set —— 后者只搬基值,struct 的成员会丢在临时槽。dst 传完整成员槽串,
+ // runtime ResolveWriteSlot 拼 +"base·key…" 即成员绝对路径。
+ let is_struct_new = inst
+ .expr
+ .as_ref()
+ .map(|e| e.op == format!("struct{}new", keytree::MEMBER_SEP))
+ .unwrap_or(false);
+ if is_struct_new && !s.contains('*') {
+ let e = inst.expr.take().unwrap();
+ inst.expr = Some(ast::call("kv·cplist", vec![e, ast::leaf(&s)]));
+ inst.writes = Vec::new();
+ inst.write_types = Vec::new();
+ return;
+ }
// 成员链写槽 p·a·b = v → 变参 kv·set(p, "a", "b", v),与读侧 #110 一致逐段拼路径。
// 不再按首个 · 压扁成 kv·set(p, "a·b", v):扁平段把「成员链」与「含 · 的成员名」混为一谈。
let mut parts = s.split(keytree::MEMBER_SEP);
diff --git a/layout/tests/pipeline_test.rs b/layout/tests/pipeline_test.rs
index dcec290d..ada355ca 100644
--- a/layout/tests/pipeline_test.rs
+++ b/layout/tests/pipeline_test.rs
@@ -25,7 +25,7 @@ fn compile_simple_func() {
// 函数签名
let sig_val = kv.get_one("/lib/sum/[0,0]");
- assert_eq!(kvkind::kind(&sig_val), "defrwfunc");
+ assert_eq!(kvkind::kind(&sig_val), "rwfunc");
assert_eq!(kvkind::array_len(&sig_val), 2); // add + return
let b = body(&sig_val);
assert_eq!(kvkind::rwfunc_num_reads(b), 2);
@@ -66,7 +66,7 @@ fn compile_string_literal_and_lib() {
// 函数在 /lib/p·hi/ 下(lib 块 pkg 前缀)
let sig_val = kv.get_one("/lib/p·hi/[0,0]");
- assert_eq!(kvkind::kind(&sig_val), "defrwfunc");
+ assert_eq!(kvkind::kind(&sig_val), "rwfunc");
// 字符串字面量读槽 → char/utf32(UTF-32 LE 码点)
let r = kv.get_one("/lib/p·hi/[1,-1]");
@@ -102,7 +102,7 @@ fn compile_control_flow_is_single_plane() {
compile(&mut kv, src).unwrap();
let sig_val = kv.get_one("/lib/f/[0,0]");
- assert_eq!(kvkind::kind(&sig_val), "defrwfunc");
+ assert_eq!(kvkind::kind(&sig_val), "rwfunc");
let children = kv.list("/lib/f/", false, false);
let old_scope = children.iter().any(|c| {
let b = c.trim_end_matches('/');
diff --git a/layout/tests/redis_roundtrip_test.rs b/layout/tests/redis_roundtrip_test.rs
index 39212c44..da7cae82 100644
--- a/layout/tests/redis_roundtrip_test.rs
+++ b/layout/tests/redis_roundtrip_test.rs
@@ -35,7 +35,7 @@ fn redis_compile() {
compile(&mut kv, src).unwrap();
let sig_val = kv.get_one("/lib/sum/[0,0]");
- assert_eq!(kvkind::kind(&sig_val), "defrwfunc");
+ assert_eq!(kvkind::kind(&sig_val), "rwfunc");
let b = body(&sig_val);
assert_eq!(kvkind::rwfunc_num_reads(b), 2);
assert_eq!(kvkind::rwfunc_num_writes(b), 1);
diff --git a/runtime-rs/src/engine.rs b/runtime-rs/src/engine.rs
index 2b1aba2a..16b92f8b 100644
--- a/runtime-rs/src/engine.rs
+++ b/runtime-rs/src/engine.rs
@@ -20,7 +20,7 @@ impl Engine {
/// 写即构造:按 (kindexpr, body) 向 kvspace 要偏移指针后直接写 body 字节——
/// key 已存在且同 body_len → WriteInPlace(原 box 就地);否则 WriteNewPlace(新 box)。
/// 两分支各调唯一原语、无预 encode 整条 TLV、无中转 buffer、无 free。
- fn write_construct(&self, key: &str, kindexpr: &str, body: &[u8]) {
+ fn write_construct(&self, key: &str, xkind: u8, kindexpr: &str, body: &[u8]) {
unsafe {
let ck = cs(key);
let mut bp: *mut u8 = null_mut();
@@ -38,6 +38,7 @@ impl Engine {
kvspaceWriteNewPlace(
self.kv,
ck.as_ptr(),
+ xkind,
cs(kindexpr).as_ptr(),
body.len() as u32,
&mut bp,
@@ -90,7 +91,7 @@ impl Engine {
/// 扩展世界(@ ref=2)句柄编码写入:kind=目标完整 kindexpr(如 "[]uint8"),body=定位串。
/// 读取该 key 时由 read_at 按 body 前缀路由给对应 /lib/networld/* 兑现器还原真实字节。
pub fn set_ext_handle(&self, key: &str, target_kindexpr: &str, locator: &str) {
- self.write_construct(key, &format!("@{target_kindexpr}"), locator.as_bytes());
+ self.write_construct(key, 2, target_kindexpr, locator.as_bytes());
}
/// 读 key 的 head,返回 (ref, body 串)。仅 ref==2 时 body 有意义(扩展句柄定位串)。
@@ -102,9 +103,9 @@ impl Engine {
unsafe {
let mut head = KvspaceHead::default();
kvspaceDecodeHead(tlv.as_ptr(), tlv.len() as u32, &mut head);
- let r = match head.kindexpr[0] {
- b'@' => 2,
- b'*' => 1,
+ let r = match head.xkind {
+ 2 => 2,
+ 1 => 1,
_ => 0,
};
if r != 2 {
@@ -172,9 +173,9 @@ impl Engine {
if kvspaceDecodeHead(tlv.as_ptr(), tlv.len() as u32, &mut h) != 0 {
return Vec::new();
}
- let r = match h.kindexpr[0] {
- b'@' => 2,
- b'*' => 1,
+ let r = match h.xkind {
+ 2 => 2,
+ 1 => 1,
_ => 0,
};
let (bo, bl) = (h.body_offset as usize, h.body_len.max(0) as usize);
@@ -221,15 +222,21 @@ impl Engine {
}
let mut v = Vec::with_capacity(count as usize);
for i in 0..count {
- let (mut out, mut olen) = (null_mut(), 0u32);
- if kvspaceListAt(self.kv, cp.as_ptr(), 0, 0, i, &mut out, &mut olen) == 0
- && !out.is_null()
+ let mut buf = [0u8; 1024];
+ let mut olen = 0u32;
+ if kvspaceListAt(
+ self.kv,
+ cp.as_ptr(),
+ 0,
+ 0,
+ i,
+ buf.as_mut_ptr(),
+ buf.len() as u32,
+ &mut olen,
+ ) == 0
&& olen > 0
{
- v.push(
- String::from_utf8_lossy(std::slice::from_raw_parts(out, olen as usize))
- .into_owned(),
- );
+ v.push(String::from_utf8_lossy(&buf[..olen as usize]).into_owned());
}
}
v
@@ -285,7 +292,7 @@ impl Engine {
.trim_end_matches('\0')
.to_string();
let (bo, bl) = (head.body_offset as usize, head.body_len.max(0) as usize);
- self.write_construct(key, &kx, &tlv[bo..bo + bl]);
+ self.write_construct(key, head.xkind, &kx, &tlv[bo..bo + bl]);
}
}
diff --git a/runtime-rs/src/ffi.rs b/runtime-rs/src/ffi.rs
index e6b1f77e..66423bec 100644
--- a/runtime-rs/src/ffi.rs
+++ b/runtime-rs/src/ffi.rs
@@ -8,7 +8,11 @@ use std::ffi::{c_char, c_int, c_void, CStr, CString};
/// kvspaceDecodeHead 输出(与 kvspace-durable/src/ffi.rs::kvspaceHead_t 对齐)。kindexpr 为唯一类型真相。
#[repr(C)]
pub struct KvspaceHead {
+ pub xkind: u8,
pub kindexpr: [u8; 256],
+ pub kind_off: i32,
+ pub ndim: i32,
+ pub dims: [i32; 8],
pub ro: u8,
pub vid: u32,
pub body_len: i32,
@@ -18,7 +22,11 @@ pub struct KvspaceHead {
impl Default for KvspaceHead {
fn default() -> Self {
KvspaceHead {
+ xkind: 0,
kindexpr: [0u8; 256],
+ kind_off: 0,
+ ndim: 0,
+ dims: [0i32; 8],
ro: 0,
vid: 0,
body_len: 0,
@@ -95,6 +103,7 @@ unsafe extern "C" {
pub fn kvspaceWriteNewPlace(
h: *mut c_void,
key: *const c_char,
+ xkind: u8,
kindexpr: *const c_char,
body_len: u32,
body: *mut *mut u8,
@@ -116,7 +125,8 @@ unsafe extern "C" {
expand_ext: c_int,
resolve: c_int,
idx: i32,
- out: *mut *mut u8,
+ buf: *mut u8,
+ buf_cap: u32,
out_len: *mut u32,
) -> c_int;
pub fn kvspaceTlvEncode(
@@ -147,6 +157,8 @@ unsafe extern "C" {
) -> c_int;
// ── kvlang runtime:rwirext 宿主 ABI(均传 kvspace 句柄)─────────
+ // C 头 kvlang_rwirext.h 导出 9 符号;此处声明 7:故意省略 KindexprValid/KindexprMatch
+ // ——kindexpr 校验属 layout 期、匹配属 C dispatch 内部,Rust term 侧不调用(非缺陷)。
pub fn kvlang_rwirextRegister(
kvspace: *mut c_void,
opcode: *const c_char,
diff --git a/runtime-rs/src/rwir/json.rs b/runtime-rs/src/rwir/json.rs
index c467fa73..81570fbf 100644
--- a/runtime-rs/src/rwir/json.rs
+++ b/runtime-rs/src/rwir/json.rs
@@ -118,7 +118,7 @@ fn parse_tlv(data: &[u8]) -> (String, Vec, usize) {
let kx = String::from_utf8_lossy(&h.kindexpr)
.trim_end_matches('\0')
.to_string();
- let (_, dims, kind) = parse_kindexpr(&kx);
+ let (dims, kind) = parse_kindexpr(&kx);
let (bo, bl) = (h.body_offset as usize, h.body_len.max(0) as usize);
let raw = if bo + bl <= data.len() {
data[bo..bo + bl].to_vec()
@@ -271,27 +271,21 @@ fn mk_map_value(n: usize) -> Vec {
// ── kindexpr 串解析(反序列化按类型/形状分发用;kvspace 未导出串解析器)─────────
-fn parse_kindexpr(kx: &str) -> (i32, Vec, String) {
- let (r, rest) = match kx.as_bytes().first() {
- Some(b'*') => (1, &kx[1..]),
- Some(b'@') => (2, &kx[1..]),
- _ => (0, kx),
- };
- if rest.starts_with('[') {
- match rest.find(']') {
+fn parse_kindexpr(kx: &str) -> (Vec, String) {
+ if kx.starts_with('[') {
+ match kx.find(']') {
Some(end) => (
- r,
- rest[1..end]
+ kx[1..end]
.split(',')
.filter(|d| !d.is_empty())
.map(|d| d.parse().unwrap_or(0))
.collect(),
- rest[end + 1..].to_string(),
+ kx[end + 1..].to_string(),
),
- None => (r, Vec::new(), rest.to_string()),
+ None => (Vec::new(), kx.to_string()),
}
} else {
- (r, Vec::new(), rest.to_string())
+ (Vec::new(), kx.to_string())
}
}
diff --git a/runtime/src/builtin.c b/runtime/src/builtin.c
index 0a10c5a9..137a3d98 100644
--- a/runtime/src/builtin.c
+++ b/runtime/src/builtin.c
@@ -360,7 +360,7 @@ static int kvlangBuiltinCmp(kvlangFrame_t *f, cmp_op op) {
r = op == CMP_EQ ? c == 0 : op == CMP_NEQ ? c != 0 : op == CMP_LT ? c < 0 : op == CMP_GT ? c > 0 : op == CMP_LE ? c <= 0 : c >= 0;
free(a); free(b);
} else if (strcmp(ka, KVSPACE_KIND_BOOL) == 0 && strcmp(kb, KVSPACE_KIND_BOOL) == 0) {
- bool a = kvlangXvalueAsBool(&in[0]), b = kvlangXvalueAsBool(&in[1]);
+ bool a = kvlangXvalueAsInt64(&in[0]) != 0, b = kvlangXvalueAsInt64(&in[1]) != 0;
r = op == CMP_EQ ? a == b : op == CMP_NEQ ? a != b : op == CMP_LT ? a < b : op == CMP_GT ? a > b : op == CMP_LE ? a <= b : a >= b;
} else {
kvlangBuiltinSetErr(f, "TypeError: cannot compare %s with %s", ka, kb); kvlangBuiltinFreeInputs(in, n); return -1;
@@ -377,21 +377,34 @@ static int kvlangBuiltinGt(kvlangFrame_t *f) { return kvlangBuiltinCmp(f, CMP_GT
static int kvlangBuiltinLe(kvlangFrame_t *f) { return kvlangBuiltinCmp(f, CMP_LE); }
static int kvlangBuiltinGe(kvlangFrame_t *f) { return kvlangBuiltinCmp(f, CMP_GE); }
+static bool require_bool(kvlangFrame_t *f, const char *op, kvlangXvalue_t *in, int n, int want) {
+ if (n < want) return false;
+ for (int i = 0; i < want; i++) {
+ if (!kvlangXvalueKindIs(&in[i], KVSPACE_KIND_BOOL)) {
+ kvlangBuiltinSetErr(f, "TypeError: %s requires bool, got %s", op, kvlangXvalueKind(&in[i]));
+ return false;
+ }
+ }
+ return true;
+}
static int kvlangBuiltinAnd(kvlangFrame_t *f) {
kvlangXvalue_t in[2]; int n = kvlangBuiltinReadInputs(f, in, 2);
- kvlangXvalue_t r; kvlangXvalueNewBool(&r, n >= 2 && kvlangXvalueAsBool(&in[0]) && kvlangXvalueAsBool(&in[1]));
+ if (!require_bool(f, "&&", in, n, 2)) { kvlangBuiltinFreeInputs(in, n); return -1; }
+ kvlangXvalue_t r; kvlangXvalueNewBool(&r, kvlangXvalueAsInt64(&in[0]) != 0 && kvlangXvalueAsInt64(&in[1]) != 0);
int rc = kvlangBuiltinWriteResult(f, &r); kvlangXvalueFree(&r); kvlangBuiltinFreeInputs(in, n);
return rc;
}
static int kvlangBuiltinOr(kvlangFrame_t *f) {
kvlangXvalue_t in[2]; int n = kvlangBuiltinReadInputs(f, in, 2);
- kvlangXvalue_t r; kvlangXvalueNewBool(&r, n >= 2 && (kvlangXvalueAsBool(&in[0]) || kvlangXvalueAsBool(&in[1])));
+ if (!require_bool(f, "||", in, n, 2)) { kvlangBuiltinFreeInputs(in, n); return -1; }
+ kvlangXvalue_t r; kvlangXvalueNewBool(&r, kvlangXvalueAsInt64(&in[0]) != 0 || kvlangXvalueAsInt64(&in[1]) != 0);
int rc = kvlangBuiltinWriteResult(f, &r); kvlangXvalueFree(&r); kvlangBuiltinFreeInputs(in, n);
return rc;
}
static int kvlangBuiltinNot(kvlangFrame_t *f) {
kvlangXvalue_t in[2]; int n = kvlangBuiltinReadInputs(f, in, 2);
- kvlangXvalue_t r; kvlangXvalueNewBool(&r, !(n >= 1 && kvlangXvalueAsBool(&in[0])));
+ if (!require_bool(f, "!", in, n, 1)) { kvlangBuiltinFreeInputs(in, n); return -1; }
+ kvlangXvalue_t r; kvlangXvalueNewBool(&r, kvlangXvalueAsInt64(&in[0]) == 0);
int rc = kvlangBuiltinWriteResult(f, &r); kvlangXvalueFree(&r); kvlangBuiltinFreeInputs(in, n);
return rc;
}
@@ -470,7 +483,10 @@ static int kvlangBuiltinCastNum(kvlangFrame_t *f, const char *kind) {
kvlangXvalue_t in[2]; int n = kvlangBuiltinReadInputs(f, in, 2);
if (n < 1 || kvlangXvalueNone(&in[0])) { kvlangBuiltinSetErr(f, "TypeError: cannot cast None"); kvlangBuiltinFreeInputs(in, n); return -1; }
kvlangXvalue_t r;
- if (strcmp(kind, KVSPACE_KIND_BOOL) == 0) kvlangXvalueNewBool(&r, kvlangXvalueAsBool(&in[0]));
+ if (strcmp(kind, KVSPACE_KIND_BOOL) == 0) {
+ if (!kvlangXvalueKindIs(&in[0], KVSPACE_KIND_BOOL)) { kvlangBuiltinSetErr(f, "TypeError: cannot cast %s to bool — use != 0", kvlangXvalueKind(&in[0])); kvlangBuiltinFreeInputs(in, n); return -1; }
+ kvlangXvalueNewBool(&r, kvlangXvalueAsInt64(&in[0]) != 0);
+ }
else if (strcmp(kind, KVSPACE_KIND_FLOAT32) == 0) { float fv = (float)kvlangXvalueAsFloat64(&in[0]); uint8_t b[4]; memcpy(b, &fv, 4); kvlangXvalueNewTlv(&r, KVSPACE_KIND_FLOAT32, b, 4, 1); }
else if (strcmp(kind, KVSPACE_KIND_FLOAT64) == 0) kvlangXvalueNewFloat64(&r, kvlangXvalueAsFloat64(&in[0]));
else { int64_t v = kvlangXvalueAsInt64(&in[0]); narrow_int(kind, kind, v, &r); }
@@ -545,7 +561,7 @@ static const struct { const char *op; kvlangBuiltinFn fn; } myrwircaps[] = {
{"array", kvlangBuiltinArray},
{"array·scatter", kvlangBuiltinScatter}, {"array·compact", kvlangBuiltinCompact},
{"array·append", kvlangBuiltinAppend}, {"array·slice", kvlangBuiltinSlice},
- {"obj", kvlangBuiltinObj}, {"map", kvlangBuiltinMap},
+ {"obj", kvlangBuiltinObj}, {"map", kvlangBuiltinMap}, {"struct·new", kvlangBuiltinStructNew},
{"ndarray·numel", kvlangBuiltinNdarrayNumel}, {"ndarray·dim", kvlangBuiltinNdarrayDim}, {"ndarray·shape", kvlangBuiltinNdarrayShape},
{"xv·at", kvlangBuiltinXvAt}, {"xv·set", kvlangBuiltinXvSet}, {"xv·reshape", kvlangBuiltinXvReshape},
{"xv·reinterpret", kvlangBuiltinXvReinterpret},
@@ -567,8 +583,8 @@ static const struct { const char *op; kvlangBuiltinFn fn; } myrwircaps[] = {
{"time·before", kvlangBuiltinTimeCmp}, {"time·after", kvlangBuiltinTimeCmp},
{"random·uint64", kvlangBuiltinRandUint64}, {"random·int63", kvlangBuiltinRandInt63}, {"random·intn", kvlangBuiltinRandIntn},
{"kv·get", kvlangBuiltinKvGet}, {"kv·set", kvlangBuiltinKvSet}, {"kv·del", kvlangBuiltinKvDel},
- {"kv·deltree", kvlangBuiltinKvDelTree}, {"kv·list", kvlangBuiltinKvList}, {"kv·listlen", kvlangBuiltinKvListLen}, {"kv·listn", kvlangBuiltinKvListN}, {"kv·mkindex", kvlangBuiltinKvMkindex},
- {"kv·extindex", kvlangBuiltinKvExtIndex}, {"kv·rmindexext", kvlangBuiltinKvRmIndexExt}, {"kv·watch", kvlangBuiltinKvWatch},
+ {"kv·deltree", kvlangBuiltinKvDelTree}, {"kv·cp", kvlangBuiltinKvCp}, {"kv·cpdir", kvlangBuiltinKvCpTree}, {"kv·cplist", kvlangBuiltinKvCpList}, {"kv·list", kvlangBuiltinKvList}, {"kv·listlen", kvlangBuiltinKvListLen}, {"kv·listn", kvlangBuiltinKvListN}, {"kv·mkindex", kvlangBuiltinKvMkindex},
+ {"kv·extindex", kvlangBuiltinKvExtIndex}, {"kv·rmindexext", kvlangBuiltinKvRmIndexExt}, {"kv·watch", kvlangBuiltinKvWatch}, {"kv·abs", kvlangBuiltinKvAbs},
{"vthread·create", kvlangBuiltinVthreadCreate},
{"vthread·run", kvlangBuiltinVthreadRun},
{"vthread·call", kvlangBuiltinVthreadCall},
diff --git a/runtime/src/builtin_collection.c b/runtime/src/builtin_collection.c
index 007a4f47..1e5816ad 100644
--- a/runtime/src/builtin_collection.c
+++ b/runtime/src/builtin_collection.c
@@ -402,6 +402,78 @@ int kvlangBuiltinObj(kvlangFrame_t *f) {
kvlangBuiltinNextPc(f); kvlangBuiltinFreeInputs(in, n); return 0;
}
+static char *dupn(const char *s, size_t n) {
+ char *r = malloc(n + 1);
+ memcpy(r, s, n);
+ r[n] = 0;
+ return r;
+}
+
+/* 在 "name:kindexpr\n..." 声明串里查字段名,返回其类型(malloc)或 NULL(无此字段)。 */
+static char *struct_field_type(const char *decl, const char *fname) {
+ size_t fl = strlen(fname);
+ const char *p = decl;
+ while (*p) {
+ const char *nl = strchr(p, '\n');
+ size_t linelen = nl ? (size_t)(nl - p) : strlen(p);
+ const char *colon = memchr(p, ':', linelen);
+ if (colon) {
+ size_t nlen = (size_t)(colon - p);
+ if (nlen == fl && memcmp(p, fname, fl) == 0)
+ return dupn(colon + 1, linelen - nlen - 1);
+ }
+ if (!nl) break;
+ p = nl + 1;
+ }
+ return NULL;
+}
+
+/* struct·new:克隆 /lib/Name 原型子树到写槽,覆盖给定字段(校验字段存在性+类型)。
+ * in[0]=structref("/lib/Name"),其后成对 (字段名, 值)。实例基值 kind=structref。 */
+int kvlangBuiltinStructNew(kvlangFrame_t *f) {
+ kvlangXvalue_t in[64]; int n = kvlangBuiltinReadInputs(f, in, 64);
+ if (n < 1) { kvlangBuiltinFreeInputs(in, n); return kvlangBuiltinSetErr(f, "TypeError: struct.new requires a type"); }
+ char *ref = kvlangXvalueValueString(&in[0]);
+ kvlangXvalue_t proto; kvlangXvalueZero(&proto); kvlangKvGetOne(f->kv, ref, &proto);
+ if (kvlangXvalueNone(&proto) || strcmp(kvlangXvalueKind(&proto), KVSPACE_KIND_STRUCT) != 0) {
+ int e = kvlangBuiltinSetErr(f, "TypeError: %s is not a struct type", ref);
+ kvlangXvalueFree(&proto); free(ref); kvlangBuiltinFreeInputs(in, n); return e;
+ }
+ kvspaceHead_t ph; kvlangXvalueHead(&proto, &ph);
+ int32_t dclen = 0; const uint8_t *dcl = kvlangXvalueBody(&proto, &ph, &dclen);
+ char *decl = dupn((const char *)dcl, (size_t)(dclen > 0 ? dclen : 0));
+ kvlangXvalueFree(&proto);
+
+ char err[256]; int rc = 0;
+ char *fr = kvlangKeytreeFrameRoot(f->pc);
+ for (int w = 0; w < f->inst->nw && rc == 0; w++) {
+ char *ok = kvlangBuiltinResolveWriteSlot(f->kv, fr, f->inst->writes[w].name);
+ if (kvlangKvCpList(f->kv, ref, ok, err, sizeof err) != 0) { rc = kvlangBuiltinSetErr(f, "%s", err); free(ok); break; }
+ kvlangXvalue_t mark; kvlangXvalueNewTlv(&mark, ref, (const uint8_t *)"", 0, 1);
+ kvlangKvPair_t p0 = { ok, mark }; kvlangKvSet(f->kv, &p0, 1, err, sizeof err); kvlangXvalueFree(&mark);
+ for (int i = 1; i + 1 < n && rc == 0; i += 2) {
+ char *fname = kvlangXvalueValueString(&in[i]);
+ char *ftype = struct_field_type(decl, fname);
+ if (!ftype) { rc = kvlangBuiltinSetErr(f, "TypeError: struct %s has no field %s", ref, fname); free(fname); break; }
+ const char *vk = kvlangXvalueKind(&in[i + 1]);
+ kvspaceHead_t vh; kvlangXvalueHead(&in[i + 1], &vh);
+ kvlang_kindexpr_t vkx; kvlang_kindexpr_parse(vh.kindexpr, &vkx);
+ if (ftype[0] && !kvlang_rwirextKindexprMatch(ftype, vk, vkx.ndim, vkx.dims)) {
+ rc = kvlangBuiltinSetErr(f, "TypeError: field %s: expected %s, got %s", fname, ftype, vk[0] ? vk : "None");
+ free(ftype); free(fname); break;
+ }
+ char *mk = kvlangKeytreeMember(ok, fname);
+ kvlangKvPair_t p = { mk, in[i + 1] }; kvlangKvSet(f->kv, &p, 1, err, sizeof err);
+ free(mk); free(ftype); free(fname);
+ }
+ free(ok);
+ }
+ free(fr); free(decl); free(ref);
+ kvlangBuiltinFreeInputs(in, n);
+ if (rc != 0) return rc;
+ kvlangBuiltinNextPc(f); return 0;
+}
+
int kvlangBuiltinMap(kvlangFrame_t *f) {
kvlangXvalue_t in[64]; int n = kvlangBuiltinReadInputs(f, in, 64);
char *fr = kvlangKeytreeFrameRoot(f->pc);
diff --git a/runtime/src/builtin_internal.h b/runtime/src/builtin_internal.h
index cc452725..a6ed9996 100644
--- a/runtime/src/builtin_internal.h
+++ b/runtime/src/builtin_internal.h
@@ -20,7 +20,7 @@ int kvlangBuiltinArray(kvlangFrame_t *f), kvlangBuiltinNdarrayNumel(kvlangFrame_
kvlangBuiltinXvAt(kvlangFrame_t *f), kvlangBuiltinXvSet(kvlangFrame_t *f), kvlangBuiltinXvReshape(kvlangFrame_t *f), kvlangBuiltinXvReinterpret(kvlangFrame_t *f),
kvlangBuiltinXvKindexpr(kvlangFrame_t *f), kvlangBuiltinXvBodylen(kvlangFrame_t *f),
kvlangBuiltinScatter(kvlangFrame_t *f), kvlangBuiltinCompact(kvlangFrame_t *f),
- kvlangBuiltinAppend(kvlangFrame_t *f), kvlangBuiltinSlice(kvlangFrame_t *f), kvlangBuiltinObj(kvlangFrame_t *f), kvlangBuiltinMap(kvlangFrame_t *f), kvlangBuiltinStringSet(kvlangFrame_t *f),
+ kvlangBuiltinAppend(kvlangFrame_t *f), kvlangBuiltinSlice(kvlangFrame_t *f), kvlangBuiltinObj(kvlangFrame_t *f), kvlangBuiltinMap(kvlangFrame_t *f), kvlangBuiltinStructNew(kvlangFrame_t *f), kvlangBuiltinStringSet(kvlangFrame_t *f),
kvlangBuiltinStringChar(kvlangFrame_t *f), kvlangBuiltinStringOrd(kvlangFrame_t *f), kvlangBuiltinStringCmp(kvlangFrame_t *f),
kvlangBuiltinStringFind(kvlangFrame_t *f), kvlangBuiltinStringLen(kvlangFrame_t *f), kvlangBuiltinStringSlice(kvlangFrame_t *f),
kvlangBuiltinStringConcat(kvlangFrame_t *f),
@@ -31,8 +31,8 @@ int kvlangBuiltinArray(kvlangFrame_t *f), kvlangBuiltinNdarrayNumel(kvlangFrame_
kvlangBuiltinDurArith(kvlangFrame_t *f), kvlangBuiltinDurCmp(kvlangFrame_t *f), kvlangBuiltinTimeCmp(kvlangFrame_t *f),
kvlangBuiltinRandUint64(kvlangFrame_t *f), kvlangBuiltinRandInt63(kvlangFrame_t *f), kvlangBuiltinRandIntn(kvlangFrame_t *f),
kvlangBuiltinKvGet(kvlangFrame_t *f), kvlangBuiltinKvSet(kvlangFrame_t *f), kvlangBuiltinKvDel(kvlangFrame_t *f),
- kvlangBuiltinKvDelTree(kvlangFrame_t *f), kvlangBuiltinKvList(kvlangFrame_t *f), kvlangBuiltinKvListLen(kvlangFrame_t *f), kvlangBuiltinKvListN(kvlangFrame_t *f), kvlangBuiltinKvMkindex(kvlangFrame_t *f),
- kvlangBuiltinKvExtIndex(kvlangFrame_t *f), kvlangBuiltinKvRmIndexExt(kvlangFrame_t *f), kvlangBuiltinKvWatch(kvlangFrame_t *f),
+ kvlangBuiltinKvDelTree(kvlangFrame_t *f), kvlangBuiltinKvCp(kvlangFrame_t *f), kvlangBuiltinKvCpTree(kvlangFrame_t *f), kvlangBuiltinKvCpList(kvlangFrame_t *f), kvlangBuiltinKvList(kvlangFrame_t *f), kvlangBuiltinKvListLen(kvlangFrame_t *f), kvlangBuiltinKvListN(kvlangFrame_t *f), kvlangBuiltinKvMkindex(kvlangFrame_t *f),
+ kvlangBuiltinKvExtIndex(kvlangFrame_t *f), kvlangBuiltinKvRmIndexExt(kvlangFrame_t *f), kvlangBuiltinKvWatch(kvlangFrame_t *f), kvlangBuiltinKvAbs(kvlangFrame_t *f),
kvlangBuiltinDebugger(kvlangFrame_t *f), kvlangBuiltinVthreadCreate(kvlangFrame_t *f),
kvlangBuiltinVthreadRun(kvlangFrame_t *f),
kvlangBuiltinVthreadCall(kvlangFrame_t *f), kvlangBuiltinVthreadSleep(kvlangFrame_t *f),
diff --git a/runtime/src/builtin_kv.c b/runtime/src/builtin_kv.c
index 0072ef23..d3d06dff 100644
--- a/runtime/src/builtin_kv.c
+++ b/runtime/src/builtin_kv.c
@@ -21,10 +21,19 @@ static char *path_arg(kvlangFrame_t *f, int idx, const kvlangXvalue_t *in) {
return NULL;
}
+/* 容器 base:object/map/index/extindex 或 struct 实例(kind=structref,以 / 起头)。
+ * 容器取其写槽路径拼成员 key;非容器把 base 值当 key 串。 */
+static bool base_is_container(const kvlangXvalue_t *base) {
+ if (kvlangXvalueNone(base)) return true;
+ const char *k = kvlangXvalueKind(base);
+ return k[0] == '/' || strcmp(k, KVSPACE_KIND_OBJ) == 0 || strcmp(k, KVSPACE_KIND_MAP) == 0 ||
+ strcmp(k, KVSPACE_KIND_INDEX) == 0 || strcmp(k, KVSPACE_KIND_EXT_INDEX) == 0;
+}
+
static char *member_path(kvlangFrame_t *f, const kvlangXvalue_t *in, int n) {
const kvlangXvalue_t *base = &in[0];
char *fr = kvlangKeytreeFrameRoot(f->pc);
- char *bp = kvlangXvalueNone(base) || (strcmp(kvlangXvalueKind(base), KVSPACE_KIND_OBJ) == 0 || strcmp(kvlangXvalueKind(base), KVSPACE_KIND_MAP) == 0 || strcmp(kvlangXvalueKind(base), KVSPACE_KIND_INDEX) == 0 || strcmp(kvlangXvalueKind(base), KVSPACE_KIND_EXT_INDEX) == 0) ? kvlangBuiltinResolveWriteSlot(f->kv, fr, f->inst->reads[0].name) : kvlangXvalueValueString(base);
+ char *bp = base_is_container(base) ? kvlangBuiltinResolveWriteSlot(f->kv, fr, f->inst->reads[0].name) : kvlangXvalueValueString(base);
free(fr);
/* 成员链:base 之后逐段拼 key(变参),每段可为静态字面量或动态键(运行时值)。 */
for (int i = 1; i < n; i++) {
@@ -74,6 +83,43 @@ int kvlangBuiltinKvDel(kvlangFrame_t *f) { return kv_path_void(f, "kv.del", kvla
int kvlangBuiltinKvDelTree(kvlangFrame_t *f) { return kv_path_void(f, "kv.deltree", kvlangKvDelTree); }
+/* 绝对路径 / 路径字符串直取,否则裸标识符解析为本帧槽位 key(对齐 kv.list 的裸变量处理)。 */
+static char *resolve_path_arg(kvlangFrame_t *f, int idx, const kvlangXvalue_t *in) {
+ char *p = path_arg(f, idx, in);
+ if (p) return p;
+ char *fr = kvlangKeytreeFrameRoot(f->pc);
+ char *base = kvlangBuiltinResolveWriteSlot(f->kv, fr, f->inst->reads[idx].name);
+ free(fr);
+ return base;
+}
+
+static int kv_two_path_void(kvlangFrame_t *f, const char *name,
+ int (*op)(kvlangKv_t *, const char *, const char *, char *, uint32_t)) {
+ kvlangXvalue_t in[2]; int n = kvlangBuiltinReadInputs(f, in, 2);
+ char *src = n >= 1 ? resolve_path_arg(f, 0, in) : NULL;
+ char *dst = n >= 2 ? resolve_path_arg(f, 1, in) : NULL;
+ if (!src || !dst) { free(src); free(dst); kvlangBuiltinFreeInputs(in, n); return kvlangBuiltinSetErr(f, "TypeError: %s requires src,dst path args", name); }
+ char err[256]; int rc = op(f->kv, src, dst, err, sizeof err);
+ free(src); free(dst); kvlangBuiltinFreeInputs(in, n);
+ if (rc != 0) return kvlangBuiltinSetErr(f, "%s", err);
+ kvlangBuiltinNextPc(f); return 0;
+}
+
+int kvlangBuiltinKvCp(kvlangFrame_t *f) { return kv_two_path_void(f, "kv.cp", kvlangKvCp); }
+
+int kvlangBuiltinKvCpTree(kvlangFrame_t *f) { return kv_two_path_void(f, "kv.cpdir", kvlangKvCpTree); }
+
+int kvlangBuiltinKvCpList(kvlangFrame_t *f) { return kv_two_path_void(f, "kv.cplist", kvlangKvCpList); }
+
+int kvlangBuiltinKvAbs(kvlangFrame_t *f) {
+ kvlangXvalue_t in[1]; int n = kvlangBuiltinReadInputs(f, in, 1);
+ char *p = n >= 1 ? resolve_path_arg(f, 0, in) : NULL;
+ if (!p) { kvlangBuiltinFreeInputs(in, n); return kvlangBuiltinSetErr(f, "TypeError: kv.abs requires a key"); }
+ kvlangXvalue_t r; kvlangXvalueNewCharUtf32(&r, p);
+ int rc = kvlangBuiltinWriteResult(f, &r); kvlangXvalueFree(&r);
+ free(p); kvlangBuiltinFreeInputs(in, n); return rc;
+}
+
int kvlangBuiltinKvList(kvlangFrame_t *f) {
if (f->inst->nw == 0) return kvlangBuiltinSetErr(f, "TypeError: kv.list requires a write param");
kvlangXvalue_t in[1]; int n = kvlangBuiltinReadInputs(f, in, 1);
@@ -184,7 +230,16 @@ int kvlangBuiltinKvListN(kvlangFrame_t *f) {
return rc;
}
-int kvlangBuiltinKvMkindex(kvlangFrame_t *f) { return kv_path_void(f, "kv.mkindex", kvlangKvMkindex); }
+int kvlangBuiltinKvMkindex(kvlangFrame_t *f) {
+ kvlangXvalue_t in[2]; int n = kvlangBuiltinReadInputs(f, in, 2);
+ char *key = n >= 1 ? path_arg(f, 0, in) : NULL;
+ if (!key) { kvlangBuiltinFreeInputs(in, n); return kvlangBuiltinSetErr(f, "TypeError: kv.mkindex requires a path"); }
+ uint32_t capacity = n >= 2 ? (uint32_t)kvlangXvalueAsInt64(&in[1]) : 0;
+ char err[256]; int rc = kvlangKvMkindex(f->kv, key, capacity, err, sizeof err);
+ free(key); kvlangBuiltinFreeInputs(in, n);
+ if (rc != 0) return kvlangBuiltinSetErr(f, "%s", err);
+ kvlangBuiltinNextPc(f); return 0;
+}
int kvlangBuiltinKvExtIndex(kvlangFrame_t *f) {
kvlangXvalue_t in[2]; int n = kvlangBuiltinReadInputs(f, in, 2);
diff --git a/runtime/src/const.h b/runtime/src/const.h
index 7ecbdc03..4e5d5ad7 100644
--- a/runtime/src/const.h
+++ b/runtime/src/const.h
@@ -27,9 +27,9 @@
#define KVSPACE_KIND_RWIR "rwir"
#define KVSPACE_KIND_RWFUNC "rwfunc"
#define KVSPACE_KIND_DEF_RWIR "defrwir"
-#define KVSPACE_KIND_DEF_RWFUNC "defrwfunc"
#define KVSPACE_KIND_RWIR_OR_RWFUNC "rwir|rwfunc"
#define KVSPACE_KIND_SCOPE "scope"
+#define KVSPACE_KIND_STRUCT "struct"
#define KVSPACE_KIND_TIME "time"
#define KVSPACE_KIND_DURATION "duration"
diff --git a/runtime/src/kindexpr.c b/runtime/src/kindexpr.c
index 7509a724..57e9e3ce 100644
--- a/runtime/src/kindexpr.c
+++ b/runtime/src/kindexpr.c
@@ -31,10 +31,31 @@ static bool known_kind(const char *s, size_t len) {
kind_eq(s, len, KVSPACE_KIND_OBJ) || kind_eq(s, len, KVSPACE_KIND_MAP) ||
kind_eq(s, len, KVSPACE_KIND_INDEX) || kind_eq(s, len, KVSPACE_KIND_EXT_INDEX) ||
kind_eq(s, len, KVSPACE_KIND_RWIR) || kind_eq(s, len, KVSPACE_KIND_RWFUNC) ||
- kind_eq(s, len, KVSPACE_KIND_SCOPE) || kind_eq(s, len, KVSPACE_KIND_TIME) ||
+ kind_eq(s, len, KVSPACE_KIND_SCOPE) || kind_eq(s, len, KVSPACE_KIND_STRUCT) ||
+ kind_eq(s, len, KVSPACE_KIND_TIME) ||
kind_eq(s, len, KVSPACE_KIND_DURATION);
}
+/* structref = "/" path:指向 /lib 下 struct 定义节点的完整路径(实例 kind / 字段类型)。
+ * 仅语法承认(`/` + 合法路径段),存在性/字段一致性留给 runtime 判定。 */
+static bool valid_structref(const char *s, size_t len) {
+ if (len < 2 || s[0] != '/') return false;
+ size_t seg = 0;
+ for (size_t i = 1; i < len; i++) {
+ if (s[i] == '/') {
+ if (seg == 0) return false;
+ seg = 0;
+ continue;
+ }
+ char c = s[i];
+ if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
+ (c >= '0' && c <= '9') || c == '_'))
+ return false;
+ seg++;
+ }
+ return seg > 0;
+}
+
/* base = any | kind(kind 为精确合法 kind 串) */
static bool valid_base(const char *s, size_t len) {
if (len == 0) return false;
@@ -63,9 +84,10 @@ static bool valid_dims(const char *s, size_t len) {
return true;
}
-/* atom = [dims] base */
+/* atom = [dims] base | structref */
static bool valid_atom(const char *s, size_t len) {
if (len == 0) return false;
+ if (s[0] == '/') return valid_structref(s, len);
const char *p = s;
if (*p == '[') {
const char *end = memchr(p, ']', len);
diff --git a/runtime/src/kv.c b/runtime/src/kv.c
index 91122dd1..4c2e7ef9 100644
--- a/runtime/src/kv.c
+++ b/runtime/src/kv.c
@@ -64,7 +64,7 @@ int kvlangKvSet(kvlangKv_t *k, const kvlangKvPair_t *pairs, int n, char *err, ui
const uint8_t *body = v->data + h.body_offset;
uint8_t *dst = NULL;
if (kvspaceWriteInPlace(k->h, pairs[i].key, 1, body_len, &dst, err, err_cap) != 0) {
- if (kvspaceWriteNewPlace(k->h, pairs[i].key, (const char *)h.kindexpr, body_len, &dst, err, err_cap) != 0)
+ if (kvspaceWriteNewPlace(k->h, pairs[i].key, h.xkind, (const char *)h.kindexpr, body_len, &dst, err, err_cap) != 0)
return -1;
}
if (body_len > 0 && dst) memcpy(dst, body, body_len);
@@ -81,8 +81,20 @@ int kvlangKvDelTree(kvlangKv_t *k, const char *prefix, char *err, uint32_t err_c
return kvspaceDelTree(k->h, prefix, err, err_cap);
}
-int kvlangKvMkindex(kvlangKv_t *k, const char *path, char *err, uint32_t err_cap) {
- return kvspaceMkindex(k->h, path, err, err_cap);
+int kvlangKvCp(kvlangKv_t *k, const char *src, const char *dst, char *err, uint32_t err_cap) {
+ return kvspaceCp(k->h, src, dst, err, err_cap);
+}
+
+int kvlangKvCpTree(kvlangKv_t *k, const char *src, const char *dst, char *err, uint32_t err_cap) {
+ return kvspaceCpTree(k->h, src, dst, err, err_cap);
+}
+
+int kvlangKvCpList(kvlangKv_t *k, const char *src, const char *dst, char *err, uint32_t err_cap) {
+ return kvspaceCpList(k->h, src, dst, err, err_cap);
+}
+
+int kvlangKvMkindex(kvlangKv_t *k, const char *path, uint32_t capacity, char *err, uint32_t err_cap) {
+ return kvspaceMkindex(k->h, path, capacity, err, err_cap);
}
int kvlangKvExtIndex(kvlangKv_t *k, const char *path, const char *ext, char *err, uint32_t err_cap) {
@@ -102,9 +114,9 @@ int kvlangKvList(kvlangKv_t *k, const char *prefix, bool expand_ext, bool resolv
if (count <= 0) return 0;
char **names = malloc(sizeof(char *) * (size_t)count);
for (int32_t i = 0; i < count; i++) {
- uint8_t *d = NULL; uint32_t len = 0;
- if (kvspaceListAt(k->h, prefix, ex, rs, i, &d, &len) == 0 && d)
- names[i] = strndup((const char *)d, len);
+ uint8_t buf[1024]; uint32_t len = 0;
+ if (kvspaceListAt(k->h, prefix, ex, rs, i, buf, sizeof buf, &len) == 0)
+ names[i] = strndup((const char *)buf, len);
else
names[i] = strdup("");
}
diff --git a/runtime/src/kvcpu.c b/runtime/src/kvcpu.c
index 4d9cf415..026190e3 100644
--- a/runtime/src/kvcpu.c
+++ b/runtime/src/kvcpu.c
@@ -241,7 +241,7 @@ static char *handle_call(kvlangKv_t *kv, const char *pc, kvlangRwirInst_t *inst)
kvlangStrbufPrintf(&sk, "%s/[0,0]", cand);
kvlangXvalue_t sv; kvlangXvalueZero(&sv);
kvlangKvGetOne(kv, sk.p, &sv);
- bool ok = !kvlangXvalueNone(&sv) && kvlangXvalueKindIs(&sv, KVSPACE_KIND_DEF_RWFUNC);
+ bool ok = !kvlangXvalueNone(&sv) && kvlangXvalueKindIs(&sv, KVSPACE_KIND_RWFUNC);
kvlangXvalueFree(&sv); kvlangStrbufFree(&sk);
if (ok) { free(pkg); pkg = cand_pkg; }
else free(cand_pkg);
@@ -261,7 +261,7 @@ static char *handle_call(kvlangKv_t *kv, const char *pc, kvlangRwirInst_t *inst)
kvlangStrbufPrintf(&sig_key, "%s[0,0]", func_dir.p);
kvlangXvalue_t sig; kvlangXvalueZero(&sig);
kvlangKvGetOne(kv, sig_key.p, &sig);
- if (kvlangXvalueNone(&sig) || !kvlangXvalueKindIs(&sig, KVSPACE_KIND_DEF_RWFUNC)) {
+ if (kvlangXvalueNone(&sig) || !kvlangXvalueKindIs(&sig, KVSPACE_KIND_RWFUNC)) {
/* 按 xvalue 的 kind 精确区分缺 rwir 还是缺 rwfunc:
* 到这里说明 opcode 已被 isothersrwir 判否(/lib/ 非 rwir)。 */
char *rk = kvlangKeytreeRwir(fn);
@@ -298,7 +298,7 @@ static char *handle_call(kvlangKv_t *kv, const char *pc, kvlangRwirInst_t *inst)
char err[256];
kvlangKvDelTree(kv, frame_root, err, sizeof err);
char *stack_fr = kvlangKeytreeStack(frame_root);
- kvlangKvMkindex(kv, stack_fr, err, sizeof err);
+ kvlangKvMkindex(kv, stack_fr, 0, err, sizeof err);
kvlangKvExtIndex(kv, stack_fr, func_dir.p, err, sizeof err);
/* 系统变量 */
@@ -421,7 +421,13 @@ static int handle_control(kvlangKv_t *kv, const char *vtid, const char *pc, kvla
kvlangXvalueFree(&cond);
return -1;
}
- bool taken = kvlangXvalueAsBool(&cond);
+ if (!kvlangXvalueKindIs(&cond, KVSPACE_KIND_BOOL)) {
+ char msg[128]; snprintf(msg, sizeof msg, "TypeError: branch condition must be bool, got %s", kvlangXvalueKind(&cond));
+ kvlangVthreadSetError(kv, vtid, pc, msg);
+ kvlangXvalueFree(&cond);
+ return -1;
+ }
+ bool taken = kvlangXvalueAsInt64(&cond) != 0;
kvlangXvalueFree(&cond);
return jump_to(kv, vtid, pc, &inst->reads[taken ? 1 : 2], OP_BR);
}
@@ -488,7 +494,7 @@ char *kvlangKvcpuBootstrap(kvlangKv_t *kv, const char *vtid, const char *funcnam
kvlangStrbufPrintf(&sig_key, "%s[0,0]", func_dir.p);
kvlangXvalue_t sig; kvlangXvalueZero(&sig);
kvlangKvGetOne(kv, sig_key.p, &sig);
- if (kvlangXvalueNone(&sig) || !kvlangXvalueKindIs(&sig, KVSPACE_KIND_DEF_RWFUNC)) {
+ if (kvlangXvalueNone(&sig) || !kvlangXvalueKindIs(&sig, KVSPACE_KIND_RWFUNC)) {
char msg[256]; snprintf(msg, sizeof msg, "Bootstrap: rwir/rwfunc not found: %s", funcname);
kvlangVthreadSetError(kv, vtid, "", msg);
kvlangXvalueFree(&sig); kvlangStrbufFree(&sig_key); kvlangStrbufFree(&func_dir);
@@ -502,7 +508,7 @@ char *kvlangKvcpuBootstrap(kvlangKv_t *kv, const char *vtid, const char *funcnam
char *frame_root = kvlangKeytreeFrameAt(vtid, 1);
char *stack_fr = kvlangKeytreeStack(frame_root);
char err[256];
- kvlangKvMkindex(kv, stack_fr, err, sizeof err);
+ kvlangKvMkindex(kv, stack_fr, 0, err, sizeof err);
kvlangKvExtIndex(kv, stack_fr, func_dir.p, err, sizeof err);
char *ep = kvlangKeytreeEntryPc(frame_root);
diff --git a/runtime/src/runtime.c b/runtime/src/runtime.c
index ba2a2192..7c958b03 100644
--- a/runtime/src/runtime.c
+++ b/runtime/src/runtime.c
@@ -85,7 +85,7 @@ char *kvlangVthreadSpawn(kvlangKv_t *kv, const char *funcname,
kvlangKeytreeVthread(vtid, &vtroot);
char *stack_vt = kvlangKeytreeStack(vtroot.p);
char e[256];
- kvlangKvMkindex(kv, stack_vt, e, sizeof e);
+ kvlangKvMkindex(kv, stack_vt, 0, e, sizeof e);
char *first_pc = kvlangKvcpuBootstrap(kv, vtid, funcname, args, nargs);
if (!first_pc) {
free(stack_vt);
diff --git a/runtime/src/runtime_internal.h b/runtime/src/runtime_internal.h
index 6ad89548..a83a7f15 100644
--- a/runtime/src/runtime_internal.h
+++ b/runtime/src/runtime_internal.h
@@ -11,13 +11,23 @@
/* ── kvspace-durable C ABI ─────────────────────────────────────────── */
typedef struct {
- uint8_t kindexpr[256]; /* NUL 终止(含 ref 前缀与 [dims],去 padding) */
+ uint8_t xkind; /* 五分类:0=None 1=Ptr 2=ExtValue 3=DefKindexpr 4=RealValue */
+ uint8_t kindexpr[256]; /* NUL 终止(含 [dims]、无前缀,去 padding) */
+ int32_t kind_off; /* base 种类在 kindexpr 内的起始字节偏移 */
+ int32_t ndim; /* 维数(标量=0) */
+ int32_t dims[8]; /* 各维长度(X_MAX_NDIM=8) */
uint8_t ro; /* 1=只读,0=可写 */
uint32_t vid; /* vthread id */
int32_t body_len; /* body 字节数 */
int32_t body_offset; /* body 在 data 内的起始偏移(= head_len) */
} kvspaceHead_t;
+#define KVSPACE_XKIND_NONE 0
+#define KVSPACE_XKIND_PTR 1
+#define KVSPACE_XKIND_EXTVALUE 2
+#define KVSPACE_XKIND_DEFKINDEXPR 3
+#define KVSPACE_XKIND_REALVALUE 4
+
extern void *kvspaceConnect(const char *dsn);
extern void kvspaceClose(void *h);
/* 借用读:*out 指向后端常驻/回收空间,调用方不得 free。resolve=1 穿透 link。 */
@@ -25,16 +35,19 @@ extern int kvspaceGet(void *h, const char *key, int resolve, uint8_t **out, ui
/* 就地写:key 已存在、body_len==原 body_len → 返回原 box body 偏移指针;否则非 0 + err。 */
extern int kvspaceWriteInPlace(void *h, const char *key, int resolve, uint32_t body_len,
uint8_t **body, char *err, uint32_t err_cap);
-/* 新位置写:按 (kindexpr, body_len) 分配新 box、写 head,返回 body 偏移指针。 */
-extern int kvspaceWriteNewPlace(void *h, const char *key, const char *kindexpr, uint32_t body_len,
- uint8_t **body, char *err, uint32_t err_cap);
+/* 新位置写:按 (xkind, kindexpr, body_len) 分配新 box、写 head,返回 body 偏移指针。 */
+extern int kvspaceWriteNewPlace(void *h, const char *key, uint8_t xkind, const char *kindexpr,
+ uint32_t body_len, uint8_t **body, char *err, uint32_t err_cap);
/* 前缀遍历:listlen 定计数,逐 idx 取名(借用回收缓冲,不得 free),不一次性返回整段名单。 */
extern int kvspaceListLen(void *h, const char *prefix, int expand_ext, int resolve, int32_t *out_count);
extern int kvspaceListAt(void *h, const char *prefix, int expand_ext, int resolve, int32_t idx,
- uint8_t **out, uint32_t *out_len);
+ uint8_t *buf, uint32_t buf_cap, uint32_t *out_len);
extern int kvspaceDel(void *h, const char *const *keys, uint32_t nkeys, char *err, uint32_t err_cap);
extern int kvspaceDelTree(void *h, const char *prefix, char *err, uint32_t err_cap);
-extern int kvspaceMkindex(void *h, const char *path, char *err, uint32_t err_cap);
+extern int kvspaceCp(void *h, const char *src, const char *dst, char *err, uint32_t err_cap);
+extern int kvspaceCpTree(void *h, const char *src, const char *dst, char *err, uint32_t err_cap);
+extern int kvspaceCpList(void *h, const char *src, const char *dst, char *err, uint32_t err_cap);
+extern int kvspaceMkindex(void *h, const char *path, uint32_t capacity, char *err, uint32_t err_cap);
extern int kvspaceMkindexExt(void *h, const char *path, const char *ext_path, char *err, uint32_t err_cap);
extern int kvspaceRmindexExt(void *h, const char *path, char *err, uint32_t err_cap);
extern int kvspaceWatch(void *h, const char *key, const uint8_t *target, uint32_t target_len,
@@ -60,7 +73,6 @@ extern int kvspaceNewFloat64(double v, uint8_t **out, uint32_t *out_len);
typedef struct {
const char *kind; /* base kind(kindexpr 子串,非 NUL 终止) */
int32_t kind_len;
- int32_t ref; /* 0=内联 1=指针 2=扩展句柄 */
int32_t ndim;
int32_t dims[X_MAX_NDIM];
int32_t array_len;
@@ -113,7 +125,6 @@ bool kvlang_rwirextKindexprVariadic(const char *expr);
int64_t kvlangXvalueAsInt64(const kvlangXvalue_t *v);
double kvlangXvalueAsFloat64(const kvlangXvalue_t *v);
uint64_t kvlangXvalueAsUint64(const kvlangXvalue_t *v);
-bool kvlangXvalueAsBool(const kvlangXvalue_t *v);
uint32_t kvlangXvalueChar32At(const kvlangXvalue_t *v, int32_t idx);
int32_t kvlangXvalueElemSize(const char *kind);
@@ -140,7 +151,10 @@ int kvlangKvGetMember(kvlangKv_t *k, const char *dir, const char *name, kvlangXv
int kvlangKvSet(kvlangKv_t *k, const kvlangKvPair_t *pairs, int n, char *err, uint32_t err_cap);
int kvlangKvDel(kvlangKv_t *k, const char *key, char *err, uint32_t err_cap);
int kvlangKvDelTree(kvlangKv_t *k, const char *prefix, char *err, uint32_t err_cap);
-int kvlangKvMkindex(kvlangKv_t *k, const char *path, char *err, uint32_t err_cap);
+int kvlangKvCp(kvlangKv_t *k, const char *src, const char *dst, char *err, uint32_t err_cap);
+int kvlangKvCpTree(kvlangKv_t *k, const char *src, const char *dst, char *err, uint32_t err_cap);
+int kvlangKvCpList(kvlangKv_t *k, const char *src, const char *dst, char *err, uint32_t err_cap);
+int kvlangKvMkindex(kvlangKv_t *k, const char *path, uint32_t capacity, char *err, uint32_t err_cap);
int kvlangKvExtIndex(kvlangKv_t *k, const char *path, const char *ext, char *err, uint32_t err_cap);
int kvlangKvDelExtIndex(kvlangKv_t *k, const char *path, char *err, uint32_t err_cap);
int kvlangKvList(kvlangKv_t *k, const char *prefix, bool expand_ext, bool resolve,
diff --git a/runtime/src/vthread.c b/runtime/src/vthread.c
index 52c708f8..c24bf976 100644
--- a/runtime/src/vthread.c
+++ b/runtime/src/vthread.c
@@ -53,7 +53,7 @@ void kvlangVthreadSetError(kvlangKv_t *kv, const char *vtid, const char *pc, con
kvlangStrbuf_t dir; kvlangStrbufInit(&dir);
kvlangStrbufPutn(&dir, msg_path.p, (size_t)(sep - msg_path.p) + 1);
char err[256];
- kvlangKvMkindex(kv, dir.p, err, sizeof err);
+ kvlangKvMkindex(kv, dir.p, 0, err, sizeof err);
kvlangStrbufFree(&dir);
}
diff --git a/runtime/src/xvalue.c b/runtime/src/xvalue.c
index aea7687d..97287f34 100644
--- a/runtime/src/xvalue.c
+++ b/runtime/src/xvalue.c
@@ -16,13 +16,11 @@ void kvlangXvalueSetBytes(kvlangXvalue_t *v, uint8_t *data, uint32_t len) {
v->data = data; v->len = len;
}
-/* 解析 kindexpr 内容 → (ref, dims, base kind)。kindexpr 为 NUL 终止串。 */
+/* 解析 kindexpr 内容 → (dims, base kind)。kindexpr 为 NUL 终止串、无前缀(ref 归 head.xkind)。 */
void kvlang_kindexpr_parse(const uint8_t *kx, kvlang_kindexpr_t *out) {
memset(out, 0, sizeof(*out));
if (!kx) return;
int32_t i = 0;
- if (kx[0] == '*') { out->ref = 1; i = 1; }
- else if (kx[0] == '@') { out->ref = 2; i = 1; }
if (kx[i] == '[') {
i++;
while (kx[i] != ']' && kx[i] != 0 && out->ndim < X_MAX_NDIM) {
@@ -107,8 +105,7 @@ bool kvlangXvalueIsPtr(const kvlangXvalue_t *v) {
if (kvlangXvalueNone(v)) return false;
kvspaceHead_t h;
if (kvlangXvalueHead(v, &h) < 0) return false;
- kvlang_kindexpr_t kx; kvlang_kindexpr_parse(h.kindexpr, &kx);
- return kx.ref == 1;
+ return h.xkind == KVSPACE_XKIND_PTR;
}
int32_t kvlangXvalueArrayLen(const kvlangXvalue_t *v) {
@@ -204,12 +201,6 @@ uint64_t kvlangXvalueAsUint64(const kvlangXvalue_t *v) {
return (uint64_t)kvlangXvalueAsInt64(v);
}
-bool kvlangXvalueAsBool(const kvlangXvalue_t *v) {
- if (kvlangXvalueNone(v)) return false;
- kvspaceHead_t h; const uint8_t *b = v_body(v, &h);
- return b && h.body_len > 0 && b[0] != 0;
-}
-
uint32_t kvlangXvalueChar32At(const kvlangXvalue_t *v, int32_t idx) {
kvspaceHead_t h; const uint8_t *b = v_body(v, &h);
if (!b) return 0;
@@ -275,9 +266,8 @@ char *kvlangXvalueValueString(const kvlangXvalue_t *v) {
if (!body) return strdup(KVSPACE_KIND_NONE);
int32_t blen = h.body_len;
const char *k = kvlangXvalueKind(v);
- kvlang_kindexpr_t kx; kvlang_kindexpr_parse(h.kindexpr, &kx);
- if (kx.ref == 1) {
+ if (h.xkind == KVSPACE_XKIND_PTR) {
kvlangStrbuf_t b; kvlangStrbufInit(&b);
kvlangStrbufPutn(&b, "\xE2\x86\x92", 3);
kvlangStrbufPutn(&b, (const char *)body, (size_t)blen);
@@ -311,9 +301,9 @@ char *kvlangXvalueValueString(const kvlangXvalue_t *v) {
if (strcmp(k, KVSPACE_KIND_MAP) == 0) {
kvlangStrbuf_t b; kvlangStrbufInit(&b);
kvlangStrbufPuts(&b, "map[");
- for (int d = 0; d < kx.ndim; d++) {
+ for (int d = 0; d < h.ndim; d++) {
if (d) kvlangStrbufPutc(&b, ',');
- kvlangStrbufPrintf(&b, "%d", kx.dims[d]);
+ kvlangStrbufPrintf(&b, "%d", h.dims[d]);
}
kvlangStrbufPutc(&b, ']');
return kvlangStrbufDetach(&b);
diff --git a/site/src/highlight.ts b/site/src/highlight.ts
index a5199e66..4a92b7bd 100644
--- a/site/src/highlight.ts
+++ b/site/src/highlight.ts
@@ -6,7 +6,6 @@ const KEYWORDS = new Set([
"rwfunc",
"rwir",
"defrwir",
- "defrwfunc",
"while",
"if",
"else",
diff --git a/stdlib/kvlang/deepdive/01-storage-compute-separation-kv-tree.kv b/stdlib/kvlang/deepdive/01-storage-compute-separation-kv-tree.kv
deleted file mode 100644
index a4f755e6..00000000
--- a/stdlib/kvlang/deepdive/01-storage-compute-separation-kv-tree.kv
+++ /dev/null
@@ -1,68 +0,0 @@
-// 欢迎加入kvspace世界
-lib kvlang/deepdive/01_storage_compute_separation_kv_tree {
- r#"# 存、算、控制流严格分离的 kv 树计算架构
-
-
-## 存、算、控制流严格分离
-
-kvlang 架构的顶层公理:**存储、计算、控制流三者严格分离,各司其职。**
-
-| 层 | 职责 | 载体 | 说明 |
-|----|------|------|------|
-| **存储** | 持有所有代码、数据、执行状态 | kvspace 树形路径 | 元存:kvspace 核心能力,管理 slot/索引/系统变量/指令树/帧栈 |
-| **计算** | 执行算子、张量运算 | op-plat(GPU/CPU 算子) | 不持有状态,只消费存储层的数据、产出写回存储层 |
-| **控制流** | 调度、跳转、调用/返回 | kvcpu(PC 路径导航) | 不产生数据,只改变 PC 在存储树中的位置 |
-
-与传统架构的对比:
-
-| | 传统 VM | kvlang |
-|--|---------|--------|
-| 存储 | 栈+堆+全局段,混在内存中 | **kvspace 树**,统一的路径地址空间 |
-| 计算 | 指令内联(ALU op + 寻址) | **rwir `<-`/`->`**:显式读参写参,计算与寻址解耦 |
-| 控制流 | PC 整数偏移,与数据同空间 | **PC = KV 路径字符串**,控制流即树导航 |
-
-分离的成果:崩溃恢复只需 PC 路径(已存 KV);算子可独立替换;调试只需 `kvspace tree` 静态观察存储树,无需 attach 进程。
-
-### 存储再分:元存与扩展存储
-
-存储层内部进一步分为两层:
-
-| 存储层 | 存放内容 | 管理方 | 可见性 |
-|--------|---------|--------|--------|
-| **元存** | slot、索引、系统变量、指令树、帧栈、lib 签名 | **kvspace**(Redis/内存 KV) | **全局公有**:任意 kvspace 连接者均可读写 |
-| **扩展存储** | tensor data(权重、激活值、梯度) | heap-plat / op-plat | **连接者私有**:仅直连该存储的节点可访问 |
-
-二者关系:
-
-```
-kvspace 元存(slot → XValue)
- ├── 基础类型:int/float/bool/string/bytes → XValue.raw 自包含
- └── tensor 类型:XValue 只存元数据(shape + dtype + 扩展存储句柄)
- ↓ 句柄指向
- 扩展存储(tensor data 本体,不在 kvspace 内)
-```
-
-**元存全局公有**:任意节点直连 kvspace 即可读写任意 slot,所有 worker 共享同一份代码(`/lib/`)与执行状态(`/vthread/`),无需独立调度器元数据中心。
-
-**扩展存储连接者私有**:GPU 显存、本地 shm 仅直连进程可访问,跨卡 tensor 搬运由 op-plat 显式管理(AllReduce/all-to-all 等)。
-
-**铁律**:kvspace 只存 tensor 元数据与扩展存储句柄,不存 tensor 原始数据。
-
-### XValue 整存整取铁律
-
-**XValue 是 kvspace 存储的原子单位,只能整存整取——禁止对单个 XValue 的 raw 做部分读写。**
-
-- **禁止部分读**:不得按字节偏移读 XValue.raw 的片段。
-- **禁止部分写**:不得按字节偏移写 XValue.raw 的片段。
-
-数组元素访问因此只有两条路,二者都保持整存整取:
-
-| 存储形态 | head kind | 元素访问 | 是否整存整取 |
-|---------|-----------|---------|-------------|
-| compact 形态 | 元素类型(`int32`,`[10]int32`) | 整读单个 XValue,内存内下标 | 是(一次整读) |
-| stringkeymap 形态(散 key) | `stringkeymap`(`{1,2,3}`) | 每元素是独立子 key `base·i` 的标量 XValue | 是(每个 key 一个整 XValue) |
-
-理由:原子单位从"raw 字节区间"上移到"XValue",使每次读写均为单 key 的原子替换,消除并发 RMW 竞态,与"元存全局公有"定位一致。
-
-"# -> /lib/kvlang/deepdive/01_storage_compute_separation_kv_tree
-}
diff --git a/stdlib/kvlang/deepdive/02-everything-is-plaintext.kv b/stdlib/kvlang/deepdive/02-everything-is-plaintext.kv
deleted file mode 100644
index a561a175..00000000
--- a/stdlib/kvlang/deepdive/02-everything-is-plaintext.kv
+++ /dev/null
@@ -1,42 +0,0 @@
-// 欢迎加入kvspace世界
-lib kvlang/deepdive/02_everything_is_plaintext {
- r#"# 一切皆明文
-
-## 一切皆明文
-
-传统 VM:PC 是整数、指令是字节码、指针是内存地址、类型在编译期丢失、调试需要反汇编器。kvlang 相反:**一切关键信息以明文字符串存于 kvspace 树**,`kvspace tree`/`kvspace get` 即完整系统自省。
-
-目标:让程序对人与 agent 彻底透明——人用 `kvspace tree` 直读,agent 用 `kv.Get` 程序读,同一份数据,零中间层。
-
-### 路径即 PC、指针、地址
-
-```
-传统:PC = 0x7fff5fbff830 指针 = 0x7fff9b3c 变量 = rbp-8
-kvlang:PC = "/vthread/run/[0,0]/[1,0]/[0,0]" 指针 = "/n0" 变量 = 帧根 + "/x"
-```
-
-PC 字符串即调用栈(路径深度 = 栈深度)。裸名即相对指针,`/` 开头即绝对指针。不存在 `&` 取址——变量名本身就是该变量的 kvspace 路径。`"/n0" -> p; p.next` 的值是路径字符串,`kvspace get` 直读。
-
-### 指令与调用:字符串 opcode,全路径调用
-
-```
-传统:B8 01 00 00 00 (mov eax, 1) 调用 = call 0x400200 (符号表间接)
-kvlang:[0,0]="+" [0,-1]="A" [0,1]="C" 调用 = /lib/math·sum(3, 4) -> s
-```
-
-opcode 是 `"+"` `"print"` `"call"` 字符串,`kvspace tree /lib/func` 即反汇编。lib 树即全局命名空间——调用即全路径,无 import/符号表/链接器重定位。
-
-### 类型与状态:kind 自描述,`/.` 暴露一切
-
-```
-传统:运行时值 = 裸字节 系统状态 = 需 ptrace
-kvlang:XValue 带 kind "int64" /vthread/7/.pc .status .rootfunc 直接 Get
-```
-
-`kvspace get /x` 返回 `int64:42`——类型跟值一起存。VM 内部状态以 `X/.var` 影子键暴露:`.pc` `.status` `.rootfunc` `.rparam` `.wparam`。源码存 `/lib/.*.src` 与指令树同目录。
-
-### 代价与补偿
-
-明文化贯彻到 kvlang 的方方面面——PC 是字符串而非整数、opcode 是 `"+"` 而非单字节、指针是路径而非地址——这天然损失了解释执行的速度。但 kvlang 的定位是**调度层**,最耗时的 tensor 计算不在 kvlang 内执行:op-gpu 将计算编译为 GPU kernel(TileLang → AOT `.so` → dlopen),通过 GPU 硬件加速弥补。透明性在调度层兑现,算力在扩展引擎层找回。
-"# -> /lib/kvlang/deepdive/02_everything_is_plaintext
-}
diff --git a/stdlib/kvlang/deepdive/03-program-as-datastructure-func-data.kv b/stdlib/kvlang/deepdive/03-program-as-datastructure-func-data.kv
deleted file mode 100644
index 247cae6c..00000000
--- a/stdlib/kvlang/deepdive/03-program-as-datastructure-func-data.kv
+++ /dev/null
@@ -1,13 +0,0 @@
-// 欢迎加入kvspace世界
-lib kvlang/deepdive/03_program_as_datastructure_func_data {
- r#"# 程序 = 数据结构 + 函数 + 数据
-
-## 程序 = 数据结构 + 函数 + 数据
-
-Niklaus Wirth 的经典公式「程序 = 数据结构 + 算法」将程序员的精力引向"先设计数据结构,再编写算法"。
-
-kvlang 的主张:**程序 = 数据结构 + 函数 + 数据**。数据结构不再由用户自定义——kvlang 的全部数据结构都是 builtin:`struct`(键族前缀),compact 形态数组(`[N]T`,元素连续打包进单个 XValue),stringkeymap 形态数组(`{...}`,元素散落 `base·i` 独立键),链表(`/n0·val`、`/n0·next` 平坦键,路径字符串作指针)。使用者只需声明 `lib`、编写 `rwfunc`,数据自然落地到 `/lib/` 与 `/vthread/` 及用户自定义路径。
-
-键族是 kvlang 唯一的数据结构机制,上层全部收敛为函数(rwfunc/rwir)与数据(kvspace slot)的组合。以 kvspace 树形路径为统一地址空间,同一语法同时承担 VM 指令、高级语言、编译器 IR 三种职能。
-"# -> /lib/kvlang/deepdive/03_program_as_datastructure_func_data
-}
diff --git a/stdlib/kvlang/deepdive/04-four-level-code-hierarchy.kv b/stdlib/kvlang/deepdive/04-four-level-code-hierarchy.kv
deleted file mode 100644
index e01ff5f9..00000000
--- a/stdlib/kvlang/deepdive/04-four-level-code-hierarchy.kv
+++ /dev/null
@@ -1,52 +0,0 @@
-// 欢迎加入kvspace世界
-lib kvlang/deepdive/04_four_level_code_hierarchy {
- r"# 代码四级层次
-
-kvlang 中所有代码组织为四个层级,从宏观到微观,每层在 kvspace 树中有对应路径。
-
-## 四级定义
-
-| 层 | 关键字 | 职责 | 拥有 |
-|----|--------|------|------|
-| **lib** | `lib name { }` | 包组织,管理命名空间下的所有 rwfunc | rwfunc 集合 |
-| **rwfunc** | `rwfunc name(...) -> (...) { }` | 函数级,拥有自己的 rwir 指令序列和变量 | rwir 序列 + scope 树 |
-| **scope** | (lower 产物,不可手写) | 域级,if/while/for 降级产生,拥有自己的指令序列和变量,可嵌套 | rwir 序列 + 子 scope |
-| **rwir** | `rwir name(...) -> (...)` | 指令级,执行由解释器直执行或委托后端引擎 | 无——原子不可分 |
-
-```
-/lib/leetcode/ ← lib: 顶层包
-└── /lib/leetcode/search/ ← lib: 嵌套子包
- ├── [rwfunc] binary(target) ← rwfunc: 函数签名
- ├── [0,0]: lo <- 0 ← rwir: 原子指令
- ├── [1,0]: hi <- 100
- ├── _while_1/ ← scope: while 循环域
- │ ├── cond/
- │ │ └── [0,0]: found == 0 -> _c
- │ ├── body/
- │ │ ├── [0,0]: lo + hi -> s
- │ │ └── _if_1/ ← scope: 嵌套 if 域
- │ │ ├── then/
- │ │ └── else/
- │ └── exit/
- └── _exit_1/
-```
-
-## 层次约束
-
-- **lib** 可嵌套子 lib(`lib a { lib b { } }`),叶子 lib 包含 rwfunc。不可直接含 rwir 或 scope。对应 `/lib//` 路径,嵌套时路径级联 `/lib/a/b/`。
-- **rwfunc** 只包含 rwir 和 scope——不可含其他 rwfunc。函数调用不嵌入 body,走 `call`/`return` 跨帧机制。rwfunc 对应 `/lib///`,运行时实例化为 `/vthread//[N,0]/` 帧。
-- **scope** 只包含 rwir 和子 scope。语义同 rwfunc 但无独立调用栈——scope 的变量和指令序列平铺在所属 rwfunc 帧内。scope 由 lower 阶段从 if/while/for 产生,不可手写。
-- **rwir** 是最小执行单元,不可再分,由 C runtime 解释器或后端引擎原子执行。rwir 是**空函数体**(仅签名,无指令体),扩展 rwir 的签名与 rwfunc 统一存于 `/lib/`(`` 可带包前缀),运行时签名可供 agent 自省;native rwir 签名内联在 C runtime 注册表中、不落盘。
-
-## 与 KV 树的映射
-
-每一层在 kvspace 树中都有对应路径,`kvspace tree` 即完整自省:
-
-| 层 | KV Kind | `/lib/` 路径 | `/vthread/` 路径 |
-|----|---------|-------------|-----------------|
-| lib | — | `/lib//` | — |
-| rwfunc | `rwfunc` | `/lib///` | `/vthread//[N,0]/` |
-| scope | `scope` | `/lib///_while_N/` | `/vthread//[N,0]/_while_N/` |
-| rwir | `rwir` | `/lib/`(扩展);native 内联 C 表不落盘 | — |
-" -> /lib/kvlang/deepdive/04_four_level_code_hierarchy
-}
diff --git a/stdlib/kvlang/deepdive/grammar/kvlang-bnf-grammar.kv b/stdlib/kvlang/deepdive/grammar/kvlang-bnf-grammar.kv
deleted file mode 100644
index 893ce04c..00000000
--- a/stdlib/kvlang/deepdive/grammar/kvlang-bnf-grammar.kv
+++ /dev/null
@@ -1,189 +0,0 @@
-// 欢迎加入kvspace世界
-lib kvlang/deepdive/grammar/kvlang_bnf_grammar {
- r##"# kvlang 语法 (BNF)
-
-> 锚定于 kvlang-deep-dive(根设计文档)——每次 deep-dive 更新后需验证本文与实现一致。
-
-## 词法
-
-```
-digit = "0" … "9"
-letter = "a" … "z" | "A" … "Z" | "_"
-ident = letter { letter | digit }
-integer = digit { digit }
-float = integer [ "." integer ] [ ("e" | "E") [ "+" | "-" ] integer ]
-path = "/" ident { ("/" | ".") ident | "·" "[" integer { "," integer } "]" }
- (* 绝对路径字面量;/ 分隔段,. 为子键,· [i,j] 为 strkeymap 坐标段 *)
-
-string = '"' { char | escape } '"'
- | "r" { "#" } '"' { char } '"' { "#" }
- | "'" { char } "'"
- (* 双引号:\ 转义(\n \t \" \\ …),可直接跨行。
- r"…" 原始串(零转义);开头 N 个 # 时须以 " 后接同样 N 个 # 闭合,
- 故 r#"…"# 内容可含 ",# 越多可嵌套越深。单引号为 char/keypath。
- 无三引号、无反引号原始串——完全对齐 Rust。 *)
-comment = "//" { char } newline (* 行注释 *)
- | "/*" { char | comment } "*/" (* 块注释,可嵌套;无 # 注释 *)
-```
-
-## 程序结构
-
-```
- (* 无 import——lib 树即全局命名空间,跨 lib 调用走全路径 /lib/{pkg}·{func}() *)
-
-file = { lib_block | rwir_decl | rwfunc_decl | instruction }
-
-lib_block = "lib" ident "{" { lib_item } "}"
-lib_item = lib_block | rwir_decl | rwfunc_decl | instruction
- (* lib 内的裸 instruction 收集为隐式 init 函数,无 init 关键字 *)
-
-rwfunc_decl = "rwfunc" ident "(" [ param_list ] ")"
- [ "->" ( "(" [ param_list ] ")" | param_list ) ]
- "{" { statement } "}"
-
-rwir_decl = "rwir" ident "(" [ param_list ] ")" [ "->" "(" [ param_list ] ")" ]
- (* 仅签名,无函数体;绑定至扩展执行器 *)
-
-param_list = param { "," param }
-param = ident ":" type_expr (* 类型必须标注;末参的 type_expr 可加 "..." 变参 *)
-
-statement = instruction | if_stmt | while_stmt | for_stmt | block_stmt
- | break_stmt | continue_stmt | return_stmt
-```
-
-## 类型表达式(签名参数/返回值类型,多态 + 高维数组)
-
-> 完整语义见 [[runtime篇-07-签名类型表达式]]。铁律:无家族简写(`int`/`uint`/`float`/`num`/`char`)——位宽是开放集合(int4/fp8/fp16…),编码须写明确;多态靠显式 `|` 枚举。
-
-```
-type_expr = atom { "|" atom } (* 并集:A|B 表 A 或 B *)
-atom = shape | mapexpr
-shape = [ dims ] ( any | kind )
-mapexpr = key "·" type_expr (* stringkeymap;value 可递归嵌套 *)
-key = "[]" char_enc (* 字符串键,等价 Go map[string]V *)
- | "[" scalar { "," scalar } "]" (* 标量元组键,物理以字符串格式落 key *)
-char_enc = "char/utf8" | "char/utf32" | "char/ascii"
-scalar = "bool"
- | "int8" | "int16" | "int32" | "int64"
- | "uint8" | "uint16" | "uint32" | "uint64"
- | "float32" | "float64"
-dims = "[]" (* 1 维,长度任意,等价 [?] *)
- | "[" dim { "," dim } "]" (* 逗号分割的维;rank = 项数 *)
-dim = integer | "?" (* 精确大小或动态维 *)
-any = "any" (* 通配,匹配任意 kind *)
-kind = "bool"
- | "int8" | "int16" | "int32" | "int64"
- | "uint8" | "uint16" | "uint32" | "uint64"
- | "float32" | "float64"
- | "char/utf8" | "char/utf32" | "char/ascii"
- | "object" | "stringkeymap"
- | "index" | "extindex"
- | "rwir" | "rwfunc" | "scope" | "time" | "duration"
-variadic = type_expr "..." (* 仅末参:0..N 个同型实参,每个按 type_expr 匹配 *)
-```
-
-## 指令
-
-```
-instruction = [ writes "=" ] expr
- | [ writes "<-" ] expr
- | expr [ "->" writes ]
- | expr (* 纯副作用调用 *)
-
-writes = write_slot { "," write_slot }
-write_slot = ident (* 裸名:帧内变量 *)
- | path (* 绝对路径 *)
- | ident "·" ident (* 成员写:base·field *)
- | ident "·" "*" ident (* 动态键写:base·*key *)
- | ident "[" expr "]" (* 下标写:arr[idx] *)
-```
-
-## 表达式
-
-```
-expr = primary { infix_primary }
- | prefix_unary primary
-
-primary = literal | ident | path
- | primary "·" ident (* 成员读:静态键 *)
- | primary "·" "*" ident (* 成员读:动态键 *)
- | primary "·" "[" expr { "," expr } "]" (* strkeymap 坐标访问 *)
- | primary "[" expr { "," expr } "]" (* compact 下标读 *)
- | "(" expr ")" (* 分组 *)
- | ident "(" [ arg_list ] ")" (* 函数调用 *)
- | ident "·" ident { "·" ident } "(" [ arg_list ] ")" (* 点号限定调用 *)
- | array_literal
- | object_literal
- | map_literal
-
-prefix_unary = "-" | "!"
-
-infix_primary = binary_op expr
-
-binary_op = "+" | "-" | "×" | "÷" | "%" | "==" | "!=" | "<" | ">" | "<=" | ">="
- | "&&" | "||" | "&" | "|" | "^" | "<<" | ">>"
- (* 乘 = ×(U+00D7),除 = ÷(U+00F7);* 保留、/ 仅路径,均非算术符 *)
-
-arg_list = expr { "," expr }
-
-literal = integer | float | string | "None" | "true" | "false"
- (* 空值字面量是 None,非 null *)
-
-array_literal = "[" [ expr { "," expr } ] "]"
- (* compact 形态数组:元素连续打包进单个 XValue,head kind=元素类型;
- 须定长同类型,元素不可为字符串字面量(变长)*)
-
-object_literal = "{" [ ident "=" expr { (";" | newline) ident "=" expr } ] "}"
- (* 对象/映射字面量:{k1=v1; k2=v2},key 为静态标识符,落 object 或 stringkeymap(map) *)
-
-map_literal = "{" [ expr { (";" | newline | ",") expr } ] "}"
- (* stringkeymap 形态数组(散 key):{v0, v1, ...},head kind=stringkeymap,
- 每元素落 base·i 独立 key;字符串数组等变长集合用此形式 *)
-```
-
-## 控制流(仅限 rwfunc 体内)
-
-```
-if_stmt = "if" "(" expr ")" "{" { statement } "}"
- { "else" "if" "(" expr ")" "{" { statement } "}" }
- [ "else" "{" { statement } "}" ]
-
-while_stmt = "while" "(" expr ")" "{" { statement } "}"
-
-for_stmt = "for" "(" ident "in" expr ")" "{" { statement } "}"
- (* iter 可为变量、路径或任意表达式(包括散 key 字面量) *)
-
-block_stmt = ident ":" "{" { statement } "}" (* 具名作用域 *)
-
-break_stmt = "break"
-continue_stmt = "continue"
-return_stmt = "return" (* 无返回值;输出通过写参传递 *)
-```
-
-## 内建函数(部分)
-
-```
-builtin_call = ("print" | "println"
- | "abs" | "neg" | "sign" | "pow" | "sqrt" | "exp" | "log"
- | "min" | "max"
- | "bool" | "int8" | "int16" | "int32" | "int64"
- | "uint8" | "uint16" | "uint32" | "uint64"
- | "float32" | "float64"
- | "char/utf8" | "char/utf32" | "char/ascii"
- | "array" | "obj" | "map"
- | "debugger") "(" [ arg_list ] ")"
-
-(* 裸名内建仅上表;string·len/char/slice/find、xv·at/set、kv·get/set/del、
- ndarray·numel/dim/shape、array·append/slice、vthread·*、time·* 等一律走
- primary 的 · 限定调用(base·method(...)),不是裸名终结符 *)
-(* 类型构造器兼转换:int8(x)/float32(x)/char/utf8(x)/bool(x) ... *)
-(* min/max 支持变参: min(a,b,c,...) *)
-(* print : Go 风格——无空格拼接,不追加换行 *)
-(* println: Go 风格——空格分隔,追加换行 *)
-(* debugger(): 内联暂停, 非调试模式 no-op *)
-(* ÷ : 两侧 int → 整除(C 风格); 任一侧 float → 浮除;/ 仅用于路径 *)
-(* s[i] 读返单字符字符串, 越界返 ""; s[i]="X" 单字符替换写回新串 *)
-(* + 作用在 string∧string → 拼接 *)
-```
-"## -> /lib/kvlang/deepdive/grammar/kvlang_bnf_grammar
-}
diff --git a/stdlib/kvlang/deepdive/kvspace/00-design-and-implementation.kv b/stdlib/kvlang/deepdive/kvspace/00-design-and-implementation.kv
deleted file mode 100644
index df9a5936..00000000
--- a/stdlib/kvlang/deepdive/kvspace/00-design-and-implementation.kv
+++ /dev/null
@@ -1,63 +0,0 @@
-// 欢迎加入kvspace世界
-lib kvlang/deepdive/kvspace/00_design_and_implementation {
- r#"# KVSpace 基础模型
-
-## 设计美学
-
-代码必须按唯一正确方式运行;遇非预期输入直接 fatal/panic,不用 if 包庇错误,不容许以奇怪方式成功运行。走唯一主干,砍一切分支。
-
-## 核心概念:KV 树
-
-KVSpace 是文件系统风格的 KV 存储抽象,`/` 管层级,`·` 管成员:
-
-- **文件 key**:普通值 key,例如 `/a/b` → `int64:42`
-- **目录 key**:以 `/` 结尾,value 为 index(子名列表),例如 `/a/` → `index: ["b"]`
-- 同一路径下 `/a` 与 `/a/` 可独立共存(文件与目录同名)
-
-分隔符:`/` = 层级;`·`(U+00B7)= 用户成员;`‥`(U+2025)= 运行时系统变量前缀(见系统变量篇)。
-
-## XValue 类型系统
-
-XValue = XValueHead + body:
-
-```
-XValueHead = [1B kind_len][N B kind][1B ref][1B ndim][ndim×4B dims LE][4B raw_len LE]
-body = [M B raw] M = raw_len
-ref: 0=内联 1=`*`软链接(body=目标key路径) 2=`@`扩展存储句柄(body=位置描述符)
-ndim: 0=标量,≥1=数组维数(无独立 arr_flag,形态由 kind 表达:compact 形态 kind=元素类型;stringkeymap 形态 kind=stringkeymap)
-```
-
-`HeadLen() = 7 + kind_len + ndim*4`;body 在 `value[HeadLen : HeadLen+raw_len]`。
-
-**kind 列表**(`runtime/src/const.h` 唯一事实源):
-
-| kind | 说明 | elemSize |
-|------|------|----------|
-| `uint8` / `bool` / `int8` / `char/utf8` | 字节类 | 1B |
-| `int16` / `uint16` | 2B 整数 | 2B |
-| `int32` / `uint32` / `float32` | 4B 数值 | 4B |
-| `int64` / `uint64` / `float64` / `char/utf32` | 8B/4B 数值 | 8B/4B |
-| `object` | 有序成员容器(`·` 成员访问) | — |
-| `stringkeymap` | 字符串键映射容器 | — |
-| `index` | 通用目录 | — |
-| `extindex` | 写时复制叠加层 | — |
-| `rwir` / `rwfunc` | 运行时指令/函数 | — |
-| `defrwir` / `defrwfunc` | 扩展注册指令/函数(/lib/ 类型) | — |
-| `scope` | 作用域帧签名 | — |
-| `None` | 空值 | — |
-
-**Ptr(软链接)**:ref=1,body=目标路径字符串。读/写/List 透明穿透,Del 末段作用于链接本体。
-
-## ExtIndex
-
-ExtIndex 是写时复制叠加层:`ExtIndex("/merge/", "/base/")` 后,读 `/merge/x` 先查本地、后回落 `/base/x`;写入本地不影响 `/base/`;List 合并两侧。不允许级联(exttarget 本身不能是 extindex)。
-
-## 辅助设施
-
-**Watch/Notify**:一次性通知机制,运行时用于 vthread 状态变更和外部 rwir 协调。
-
-**路径工具**:`JoinPath` 拼路径避免 `//`;`SepPath` 拆前缀+末段。
-
-**常量集中管理**:所有路径/分隔符/kind 字符串在 `runtime/src/const.h`(C)与 `layout/src/keytree.rs`(Rust),禁止散落硬编码。
-"# -> /lib/kvlang/deepdive/kvspace/00_design_and_implementation
-}
diff --git a/stdlib/kvlang/deepdive/kvspace/01-address-space.kv b/stdlib/kvlang/deepdive/kvspace/01-address-space.kv
deleted file mode 100644
index 78c9e0ef..00000000
--- a/stdlib/kvlang/deepdive/kvspace/01-address-space.kv
+++ /dev/null
@@ -1,46 +0,0 @@
-// 欢迎加入kvspace世界
-lib kvlang/deepdive/kvspace/01_address_space {
- r#"# 地址空间
-
-> 本章讲述 kvlang **使用** kvspace 的过程设计与约束,而非 kvspace 自身的设计实现。
-
-## 系统域
-
-kvspace 树形路径只保留两个系统域,借用 Unix 文件系统思想;**其余 `/` 路径全部自由,由用户定义**:
-
-```
-/lib/{pkg}·{name} 编译优化后函数(签名 + 指令树)+ .src 源码副本;扩展 rwir 也注册于此
-/vthread/{vid}/ 虚线程栈帧(运行时)
-```
-
-> 代码里只有 `LIB_ROOT="/lib"` 与 `VTHREAD_ROOT="/vthread"` 两个前缀(`runtime/src/runtime_internal.h`)。曾设想的 `/sys/`(基础设施注册表)与 `/dev/`(I/O 设备域)**已废弃**:基础设施与扩展 rwir 统一落在 `/lib/`,I/O 不经设备域(见下"没有 /dev 设备域")。
-
-### `/lib/`
-
-借鉴 Unix `/lib/`——共享库的标准路径,是函数(layout 产物)的单一事实源。`lib name { }` 命名空间块声明包。多文件通过 `kvlang layoutrwir ` 拼接为单一源 → parse → lower → 写入 `/lib/`,无 `import` 关键字——lib 树即全局命名空间,跨 lib 调用走全路径 `/lib/{lib}·{func}()`。`.src` 源码副本与指令树同目录。已加载文件自动去重。
-
-### `/vthread/`
-
-运行时栈帧,借用 Unix `/proc//` 思想——每 vthread 一棵子树,`‥pc`/`‥status` 等系统键暴露执行状态(见系统变量篇);帧根本身是 extindex 指向 `/lib/` 指令树。
-
-### 没有 /dev 设备域
-
-KV 世界里没有终端、没有设备文件,只有 key 和 value。`print`/`println`/`cerr`/`input` 这类 I/O **不是**地址空间的一个域,也不是 runtime 的 native builtin——它们是**扩展 rwir**:`term` 扩展运行时把签名注册到 `/lib/`(kind=`defrwir`),执行时直接写宿主进程的 `stdout`/`stderr`,不经任何 `/dev/*` 键。与 `json·to`/`json·from`、tensor 算子同一套 rwir 扩展机制(见扩展运行时篇)。
-
-### 两域之外
-
-`/` 路径(如 `/counter`、`/n0·val`、`/tmp/seen`)完全由用户代码定义——kvspace 不预设 schema,只提供 Write/Read/Watch 原语。
-
-## 存储铁律与扩展存储
-
-**kvspace 存储铁律**:Key 必须是字符串路径(`/` 分隔的树形层级);Value 必须是 XValue 序列化后的字节数组。**严禁**直接写入裸基础类型——所有值必须经 XValue 编解码。违反此铁律的写入在 reader 侧读到非法字节时 behavior undefined。
-
-kvspace 存储两类数据:**基础数据类型**(int、float、bool、string)和 **tensor 元数据**(shape、dtype、指向扩展存储的句柄)。tensor 完整数据在扩展存储中:
-
-| 扩展位置 | 典型数据 |
-|---------|---------|
-| 集群节点共享内存 | 大张量、激活值(heap-plat 管理生命周期) |
-| GPU 显存 | 计算张量(op-plat 在设备侧持有句柄) |
-| 文件系统/对象存储 | 模型权重、检查点、数据集 |
-"# -> /lib/kvlang/deepdive/kvspace/01_address_space
-}
diff --git a/stdlib/kvlang/deepdive/kvspace/02-addressing-model-and-naming.kv b/stdlib/kvlang/deepdive/kvspace/02-addressing-model-and-naming.kv
deleted file mode 100644
index 54352ced..00000000
--- a/stdlib/kvlang/deepdive/kvspace/02-addressing-model-and-naming.kv
+++ /dev/null
@@ -1,76 +0,0 @@
-// 欢迎加入kvspace世界
-lib kvlang/deepdive/kvspace/02_addressing_model_and_naming {
- r#"# 寻址模型与命名
-
-## 寻址模型:KV 路径 vs 内存地址
-
-### 传统 VM (Python/Lua/JVM)
-
-```
-程序计数器 PC = 0x7fff5fbff830 (64-bit 内存地址)
-指令 = 内存[PC] → 1 字节 opcode → 操作数
-跳转 = PC = 新地址 (直接修改寄存器)
-调用 = push 返回地址 → PC = 函数入口地址
-栈帧 = 连续内存 [rbp-8] = 局部变量
-```
-
-内存地址是**一维线性整数**,跳转和调用本质是整数算术。
-
-### kvlang
-
-```
-程序计数器 PC = "[0,0]/entry/[0,0]" (KV 路径字符串)
-指令 = kv.Get("/vthread/tid/[0,0]/entry/[0,0]")
-跳转 = PC = "[0,0]/merge/[0,0]" (字符串拼接)
-调用 = PC = "[0,0]/then/[0,0]" (路径嵌套)
-栈帧 = /vthread/tid/[0,0]/ 子树 (KV key 层级)
-```
-
-KV 路径是**树形层级字符串**,跳转和调用本质是路径拼接 + 子树导航。
-
-| 维度 | x86/ARM | Python | Lua | kvlang |
-|------|---------|--------|-----|--------|
-| PC 类型 | `uint64` | `*PyCodeObject + offset` | `Instruction*` | `string` (KV path) |
-| 指令获取 | `mov rax, [rip]` | `_PyEval_EvalFrameDefault` 循环 | `luaV_execute` 循环 | `kv.Get("/vthread/tid/" + pc)` |
-| 跳转 | `jmp 0x400100` | `next_instr += oparg` | `pc++` | `pc = new_path` |
-| 调用 | `call 0x400200` | `call_function` 压栈 | `luaD_precall` | `pc = pc + "/[0,0]"` |
-| 栈帧 | `push rbp; sub rsp, N` | `PyFrameObject` (堆分配) | `CallInfo + L->stack` | `/vthread/tid//` KV 子树 |
-| 作用域 | 栈偏移 | `f_localsplus` 数组 | 寄存器索引 | KV key 子路径(裸名 `x`, `y`) |
-
-## 变量名即指针
-
-kvlang 没有 `&` 取址运算符——**代码中对象的变量名,本身就是这个变量的指针**(kvspace 路径)。指令槽里存的从来不是值,而是指针文本(`[0,-1] = "A"`、`[0,1] = "C"`),求值永远经过一次指针间接。
-
-指针分两种形态:
-
-| 形态 | 写法 | 语义 | 解析时机 |
-|------|------|------|---------|
-| **相对指针** | 裸标识符 `x` | 相对当前栈帧的偏移 | 运行时与栈路径拼接 |
-| **绝对指针** | `/counter` | kvspace 全局绝对路径 | 零拼接,直接 Get/Set |
-
-**局部变量的变量名就是相对指针**。运行时解析公式:
-
-```
-绝对路径指针 = FrameRoot(PC) + "/" + 相对指针
-
-例:PC = /vthread/7/[3,0]/[1,0]
- FrameRoot(PC) = /vthread/7/[3,0] ← 去掉末尾 /[coord]
- x → /vthread/7/[3,0]/x
-```
-
-栈路径(帧根)不需要单独的寄存器——PC 本身是帧内路径(帧根本身是 extindex 指向 `/lib/` 指令树),`FrameRoot(PC)` 截取即得。这与 C 的 `rbp + offset` 同构:
-
-| | C/x86 | kvlang |
-|--|-------|--------|
-| 帧基址 | `rbp` 寄存器 | `FrameRoot(PC)`——从 PC 截取 |
-| 局部变量地址 | `rbp - 8`(基址 + 偏移) | `帧根 + "/x"`(栈路径 + 相对指针) |
-| 全局变量地址 | `.data` 固定地址 | `/` 开头绝对指针,零拼接 |
-| 指针变量 | 存整数地址 | 存路径字符串:`"/n0" -> ptr`,`ptr·val` 解引用 |
-
-`/lib/` 下的函数模板中只有相对指针,因此天然可重入:每次调用创建不同的帧路径,同一份相对指针拼接出互不干扰的绝对指针——递归、TCO(尾调用优化:goto/br 不建新帧)无需任何额外机制。
-
-全局变量 `/counter` 零成本——绝对指针不经过帧前缀拼接。数组能作为参数传递——`flattenNestedCalls` 将 `[1,2,3]` 展开为临时变量,再将临时变量(持有 XValue)作为普通参数传递。
-
-**参数不得同名(fix-032)**:变量名即指针——同一帧内两个同名参数将指向同一个 kvspace 位置。读参列表内部、写参列表内部、以及读写列表之间均不可同名。`rwfunc f(A:int64) -> (A:int64)` 签名非法。layout 的 `checkParamDup` 阻断源码路径,C runtime 兜底非法签名。
-"# -> /lib/kvlang/deepdive/kvspace/02_addressing_model_and_naming
-}
diff --git a/stdlib/kvlang/deepdive/kvspace/03-instruction-layout-format.kv b/stdlib/kvlang/deepdive/kvspace/03-instruction-layout-format.kv
deleted file mode 100644
index 164c3a5f..00000000
--- a/stdlib/kvlang/deepdive/kvspace/03-instruction-layout-format.kv
+++ /dev/null
@@ -1,104 +0,0 @@
-// 欢迎加入kvspace世界
-lib kvlang/deepdive/kvspace/03_instruction_layout_format {
- r#"# 代码指令的布局格式
-
-> 签名参数/返回值的 `type` 用**签名类型表达式**(并集 `A|B`、通配 `any`、高维 shape `[2,3]`、动态维 `?`),BNF 见 `grammar.bnf`。
-
-## layoutrwir 的设计原理与函数调用 extindex 机制
-
-传统 VM:编译器产线性字节码,call = push 返回地址 + 跳转到函数入口。kvlang 不用字节码拷贝——**函数体永不被复制,调用 = ExtIndex 将帧根设为扩展索引**指向 `/lib/` 下的指令树。
-
-layoutrwir 在五语言中的对标:
-
-| 语言 | 阶段名 | 产物 |
-|------|--------|------|
-| **C (GCC)** | codegen + assemble + link | 线性机器码 |
-| **Go** | compile (walk + SSA) | 线性机器码 |
-| **Rust** | codegen (MIR→LLVM IR) | 线性机器码 |
-| **Python** | compile | 线性字节码 `.pyc` |
-| **V8** | Ignition bytecode + TurboFan | 线性字节码→机器码 |
-| **kvlang** | **layoutrwir** | **树形 KV 键**,可逐槽寻址 |
-
-五种语言都在生成线性序列。kvlang 的 layoutrwir 不是序列化——是**空间布局**:每条指令展开为一组 `[s0,s1]` 坐标,读参负轴、写参正轴、opcode 零点。产物可逐槽 `kv·get`/`kv·list`,无需反汇编器。
-
-### 指针传址方案(φ1)
-
-函数定义利用 slot 坐标 row 0,指令从 row 1 开始。参数名通过命名 Ptr key 映射到 slot 坐标,运行时走 3 跳 Ptr 链解析。
-
-**Layout(`/lib/` 下,只读):**
-
-```
-/lib/main·add/[0,0] → Rwfunc(nr=2, nw=1, al=2) ← 函数签名(仅计数)
-/lib/main·add/a → Ptr(string, "[0,-1]", 1) ← 命名参数→slot
-/lib/main·add/b → Ptr(string, "[0,-2]", 1)
-/lib/main·add/c → Ptr(string, "[0,1]", 1) ← 命名返回值→slot
-/lib/main·add/[1,0] → "+" ← 指令0(idx+1)
-/lib/main·add/[1,-1] → Rwir("a") ← 指令0 read slot
-/lib/main·add/[1,-2] → Rwir("b")
-/lib/main·add/[1,1] → Rwir("c")
-/lib/main·add/[2,0] → "return" ← 指令1
-```
-
-**Runtime(`/vthread/.../` 帧根,extindex → `/lib/main·add/`):**
-
-```
-frameRoot/a → ext→ Ptr("[0,-1]") ← layout 写入,只读
-frameRoot/b → ext→ Ptr("[0,-2]") ← 只读
-frameRoot/c → ext→ Ptr("[0,1]") ← 只读
-frameRoot/[0,-1] → Char("/vthread/1/_lit0") ← runtime 写入,无 ext 冲突
-frameRoot/[0,-2] → Char("/vthread/1/x") ← runtime 写入
-frameRoot/[0,1] → Char("/vthread/1/result") ← runtime 写入
-frameRoot/[1,0] → ext→ "+" ← 指令
-```
-
-**Resolve(3 跳 Ptr 链):**
-
-```
-指令 [1,-1]=Rwir("a"):
- 1. GetOne(frameRoot+"/a") → ext→ Ptr("[0,-1]") ← name→slot
- 2. GetOne(frameRoot+"/[0,-1]") → Char(path) ← slot→arg地址
- 3. GetOne(path) → value ← 解引用
-```
-
-**XValueHead ref 字段**:`ref=0` 内联,`ref=1` 软链接(body=目标路径),`ref=2` 扩展存储句柄。完整格式见 key系统篇。
-
-### ExtIndex:帧根指向指令树
-
-函数调用时,不是把指令字节码拷贝到新帧——而是通过 **ExtIndex** 让帧根成为指向 `/lib/` 指令树的扩展索引:
-
-```
-编译期(WriteFunc):
- AST → KV 结构化写入 /lib/main·add/:
- /lib/main·add/[0,0] = Rwfunc(r2/w1) ← 函数签名
- /lib/main·add/a = Ptr("[0,-1]") ← 命名参数→slot
- /lib/main·add/b = Ptr("[0,-2]")
- /lib/main·add/c = Ptr("[0,1]") ← 命名返回值→slot
- /lib/main·add/[1,0] = "+" ← 指令0
- /lib/main·add/[1,-1] = Rwir("a")
- /lib/main·add/[1,-2] = Rwir("b")
- /lib/main·add/[1,1] = Rwir("c")
- /lib/main·add/[2,0] = "return" ← 指令1
-
-调用时:
- kv·ExtIndex(frameRoot+"/", "/lib/main·add/") ← 帧根→/lib/ 指令树
- kv·Set(frameRoot+"/[0,-1]", Char(argAddr)) ← runtime arg 槽,无 ext 冲突
- kv·Set(frameRoot+"/[0,-2]", Char(argAddr))
- kv·Set(frameRoot+"/[0,1]", Char(resultAddr))
- # 所有帧共享 /lib/ 下同一份指令树,零拷贝
-```
-
-**关键设计**:`[0,-j]` key 在 `/lib/` 下不存在(只有 named key `a`/`b`/`c`),因此 runtime 写入 `frameRoot/[0,-j]` 不会触发 extindex 写保护。
-
-### 与传统 VM 的关键差异
-
-| | 传统 VM | kvlang |
-|--|---------|--------|
-| 代码传递 | copy 字节码到新栈帧 | **ExtIndex**(所有帧共享 /lib/ 下同一份指令树) |
-| 帧模型 | 一种帧(call/return) | **两种帧**:rwfunc(函数调用)+ scope(goto/br,详见控制流篇) |
-| 崩溃恢复 | 栈帧在内存,进程死即全失 | PC=路径字符串、frameRoot=返回点落 KV——重启续跑 |
-| 可观测 | 需调试器 attach | `kvspace tree /vthread/…` 看 extindex 指向、frameRoot,局部变量直读帧根 |
-| 参数模型 | 寄存器/栈槽传值 | Ptr 链:name→slot→arg→value(3 跳) |
-
-**`=` 操作码是值拷贝,不是函数调用**:`a -> b` 编码为 `[s0,0]="="`(值拷贝),函数调用 opcode 位是 `call`,ExtIndex 发生在调用处理函数内部。二者在 KV 层无歧义,opcode 位永远不放变量引用。
-"# -> /lib/kvlang/deepdive/kvspace/03_instruction_layout_format
-}
diff --git a/stdlib/kvlang/deepdive/kvspace/04-system-variables.kv b/stdlib/kvlang/deepdive/kvspace/04-system-variables.kv
deleted file mode 100644
index ffebaddf..00000000
--- a/stdlib/kvlang/deepdive/kvspace/04-system-variables.kv
+++ /dev/null
@@ -1,66 +0,0 @@
-// 欢迎加入kvspace世界
-lib kvlang/deepdive/kvspace/04_system_variables {
- r#"# 系统变量
-
-## `X/‥var` 影子键
-
-> **本节是全部 `‥` 系统键的唯一事实源。**
-> 任何代码变更(新增、修改、删除 `‥` 键)**必须先更新本节**,再改代码。
-
-VM 运行时为它管理的对象生成**内置变量(系统变量)**,以 `{对象key}/‥var` 形式存放:`/` 下探一层、键名以 `‥`(U+2025,`RUNTIME_MEMBER_SEP`)开头。kvlang 标识符不能以此字符开头,因此所有 `‥` 前缀键均为引擎保留,用户代码无法直接读写——类比 Unix 隐藏文件:默认视图不显示,引擎可见。
-
-**与用户成员键的区分**:`X·attr`(`·` 中点键,U+00B7,如 `obj·prop`、`lib·func`)是用户 kv 代码可访问的正常成员;`X/‥attr`(`/` + `‥` 前缀)是引擎专属。零交集:用户侧永远造不出 `‥` 开头的路径段。
-
-### 全量清单(按宿主对象分类)
-
-**vthread 对象**(宿主 = `/vthread/`;代码 `runtime/src/keytree.c`、`layout/src/keytree.rs`):
-
-| 键 | 语义 |
-|----|------|
-| `‥pc` | 当前执行 PC(绝对路径字符串) |
-| `‥status` | 运行状态:`init`/`running`/`wait`/`paused`;终态 Del + Notify(retVal) |
-| `‥debugger` | 调试控制:`""` 正常,`"paused"` 暂停;`debugger()` builtin 写此键 |
-
-**帧对象**(宿主 = frameRoot;代码 `runtime/src/keytree.c`、`layout/src/keytree.rs`):
-
-| 键 | 语义 |
-|----|------|
-| *(帧根 extindex)* | rwfunc 帧根 extindex → `/lib/·` 只读指令区;scope 帧不建 extindex |
-| `‥lib` | rwfunc 帧的 lib 路径(如 `/lib/sum_to`),用于识别 rwfunc 帧边界 |
-| `‥callpc` | 每帧执行进度(每 op 更新);scope 帧每次重入更新 |
-| `‥returnpc` | 返回地址(帧创建时固化);scope 帧仅首次设置,重入不覆写 |
-| `‥ro` | 只读参数名单(逗号分隔),kvcpu 写槽检查用;无读参函数不写 |
-| `‥rparam/` | 读参重定向:存调用方值的绝对路径;CPU 读参从此路径直读,零拷贝(layout 侧定义,C runtime 待对齐) |
-| `‥wparam/` | 写参重定向:存调用方写目标的绝对路径;CPU 写参直写此路径(layout 侧定义,C runtime 待对齐) |
-
-**语法层保留名(不落盘,`frameSlotKey` 拦截)**:
-
-| 键 | 语义 |
-|----|------|
-| `._` | 丢弃槽——`frameSlotKey` 遇到此名返回空路径,不写入 kvspace |
-
-注意:`._` 与上述 `‥` 键不同,这是源码层的语法占位符,不落 kvspace。
-
-**内联暂停指令**:`debugger()`(对齐 V8/TypeScript `debugger;` 语句)——源码内联暂停点;非调试模式下 no-op,调试模式下将 `‥status` 置为 `paused`,外部驱动改回 `running` 恢复执行。
-
-注意区分:地址空间的系统**域**(`/lib/`、`/vthread/` 顶层树,见地址空间篇)与对象随身的 `‥var` 系统**变量**是两种机制。
-
-### 三种键形态:一眼判型
-
-任意 key 的形态唯一确定其性质:
-
-| 形态 | 例 | 性质 | 所有权 |
-|------|----|------|--------|
-| `X/名`(`/` + 普通名) | `/vthread/7/[3,0]`、`/_while_2/[0,0]` | 结构:帧、指令槽、scope 帧 | VM |
-| `X·名`(`·` 中点键) | `/c0·next`、`frame/obj·prop` | 用户数据成员 | 用户 |
-| `X/‥名`(`/` + `‥` 名) | `/vthread/7/‥pc`、`/vthread/7/‥status` | 系统变量(影子元数据) | VM |
-
-### 设计结论:系统变量维持 `/‥` 分隔
-
-系统变量用 `/‥` 分隔,与用户成员的 `·` 分隔形成正交:
-
-1. **零冲突的专属命名空间**。用户成员语法只产生 `·` 中点键,标识符禁止 `‥` 开头;用户侧永远造不出 `‥` 序列。若系统变量也用 `·` 拼接,则需维护保留字表,且动态键注入可能命中系统键。
-2. **生命周期绑定**。`X/‥var` 在 X 的 `/` 子树内,`DelTree(X)` 连带清除全部系统变量;用户键族 `X·*` 由前缀删除管理。两个删除平面各归其主。
-3. **统一公理**。任何 kvspace 对象 X:VM 元数据在 `X/‥名`(引擎保留),帧根 extindex 指向 `/lib/` 代码区,用户数据在 `X·名`(成员),子级在 `X/名`(结构)。
-"# -> /lib/kvlang/deepdive/kvspace/04_system_variables
-}
diff --git a/stdlib/kvlang/deepdive/kvspace/05-key-system-and-array-access.kv b/stdlib/kvlang/deepdive/kvspace/05-key-system-and-array-access.kv
deleted file mode 100644
index 5a346e1f..00000000
--- a/stdlib/kvlang/deepdive/kvspace/05-key-system-and-array-access.kv
+++ /dev/null
@@ -1,151 +0,0 @@
-// 欢迎加入kvspace世界
-lib kvlang/deepdive/kvspace/05_key_system_and_array_access {
- r#"# key 系统与数组访问
-
-## 背景:分隔符语义化
-
-kvspace 的树形 key 与 XValue 的 kindexp 共用一套分隔符语义,每个分隔符承载固定含义:
-
-| 分隔符 | 语义 | key 层 | kindexp 层 |
-|--------|------|--------|-----------|
-| `/` | 层级 | `/lib/f/`、`/vthread/1/` | — |
-| `·` | 成员(U+00B7) | `obj·x`、`lib·func` | — |
-| `[]` | 数组访问 | `arr[3]` 数组下标 | `[]int32`、`[10]int32`、`[256,256]uint8` |
-| `@` | 扩展存储句柄 | — | `@[256,256]uint8` |
-
-## rwir 指令序列的 key:`[s0,s1]`
-
-函数 layout 后的 rwir 指令序列,每个指令槽用 `[s0,s1]` 坐标 key(与当前实现一致)。
-
-```
-/lib/main·add/[0,0] → Rwfunc(nr=2, nw=1) ← 函数签名
-/lib/main·add/[1,0] → "+" ← 指令 0 opcode
-/lib/main·add/[1,-1] → Rwir("a") ← 指令 0 读槽 1
-/lib/main·add/[1,-2] → Rwir("b") ← 指令 0 读槽 2
-/lib/main·add/[1,1] → Rwir("c") ← 指令 0 写槽 1
-/lib/main·add/[2,0] → "return" ← 指令 1
-```
-
-坐标约定:`[s0,0]` = opcode,`[s0,-j]` = 第 j 个读槽,`[s0,+j]` = 第 j 个写槽。
-
-## 索引目录符号
-
-kvspace 路径系统有 `/`(层级目录)与 `·`(成员目录)两个索引目录符号。stringkeymap 形态(散 key)的元素 key 用 `base·i` 后缀作为**内部命名**——后端存储约定,非用户语法;遍历经 `for-in`/`kv·get`。compact 形态无子 key——元素打包在单个 body,`arr[i]` desugar 为 `xv·at` 在 body 内定位。
-
-| 符号 | 位置 | 语义 |
-|------|------|------|
-| `/` | 后缀 | 层级目录 |
-| `·` | 后缀 | 成员目录 |
-| `·i` | 内部后缀 | stringkeymap 形态元素 key(存储层,`arr·0`, `arr·1` …) |
-
-## kind 与 kindexp 二分
-
-| 概念 | 内容 | 例子 |
-|------|------|------|
-| **kind** | 基础类型字符串,标量/元素类型 | `uint8` `int16` `int32` `float64` `bool` `char/utf32` `object` `stringkeymap` `index` `rwir` `rwfunc` … |
-| **kindexp** | 完整类型表达式,kind + 修饰符 | `int8` `*int8` `*[]int32` `*[16]uint8` `[256,256]uint8` `[10]int32` `@[256,256]uint8` |
-
-**kind 是 kindexp 的叶子**:剥掉所有 `*`/`@`/`[]` 修饰符即得 kind。kindexp 字符串是显示/讨论形式,落盘为下方 XValueHead 的 3 区二进制 head。
-
-## kindexp 文法
-
-**全前缀**:从左到右读,每个前缀修饰其右侧的类型;最左符号即最外层构造器,无优先级歧义(对标 Go/Rust 的 `*[]int`、`*[10]int`)。
-
-```bnf
-kindexp ::= kind # 标量
- | '*' kindexp # 指针/软链接(body = 目标 key 路径)
- | '@' kindexp # 扩展存储句柄(body = 位置信息,data 在扩展存储)
- | '[' ']' kindexp # 变长一维数组类型;compact/stringkeymap 由初始化括号([...]/{...})定
- | '[' dims ']' kindexp # 定长/多维数组(compact 形态,单 XValue 连续 body)
-dims ::= INT (',' INT)*
-kind ::= uint8 | int8 | int16 | uint16 | int32 | uint32 | int64 | uint64
- | float32 | float64 | bool | char/utf32 | char/utf8 | char/ascii | time | duration
- | object | stringkeymap | index | extindex | rwir | rwfunc | scope
-```
-
-## 「数组」的两种存储形态:compact 与 stringkeymap
-
-计算机理论中的数组(含多维数组)在 kvlang 有两种物理存储形态,落盘为不同 kind:
-
-| 形态 | head kind | 触发写法 | 元素位置 | XValue 数 |
-|------|-----------|---------|---------|----------|
-| **compact 形态** | 元素 kind(`int64`…) | `[1,2,3]`、`[N]T`、`[d0,d1]T` | 连续打包进**单个 XValue** 的 body | **1** |
-| **stringkeymap 形态**(散 key) | `stringkeymap` | `{v0,v1,…}`、`array·append`/`slice`/`scatter` | 每元素落 `base·0`、`base·1`… **独立 key** | N+1 |
-
-- **compact 形态**:元素连续打包进一个 XValue,`raw_len = ∏dims × ElemSize`,head 的 kind **即元素类型**。对齐 C `int[10]`、Go `[10]int`、Rust `[i32;10]`。多维 `[256,256]uint8` = `ndim=2`,即 **ndarray/tensor** 连续布局(与 op-gpu 对齐)。要求元素定长同类型——含变长字符串字面量的 `[...]` 在 layout 阶段报错。支持 `arr[i]`/`xv·at`/`ndarray·numel/dim/shape` 随机访问,可零拷贝整块读。
-- **stringkeymap 形态**:head kind=`stringkeymap`、`ndim=1`、`dims=[n]`,每个元素是独立子 key `base·i`(`·` 内部后缀,见上)。变长、可增长、允许变长元素——**字符串数组、可追加数组走这里**。`array·append`/`array·slice` 作用于 compact 数组时会先自动转成 stringkeymap 形态(见「转换与变长」)。
-
-## 字面量括号即形态:`[...]` 与 `{...}`
-
-| 字面量 | 形态 | 约束 |
-|--------|------|------|
-| `[1, 2, 3]` | **compact**(kind=元素类型) | 元素须定长同 kind、固定字节宽;含变长字符串成员时 layout 阶段报错 |
-| `{1, 2, 3}` / `{"a", "bb"}` | **stringkeymap**(散 key) | 变长/可增长;**字符串数组必须走这里** |
-| `{k = v; ...}` | object / stringkeymap(map) | 靠 `=` 键值对与散 key 数组区分;空 `{}` 须带类型标注 |
-
-- **为何字符串禁入 `[...]`**:compact 要求元素定长连续打包,变长字符串无法定长打包,故 layout 阶段报错,改用 `{...}`。
-- **散 key 字面量位置约束**:`{...}` 只允许作赋值右值 `x = {...}` 或 for-in 源 `for (s in {...})`。
-- **随机访问**:compact 形态支持 `arr[i]`/`xv·at`;stringkeymap 形态目前经 `for-in` 或 `kv·get`/`kv·list` 遍历访问。
-
-## `@`:扩展存储句柄
-
-| 符号 | 语义 | body 存什么 |
-|------|------|-----------|
-| (无) | 内联值 | 数据本体 |
-| `*` | kvspace 内软链接 | kvspace key 路径 |
-| `@` | 扩展存储句柄 | 扩展存储位置(device + address) |
-
-- `@[256,256]uint8` = 256×256 uint8 tensor 的句柄,data 在 SHM/GPU,body 存 `{device, shm_name/offset}`。
-- `*` 与 `@` 的差别是**目标命名空间**:`*` 指向元存内另一个 key,`@` 指向元存外(SHM/GPU/文件)的一块连续数据。
-- **约束**:`@` 只组合 `kind` 与 `[dims]kind`(compact 形态);外部分散数组无意义,拒绝。
-
-## XValueHead 与 body
-
-```
-XValue = XValueHead + body
-XValueHead = [1B kind_len][N B kind][1B ref][1B ndim][ndim×4B dims LE][4B raw_len LE]
-body = [M B raw] M = raw_len,offset = HeadLen()
-```
-
-**XValueHead 字段**:
-
-| 字段 | 大小 | 含义 |
-|------|------|------|
-| `kind_len` | 1B | kind 字符串字节数 |
-| `kind` | N B | 基础类型叶子(明文字符串) |
-| `ref` | 1B | 0=内联 1=`*`软链接 2=`@`扩展句柄 |
-| `ndim` | 1B | 0=标量,≥1=数组维数 |
-| `dims` | ndim×4B | 各维长度 LE |
-| `raw_len` | 4B | body 字节数 LE |
-
-`HeadLen() = 7 + kind_len + ndim*4`;派生字段:`isptr=(ref==1)`、`isext=(ref==2)`、`arraylength = ∏dims`。
-
-**形态由 `kind` 与 `ndim` 表达,无独立 flag**:compact 形态 head 的 kind 是元素类型(`int32`…)、`ndim≥1`;stringkeymap 形态 head 的 kind 是 `stringkeymap`、`ndim=1`、body 只记形状而元素散落子 key;标量 `ndim=0`。
-
-**kindexp 字符串 ↔ 二进制 head 的映射**:
-
-| kindexp 字符串 | ref | ndim | dims | kind |
-|---------------|-----|------|------|------|
-| `int32` | 0 | 0 | — | `int32` |
-| `[10]int32` | 0 | 1 | [10] | `int32` |
-| `[256,256]uint8` | 0 | 2 | [256,256] | `uint8` |
-| `*[]int32` | 1 | 1 | — | `int32` |
-| `@[256,256]uint8` | 2 | 2 | [256,256] | `uint8` |
-
-## 转换与变长:`array·scatter` / `array·compact` / `array·append` / `array·slice`
-
-| rwir | 方向 | 语义 |
-|------|------|------|
-| `array·scatter(arr) -> dst` | compact → stringkeymap | 连续数组 `arr` 拆成 `dst·0..dst·N-1` 标量 key,不动 `arr` |
-| `array·compact(arr) -> dst` | stringkeymap → compact | 读 `arr·0..arr·N-1` 打包成连续数组 `dst`,不动 `arr` |
-| `array·append(arr, elem) -> arr` | 变长 +1 | 追加 `elem`;若 `arr` 为 compact 先自动 scatter 成 stringkeymap |
-| `array·slice(arr, lo, hi) -> arr` | 变长截取 | 切片 `arr[lo:hi]`;若 `arr` 为 compact 先自动 scatter 成 stringkeymap |
-
-## 待定项
-
-- stringkeymap 形态 body schema(shape/元素类型/稀疏索引)细化。
-- compact 多维 `[256,256]uint8` 的 row-major 排布约定(与 op-gpu tensor 连续布局对齐)。
-- stringkeymap 形态随机访问:元素散落 `base·i` 子 key,`for-in`/`kv·get` 可遍历,但 `arr[i]`/`ndarray·numel` 随机访问尚未打通;需随机访问的数值数组用 compact 形态。
-- 扩展存储句柄 body 的位置 schema(device 枚举、shm_name/offset、fd、GPU ptr 的统一编码)。
-"# -> /lib/kvlang/deepdive/kvspace/05_key_system_and_array_access
-}
diff --git a/stdlib/kvlang/deepdive/layout/01-instruction-architecture.kv b/stdlib/kvlang/deepdive/layout/01-instruction-architecture.kv
deleted file mode 100644
index fa3b4113..00000000
--- a/stdlib/kvlang/deepdive/layout/01-instruction-architecture.kv
+++ /dev/null
@@ -1,139 +0,0 @@
-// 欢迎加入kvspace世界
-lib kvlang/deepdive/layout/01_instruction_architecture {
- r#"# Instruction Architecture(指令架构)
-
-## 指令分类
-
-指令分两层,kvcpu 只见执行层:
-
-**执行层**(kvcpu 直接处理):
-1. **原子 rwir**:`writes <- opcode(reads...)` 或 `opcode(reads...) -> writes`。读/写角色由箭头方向决定,无隐式栈、无匿名寄存器。`writes = expr` 是 `<-` 的等价书写;`=` 不是表达式,不可嵌套在条件中。控制流原语 `call`/`return`/`br`/`goto` 是 rwir 的子集。
-2. **复合 rwir(rwfunc)**:`rwfunc funca(ra,rb) -> (wa,wb) { … }` 把多条 rwir 打包为命名单元,对外暴露相同的 `(reads) -> (writes)` 箭头接口。HandleCall 将实参绑入子帧读槽,HandleReturn 将子帧写槽写回父帧——没有"返回值",只有槽位间的数据流动。调用时**必须匹配全部写参**,不需要的用 `_` 丢弃(与 Go/Rust `_` 约定一致,写入 `_` 帧槽,不影响语义)。
-
-**源码层**(lower 后消失):`if`/`else`/`while`/`for`——lower pass 将其降级为 ScopeStmt + `br`/`goto`,kvcpu 不感知。
-
-### `->` / `<-` / `=` 与写槽
-
-三种书写形态,写槽约束完全一致:
-
-| 形态 | 写槽位置 | 例 |
-|------|---------|-----|
-| `expr -> writes` | 右 | `A + B -> C` |
-| `writes <- expr` | 左 | `C <- A + B` |
-| `writes = expr` | 左(≡ `<-`) | `C = A + B`、`p·val = 8` |
-
-**铁律**:`->` 右侧 / `<-`、`=` 左侧必须是**位置**(裸名、`/abs`、`base·名`);字面量在写槽位置是语法错误,layout 报错拒绝。
-
-调用时**写参 arity 强制匹配**(对齐 Go/Rust 阵营):`f() -> s` 对多写参函数是 layout 错误;不需要的写参用 `_` 接收。
-
-## 指令的二维空间模型:`[s0, s1]`
-
-### 两个轴的含义
-
-每条指令在 KV 树中占据一个**二维坐标** `[s0, s1]`:
-
-```
-s0 轴(横轴) — 执行顺序轴:第几条指令
-s1 轴(纵轴) — 参数轴:该槽的角色
-
- s1 < 0 s1 = 0 s1 > 0
- (读参,输入) (操作码) (写参,输出)
- ←─────────────── 0 ───────────────→
-s0 = 0 │ [0,-2] [0,-1] [0,0] [0,1] [0,2]
-s0 = 1 │ [1,-2] [1,-1] [1,0] [1,1]
-s0 = 2 │ [2,-1] [2,0] [2,1]
- ...
-```
-
-**铁律**:
-- `[s0, 0]` **永远是 opcode**(操作符或被调用函数名)
-- `[s0, -1], [s0, -2], ...` **读参**(read slots),负号代表"消费数据"
-- `[s0, 1], [s0, 2], ...` **写参**(write slots),正号代表"产出数据"
-
-### 具体示例
-
-```kv
-rwfunc add(A: int64, B: int64) -> (C: int64) {
- A + B -> C
-}
-```
-
-lower + layoutrwir 后写入 KV:
-
-```
-/lib/main·add/[0,0] = "+" ← s1=0: opcode
-/lib/main·add/[0,-1] = "A" ← s1=-1: 第1个读参(left operand)
-/lib/main·add/[0,-2] = "B" ← s1=-2: 第2个读参(right operand)
-/lib/main·add/[0,1] = "C" ← s1=1: 第1个写参(result destination)
-
-/lib/main·add/[1,0] = "return" ← s1=0: opcode(隐式 return,appendReturn 补充)
-```
-
-图示为一张二维表格:
-
-```
- s1=-2 s1=-1 s1=0 s1=1
-s0=0 │ "B" "A" "+" "C"
-s0=1 │ "return"
-```
-
-数据流方向清晰:**从负轴读入,在零轴执行,向正轴写出**。
-
-
-### 多参数指令与扇出
-
-```kv
-print("hello", x, y)
-```
-
-```
-/lib/main·foo/[3,0] = "print" ← opcode
-/lib/main·foo/[3,-1] = "\"hello" ← 第1读参(字符串字面量," 前缀编码)
-/lib/main·foo/[3,-2] = "x" ← 第2读参
-/lib/main·foo/[3,-3] = "y" ← 第3读参
-(无写参,副作用是输出)
-
-`print` 多参数直接拼接(无空格分隔),末尾不追加换行。`println` 空格分隔参数,末尾追加换行(Go 风格)。
-```
-
-写参扇出(同一结果写入多个槽):
-
-```kv
-a + b -> sum, backup
-```
-
-```
-/lib/main·foo/[2,0] = "+"
-/lib/main·foo/[2,-1] = "a"
-/lib/main·foo/[2,-2] = "b"
-/lib/main·foo/[2,1] = "sum" ← 第1写参
-/lib/main·foo/[2,2] = "backup" ← 第2写参(扇出)
-```
-
-拷贝指令(叶表达式 → 写槽)编码为显式操作码 `=`,值引用放读槽:
-
-```kv
-a -> b # [s0,0]="=" [s0,-1]="a" [s0,1]="b"
-42 -> x # [s0,0]="=" [s0,-1]="42" [s0,1]="x"
-```
-
-opcode 位**永远是操作码**,从不放变量引用——`=` 使拷贝与零参函数调用(`greet() -> x`,opcode="greet")在 KV 层无歧义。
-
-
-### 解码与写函数约束
-
-kvcpu 沿 s1 轴向两侧扩展,直到遇到空 key 停止,参数数量**隐式编码**,无需在 opcode 中存储 arity。
-
-**WriteFunc 正确性约束**:写新函数前必须先 `del_tree` 清除旧数据。若旧函数在 `[0,-1]` 有遗留值,Decode 会误读为真实读参。
-
-### 与传统字节码的对比
-
-| 维度 | 传统字节码 | kvlang `[s0, s1]` |
-|------|-----------|-------------------|
-| 指令存储 | 线性数组 `code[PC]` | KV 树 `kv·get(prefix + "[s0,0]")` |
-| 操作数位置 | opcode 后紧跟操作数 | `s1<0`(读)/ `s1>0`(写)分离 |
-| 参数数量 | opcode 内编码 arity | 隐式:扫描到空 key 停止 |
-| 数据流方向 | 单向(操作数 → 结果) | 符号编码(负=读, 正=写) |
-| 可观察性 | 字节不可独立寻址 | 每个槽是独立 KV key,可单独 Get/Watch |
-"# -> /lib/kvlang/deepdive/layout/01_instruction_architecture
-}
diff --git a/stdlib/kvlang/deepdive/layout/02-functions.kv b/stdlib/kvlang/deepdive/layout/02-functions.kv
deleted file mode 100644
index f459e099..00000000
--- a/stdlib/kvlang/deepdive/layout/02-functions.kv
+++ /dev/null
@@ -1,53 +0,0 @@
-// 欢迎加入kvspace世界
-lib kvlang/deepdive/layout/02_functions {
- r#"# 函数
-
-> 签名参数/返回值的 `type` 用签名类型表达式(并集 `A|B`、通配 `any`、高维 shape `[2,3]`、动态维 `?`),见 `grammar.bnf`。
-
-## 函数无返回值:只有读参与写参
-
-kvlang 函数**没有返回值**,只有两种参数:
-
-| 参数类型 | KV 槽位 | 方向 |
-|---------|---------|------|
-| **读参** | `[s0, -1], [s0, -2], ...` | 调用方 → 被调方 |
-| **写参** | `[s0, +1], [s0, +2], ...` | 被调方 → 调用方 |
-
-`-> result` 是**写参的跨帧路径映射**:HandleReturn 将子帧写参直写调用方帧目标路径。没有"返回值",只有槽位间的数据流动。
-
-### 写槽即位置
-
-写槽(`->` 右侧 / `<-`、`=` 左侧)必须是**位置**:裸名、`/abs`、`base·名`。字面量在写槽位置是语法错误。多写参逗号分隔,与签名写参一一对应:
-
-```kv
-divmod(17, 5) -> q, r # q←商, r←余数
-add(a, b) -> _ # _ 丢弃(约定,写入 _ 帧槽)
-```
-
-### 读参只读
-
-读参是调用方 → 被调方的输入绑定。函数体内将读参裸名放入写槽(含 `for` 迭代变量)破坏 rwir 数据流方向——layout `check_read_only_params` 报 error 拒绝装载。成员写(`A·x = v`,脱糖为 set 本体回写)不写本体,豁免。
-
-**签名诚实原则**:若函数体内写了某参数,该参数必须在写参侧:
-
-```kv
-# ❌ 签名撒谎:acc 被写但在读参侧 → 报错
-rwfunc sum(arr, acc:int64) -> (r:int64) { acc + arr[0] -> acc }
-
-# ✅ 签名诚实:acc 在写参侧,体内可读可写
-rwfunc sum(arr) -> (acc:int64) { acc + arr[0] -> acc }
-```
-
-### 定义与调用的参数同名规则
-
-**定义时**:读参与写参不得同名——`rwfunc f(A:int64) -> (A:int64)` 非法,`check_param_dup` 报错拒绝。
-
-**调用时**:同变量可同时出现在读槽和写槽——`inc(x) -> x` 合法,HandleCall 对两者独立解析,不冲突。
-
-### layout 写槽校验(`collect_write_list`)
-
-- 字面量写槽(数字/引号串开头)→ warn「unexpected token in write slot position」
-- 写槽后紧跟 `(` → warn「function call on same line as write slot」
-- 合法写槽:裸名、`/abs`、`base·名`
-"# -> /lib/kvlang/deepdive/layout/02_functions
-}
diff --git a/stdlib/kvlang/deepdive/layout/03-control-flow.kv b/stdlib/kvlang/deepdive/layout/03-control-flow.kv
deleted file mode 100644
index 4b95434f..00000000
--- a/stdlib/kvlang/deepdive/layout/03-control-flow.kv
+++ /dev/null
@@ -1,141 +0,0 @@
-// 欢迎加入kvspace世界
-lib kvlang/deepdive/layout/03_control_flow {
- r"# 控制流:Scope 帧模型
-
-# Part 1: Layout
-
-## Lower Pass(`lower_func`)
-
-`lower_func` 将 `if`/`while`/`for` 降级为 ScopeStmt + `br`/`goto`,goto/br 目标用短名(如 `_while_2`)。
-
-```
-# 源 # lower 后
-while (found == 0) { goto(_while_2)
- s = lo + hi _while_2: {
- int(s/2) -> mid found == 0 -> _1
- tries = tries + 1 br(_1, _do_3, _exit_4)
- mid == target -> hit }
- if (hit) { ... } _do_3: {
- else { lo + hi -> s
- too_low = mid < target tries + 1 -> tries
- if (too_low) { mid == target -> hit
- mid + 1 -> lo goto(_if_5)
- } }
-} _if_5: {
- br(hit, _then_6, _else_7)
- }
- _then_6: { ... }
- _else_7: {
- mid < target -> too_low
- goto(_if_9)
- }
- _if_9: {
- br(too_low, _then_10, _else_11)
- }
- _then_10: { mid + 1 -> lo; goto(_merge_12) }
-```
-
-- 所有 ScopeStmt 为函数体平级兄弟节点
-- `inject_goto_blocks` 补全提升后缺失的 goto
-- break/continue → `goto exitLabel` / `goto condLabel`
-
-## 指令布局
-
-**函数指令**:`/lib//[i,j]`(标准格式,供 extindex 解析)
-
-**Scope 指令**:`/lib//[i,j]`(flat key,scope 名直接拼在 coord 前)
-
-```
-/lib/sum_to/[0,0] ← 函数体指令
-/lib/sum_to/[1,0] ← goto _while_2
-/lib/sum_to/_while_2[0,0] ← scope 条件块
-/lib/sum_to/_while_2[1,0] ← br(bool, _do_3, _exit_4)
-/lib/sum_to/_do_3[0,0] ← scope 循环体
-```
-
----
-
-# Part 2: Runtime
-
-## 帧类型
-
-| | rwfunc 帧 | scope 帧 |
-|--|----------|---------|
-| 创建者 | `call(func, args...)` | `goto(label)` / `br(cond, t, f)` |
-| extindex | ✅ → /lib// | ❌ 不建 extindex |
-| `.rparam` / `.wparam` | ✅ | ❌ |
-| `.lib` 标记 | ✅ | ❌ |
-| `.returnpc` / `.callpc` | ✅ | ✅ |
-| 隐式 return | DelTree 整帧 | DelTree 自身,变量不可被父 scope 访问 |
-| 帧位置 | callPC | rwfunc 帧下平级子目录 |
-
-```
-/vthread/1/[0,0]/ ← rwfunc 帧(call 创建)
-├── .lib = /lib/sum_to ← rwfunc 标记(funcFrameRoot 检测用)
-├── .rparam/n → ... ← 读参零拷贝
-├── .wparam/total → ... ← 写参零拷贝
-├── .returnpc / .callpc
-├── total = 0, i = 1 ← 局部变量(所有变量均在 rwfunc 帧)
-├── _while_2/ ← scope 帧(goto/br 创建,平级)
-│ ├── .callpc ← 每次重入更新
-│ └── .returnpc ← 首次设置,不覆写
-├── _do_3/ ← scope 帧(平级)
-│ ├── .callpc
-│ └── .returnpc
-└── _exit_4/ ← scope 帧(平级)
-```
-
-## 变量作用域
-
-**所有变量存储于 rwfunc 帧 Stack**。`funcFrameRoot` 沿帧树向上查找 `.lib` 标记识别 rwfunc 帧。
-
-- 写:`resolveWriteSlot` 先查 `.wparam` 重定向,否则写 rwfunc Stack
-- 读:`resolveReadValue` 先查 `.rparam` 重定向,再查 rwfunc Stack
-- scope 帧不存储变量;scope 退出 DelTree 自身
-- 子 scope 可访问父变量(都在 rwfunc 帧),scope 退出后变量不可被父访问(scope 帧已删除)
-
-## Decode:scope 感知 key 构造
-
-scope 帧不建 extindex,Decode 手动拼接 scope 前缀 key(如 `_while_2[0,0]`),经父帧 extindex 解析到 `/lib/func/_while_2[0,0]`。
-
-## HandleScope(goto/br)
-
-`HandleScope` 在 rwfunc 帧下创建 scope 子目录,不建 extindex。`.returnpc` 仅首次设置(防止 while 循环退出路径错误),`.callpc` 每次更新。
-
-## HandleScopeReturn
-
-scope 帧隐式 return:读 `.returnpc` → DelTree 自身 → 返回父上下文。
-
-## 系统变量
-
-| 变量 | 位置 | 职责 |
-|------|------|------|
-| `.pc` | vthread 级 | 外部视图 |
-| `.callpc` | 每帧 | 本帧执行进度 |
-| `.returnpc` | 每帧 | 返回地址 |
-| `.lib` | rwfunc 帧 | extindex 目标路径(funcFrameRoot 检测用) |
-
-## HandleCall
-
-1. frameRoot = callPC,ExtIndex → /lib//
-2. 写 `.lib` = funcKey,`.returnpc`,`.callpc`
-3. 读参零拷贝:`.rparam/` → 调用方值位置
-4. 写参零拷贝:从 inst.Writes 直接读 write target(不从帧路径查)
-
-## Bootstrap
-
-虚线程根 `/vthread/1/`,extindex → 入口函数。写 `.lib` = funcKey。
-
-## 与传统 VM 的关键差异
-
-| | 传统 VM | kvlang |
-|--|---------|--------|
-| 代码传递 | copy 字节码 | **ExtIndex**(共享 /lib/ 指令树) |
-| 帧模型 | 一种帧 | **两种帧**:rwfunc + scope |
-| rwfunc 帧检测 | — | **`.lib` 标记**(避免 extindex 层叠干扰) |
-| 变量作用域 | 词法作用域 | **rwfunc 帧集中存储**,funcFrameRoot 定位 |
-| scope 指令查找 | — | **Decode scope 前缀 key** + 父帧 extindex |
-| 返回地址 | 硬件栈 | **`.returnpc`** 显式记录 |
-| 崩溃恢复 | 内存栈,死即全失 | PC + frameRoot 落 KV——重启续跑 |
-" -> /lib/kvlang/deepdive/layout/03_control_flow
-}
diff --git a/stdlib/kvlang/deepdive/layout/04-layout-pipeline.kv b/stdlib/kvlang/deepdive/layout/04-layout-pipeline.kv
deleted file mode 100644
index 1406a97a..00000000
--- a/stdlib/kvlang/deepdive/layout/04-layout-pipeline.kv
+++ /dev/null
@@ -1,37 +0,0 @@
-// 欢迎加入kvspace世界
-lib kvlang/deepdive/layout/04_layout_pipeline {
- r#"# Layout Pipeline(layout 流水线)
-
-## kvlang 流水线
-
-```
-源代码 → scanner(scan)→ []Token → parser(parse_code)→ ast::File
- → lower(lower_func) 结构化控制流 → ScopeStmt + br/goto
- → write_func AST → KV 指令树(/lib/·/[i,j])
-```
-
-layout 产物写入 `/lib/` 后由 kvcpu 执行。
-
-关键特征:
-- **PC 是 KV 路径字符串**,不是整数
-- **指令存储在 KV 树**中,通过 `kv·get` 获取
-- **控制流块(ScopeStmt)**不建 extindex,由 Decode 拼接 scope 前缀 key 解析
-
-## 与传统流水线的差异
-
-Python(CPython):AST → 基本块(整数跳转偏移)→ .pyc 字节码 → ceval 线性递增 PC。
-
-kvlang:无字节码数组,无整数 PC,控制流通过 KV 路径跳转;结构化控制流在 lower pass 降级为 ScopeStmt。
-
-## 前端设计要点
-
-- 块结构由消费 `LBrace`/`RBrace` Token 自然追踪,禁止 `strings.Count/Index` 做语法判断
-- 换行是语句分隔符(`Newline` token),`{ }` 负责块结构
-- `parser` 以 `tokens[]` + `pos` + `peek/advance/expect` 递归下降驱动
-- 错误收集不首错即止:`parser.errors: Vec` 累积全量诊断
-
-## AST 类型标记——`quote` 字段
-
-`Expr.quote` 区分字符串字面量和变量名(替代旧的 `"` 前缀 hack)。`flat()` 在 KV 传输层对字符串字面量加 `"` 前缀,数字字面量不加引号。
-"# -> /lib/kvlang/deepdive/layout/04_layout_pipeline
-}
diff --git a/stdlib/kvlang/deepdive/layout/05-diagnostic-output.kv b/stdlib/kvlang/deepdive/layout/05-diagnostic-output.kv
deleted file mode 100644
index 75de20e7..00000000
--- a/stdlib/kvlang/deepdive/layout/05-diagnostic-output.kv
+++ /dev/null
@@ -1,26 +0,0 @@
-// 欢迎加入kvspace世界
-lib kvlang/deepdive/layout/05_diagnostic_output {
- r"# Diagnostic Output(诊断输出规范)
-
-## 诊断输出架构(Rust layout + C runtime)
-
-诊断输出分两层,格式约定一致:无时间戳、无 key=value,对齐 GCC/Go/Rust 编译器风格。
-
-**Rust layout**:`Diagnostic.string()` 输出 `{kind}: {src}:{line}:{col}: {msg}`,kind 为 `error`/`warn`/`info`。`parser.errors: Vec` 累积全量诊断,不首错即止。
-
-**C runtime(`logx.c`)**:`kvlangLogDebug/Info/Error` 以 `{exe}: ` 或 `{exe}: error: ` 前缀输出到 stderr,由 `LOG_LEVEL` 环境变量控制(默认 `warn`,可选 `debug`/`info`/`error`)。
-
-## LOG_LEVEL 级别
-
-| 级别 | layout 可见 | runtime 可见 |
-|------|------------|-------------|
-| `debug` | info/warn/error 全量 | debug/info/warn/error |
-| `info` | info/warn/error | info/warn/error |
-| `warn`(默认) | warn/error | warn/error |
-| `error` | error | error |
-
-## 原则
-
-诊断(layout 报错/运行时错误)走各层的诊断接口;stdout 结果(`print` 输出、格式化内容、命令成功状态)不加前缀直接输出。
-" -> /lib/kvlang/deepdive/layout/05_diagnostic_output
-}
diff --git a/stdlib/kvlang/deepdive/layout/06-layout-rwir.kv b/stdlib/kvlang/deepdive/layout/06-layout-rwir.kv
deleted file mode 100644
index 161a5ede..00000000
--- a/stdlib/kvlang/deepdive/layout/06-layout-rwir.kv
+++ /dev/null
@@ -1,53 +0,0 @@
-// 欢迎加入kvspace世界
-lib kvlang/deepdive/layout/06_layout_rwir {
- r#"# Layoutrwir: 装载与执行
-
-## lib 树与装载
-
-`write_func` 将多个 `.kv` 文件 parse → lower → 写入 `/lib/`。每个 `lib name { }` 块形成一个 lib 节点,每个 lib 有且仅有一个 `init` 函数(init 体 + 顶层代码合并)。
-
-**CLI 入口**:
-- `kvlang ` → layout 后运行约定入口 `test`
-- `kvlang -c ""` → layout 内存源码 → 运行 `init`
-- `kvlang layout ` → 仅 layout,打印 `ENTRY=`
-
-**跨 lib 调用**:全路径 `/lib/{childlib}·{func}()`,无 `import` 关键字。
-
-## `init` 函数
-
-裸顶层代码自动封装为 `rwfunc init() -> () { }`。`lib name { }` 中各函数注册在 `/lib/·{func}`,无 lib 包裹的属匿名 lib(路径 `/lib/·{func}`)。源码副本写入 `/lib/·‥src`。
-
-## XValue Kind
-
-`/lib/` 下槽位的 XValue kind:
-
-| Kind | 示例 | 写入者 |
-|------|------|--------|
-| `rwir` | `/lib/func/[1,0] = "+"` | `write_body`(指令槽) |
-| `defrwfunc` | `/lib/func/[0,0]` | `write_func`(函数签名:`[nr\|nw][kindexp…]`) |
-| `ptr` | `/lib/func/A = →[0,-1]` | `write_func`(命名参数→slot 指针) |
-
-帧类型判定:`func_frame_root` 沿帧树向上查找 `‥lib` 标记 → rwfunc 帧;无则为 scope 帧。
-
-## `write_func`:函数布局
-
-1. `funcDir = /lib/·/`
-2. `[0,0]` → `defrwfunc` 签名(nr, nw, num_insts, kindexp 列表)
-3. 读参 `p`: `funcDir/p` → `Ptr("[0,-j]")`;写参 `r`: `funcDir/r` → `Ptr("[0,+j]")`
-4. `write_body(..., offset=1)` → 指令从 `[1,0]` 开始
-
-**EntryPC**:`root/[1,0]`(函数签名占 row 0)。
-
-## HandleCall:运行时调用
-
-1. 读 `[0,0]`(defrwfunc)→ nr, nw
-2. ExtIndex(frameRoot, funcDir)(帧→指令树)
-3. 写 `‥returnpc`、`‥callpc`、`‥lib`
-4. 读参绑入 `[0,-(i+1)]`,写参路径写入 `[0,+(i+1)]`
-5. 返回 EntryPC = `[1,0]`
-
-## `=` 操作码
-
-`a -> b` 编码为 `[s0,0]="="`(值拷贝)。函数调用 opcode 位为 `call`。opcode 槽位永远不放变量引用。
-"# -> /lib/kvlang/deepdive/layout/06_layout_rwir
-}
diff --git a/stdlib/kvlang/deepdive/layout/07-rwir-and-lib-data.kv b/stdlib/kvlang/deepdive/layout/07-rwir-and-lib-data.kv
deleted file mode 100644
index 837bda41..00000000
--- a/stdlib/kvlang/deepdive/layout/07-rwir-and-lib-data.kv
+++ /dev/null
@@ -1,86 +0,0 @@
-// 欢迎加入kvspace世界
-lib kvlang/deepdive/layout/07_rwir_and_lib_data {
- r#"# rwir 与 lib 数据:注册布局
-
-> 签名参数/返回值的 `type` 用签名类型表达式(并集 `A|B`、通配 `any`、高维 shape `[2,3]`、动态维 `?`),见 `grammar.bnf`。
-
-## 三类 KV 内容
-
-`/lib/` 下统一三类内容:
-
-| 类别 | 语义 | 有指令体? | KV Kind | 布局路径 |
-|------|------|-----------|---------|---------|
-| **rwfunc** | 用户函数 | ✅ 指令树 | `defrwfunc` | `/lib/·/` |
-| **lib 数据** | 常量 | ❌ 单个 XValue | 值类型 | `/lib/` |
-| **rwir 声明** | 扩展/用户声明 rwir | ❌ 仅签名 | `defrwir` | `/lib/` |
-
-## 铁律
-
-- **三类内容同存 `/lib/`**:无独立 `/rwir/{runtime}/` 命名空间。
-- **`defrwir` 与 `defrwfunc` 同定义体格式**:`[nr:u16 LE][nw:u16 LE][kindexp 以 "\n" 连接]`,区别仅在 KV kind 与有无指令体子节点(`[i,j]`)。
-- **native rwir 不落盘**:`+`/`==`/`array`/`sqrt` 等内建在 C runtime `builtins[]`(`opcode → bi_fn`),不写 kvspace、运行时不回查。
-
-## rwir:`/lib/`
-
-**扩展 rwir**(宿主注入,如 `numpy.add`)经 `kvlang_rwirextRegister(opcode, nr, nw, sig)` 写入 `/lib/`(kind=`defrwir`),写入前 `kvlang_rwirextTypeValid` 校验各参 kindexp。**用户 rwir 声明**(`rwir myop(A:int64) -> (C:int64)`)由 layout `write_rwir_decl` 写入同路径。
-
-**native rwir** 数值多类型算子在 `builtins[]` 中融合为单条(`add` 一条覆盖 int8…float64),派发前 `strip_num_kind` 剥掉 `·` 前缀,输出 kind 由实参决定。
-
-## lib 数据:`/lib/`
-
-`/lib/` 存单个 XValue 常量,任意 kvlang 代码以绝对路径读写:
-
-```
-/lib/math·Pi float64 3.141592653589793
-/lib/math·E float64 2.718281828459045
-```
-
-```kv
-lib math {
- /lib/math·Pi = 3.141592653589793
- /lib/math·E = 2.718281828459045
-}
-```
-
-`lib` body 内的绝对路径赋值即写常量;kv 代码直接以绝对路径访问 `print(/lib/math·Pi)`。裸名(`Pi = 3.14`)是 `/vthread` 帧局部变量、跑完回收,不入 `/lib/`。
-
-> 注:Go/oldhero 曾用 `//go:embed stdlib/*.kv` + 启动 layout+run 各 lib `init` 自举内置常量。当前 Rust layout + C runtime **不内置 stdlib 自举**;常量由用户/宿主显式 layout 写入 `/lib/`。
-
-## 落盘流程(Rust layout + C runtime)
-
-| 步骤 | 内容 |
-|------|------|
-| 建目录 | `init_dirs`:`mkindex("/lib/")`、`mkindex("/vthread/")` |
-| 写 rwfunc | `write_func` → `/lib/·/`:`[0,0]` 签名(defrwfunc)、参数 Ptr、`[i,j]` 指令(rwir,i≥1)、`‥src` 源码 |
-| 写用户 rwir | `write_rwir_decl` → `/lib/`(kind=defrwir,无指令体) |
-| 注册 native | runtime `builtins[]`,不落盘 |
-| 注入扩展 rwir | `kvlang_rwirextRegister(opcode, nr, nw, sig)` → `/lib/`(kind=defrwir) |
-
-## 示例
-
-宿主注入扩展 rwir(各参 kindexp 以 `\n` 连接):
-
-```c
-kvlang_rwirextRegister(c, "numpy.add", 2, 1, "int64|float64\nint64|float64\nint64|float64");
-```
-
-用户在 kvlang 源码声明 rwir(无体,仅签名)→ layout 落 `/lib/myop`:
-
-```kv
-rwir myop(A:int64, B:int64) -> (C:int64)
-```
-
-## 实现要点(相关文件)
-
-| 文件 | 职责 |
-|------|------|
-| `layout/src/keytree.rs` | `LIB_ROOT`/`RWIR_ROOT` = `/lib`;`lib_func`/`rwir`/`lib_src` 路径构造 |
-| `layout/src/code.rs` | `init_dirs`、`write_func`(rwfunc→`/lib`)、`write_rwir_decl`(rwir→`/lib/`) |
-| `layout/src/kvkind.rs` | `new_rwfunc` / `new_rwir` 定义体编码(`nr`u16 + `nw`u16 + `\n` 连接 kindexp) |
-| `runtime/src/keytree.c` | `kt_rwir(opcode)` = `/lib/` |
-| `runtime/src/builtin.c` | native `builtins[]`(opcode→`bi_fn`,数字多类型融合)、`strip_num_kind` 派发 |
-| `runtime/src/rwirext.c` | `kvlang_rwirextRegister(opcode, nr, nw, sig)` → `/lib/` |
-| `runtime/src/kvcpu.c` | execute 循环 `load_def_reads` + `check_read_types` 内联类型匹配 |
-| `runtime/src/type_expr.c` | `kvlang_rwirextTypeValid`(装载校验)+ `kvlang_rwirextTypeMatch`(运行时匹配) |
-"# -> /lib/kvlang/deepdive/layout/07_rwir_and_lib_data
-}
diff --git a/stdlib/kvlang/deepdive/reference/01-how-to-design-a-language.kv b/stdlib/kvlang/deepdive/reference/01-how-to-design-a-language.kv
deleted file mode 100644
index 8174d64b..00000000
--- a/stdlib/kvlang/deepdive/reference/01-how-to-design-a-language.kv
+++ /dev/null
@@ -1,121 +0,0 @@
-// 欢迎加入kvspace世界
-lib kvlang/deepdive/reference/01_how_to_design_a_language {
- r#"# reference篇-01: 如何设计编程语言
-
-编程语言设计:核心准则、设计约束与系统性避坑规范
-
----
-
-## 一、顶层设计核心原则:语言是自洽的取舍体系
-
-语言设计的核心价值不在于特性堆砌,而在于贯穿全栈的统一设计哲学与权衡体系。所有底层模块必须遵循统一约束,不存在孤立设计。
-
-必须统一对齐的核心维度:
-
-- 类型系统模型(强/弱类型、隐式转换规则、空值语义)
-- 求值执行策略(eager/lazy、执行顺序、指令语义)
-- 内存与状态模型(变量生命周期、作用域规则、状态存储方式)
-- 控制流模型(跳转、调用、返回、异常、恢复语义)
-- 错误与崩溃语义(故障恢复、状态一致性)
-- 调试与可观测性模型(状态可见、可回溯、可快照)
-- 版本与兼容策略
-
-每项特性的收益、代价、替代方案、边界场景必须可完整答辩;语言设计是长期迭代工程。
-
----
-
-## 二、语言创新的两层分级
-
-### 1. 表层创新(增量改良)
-
-仅优化语法糖、关键字、API封装,不改动底层执行与语义模型。绝大多数自研脚本语言停留在该层级。
-
-### 2. 深层创新(范式突破)
-
-重构底层执行范式、状态存储模型、控制流抽象、类型语义体系。典型例子:全新PC寻址模型、明文可持久化VM、源码即数据无独立中间层设计。
-
-学术社区(PLDI/POPL)只认可深层语义与执行模型创新,表层语法优化不构成核心贡献。
-
----
-
-## 三、可落地语言的硬性标准
-
-合格的编程语言/VM系统必须满足:
-
-- 具备可运行的完整原型,而非文字构想
-- 配套成体系测试用例:基础语法、算法案例、边界用例、负面异常用例
-- 拥有明确的错误诊断与报错机制
-- 设计语义可形式化、可与主流工作横向对比
-
----
-
-## 四、拒绝"全能杂糅设计"
-
-成熟语言遵循"有舍才有得",强行融合对立设计会导致语义冲突、维护成本爆炸。
-
-高危杂糅陷阱:
-
-- 同时混用动态/静态类型规则,无统一类型约束
-- 同时兼容隐式类型转换与强类型校验
-- 混合多种内存管理模型(GC+手动内存+所有权无规范混用)
-- 堆砌多种范式语法,无统一执行语义
-
----
-
-## 五、可观测性与故障语义
-
-顶级语言设计必须提前定义异常与崩溃体系,这是工业级系统与玩具项目的核心分水岭:
-
-- 程序崩溃后,执行状态是否可保留、可恢复、可重启
-- 运行时状态是否可观测、可遍历、可快照
-- 是否支持无侵入调试,无需附着进程、无需底层调试器
-- 状态持久化、指令回放、断点续算的底层语义
-
-这是现代分布式、训练推理、长时运行系统的核心刚需,也是传统脚本语言缺失的关键能力。
-
----
-
-## 六、学术级语言设计的四大评审标准
-
-新语言/VM获得学术认可,必须完整满足:
-
-1. **明确的动机(Motivation)**:精准指出现有语言/VM无法解决的痛点与固有架构瓶颈
-2. **清晰的执行语义(Semantics)**:类型、求值、控制流、状态变换规则可精确定义,无模糊歧义
-3. **可复现的工程实现**:可运行原型、完整测试体系、性能与功能评估
-4. **充分的横向对比**:与现有PL、VM、IR体系明确差异,论证创新性与优势
-
----
-
-## 七、语言架构设计的底层约束
-
-语言顶层设计需要长程一致性、工程约束感知、系统性取舍:
-
-- **拒绝折中妥协**:主动做艰难取舍,而非兼容所有方案、回避冲突
-- **坚持范式原创**:不能依赖整合现有特性,必须内生全新执行范式与底层架构
-- **全局一致性优先**:所有语法、语义、底层机制必须服从同一套顶层设计规范
-- **完备的边界推理**:穷举极端case、嵌套语义、异常交互、并发冲突
-- **贴合工程落地约束**:考虑存储开销、序列化、调度、硬件适配、分布式一致性
-- **可量化论证Trade-off**:能清晰阐述每项设计的长期代价、适用场景、替代方案
-
----
-
-## 八、工具与设计者的角色边界
-
-自动化工具可用于:样板代码生成、文档撰写、测试用例辅助、语法草稿、代码重构。
-
-顶层架构、执行模型、语义规范、核心取舍、体系一致性,必须由设计者独立完成与维护。
-
----
-
-## 九、范式创新型VM语言的设计要点(以kvlang为例)
-
-区别于传统语法改良型语言,范式创新型VM语言的核心设计体现在:
-
-- 重构程序状态存储与PC寻址范式(kvlang以KV路径字符串作PC,而非整数计数器)
-- 将代码与数据统一在一棵KV树,消除运行时独立内存模型与中间表示层的隔离
-- 内置全明文可观测、可持久化、支持崩溃恢复的原生语义
-- 通过扩展机制(rwir/rwext)实现算子融合;layout层只做检查与布局,runtime层只做解释执行
-
-该类项目的核心价值在于重新定义程序执行与状态存储的底层范式。
-"# -> /lib/kvlang/deepdive/reference/01_how_to_design_a_language
-}
diff --git a/stdlib/kvlang/deepdive/runtime/01-type-system.kv b/stdlib/kvlang/deepdive/runtime/01-type-system.kv
deleted file mode 100644
index de7e1b85..00000000
--- a/stdlib/kvlang/deepdive/runtime/01-type-system.kv
+++ /dev/null
@@ -1,136 +0,0 @@
-// 欢迎加入kvspace世界
-lib kvlang/deepdive/runtime/01_type_system {
- r#"# Type System(类型系统)
-
-## 类型系统
-
-kvlang 是**严格类型语言**。所有变量、参数、返回值必须有确定的类型——不允许无类型变量,不允许运行时类型隐式改变。
-
-### 数字类型:无 float/int,只有具体位宽类型
-
-**kvlang 没有 `float`、没有 `int`。** 只存在携带具体位数的数字类型:
-
-| 类别 | 类型 |
-|------|------|
-| 有符号整数 | `int8` `int16` `int32` `int64` |
-| 无符号整数 | `uint8` `uint16` `uint32` `uint64` |
-| IEEE 754 浮点 | `float32` `float64` |
-
-**设计理由**:位数是类型契约的核心部分。`int64` 跨 kvspace-go → kvspace-c → kvregion shm → op-gpu tensor dtype 传播时,每一层都依赖精确的位数。`float` / `int` 在不同语言/平台映射到不同位数,破坏跨语言类型契约。
-
-**实现约束**:XValue kindexpr 只接受上表所列 10 个精确名称。`"int"`、`"float"` 等短名在任何代码路径中均为非法 kind。
-
-### 类型归属规则
-
-| 归属 | 存放位置 |
-|------|---------|
-| **函数签名** | `/lib/·` — `defrwfunc` 值,kindexpr 列表 |
-| **指令槽引用** | `/lib/·/[s0,s1]` — `rwir` 文本引用 |
-| **运行时值** | `/vthread///` — 携带 kindexpr 的 XValue |
-
-**铁律**:
-- `def` 签名中每个参数和返回值**必须声明类型**(`name:type`)
-- 签名缺类型的 rwfunc **拒绝装载**
-- 指令槽 `[s0,s1]` 是槽位描述符,类型信息在签名中
-- 运行时通过 kindexpr 标签自描述,无需查签名
-- 与五语言对齐:C/Rust/Go 必须声明——kvlang 选此阵营
-
-### XValue 与 kindexpr
-
-XValue 是 TLV 编码的字节串,编解码由链接的 kvspace .so(`kvspaceTlvEncode`/`kvspaceDecodeHead`)负责。解码后的 head(`kvspaceHead_t`)包含:
-
-- `kindexpr`:NUL 终止字符串,格式 `[*|@][dims]base_kind`
- - 可选前缀 `*`(ptr)或 `@`(扩展句柄)
- - 可选 `[d,d,...]` 维度列表
- - 紧跟 base kind 字符串
-- `body_offset` / `body_len`:值数据在字节串中的位置
-
-**kind 完整清单**:
-
-| kind 字符串 | 说明 |
-|------------|------|
-| `"int8"` `"int16"` `"int32"` `"int64"` | 有符号整数,小端编码 |
-| `"uint8"` `"uint16"` `"uint32"` `"uint64"` | 无符号整数 |
-| `"float32"` `"float64"` | IEEE 754 浮点 |
-| `"bool"` | 1 字节:0=false, 1=true |
-| `"char/utf32"` | 码点,4B×N,**默认字符串**,定宽(可索引)|
-| `"char/utf8"` | UTF-8 字节串,1B×N,变宽(存储/交换,禁索引)|
-| `"char/ascii"` | ASCII 字节串,1B×N,定宽(可索引)|
-| `"object"` | 异构命名成员容器(类 struct/record),成员经 `·` 访问 |
-| `"stringkeymap"` | map 容器,kindexpr `key·value`(如 `[]char/utf8·int64`) |
-| `"scope"` | 词法作用域帧目录 |
-| `"index"` | 通用目录索引(尾 `/` 的 key) |
-| `"extindex"` | 扩展索引 |
-| `"rwir"` | 指令槽文本引用 |
-| `"defrwir"` | 扩展 rwir 定义(签名,存 `/lib/`) |
-| `"rwfunc"` | rwir 文本中的函数引用 |
-| `"defrwfunc"` | 用户函数定义(签名,存 `/lib/·`,kindexpr 列表) |
-
-kvkind 枚举即上表(源码 `layout/src/kvkind.rs`)。**None 不是 kvkind**——它是 kindexpr 为空的 XValue;**ptr 也不是 kvkind**——软链接以 kindexpr 前缀 `*` 表示、body 为目标 key 路径。
-
-**字符家族(`char/<编码>`)**:定宽编码(`utf32` 4B、`ascii` 1B)支持 O(1) 码点索引;变宽编码 `utf8` **拒绝索引操作**,仅用于存储/交换。判定:`IsCharKind(kind) = HasPrefix(kind, "char/")`。字符串字面量默认落 `char/utf32`。
-
-**kind 铁律——禁止别名**。`"int"`、`"float"` 等短名在任何代码路径中均非法。
-
-### 变量名即地址,未赋值即 None
-
-kvlang 的每个变量名即 kvspace 中的相对地址。声明变量即在当前帧分配一个 KV slot(如 `/vthread///x`):
-
-- **有变量名 ⇒ 有地址**
-- **有地址 ⇒ 有 XValue**
-- **未赋值 ⇒ XValue 为 None**(kindexpr 为空,`None()` 编码)
-
-None 参与算术/比较直接 TypeError,迫使代码显式初始化。
-
-**访问器分级**:
-- **宽容读取器**:`AsInt64()` 按 kind 实际宽度解码 + 符号扩展,`AsUint64()` 同理。算术/比较走宽容读取器。
-- **精确访问器**:`Int8()` `Float32()` 等严格校验 kind,不匹配返回零值。
-
-### 数字类型算子(构造器兼转换器)
-
-十个数字类型算子,**既是构造器也是转换器**:
-
-```kv
-f = float32(3) # kind=float32
-i <- int8(0.1) # 0(float→int 截断向零)
-int8(300) -> w # 44(窄化 = 补码回绕)
-```
-
-| 语义 | 对齐阵营 |
-|------|---------|
-| float→int 截断向零 | 五语言一致 |
-| 窄化 = 补码回绕(`uint8(-1)`=255) | Go / Rust `as` / C |
-| None 输入直接 TypeError | strict None |
-
-### 字符编码转换
-
-字符家族三个 kind **既是构造器也是转换器**:
-
-```kv
-s:char/utf8 = "hello"
-t <- char/utf32(s) # 转定宽(可索引)
-u <- char/ascii(t) # 拒非 ASCII 码点 → TypeError
-```
-
-### 数值运算域
-
-1. **int ∧ int → 原生 int64 运算**,溢出 = 补码回绕
-2. **任一侧 float → float64 提升**;混合比较 `3 == 3.0` 为 true
-3. **None 参与算术直接 TypeError**
-
-### Bool 铁律
-
-**bool 只能是 `true`/`false`,禁止一切隐式 coerce。**
-
-| 输入 | kvlang |
-|------|--------|
-| `true`/`false` | ✅ |
-| `0`/`1` 整数 | panic — 必须写 `!= 0` |
-| 非空字符串 | panic — 必须写 `!= ""` |
-| None | panic |
-
-隐式 coerce 会使控制流条件取决于运行时 kind,agent 无法静态判定控制流走向。强制显式比较使 br 指令的 cond 槽永远是 bool。
-
-**实现**:`kvlangXvalueAsBool`(`xvalue.c`)仅接受 `kind=="bool"`,其他 kind 直接 panic。
-"# -> /lib/kvlang/deepdive/runtime/01_type_system
-}
diff --git a/stdlib/kvlang/deepdive/runtime/02-member-access-and-data-structures.kv b/stdlib/kvlang/deepdive/runtime/02-member-access-and-data-structures.kv
deleted file mode 100644
index 82abe618..00000000
--- a/stdlib/kvlang/deepdive/runtime/02-member-access-and-data-structures.kv
+++ /dev/null
@@ -1,77 +0,0 @@
-// 欢迎加入kvspace世界
-lib kvlang/deepdive/runtime/02_member_access_and_data_structures {
- r#"# Member Access and Data Structures(成员访问与数据结构)
-
-## 两个索引符号:`[]` 与 `·`
-
-kvlang 用两个符号访问复合数据,语义严格分离:
-
-| 符号 | 目标 | 说明 |
-|------|------|------|
-| `a[i]` | **数组下标** | `[]T` 数组的元素访问,`i` 为整数 |
-| `base·name` | **容器成员 / lib 函数** | `·`(U+00B7 中点)是成员访问符 |
-
-`·` 之所以取代旧的 `.`:`.` 被释放给小数字面量与浮点 key。成员分隔符在 `layout/src/keytree.rs` 定义为 `MEMBER_SEP = "·"`,成员键 = `base·name`(`keytree::member`)。
-
-**铁律**:容器成员一律走 `·`(或 `kv·get`/`kv·set`),**绝不用 `[]`**;`[]` 只索引 `[]T` 数组。
-
-## 容器类型:object 与 stringkeymap
-
-kvlang 没有 `dict`。复合命名数据只有两种 kind:
-
-- **object**:异构命名成员,类 struct / record。成员名固定写在源码里。
-- **stringkeymap**(`kvkind.rs` KIND_MAP):一等 map 类型,kindexpr 用 `·` 分隔 `key·value`——`[]char/utf8·int64` 即 `map[string]int64`;value 可递归嵌套(`[]char/utf8·[]char/utf8·int64`)。
-
-容器 = 值 + memindex,`·` 是唯一的 memindex 标记:`base` 持容器值,`base·name` 是其成员,成员在 kvspace 中作为独立 key 落库。
-
-### 构造与写成员
-
-```kv
-rec:object = {} # 空容器字面量必须带类型标注(layout 生成 obj 构造指令)
-rec·name = "kv" # 成员写:= 值拷贝,写槽是完整成员键 rec·name
-rec·ver = 1
-m:[]char/utf8·int64 = {} # 空 map 同样须标注
-m·a = 10 # 命名成员写
-kv·set(m, "b", 20) -> _ # 动态键写
-```
-
-### 读成员
-
-```kv
-rec·ver -> v # 命名成员读,直接取 key rec·ver
-kv·get(m, "a") -> x # 动态键读;缺失返回 None
-k = "a"; m·*k -> y # 动态成员名:k 的值作为成员名(读 m·a)
-```
-
-`·*k` 动态成员语法用于**局部**容器变量。
-
-## 指针解引用:按值优先,按名回退
-
-`base·name`(读写同规则)中 base 的解析:
-
-1. **按值解引用**:base 持有非空字符串值(路径指针)→ 成员键 = `值(base)·name`。如 `"/n0" -> p` 后 `p·next` 解析为 `/n0·next`。
-2. **按名回退**:base 无值(或非字符串)→ 成员键 = `解析(base)·name`,`解析()` 帧感知:裸名 → `帧根/base`,`/` 开头 → 直通。
-
-该规则让"局部结构体"与"指针解引用"共用一套语法:结构体的 base 保持无值(按名),指针变量存路径字符串(触发按值)。
-
-```kv
-/n1:object = {} # 跨函数共享数据放绝对路径
-/n1·val = 1; /n1·next = "/n2"
-"/n1" -> p; p·val -> v # 引号=路径串(指针),按值解引用
-```
-
-## 数组元素读写(compact 形态)
-
-数组有两种存储形态:**compact**(`[...]` 字面量,元素连续打包进单个 XValue,head kind=元素类型)与 **stringkeymap**(`{...}` 字面量,散 key,每元素落 `base·i` 独立子 key、head kind=`stringkeymap`)。下标 `a[i]` / `xv·at` / `xv·set` 用于 **compact 形态**;stringkeymap 形态用 `for-in` / `kv·get` 遍历访问。compact 形态:
-
-```kv
-a:[]int64 = [7, 2, 9]
-a[1] -> e # 2(下标读,layout desugar 为 kv·get)
-a[2] = 99 # 下标写,a = [7, 2, 99]
-xv·at(a, 1) -> e # 显式读,等价
-xv·set(a, 2, 99) -> a # 显式写,等价
-```
-
-下标写用赋值式 `a[i] = v`;`->` 形式的写槽不能带下标(`v -> a[i]` 被 layout 拒绝),改用 `a[i] = v` 或 `xv·set`。
-"# -> /lib/kvlang/deepdive/runtime/02_member_access_and_data_structures
-}
diff --git a/stdlib/kvlang/deepdive/runtime/03-debugging-and-observability.kv b/stdlib/kvlang/deepdive/runtime/03-debugging-and-observability.kv
deleted file mode 100644
index 64bf110b..00000000
--- a/stdlib/kvlang/deepdive/runtime/03-debugging-and-observability.kv
+++ /dev/null
@@ -1,99 +0,0 @@
-// 欢迎加入kvspace世界
-lib kvlang/deepdive/runtime/03_debugging_and_observability {
- r#"# Debugging and Observability(调试与可观测性)
-
-## 调试模型:暂停即落盘,观察即读 kvspace
-
-kvlang 没有独立调试器进程,也没有 `--debug` 开关。调试就是**让 vthread 停在某处、把整个执行状态留在 kvspace,再用 kvspace 命令静态读取**。因为 PC 和栈帧本就是 kvspace 里的 KV 路径与值,暂停后进程可以直接退出——状态不丢,可崩溃恢复。
-
-### 暂停:`debugger()`
-
-`debugger()` 是 native builtin,等价于把当前 vthread 的 `‥status` 置 `paused`(`vthread·setstatus("paused")` 同义)。execute 循环只在 `init`/`running`/`wait` 状态下继续,读到 `paused` 即停机,进程正常退出。
-
-**关键:暂停时 PC 已前进到 `debugger()` 的下一条指令**——恢复后从下一条继续,不会重复执行断点。
-
-```kv
-rwfunc g() -> (s:int64) { debugger(); 30 -> s }
-rwfunc f() -> (s:int64) { g() -> s }
-rwfunc test() -> () { f() -> r; println(r) } # 70
-```
-
-```bash
-kvlang prog.kv # 跑到 debugger() 暂停,进程退出;输出 vthread 号(如 vthread 3)
-```
-
-### 观察 PC 与状态
-
-vthread 的运行时保留字段以 `‥`(U+2025)为前缀,不进普通目录索引,故用 `kvspace get` 直接按 key 读,不用 `tree`:
-
-```bash
-kvspace get /vthread/3/‥status # char/utf8:paused
-kvspace get /vthread/3/‥pc # char/utf8:/vthread/3/[1,0]/[1,0]/[2,0]
-```
-
-### PC 字符串即调用栈
-
-PC = `/vthread/3/[1,0]/[1,0]/[2,0]`,逐段解读(坐标 `[s0,s1]`:s0=指令行,行 0 为签名、指令从 1 起;s1=参数轴,0 为 opcode):
-
-| 路径段 | 含义 |
-|--------|------|
-| `/vthread/3/` | 根帧(test) |
-| `[1,0]/` | test 指令行 1(`f() -> r`)发起的调用 → f 帧 |
-| `[1,0]/` | f 指令行 1(`g() -> s`)发起的调用 → g 帧 |
-| `[2,0]` | g 指令行 2(`30 -> s`)——`debugger()` 在行 1,PC 已前进到此 |
-
-嵌套帧路径即调用链,无需另存栈结构。单帧程序 PC 形如 `/vthread/3/[3,0]`。
-
-### 栈帧字段
-
-每个调用帧(`/vthread//[s0,s1]/...`)的运行时字段,均 `‥` 前缀:
-
-| 字段 | 含义 |
-|------|------|
-| `‥lib` | 软链接到 `/lib/·`——指令树零拷贝共享,全帧只存一份 |
-| `‥callpc` | 发起本帧调用的指令 PC |
-| `‥returnpc` | 返回后继续的 PC |
-| `‥ro` | 只读读参绑定 |
-| `‥pc` / `‥status` | 仅根帧持有,记录整个 vthread 的当前 PC 与状态 |
-
-无 `rootfunc` 字段,也无 `.debugger` JSON 控制协议——这些是上一代设计的残留。
-
-```bash
-kvspace head /vthread/3/[1,0]/‥lib # 子帧 f 的指令树软链
-kvspace head /vthread/3/[1,0]/[1,0]/[2,0] # 当前指令槽
-```
-
-### 恢复执行
-
-暂停状态已落盘,恢复只需把状态改回 `running` 再驱动该 vid:
-
-```bash
-kvspace set /vthread/3/‥status string:running
-kvlang run 3 # 从持久化的 ‥pc 继续;子进程/重启后亦可,PC 可崩溃恢复
-```
-
-`kvlang run ` 接 vid(整数句柄,非函数名),从帧里的 `‥pc` 续跑到结束。
-
-### 观察源码:`kvlang dump`
-
-`/lib` 顶层无目录索引,`tree /lib` 为空。查看已 layout 的函数用 `dump`——它把 `/lib` 子树逆向重建为可运行 kvlang,并以 `#` 注释标出每条指令的 `[s0,s1]` 槽位:
-
-```bash
-kvlang dump prog.kv # 先 layout prog.kv,再把整个 /lib dump 为源码
-kvlang dump prog.kv /lib/g # 只 dump 某函数子树
-```
-
-签名槽 `[0,0]`(kind=`defrwfunc`)、读参绑定 `[0,-1]..`、写参绑定 `[0,1]..`、指令从行 1 起——dump 输出与此坐标系一一对应,是核对 layout 结果与定位坐标 bug 的首选透视镜。
-
-### 完整调试闭环
-
-```
-kvlang prog.kv # 1. debugger() 暂停,进程退出
-kvspace get /vthread//‥pc / ‥status # 2. 读 PC、状态
-kvspace head /vthread//<帧路径> # 3. 读栈帧变量槽
-kvlang dump prog.kv # 4. 对照源码与槽位
-kvspace set /vthread//‥status string:running
-kvlang run # 5. 恢复到结束
-```
-"# -> /lib/kvlang/deepdive/runtime/03_debugging_and_observability
-}
diff --git a/stdlib/kvlang/deepdive/runtime/04-function-call-builtin.kv b/stdlib/kvlang/deepdive/runtime/04-function-call-builtin.kv
deleted file mode 100644
index 6af05ee7..00000000
--- a/stdlib/kvlang/deepdive/runtime/04-function-call-builtin.kv
+++ /dev/null
@@ -1,80 +0,0 @@
-// 欢迎加入kvspace世界
-lib kvlang/deepdive/runtime/04_function_call_builtin {
- r#"# 函数调用(layout → runtime)
-
-## 三种调用形态,收敛到同一 KV key
-
-用户函数的调用有三种源码形态,最终都解析为 `/lib/·`:
-
-| 源码形态 | 示例 | 多级 pkg? |
-|---------|------|-----------|
-| 全路径 | `/lib/a/b·add(3, 4) -> s` | ✅ 段用 `/` |
-| 限定名 | `math·sum(3, 4) -> s` / `a/b·add(3, 4) -> s` | ✅ |
-| 裸名 | `sum(3, 4) -> s` | 同 pkg 内 |
-
-`·`(U+00B7)是成员/包分隔符(`const.h` `MEMBER_SEP`);`/` 是路径段分隔符。多级 pkg 的段用 `/`,末段用 `·` 接函数名。
-
-## Scanner(layout/src/scanner.rs)
-
-- `·` → `Kind::Dot`:成员/包限定符。
-- `/` 三态:`//` 行注释;后跟路径起始字符 → **绝对路径字面量**(`Literal`,其中 `·` 与 `.` 作路径字符读入,不再切分);否则 **除法算子**。因此 `/lib/a/b·add` 是单个 Literal token,`a/b·add` 中 `/` 也并入标识符。
-
-opcode 生成:`math·sum` → opcode `"math·sum"`;`/lib/a/b·add` → 原样;裸名 `sum` → `"sum"`。
-
-## Execute 分发(runtime kvcpu.c)
-
-派发优先级:
-
-1. `op_is_control` — call / return / br / goto
-2. `kvlangBuiltinIsNative` — native 算子(静态注册表)
-3. `is_copy_op` — opcode 为 `=` 的值拷贝
-4. `isothersrwir` — `/lib/` kind=`defrwir`(扩展 rwir)
-5. 否则 → 用户 rwfunc:opcode 移到 `reads[0]`,改写为 call 指令
-
-## HandleCall:函数名 → KV key(kvcpu.c `handle_call`)
-
-```
-if HasPrefix(fn, "/lib/"): 剥 "/lib/",rest 里 rfind("·") → pkg, name
-elif fn 含 "·": rfind("·") → pkg, name
-else (裸名,无 /lib/ 无 ·):
- 同 pkg 优先——从帧的 ‥lib 槽取调用者 pkg,
- 补成 /lib/·(lib a/b/math 内 sum → /lib/a/b/math·sum),
- 否则退回 /lib/
-funcKey = "/lib/" + pkg + "·" + name (pkg 空时 "/lib/" + name)
-```
-
-所有形态收敛到同一 key:
-
-| 源码 | KV key |
-|------|--------|
-| `/lib/a/b·add(3,4)` | `/lib/a/b·add` |
-| `a/b·add(3,4)` | `/lib/a/b·add` |
-| `math·sum(3,4)` | `/lib/math·sum` |
-
-查找失败(`[0,0]` 签名槽为 None):`NameError: rwfunc not found: `(或 `rwir 未注册/签名不匹配`、`不是 rwfunc (kind=…)`)。
-
-## Resolve:Ptr 链变量解析(kvcpu.c `resolve_read_path`)
-
-调用后指令的读写槽引用走 Ptr 链解析:
-
-```
-1. 绝对路径 → 直取
-2. 由 PC 定帧根
-3. 命名 Ptr key → Ptr 目标(参数地址)→ 值(最多三跳)
-4. fallback:帧根/名 → 局部变量
-```
-
-`·rparam`/`·wparam` 重定向表已移除,改由 Ptr 链路径别名实现零拷贝跨帧传参。
-
-## native builtin 与 kind
-
-native 算子按类别注册于 `runtime/src/builtin*.c`(无独立包目录):
-
-- 算术/比较/逻辑:`add sub mul div mod ... eq lt gt ... and or not`(源码 `+ - × ÷ % == < …` 映射到这些 opcode)
-- 容器/数组:`obj`、`map`、`array`
-- 类型构造兼转换:`int8..uint64 float32 float64 bool char/utf8 char/utf32 char/ascii`
-- 带 `·` 的方法:`string·* xv·* kv·* ndarray·* array·* vthread·* time·* random·intn`、`debugger`、`print`/`println`
-
-kind 的字节宽由 `kvlangXvalueElemSize(kind)` 决定(char/utf8=1,int32/float32=4,int64/float64=8 …),数组与字符串的元素访问据此零拷贝定位。
-"# -> /lib/kvlang/deepdive/runtime/04_function_call_builtin
-}
diff --git a/stdlib/kvlang/deepdive/runtime/05-rwirext-extension-runtime.kv b/stdlib/kvlang/deepdive/runtime/05-rwirext-extension-runtime.kv
deleted file mode 100644
index c20f0668..00000000
--- a/stdlib/kvlang/deepdive/runtime/05-rwirext-extension-runtime.kv
+++ /dev/null
@@ -1,142 +0,0 @@
-// 欢迎加入kvspace世界
-lib kvlang/deepdive/runtime/05_rwirext_extension_runtime {
- r#"# runtime篇-05: rwirext 扩展运行时
-
-> 状态:与实现同步。代码:`runtime/src/rwirext.c`(C 扩展 ABI)、`runtime-rwirext_example/rust/term`(Rust term)、`runtime-rwirext_example/go/json`(Go json)。C runtime 侧实现见 [[runtime篇-06-C运行时与后端抽象]]。
-
-## 一、核心模型
-
-kvlang runtime 是**中央调度 runtime**,默认执行全部 native rwir / rwfunc / 控制流。某些 rwir(tensor 计算、LLM 调用、agent 循环)不由它求值,而是交给**扩展运行时**。
-
-**扩展运行时 = 只解析己方 opcode 的迷你 kvcpu**:从中央 runtime 拿到 PC,连续执行己方 rwir,直到遇到非己方指令,把最终 PC 交还中央 runtime。
-
-| 类别 | rwir 示例 | 扩展运行时 |
-|------|----------|-----------|
-| 计算委托 | `tensor·matmul(a,b) -> c` | op-gpu |
-| API 封装 | `llm·chat(prompt) -> resp` | llm worker |
-| Agent 封装 | `agent·search(q) -> r` | sub-agent |
-
-**核心公理**:
-
-1. **rwir 自描述**:opcode + 读写参已含执行所需全部信息。
-2. **注册即签名**:扩展运行时写 `/lib/`(kind=`defrwir`,含签名),不再有 `/sys/`。
-3. **批量执行**:扩展运行时连续执行己方 rwir 到非己方指令,把最终 PC 写回 `/vthread//pc`。
-4. **被动消费**:扩展运行时只监控己方 `/lib//vids` 队列。
-
-## 二、注册与发现
-
-### 签名注册
-
-扩展运行时把己方每个 opcode 的签名写到 `/lib/`(kind=`defrwir`,空函数体,仅签名):
-
-定义体格式 `[nr:u16 LE][nw:u16 LE][读参+写参 kindexpr,"\n" 连接]`(详见 [[runtime篇-07-签名类型表达式]] §八):
-
-```
-/lib/json·to → defrwir(nr=1, nw=1, "char/utf8\n[]char/utf8")
-/lib/print → defrwir(nr=1, nw=0, "any...")
-```
-
-**与 native builtin 的区分**:native 签名不落盘——内建在 C 注册表 `builtins[]`(`opcode → bi_fn`),直接查表;扩展签名落 `/lib/`(kind=`defrwir`),C runtime 通过 `isothersrwir` 识别:读 `/lib/` 的 kind,等于 `defrwir` 即为扩展 rwir。
-
-### 全局标记
-
-`kvlang_rwirextRegister` 标记裸 opcode(如 `print`/`input`)在 layout 阶段不被补 `pkg·` 前缀。带 `·` 的限定 opcode(`json·to`)本就不被补前缀。
-
-term 在**进程启动时**注册全局:与中央 runtime 同进程,`vet`/`format` 也会 layout 用户代码,若不在启动期注册,裸 opcode 会被补 `pkg·` 前缀。
-
-### 幂等重注册
-
-`kvlang_rwirextRegister` 幂等。若 vids 队列已存在则跳过——否则重复注册时 Set 经路径穿透会把首队列改成自指 Ptr,令 `resolve_path` 死循环(共享 redis 时的挂起根因)。
-
-## 三、handoff 协议
-
-### 键布局
-
-```
-/lib//vids/ = pc # 中央 runtime 写,扩展运行时消费(strkeymap 队列)
-```
-
-第一个 rwir 的 vids 是真实 strkeymap;后续同 opcode 的 vids 是 Ptr 指向第一个(共享同一队列)。
-
-### 时序
-
-```
-kvlang runtime(C) 扩展运行时
-───────────────── ──────────
-1. isothersrwir(opcode) 命中
-2. handoff_external_rwir:
- Set /lib//vids/=pc
- 3. 发现队列中的 vtid
- RunSeq(pc):逐条执行己方 rwir 到非己方指令
- WriteFinalPC:Set /vthread//pc = finalPC
- Del /lib//vids/
-4. Watch 直到 vtid 从队列消失(30s 超时)
-5. 继续(PC 已由扩展运行时写回)
-```
-
-中央 runtime **不推进 PC**——扩展运行时批量执行后已写回最终 PC,中央 runtime 直接读新 PC 继续。
-
-### RunSeq(顺序执行)
-
-扩展运行时从 PC 起逐条解码,只要 opcode ∈ 己方集合就执行,遇第一条非己方指令即停。**顺序执行,非并行 batch**:ext rwir 之间存在顺序依赖。
-
-## 四、kvcpu 集成(C dispatch 链)
-
-`kvcpu.c:kvlangRuntimeExecuteVthread` 的 dispatch 链:
-
-```
-1. op_is_control → handle_control (call/return/br/goto)
-2. kvlangBuiltinIsNative → kvlangBuiltinNative (~50 native 算子,静态注册表)
-3. is_copy_op → kvlangBuiltinExecuteCopy (= 赋值)
-4. isothersrwir → handoff_external_rwir (/lib/ kind=defrwir)
-5. else → 重写为 call(用户函数)
-```
-
-`isothersrwir(kv, opcode)`:`opcode[0]=='/' → false`;否则读 `/lib/`,kind==`defrwir` → true。
-`handoff_external_rwir`:Set 共享队列、Watch 直到消费完成(30s 超时),不推进 PC。
-
-Rust runtime(runtime-rs)中,**就地 rwir**直接在 `run_vid` 驱动循环里派发(`rwir::is_inproc(op)` 命中 → `rwir::dispatch`),无 handoff、无 watch、与中央 runtime 同进程。当前就地集合(`rwir/mod.rs::is_inproc`):
-
-```
-term print / println / cerr / input
-json json·to / json·from
-http http·call
-layout kvlanglayout·vet / ·format / ·layout / ·dump
-networld networld/proc·exec
- networld/fs·size / ·read / ·write / ·append / ·list / ·del / ·mkdir / ·exists
-```
-
-非就地 rwir(如 numpy tensor 计算)经 `kvlang_rwirextHandoff` 移交独立进程扩展。**注意**:就地与独立进程只是**执行位置**之别,职责线一致——两者都只经 `kvlang_rwirext*` 解析参数、只经 `kvspace*` 正典 ABI 读写与编解码(详见 [[runtime篇-06-C运行时与后端抽象]] §七)。
-
-## 五、标杆:term 与 json
-
-| | term | json |
-|--|------|------|
-| op | print/println/cerr/input | json·to/json·from |
-| 进程 | 与中央 runtime 同进程 | 独立进程 |
-| opcode | 裸名(启动期注册全局) | 带 `·` 限定(`json·to`) |
-
-两者结构统一:`kvlang_rwirextRegister` + `Serve` 循环 + `exec` 分发。livebyte/op-gpu 扩展照此模板。
-
-## 六、与 /ext/ 拓扑的关系
-
-| 目录 | 回答 | 内容 |
-|------|------|------|
-| `/lib/` | 有什么 op(签名) | `defrwir` 签名(读参/写参/类型) |
-| `/ext/` | 在哪、怎么执行(拓扑) | 存储/计算/通信注册 |
-
-无状态扩展运行时(term/json)只写 `/lib/`;有状态扩展引擎(op-gpu/heap-plat)写 `/lib/` + `/ext/`。handoff 协议一致,后者多一次 `/ext/` 查表定位引擎。
-
-## 七、扩展的职责与不可越界
-
-扩展回答的唯一问题是「**算什么、怎么算**」——tensor 怎么乘、LLM 怎么调、JSON 怎么按类型分发写回子树。它**不回答**「值长什么样、指令怎么解码、类型怎么校验」——这些是 runtime-c 的值语义,扩展只**调用**、不**复刻**。
-
-扩展只有三个合法动作,一步都不许多做:
-
-1. **拿 PC**:从 handoff 队列 / drive 循环取当前 PC,跑己方 rwir,`NextPc` 求后继。
-2. **解析参数**:**只经** `kvlang_rwirext*`(`Params` / `ResolveRead` / `ResolveReadPath` / `ResolveWrite`)。不自行解析 rwir 槽位。
-3. **读写 kvspace**:**只经** `kvspace*` 正典 ABI(`Get` 借用读、`WriteInPlace`/`WriteNewPlace` 写、`TlvEncode`/`DecodeHead` 编解码)。**绝不自造 kindexpr 构造器、绝不手写 TLV/head。**
-
-**曾越界、已拉回**:runtime-rs 一度有 Rust 版 `build_kindexpr`(与 `frontend.c` 逐字节等价)——对编解码器的复刻,违反职责线,**已删**,编码统一走 `kvspaceTlvEncode`。唯一保留的例外是 json 反序列化里的 kindexpr 串**解析器**(`json.rs::parse_kindexpr`):kvspace 只导出编码器不导出串解析器,而「按类型/形状把外部文本分发写回」是扩展**自身的反序列化职责**,故留在扩展侧,且只读 head、不造 head。runtime-c 侧的权威边界见 [[runtime篇-06-C运行时与后端抽象]] §七。
-"# -> /lib/kvlang/deepdive/runtime/05_rwirext_extension_runtime
-}
diff --git a/stdlib/kvlang/deepdive/runtime/06-c-runtime-and-backend-abstraction.kv b/stdlib/kvlang/deepdive/runtime/06-c-runtime-and-backend-abstraction.kv
deleted file mode 100644
index c9ae8418..00000000
--- a/stdlib/kvlang/deepdive/runtime/06-c-runtime-and-backend-abstraction.kv
+++ /dev/null
@@ -1,102 +0,0 @@
-// 欢迎加入kvspace世界
-lib kvlang/deepdive/runtime/06_c_runtime_and_backend_abstraction {
- r#"# runtime篇-06: C 运行时与后端抽象
-
-> 状态:与实现同步。代码:`kvlang/runtime/`(纯 C)、`kvlang/runtime-rwirext_example/rust/term/`、`kvlang/runtime-rwirext_example/go/json/`、`kvlang/runtime-rwirext_example/py/numpy/`、`array2d/kvspace-c/`(SHM)、`array2d/kvspace-durable/`(fs/redis)。
-
-## 一、小 runtime 大扩展
-
-kvlang 是**小 runtime 大扩展**架构。中央 runtime 只实现最核心的 execute 大循环(fetch-decode-execute、call/return/br/goto、native rwir 派发、`=` 拷贝、用户函数调用),其余能力(tensor 计算、LLM、agent、print/println/cerr)全部交给**扩展 runtime**。
-
-扩展 runtime 从中央 runtime 拿到 PC,连续执行己方 rwir 到非己方指令,再把最终 PC 交还。op-gpu 扩展收到 handoff 后连续跑完整段 tensor 计算,不必每算一个 op 就回报中央。
-
-## 二、C 运行时(纯 C + extern "C" ABI)
-
-`kvlang/runtime/` 是通用嵌入式执行器,嵌入到 rwirext 项目(op-gpu、agent、livebyte)。
-
-**两组对外 C ABI**:
-- `kvlang_runtime.h`(`kvlangRuntimeConnect/Disconnect/Execute/Bootstrap/...`):核心执行器
-- `kvlang_rwirext.h`:扩展 runtime 语义,**只暴露 kvspace 不提供的部分**。KV 存取(connect/get/write/del/list/tlv)**不在此**——扩展宿主自己连 kvspace ABI,把 kvspace 句柄(`void *`)传进带句柄的 rwirext 函数。
-
-`kvlang_rwirext.h` 现有 9 个符号:`Register`(写 `/lib/` 签名)、`Handoff`(把非己方 rwir 移交外部执行器)、`NextPc`(纯函数,下一条 PC)、`Params`(opcode + 读/写参名,\n 分隔)、`ResolveRead`/`ResolveReadPath`/`ResolveWrite`(读/写参解析,`ResolveReadPath` 供零拷贝读整块 ndarray)、`KindexprValid`/`KindexprMatch`(签名类型表达式校验与值判定)。**print/println/cerr 不在此**——term 扩展与中央 runtime 同进程,在 drive 循环里就地 `ResolveRead` + display,直写宿主 stdout/stderr,无专用打印 ABI。
-
-**模块**(内部实现统一 `kvlang`/`kvspace` 前缀):`xvalue.c`(TLV 编解码)、`kv.c`(kvspace ABI 封装)、`keytree.c`(路径构造)、`rwir.c`(PC 解析 + Decode)、`vthread.c`、`builtin.c`(~50 native 算子 + 静态注册表)、`kvcpu.c`(Execute 循环)、`runtime.c`(ABI 层)、`rwirext.c`(扩展 ABI,含 `isothersrwir`)。
-
-**注册表**:静态数组 + 线性查找(C 版,对应 Go 原 `map[string]nativeRwir`)。
-
-**print/println/cerr 是扩展 rwir**(不在 builtin),在 `/lib/`(kind=`defrwir`)注册,dispatch 经 `isothersrwir` 命中。执行分两种模式:
-- **嵌入式**(`KVMODE_RETURN`):runtime-rwirext 的 Rust `term` 与 runtime 同进程,execute 循环经 `out_pc` 把控制交回扩展,扩展直接写宿主进程 stdout/stderr,零轮询。
-- **handoff**:`handoff_external_rwir` 写 `/lib//vids/`,watch 消费完成(30s 超时),供独立进程扩展(Go json、Py numpy)。
-
-## 三、kvspace 统一 C ABI(去特化)
-
-layout 与 runtime **都不对 kvspace 做特化处理**:不 dlopen、不双后端、不解析 scheme。二者只走一套 `kvspace*` 兼容 C ABI(无下划线 camelCase):
-
-```
-kvspaceConnect / Close
-kvspaceGet // 借用读:*out 指向后端常驻/回收空间,调用方不得 free
-kvspaceWriteInPlace // key 已存在且 body_len 相等 → 返回原 box body 偏移指针
-kvspaceWriteNewPlace // 否则按 (kindexpr, body_len) 分配新 box、写 head,返回 body 指针
-kvspaceListLen / ListAt / Del / DelTree / Cp / CpTree
-kvspaceMkindex / MkindexExt / RmindexExt / Watch
-kvspaceTlvEncode / TlvEncodeMode / DecodeHead
-kvspaceNewPtr / NewChar / NewBool / NewInt64 / NewFloat64
-```
-
-**零拷贝写读模型**:读走 `kvspaceGet`——返回后端常驻内存的**借用偏移指针**,调用方只读、**不 free**(旧 `kvspaceBytesFree` 已删)。写不再有「先 encode 整条 TLV 再交后端」的 `kvspaceSet`(已删):改为向后端**要一个可写 body 偏移指针**再直接写字节——`kvspaceWriteInPlace`(key 已存在且 body 尺寸不变,原 box 就地改)与 `kvspaceWriteNewPlace`(新建 / 换 kind / 换尺寸,分配新 box 并写 head)两条原语,各自唯一、无中转 buffer。前缀枚举同样不再一次性返回整段名单缓冲(旧 `kvspaceList` 已删,连同批量读的 `kvspaceGetBatch`):`kvspaceListLen` 只返子项计数、无缓冲无需释放,`kvspaceListAt(idx)` 借用回收缓冲逐项取名——遍历即「先 ListLen 定计数、再逐 idx ListAt」,与借用读模型一致、绝不外泄大块名单。
-
-**后端由链接决定**:`KVLANG_KVSPACE_LIB` 环境变量在**构建期**选择链接哪个 kvspace 库(`kvspace-c` 或 `kvspace_durable`),两者导出同一 ABI。runtime 的 `kvlangKv_t` 只保留 `void *h`,代码零后端分支。
-
-**kvspace-c 补齐 ABI**:`kvspace-c/src/durable_abi.c` 导出完整符号(内部复用 `kvspaceShm*` + `kvspaceXvalue*`),其中 `Watch`(轮询到值==target 或超时)为补齐的手工实现。
-
-## 四、三个后端
-
-| 后端 | 库 | 存储 | 场景 |
-|------|-----|------|------|
-| shm | kvspace-c(C) | ART 树 + slotsboxmalloc + file-backed mmap | 高性能(训练/推理) |
-| redis | kvspace-durable(Rust) | Redis | 基线验证 |
-| fs | kvspace-durable(Rust) | 文件系统 | 本地持久化 |
-
-`conn(dsn)` 按 scheme 选后端(`shm://`、`redis://`、`fs://`),DSN 是唯一的后端区分。
-
-## 五、numpy 扩展(零拷贝 buffer 在 kvspace)
-
-`runtime-rwirext_example/py/numpy/` 是第一个 tensor 类 rwirext(CPU 侧,为 op-gpu 铺垫)。tensor 本体较大,**走 kvspace-c SHM**(redis/fs 有 I/O 拷贝)。
-
-**零拷贝核心**(`numpy.py` 的 `Engine.view`):tensor 存 kvspace 为 XValue 定长数组(`float64`/`int64` 等)。`view(key)` 经 `kvspaceShmGet` 拿 TLV 指针,`kvspaceDecodeHead` 解出 `kvspaceHead_t` 定位 body 段,用 `numpy.ctypeslib.as_array` 在该地址建 ndarray——ndarray 的 buffer 就是 SHM 的 raw data,读写 ndarray 即读写 kvspace,无拷贝;写走 `kvspaceTlvEncode` 直接 N 维落盘。
-
-**扩展宿主自连 kvspace**:`Engine` 自己 `kvspaceConnect(dsn)` 拿句柄,rwir handoff 只用 `kvlang_rwirext*` 的 runtime 语义(`Register/Params/ResolveRead/ResolveReadPath/ResolveWrite/NextPc`)。Go json 扩展同构。
-
-**测试**:`tutorial/14-numpy/`(六例:creation/elementwise/linalg/reduce/manipulation/pipeline,shm 全流程)。
-
-## 六、验证(Rust term 扩展 + C runtime)
-
-`tutorial/test.py --runtime c`(Rust layout → kvspace → C runtime),全量 tutorial:
-
-| 后端 | 结果 |
-|------|------|
-| shm | **185 PASS / 0 FAIL / 3 SKIP** |
-| redis | **185 PASS / 0 FAIL / 3 SKIP** |
-| fs | **185 PASS / 0 FAIL / 3 SKIP** |
-
-三后端**语义完全一致**——早期 redis/fs 上 `prime_sieve` 的超时与 `time.kv` 的 RTT/文件 I/O 时序偏差已随指令重读稠密探查修复(`RwirDecode` 遇空槽即停,不再每步固定读满 257 槽),不再有后端专属失败。3 个 SKIP 为跨进程扩展 / WIP 用例,三后端一致跳过。
-
-**后端存储布局差异(非语义 bug)**:fs 后端(`kvspace-durable/src/fs`)把成员分隔符 `·`(OBJ_SEP)编码为 `·/`——尾中点目录 + `/` 目录边界,故限定名 `/lib/math·sum` 在 fs 上呈嵌套目录 `lib/math·/sum`,而 redis/shm 后端存为扁平单键 `/lib/math·sum`。读写经对称编解码还原(`·/`↔`·`),三后端语义一致。
-
-## 七、runtime-c 的边界与扩展的职责(单一正确路径)
-
-「小 runtime 大扩展」不是模糊分工,而是一条**不可越界**的职责线。runtime-c 独占三件事,扩展一件都不许重做:
-
-**runtime-c 拥有(唯一实现,扩展不得复刻)**:
-1. **执行核心**:fetch-decode-execute 大循环、call/return/br/goto、vthread 调度、native builtin 派发(~50 基础算子)、`=` 拷贝语义。
-2. **值语义与编解码**:TLV / kindexpr 的**唯一编解码器**在 kvspace 正典 codec(`kvspaceTlvEncode` / `kvspaceDecodeHead` / `kvspaceNewPtr/NewChar/NewBool/NewInt64/NewFloat64`),runtime-c 的 `xvalue.c` 只是其薄封装。kindexpr 串是类型的唯一真相,怎么拼、怎么解,只此一处。
-3. **指令解码与签名校验**:`rwir.c` 的 `RwirDecode`(稠密探查、遇空即停)、`/lib/` 签名的读写码规范、`KindexprValid` / `KindexprMatch` 类型判定。
-
-**扩展只许做三件事(无论就地 rwir 还是独立进程)**:
-1. **拿 PC**:经 handoff / drive 循环从 runtime 拿到当前 PC 与后继 PC(`NextPc`),连续跑己方 rwir。
-2. **解析参数**:**只经 `kvlang_rwirext*` 宿主 ABI**(`Params` / `ResolveRead` / `ResolveReadPath` / `ResolveWrite`)拿读/写参名与值。不许自行解析 rwir 槽位。
-3. **读写 kvspace**:**只经上文的 `kvspace*` 正典 ABI**。要落一个类型化值,走 `kvspaceTlvEncode` + `WriteInPlace/WriteNewPlace`;**绝不自造 kindexpr 构造器、绝不手写 TLV/head**。
-
-**一条曾越界、已拉回的实例**:runtime-rs 早期在 Rust 侧有一份 `build_kindexpr`,与 `frontend.c` 逐字节等价——这是对编解码器的复刻,违反职责线,**已删除**,所有编码统一路由到 `kvspaceTlvEncode`(见 `ffi.rs::tlv_encode` 注释「唯一编码入口,不在 Rust 侧复刻 kindexpr 构造」)。**唯一保留的例外**是 json 扩展反序列化里的 kindexpr 串**解析器**(`json.rs::parse_kindexpr`):kvspace 只导出编码器、不导出串解析器,而「把外部 JSON 文本按类型/形状分发写回子树」是扩展**自己的反序列化职责**,不属于 runtime-c 的值语义——故这份解析留在扩展侧,且只读 head 不造 head。这条例外恰恰印证边界:**能调用 kvspace 的,一律调用;kvspace 没提供、且属扩展自身语义的,才自理**。
-"# -> /lib/kvlang/deepdive/runtime/06_c_runtime_and_backend_abstraction
-}
diff --git a/stdlib/kvlang/deepdive/runtime/07-signature-type-expression.kv b/stdlib/kvlang/deepdive/runtime/07-signature-type-expression.kv
deleted file mode 100644
index 4f8e19d8..00000000
--- a/stdlib/kvlang/deepdive/runtime/07-signature-type-expression.kv
+++ /dev/null
@@ -1,135 +0,0 @@
-// 欢迎加入kvspace世界
-lib kvlang/deepdive/runtime/07_signature_type_expression {
- r#"# runtime篇-07: 签名类型表达式(多态 + 高维数组)
-
-> 状态:设计定稿。代码:签名字符串存 `/lib/·`(kind=`defrwfunc`/`defrwir`),参数类型即本文件的「类型表达式」。
-
-## 一、动机
-
-函数签名里参数/返回值的类型需要支持**多态**(一个参数声明时接受多种类型,含高维数组),需要一个:
-
-- 人和 AI 都容易读、容易生成的类型定义表达式;
-- 不比正则长;
-- 不撞 kvlang 的 rwir/rwfunc 语法分隔符(`(` `)` `,` `:` `->` 空格)。
-
-**kind 铁律**:`charbyte` 是旧名,一律作废,字符类型用 `char/utf32` / `char/utf8` / `char/ascii`。
-
-## 二、文法
-
-```
-type := union ( "..." )? # 末参可带 "..." 变参:0..N 个同型实参
-union := atom ( "|" atom )* # 并集:A|B 表 A 或 B
-atom := dims ( any | kind )
-dims := ε # 无 [] = 标量(0 维)
- | "[]" # 空 [] = 1 维、长度任意(等价 [?])
- | "[" dim ("," dim)* "]"
-dim := int | "?" # 精确大小 或 动态维
-any := "any" # 通配,匹配任意 kind
-kind := 精确 kind 串(bool、int8..int64、uint8..uint64、float32/64、char/utf32|utf8|ascii、object、stringkeymap、scope、index、extindex、rwir、defrwir、rwfunc、defrwfunc)
-```
-
-**变参 `...`**:仅**末**读参可带尾缀 `...`(如 `A:any...`、`A:int64|float64...`),表「0..N 个同型实参」。用于 `print`/`println`/`cerr`/`min`/`max` 等 arity 开放的 rwir。非末参带 `...` 是装载期错误。
-
-**铁律:无家族简写**。`int`/`uint`/`float`/`num` 这类简写**不提供**——位宽是开放集合(未来有 int4、fp8、fp16…),封闭枚举会漏。`char` 编码简写同样不提供。多态靠显式 `|` 枚举:`int8|int16|int32|int64`。仅保留一个与「位宽/编码枚举」无关的简写:
-
-| 简写 | 展开 | 说明 |
-|------|------|------|
-| `any` | 全部 kind | 通配,不是位宽/编码聚族 |
-
-## 三、实例
-
-```
-A:int64 # 标量 int64
-A:int64|float64 # 标量并集(多态核心)
-A:int8|int16|int32|int64 # 任意整数(显式枚举)
-A:char/utf8 # 单个 utf8 字符(标量);字符串用 []char/utf8
-
-A:[]float32 # 1-D float32,长度任意(= [?]float32)
-A:[2]float32 # 1-D,恰好 2 元素
-A:[2,3]float32 # 2-D,恰好 2×3 矩阵
-A:[?,768]float32 # 2-D,第一维动态、第二维 768(weight 场景)
-A:[]float32|[]float64 # 多精度 1-D
-
-A:[2,3]float32|float32 # shape 或标量
-A:bool|char/utf8 # bool 或 单个 utf8 字符
-A:index|object # 目录或命名成员容器
-```
-
-## 四、匹配语义
-
-一个值(kind=`k`,ndim=`n`,dims=`d`)匹配类型表达式 `E` 的判定:
-
-```
-match(E, k, n, d):
- 对 E 按 "|" 拆成若干 atom,任一 atom 命中即 true
- matchAtom(atom, k, n, d):
- atom == "any" → true
- 有 "[" 前缀 → 解析出 shape 与剩余 type:
- matchShape(shape, n, d) 且 base(type) 匹配 k
- 无 "[" → 单值:n == 0 且 kind 匹配 k
- matchShape(shape, n, d):
- shape == "" → n == 1 # "[]" 等价 "[?]":恰一维、任意长
- len(拆逗号) != n → false
- 逐维:p=="?" 跳过;否则 d[i] == int(p)
-```
-
-## 五、语法冲突规避(`[` `]` 感知切分)
-
-签名用 `,` 分隔参数,shape 里也用 `,` 分隔维:
-
-```
-matmul(A:[2,3]float32, B:[3,4]float32) -> (C:[2,4]float32)
-```
-
-解法:签名解析器**跟踪方括号深度**——见 `[` 进 shape 态、见 `]` 退出;shape 态内的 `,` 归维、shape 态外的 `,` 归参数。类型表达式可出现的字符里,`(` `)` `:` `->` 空格**都不出现**,故与签名外层结构无歧义。
-
-## 六、匹配器实现
-
-Rust 侧在 `layout/src/kindexpr.rs`;C 侧在 `runtime/src/kindexpr.c`(`kvlang_rwirextKindexprValid` / `kvlang_rwirextKindexprMatch` / `kvlang_rwirextKindexprVariadic`)。
-
-```go
-func match(expr, kind string, ndim int, dims []int32) bool {
- for _, atom := range strings.Split(expr, "|") {
- if matchAtom(atom, kind, ndim, dims) { return true }
- }
- return false
-}
-func matchAtom(atom, kind string, ndim int, dims []int32) bool {
- if strings.HasPrefix(atom, "[") {
- end := strings.Index(atom, "]")
- if !matchShape(atom[1:end], ndim, dims) { return false }
- return matchAtom(atom[end+1:], kind, -1, nil)
- }
- if ndim >= 0 && ndim != 0 { return false }
- switch atom {
- case "any": return true
- default: return atom == kind
- }
-}
-```
-
-`any` 是唯一简写,`kind` 走精确字符串相等。
-
-## 七、多态派发
-
-- native 算子(`+`)内建多态,签名只做类型检查。
-- rwirext 扩展(numpy·add)经 `kvlang_rwirextResolveRead` 拿实参实际 kind,按精确 kind 分派;高维 shape 由扩展自行处理。
-- rwfunc 用户函数:并集声明接受集,函数体 `kind(x)` 分支。
-
-## 八、参数 kindexpr 的落盘与运行时内联匹配
-
-**铁律**:rwir/rwfunc 每个参数落盘的 **kindexpr 与源码里的类型定义表达式逐字节相同**(同一文法,含 `...`)。
-
-**统一落盘于 `/lib/`**。rwir 定义(扩展算子)与 rwfunc(用户函数)**同一存储位置**——不再有独立的 `/rwir/{runtime}//` 槽位树。定义体(`char/utf8` 值)布局:
-
-```
-[nr : u16 LE][nw : u16 LE][读参 kindexpr × nr, 再 写参 kindexpr × nw,全部以 "\n" 连接]
-```
-
-**native op 不落盘**:其 kindexpr 内联在 C 注册表中,是唯一权威来源,**运行时匹配直接读 C 表,不回查 kvspace**。数值多类型算子在 C 表中融合为单条(如 `add(a:int64|int32|…, b:…)`)。
-
-**扩展 op** 经 `kvlang_rwirextRegister(opcode, nr, nw, sig)` 注册,runtime 把 `sig` 按方括号感知切分为各参 kindexpr、做 `kvlang_rwirextKindexprValid` 校验(拒绝 `path` 等非 kind),并按上述定义体格式写入 `/lib/`(kind=`defrwir`)。
-
-**运行时内联匹配**:execute 循环走到 `isothersrwir` 派发前,按 opcode 从 `/lib/` 取定义体、解出读参 kindexpr,对每个已解析实参(kind/ndim/dims)跑 `kvlang_rwirextKindexprMatch`;变参 `...` 把尾随实参全部对末 kindexpr 判定。任一失配 → `TypeError` 写 vthread 错误并停机。
-"# -> /lib/kvlang/deepdive/runtime/07_signature_type_expression
-}
diff --git "a/stdlib/kvlang/spec/00-\345\257\274\350\250\200/01-\350\214\203\345\233\264\344\270\216\344\270\200\350\207\264\346\200\247.kv" "b/stdlib/kvlang/spec/00-\345\257\274\350\250\200/01-\350\214\203\345\233\264\344\270\216\344\270\200\350\207\264\346\200\247.kv"
new file mode 100644
index 00000000..95601a7f
--- /dev/null
+++ "b/stdlib/kvlang/spec/00-\345\257\274\350\250\200/01-\350\214\203\345\233\264\344\270\216\344\270\200\350\207\264\346\200\247.kv"
@@ -0,0 +1,37 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/导言/范围与一致性 {
+ r####"# 范围与一致性
+
+## 本规范的地位
+
+本规范是 kvlang 语言的**唯一事实源**。语言核心的任何设计或实现调整,一律**规范驱动**:先改本规范的相应条款及其锚定示例,再改实现,直至锚例在三后端全绿。规范与实现不符时,以规范为准,实现视为缺陷。
+
+规范以 kvlang 自身书写(`.kv`),layout&run 后落进 `/lib/kvlang/spec/…`——规范即 KV 树里的数据,可被 kvlang 自解析与自校验。
+
+## 范围
+
+本规范界定 kvlang 语言本体:
+
+- **词法**(卷 01)——源码表示、词法单元、注释、标识符、字面量、运算符。
+- **kvspace 模型**(卷 02)——地址空间、寻址与命名、键系统与数组访问、指令布局格式、系统变量。kvspace 既是寻址空间也是内存空间,是 kvlang 的第一性前置概念,故前置于语义两卷。
+- **类型系统**(卷 03)——种类与定宽类型、kindexpr 签名类型表达式、数组形态、容器。类型跨 layout 与 runtime 两阶段,故独立成卷。
+- **layout 语义**(卷 04)——静态语义:语法检查与布局。layout 是 **o0 编译器**:做检查、布局与降级,**不做任何优化**(一旦优化即丢失高层语义,使扩展编译器无法按原语义在异构硬件上优化),可报诊断。
+- **runtime 语义**(卷 05)——动态语义:纯解释执行。
+
+附录给出唯一权威文法;设计理由卷为非规范(non-normative)的动机说明。
+
+## 核心与扩展边界
+
+kvlang 是**小核心 + 扩展主导**的语言。本规范只界定语言核心必须保证的语义,以及核心与 rwir 兑现方之间的契约(def rwir 路由头与各 runtime 的 myrwircaps)。具体 runtime(numpy、fs、networld、gpu 等)提供的 rwir 实现不属本规范,由各 runtime 文档界定;kv 源码**不声明** rwir——`def rwir` 路由头由各 runtime 注册到 `/lib`,本规范只规定 kvlang 如何定位与调用 rwir、经 def rwir 路由兑现(见卷 05)。
+
+## 一致性
+
+**tutorial 套件即一致性测试。** 一个实现是否符合本规范,由 `tutorial/` 下的可运行 `.kv` 示例判定:三后端(shm / fs / redis)全部通过、输出逐字节一致,即为符合。
+
+本规范每条 normative 条款应锚定至 tutorial 中至少一条示例。修改语言的流程恒为:
+
+1. 修改本规范条款;
+2. 增改其锚定的 tutorial 示例(新增条款须补锚例,不改动既有冻结示例的语义);
+3. 修改 layout / runtime 实现,直至锚例三后端全绿。
+ "#### -> /lib/kvlang/spec/导言/范围与一致性
+}
diff --git "a/stdlib/kvlang/spec/00-\345\257\274\350\250\200/02-\350\247\204\350\214\203\347\224\250\350\257\255\344\270\216\351\230\205\350\257\273\347\272\246\345\256\232.kv" "b/stdlib/kvlang/spec/00-\345\257\274\350\250\200/02-\350\247\204\350\214\203\347\224\250\350\257\255\344\270\216\351\230\205\350\257\273\347\272\246\345\256\232.kv"
new file mode 100644
index 00000000..ac38e8ca
--- /dev/null
+++ "b/stdlib/kvlang/spec/00-\345\257\274\350\250\200/02-\350\247\204\350\214\203\347\224\250\350\257\255\344\270\216\351\230\205\350\257\273\347\272\246\345\256\232.kv"
@@ -0,0 +1,21 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/导言/规范用语与阅读约定 {
+ r####"# 规范用语与阅读约定
+
+## 规范用语
+
+规范用语对齐 RFC 2119 语义:
+
+- **必须 / 不得**(must / must not / shall)——绝对要求 / 绝对禁止。违反即不符合规范。
+- **应 / 不应**(should / should not)——存在正当理由时可偏离,但须权衡后果。
+- **可**(may)——纯可选。
+
+未加此类限定词的陈述句为**事实性描述**(语言如此这般),同样是 normative 的。设计动机、历史与取舍一律归入非规范的**设计理由**卷,不混入正文条款。
+
+## 阅读约定
+
+- 文法元记法与本规范其余用语约定见 [[文法]]。
+- 完整权威文法汇总于 [[文法]](附录);正文各章只引用其片段,不各自另立文法。
+- 章节间引用以 `[[章节名]]` 链接。
+ "#### -> /lib/kvlang/spec/导言/规范用语与阅读约定
+}
diff --git "a/stdlib/kvlang/spec/01-\350\257\215\346\263\225/01-\346\272\220\347\240\201\347\273\223\346\236\204.kv" "b/stdlib/kvlang/spec/01-\350\257\215\346\263\225/01-\346\272\220\347\240\201\347\273\223\346\236\204.kv"
new file mode 100644
index 00000000..519980bf
--- /dev/null
+++ "b/stdlib/kvlang/spec/01-\350\257\215\346\263\225/01-\346\272\220\347\240\201\347\273\223\346\236\204.kv"
@@ -0,0 +1,27 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/词法/源码结构 {
+ r####"# 源码结构
+
+## 锚例
+
+- `tutorial/01-basics/hello.kv`——最小源文件与 `Ident`/`Literal`/调用记号。
+- `tutorial/01-basics/vars.kv`——换行作语句分隔、`=`/`->` 记号、行注释。
+
+## 源码表示
+
+kvlang 源文件是一段 **UTF-8 字节序列**。词法分析按字节推进:ASCII 字节触发语法结构,其余多字节序列(如中文、`é`)作为普通字符原样穿过,出现在标识符、字符串与路径内部。
+
+一处**行**由换行符 `\n`(U+000A)界定;`\r`(U+000D)在词法阶段被直接跳过,不产生任何词法单元,故 `\r\n` 与 `\n` 等价。位置以 1 起始的 `line`、`col` 计。
+
+## 空白与语句分隔
+
+空格 ` ` 与制表符 `\t` 是词法单元之间的分隔符,本身不产生词法单元;除用于分隔相邻词法单元外不具意义。
+
+**语句分隔**由换行符 `\n` 与分号 `;` 表达,二者语义等价,均产生一个 `Newline` 词法单元。词法器执行两条归并规则:
+
+- 连续的语句分隔(多个换行/分号、含其间空白)**折叠**为单个 `Newline`;
+- 词法单元流开头的语句分隔被**抑制**,不产生 `Newline`。
+
+字符串与原始字符串字面量内部的物理换行**不**产生 `Newline`(它是字面量内容的一部分),但行号仍随之前进。
+ "#### -> /lib/kvlang/spec/词法/源码结构
+}
diff --git "a/stdlib/kvlang/spec/01-\350\257\215\346\263\225/02-\350\257\215\346\263\225\345\215\225\345\205\203.kv" "b/stdlib/kvlang/spec/01-\350\257\215\346\263\225/02-\350\257\215\346\263\225\345\215\225\345\205\203.kv"
new file mode 100644
index 00000000..8256e504
--- /dev/null
+++ "b/stdlib/kvlang/spec/01-\350\257\215\346\263\225/02-\350\257\215\346\263\225\345\215\225\345\205\203.kv"
@@ -0,0 +1,39 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/词法/词法单元 {
+ r####"# 词法单元
+
+## 词法单元种类
+
+词法分析把源码切分为下列种类的词法单元,末尾附一个 `EOF` 哨兵:
+
+- `Ident`——标识符,以及未被单独归类的符号运算符(见 [[运算符基础]]);
+- `Literal`——字面量:数值、字符串、原始字符串、绝对路径(见 [[字面量基础]]、[[标识符]]);
+- `Arrow`——两种赋值/方向记号 `=`、`->`(见 [[运算符基础]]);
+- `Dot`——成员分隔符 `·`(U+00B7,见 [[标识符]]);
+- `LParen` `RParen` `LBrace` `RBrace` `LBrack` `RBrack`——`( ) { } [ ]`;
+- `Comma` `Colon`——`,` `:`;
+- `Newline`——语句分隔(`\n` 或 `;`,见上);
+- `Comment`——注释(见 [[注释]]);
+- 关键字词法单元 `Return` `If` `Else` `For` `While` `Break` `Continue`;
+- `EOF`——源码结束哨兵。
+
+## 关键字
+
+kvlang 只有 **7 个词法关键字**,它们在词法阶段即被识别,不得用作标识符:
+
+```
+return if else for while break continue
+```
+
+其余在语言中具有特殊含义的词(`lib`、`rwir`、`rwfunc`、`in`、`any`、`None`、`true`、`false`、种类名如 `int64`/`float32`/`struct` 等)**不是**词法关键字:它们一律词法化为 `Ident`,其含义由 layout 阶段依上下文赋予。这类词称为**上下文词**。
+
+`def` **不是** kvlang 关键字,kv 源码中永不出现:`def rwir`/`def struct`/`def kindexpr` 是 head 的 langtype 元层「定义节点」标记,只在 layout 之后(`def struct`、`def kindexpr`)或 runtime 注册时(`def rwir`)产生,与源码词法无关(见 [[langtype语义类型]])。
+
+## 最长匹配
+
+词法分析遵循**最长匹配**(maximal munch):在每个位置,词法器取能构成合法词法单元的最长字符序列。特别地:
+
+- 以数字开头的序列必为数值字面量,不会被识别为标识符;
+- `-` 后紧跟 `>` 构成 `->`,`<` 后紧跟 `<` 构成 `<<`,依此类推——双字符运算符优先于其单字符成分。
+ "#### -> /lib/kvlang/spec/词法/词法单元
+}
diff --git "a/stdlib/kvlang/spec/01-\350\257\215\346\263\225/03-\346\263\250\351\207\212.kv" "b/stdlib/kvlang/spec/01-\350\257\215\346\263\225/03-\346\263\250\351\207\212.kv"
new file mode 100644
index 00000000..2ba251a3
--- /dev/null
+++ "b/stdlib/kvlang/spec/01-\350\257\215\346\263\225/03-\346\263\250\351\207\212.kv"
@@ -0,0 +1,42 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/词法/注释 {
+ r####"# 注释
+
+kvlang 有两种注释,语法与 Rust 一致。**不存在** `#` 注释。
+
+## 锚例
+
+- `tutorial/01-basics/vars.kv`、`tutorial/01-basics/arith.kv`——行注释(含期望输出注释块与行尾 )。
+
+## 行注释
+
+行注释以 `//` 开始,延伸至(但**不含**)该行的换行符:
+
+```
+x = 42 // 这是行注释
+```
+
+行注释不消费其后的换行符,故一行末尾的行注释之后仍产生一个 `Newline` 语句分隔。行注释不嵌套:其内部的 `//`、`/*` 均无特殊含义。
+
+## 块注释
+
+块注释由 `/*` 与 `*/` 界定,**可跨行**:
+
+```
+/* 这一段
+ 跨越多行 */
+```
+
+块注释**可嵌套**:词法器对 `/*` 计数、对 `*/` 递减,仅当计数归零才结束。因此下例整体是一条注释:
+
+```
+/* 外层 /* 内层 */ 仍在注释内 */
+```
+
+嵌套能力使得注释掉一段本身含块注释的代码是安全的。若源码结束时块注释仍未闭合,注释延伸至文件末尾。
+
+## 注释的地位
+
+注释被词法化为 `Comment` 词法单元,在词法流中保留,但对程序语义无贡献——layout 阶段将其忽略。注释不是语句分隔符:其内部的换行不产生 `Newline`(块注释),行注释后的换行照常产生 `Newline`。
+ "#### -> /lib/kvlang/spec/词法/注释
+}
diff --git "a/stdlib/kvlang/spec/01-\350\257\215\346\263\225/04-\346\240\207\350\257\206\347\254\246.kv" "b/stdlib/kvlang/spec/01-\350\257\215\346\263\225/04-\346\240\207\350\257\206\347\254\246.kv"
new file mode 100644
index 00000000..4e1158a6
--- /dev/null
+++ "b/stdlib/kvlang/spec/01-\350\257\215\346\263\225/04-\346\240\207\350\257\206\347\254\246.kv"
@@ -0,0 +1,42 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/词法/标识符 {
+ r####"# 标识符
+
+## 锚例
+
+- `tutorial/01-basics/vars.kv`——标识符 `x`、`y`。
+- `tutorial/01-basics/kv_tree.kv`——绝对路径 `/tmp/kvt`、子键路径 `/tmp/kvt·data`、层级路径 `/tmp/kvt/a`,以及成员/方法 `kv·set`、`kv·get`。
+
+## 标识符
+
+标识符命名帧内变量、参数、lib 段、rwir/rwfunc、成员键等。其规范形态为:
+
+```
+letter = unicode_letter | "_"
+ident = letter { letter | digit }
+```
+
+其中 `unicode_letter` 为任意 Unicode 字母。因此标识符**可含非 ASCII 字母**,中文标识符合法:
+
+```
+变量数 = 42
+println("值 =", 变量数)
+```
+
+此决策使 kvlang 与 C99、Go、Python、Rust、TypeScript 在「允许 Unicode 标识符」上对齐。
+
+7 个词法关键字(`return if else for while break continue`)为保留字,不得用作标识符;其余上下文词(`lib`、`None`、`true`、`false`、种类名等)不保留,但用作普通标识符会遮蔽其上下文含义,不应如此使用。
+
+> 实现说明(非规范):当前词法器以「最长非分隔符字节串」切分标识符,未逐字符校验上述字母表,故比本节所述更宽松。分隔符集合为空白、`; , ( ) { } [ ] :`、成员分隔符 `·`,以及运算符字符 `+ - * % ! = < > & | ^`。
+
+## 成员分隔符
+
+`·`(U+00B7,中点)是 kvlang 唯一的成员/方法分隔符,词法化为独立的 `Dot` 词法单元。它出现于:
+
+- 成员访问 `base·field`;
+- 方法/限定调用 `base·method(...)`、`pkg·func(...)`;
+- 坐标访问 `base·[i,j]`。
+
+kvlang **不使用** ASCII 句点 `.` 作成员分隔符(`.` 仅作路径子键,见下)。
+ "#### -> /lib/kvlang/spec/词法/标识符
+}
diff --git "a/stdlib/kvlang/spec/01-\350\257\215\346\263\225/05-\347\273\235\345\257\271\350\267\257\345\276\204\345\255\227\351\235\242\351\207\217.kv" "b/stdlib/kvlang/spec/01-\350\257\215\346\263\225/05-\347\273\235\345\257\271\350\267\257\345\276\204\345\255\227\351\235\242\351\207\217.kv"
new file mode 100644
index 00000000..6af8fba0
--- /dev/null
+++ "b/stdlib/kvlang/spec/01-\350\257\215\346\263\225/05-\347\273\235\345\257\271\350\267\257\345\276\204\345\255\227\351\235\242\351\207\217.kv"
@@ -0,0 +1,20 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/词法/绝对路径字面量 {
+ r####"# 绝对路径字面量
+
+绝对路径直接寻址 kvspace 树中的节点,是一类字面量(词法化为以 `/` 起始的 `Literal`)。路径以 `/` 开头,后随一个 ASCII 字母、数字或下划线,随后是由下列成分构成的最长序列:
+
+- `/`——段分隔符,划分树的层级;
+- `.`——子键分隔符,寻址同一节点下的子键;
+- `·[i,j,…]`——坐标段,按整数下标寻址 strkeymap/容器的坐标;
+- 其余非分隔符字符构成段名(同样允许非 ASCII)。
+
+```
+kv·set("/tmp/kvt·data", 42)
+kv·get("/tmp/kvt", "data") -> x
+kv·set("/tmp/kvt/a", 1)
+```
+
+路径的完整寻址语义见 [[寻址与命名]];本节只界定其词法形态。裸 `/`(其后不接字母/数字/下划线,且非 `//`、`/*`)不构成路径,见 [[运算符基础]]。
+ "#### -> /lib/kvlang/spec/词法/绝对路径字面量
+}
diff --git "a/stdlib/kvlang/spec/01-\350\257\215\346\263\225/06-\345\255\227\351\235\242\351\207\217\345\237\272\347\241\200.kv" "b/stdlib/kvlang/spec/01-\350\257\215\346\263\225/06-\345\255\227\351\235\242\351\207\217\345\237\272\347\241\200.kv"
new file mode 100644
index 00000000..1a956a60
--- /dev/null
+++ "b/stdlib/kvlang/spec/01-\350\257\215\346\263\225/06-\345\255\227\351\235\242\351\207\217\345\237\272\347\241\200.kv"
@@ -0,0 +1,30 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/词法/字面量基础 {
+ r####"# 字面量基础
+
+字面量是源码中直接书写的常量值。kvlang 有四类字面量:数值、字符串、绝对路径(词法见 [[标识符]]),以及上下文空/布尔字面量。
+
+## 锚例
+
+- `tutorial/01-basics/float_literal.kv`——浮点字面量 `3.14`、结果 `6.28`。
+- `tutorial/01-basics/arith.kv`、`tutorial/01-basics/numtypes.kv`——整数字面量与定宽落定。
+- `tutorial/01-basics/strings.kv`——双引号串、`+` 拼接、单字符字符串。
+- `tutorial/11-string/07-multiline.kv`——字符串三形式(`"…"` 跨行、`r"…"`、`r#"…"#`)。
+- `tutorial/01-basics/none.kv`——`None` 空值。
+- `tutorial/01-basics/kv_tree.kv`、`tutorial/03-control/if.kv`——`true`/`false` 布尔字面量。
+
+## 数值字面量
+
+```
+digit = "0" … "9"
+integer = digit { digit }
+float = integer [ "." integer ] [ ("e" | "E") [ "+" | "-" ] integer ]
+```
+
+- 整数为一串十进制数字。**无**十六进制、八进制、二进制前缀,**无**下划线数字分隔符。
+- 浮点数为整数部分后可选跟小数部分 `.digits` 与可选指数 `(e|E)[±]digits`。小数点前必须有数字(不支持 `.5` 这类前导点写法)。
+- 数值字面量本身**无符号**;负数由前缀一元运算符 `-` 与字面量组合而成(见 [[运算符基础]])。
+
+`3` 是整数字面量,`3.14`、`6.28`、`1e3`、`2.5E-4` 是浮点字面量。字面量到具体定宽种类的落定由类型系统与上下文决定(见 [[种类与定宽类型]])。
+ "#### -> /lib/kvlang/spec/词法/字面量基础
+}
diff --git "a/stdlib/kvlang/spec/01-\350\257\215\346\263\225/07-\345\255\227\347\254\246\344\270\262\344\270\216\347\251\272\345\200\274\345\270\203\345\260\224\345\255\227\351\235\242\351\207\217.kv" "b/stdlib/kvlang/spec/01-\350\257\215\346\263\225/07-\345\255\227\347\254\246\344\270\262\344\270\216\347\251\272\345\200\274\345\270\203\345\260\224\345\255\227\351\235\242\351\207\217.kv"
new file mode 100644
index 00000000..667f99a6
--- /dev/null
+++ "b/stdlib/kvlang/spec/01-\350\257\215\346\263\225/07-\345\255\227\347\254\246\344\270\262\344\270\216\347\251\272\345\200\274\345\270\203\345\260\224\345\255\227\351\235\242\351\207\217.kv"
@@ -0,0 +1,44 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/词法/字符串与空值布尔字面量 {
+ r####"# 字符串与空值布尔字面量
+
+## 字符串字面量
+
+kvlang 有三种字符串书写形式,与 Rust 一致;**无**三引号串,**无**反引号原始串。
+
+### 转义串 `"…"`
+
+以双引号界定,**可跨行**(内部的物理换行成为内容中的换行字符)。反斜杠 `\` 引入转义:
+
+- `\n`→换行、`\t`→制表符、`\r`→回车、`\0`→空字符;
+- `\<其他字符>`→该字符本身,故 `\"`→`"`、`\\`→`\`。
+
+```
+s = "line1
+line2" // 跨行,含一个真实换行
+t = "one\ntwo" // 转义换行
+```
+
+### 原始串 `r"…"` / `r#"…"#` / `r##"…"##` …
+
+以 `r` 引导,**零转义**、可跨行。可在 `r` 与首个 `"` 之间加 `N` 个井号 `#`,此时须以 `"` 后接同样 `N` 个 `#` 闭合;井号越多可嵌套越深,内容因而能包含 `"`:
+
+```
+r = r"raw\nliteral" // 输出含反斜杠与 n,非换行
+q = r#"he said "hi""# // 内容含双引号
+```
+
+### 单引号形式 `'…'`
+
+以单引号界定,用于 char / keypath 场景,与转义串共享同一套转义规则。其内容作为裸字面量交由后续阶段依上下文(char 种类、键路径)解释。
+
+kvlang 的动态字符串阵营中,单个字符通常以**长度为 1 的字符串**表示(如 `s[i]` 读返单字符字符串),char 的定宽种类见 [[种类与定宽类型]]。
+
+## 空值与布尔字面量
+
+- `None`——空值字面量。kvlang 的空值**只有** `None`;书写 `null` 是错误,layout **必须**显式拒绝,**不得**当作裸标识符静默放行。未赋值的变量地址即读作 `None`。
+- `true` / `false`——布尔字面量。
+
+三者均为**上下文词**:词法阶段化为标识符,由 layout/runtime 依类型上下文解释为对应值。
+ "#### -> /lib/kvlang/spec/词法/字符串与空值布尔字面量
+}
diff --git "a/stdlib/kvlang/spec/01-\350\257\215\346\263\225/08-\350\277\220\347\256\227\347\254\246\345\237\272\347\241\200.kv" "b/stdlib/kvlang/spec/01-\350\257\215\346\263\225/08-\350\277\220\347\256\227\347\254\246\345\237\272\347\241\200.kv"
new file mode 100644
index 00000000..3dd99554
--- /dev/null
+++ "b/stdlib/kvlang/spec/01-\350\257\215\346\263\225/08-\350\277\220\347\256\227\347\254\246\345\237\272\347\241\200.kv"
@@ -0,0 +1,57 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/词法/运算符基础 {
+ r####"# 运算符基础
+
+本节界定运算符与方向记号的**词法**:有哪些符号、各写作什么字形。其求值与结合语义见 [[指令架构]]与 [[执行模型]]。符号表是权威的双向查找表,其余部分不得另行硬编码符号字符串。
+
+## 锚例
+
+- `tutorial/01-basics/arith.kv`——`+ - × ÷ %` 与一元 `√`(`√(144)`)、`=`/`->` 二记号。
+- `tutorial/01-basics/vars.kv`——`=` 与 `+`。
+- `tutorial/03-control/if.kv`——比较与逻辑运算符。
+- `tutorial/01-basics/kv_tree.kv`——`!= None` 比较。
+
+## 赋值与方向记号
+
+kvlang 有两种赋值/方向记号,均词法化为 `Arrow`:
+
+- `=`——写入左侧;
+- `->`——写入右侧(数据从左流向右)。
+
+```
+x = 42
+42 -> x // 写入右侧
+```
+
+`=` 仅为写入记号,kvlang **无**独立的等号赋值语义之外用法;相等比较写作 `==`。**无 `<-`**:历史上有第三种 `<-`(写入左侧),与 `=` 完全重复,已删除——写入左侧一律写 `=`。
+
+## 算术运算符
+
+| 字形 | 含义 | 一元 |
+|------|------|------|
+| `+` | 加 | 是(一元正) |
+| `-` | 减 | 是(一元负) |
+| `×` | 乘(U+00D7) | 否 |
+| `÷` | 除(U+00F7) | 否 |
+| `%` | 取模 | 否 |
+
+**乘法是 `×`、除法是 `÷`**,非 ASCII 的 `*` 与 `/`:
+
+- `*`(U+002A)**不是**乘号。它在符号表中登记为 `pointer`,非算术运算符。
+- `/`(U+002F)**不是**除号。它只用于绝对路径字面量与注释(`//`、`/*`);出现在其他位置的裸 `/` 不承载算术除法语义。
+
+一元 `+`、`-` 作前缀;`√`(U+221A,平方根)亦为一元前缀运算符。
+
+## 比较运算符
+
+```
+== != < > <= >=
+```
+
+其中三者另有等价的 Unicode 字形别名,词法上与 ASCII 形式同义:
+
+- `!=` ≡ `≠`(U+2260)
+- `<=` ≡ `≤`(U+2264)
+- `>=` ≡ `≥`(U+2265)
+ "#### -> /lib/kvlang/spec/词法/运算符基础
+}
diff --git "a/stdlib/kvlang/spec/01-\350\257\215\346\263\225/09-\351\200\273\350\276\221\344\275\215\350\277\220\347\256\227\344\270\216\344\274\230\345\205\210\347\272\247.kv" "b/stdlib/kvlang/spec/01-\350\257\215\346\263\225/09-\351\200\273\350\276\221\344\275\215\350\277\220\347\256\227\344\270\216\344\274\230\345\205\210\347\272\247.kv"
new file mode 100644
index 00000000..23491f22
--- /dev/null
+++ "b/stdlib/kvlang/spec/01-\350\257\215\346\263\225/09-\351\200\273\350\276\221\344\275\215\350\277\220\347\256\227\344\270\216\344\274\230\345\205\210\347\272\247.kv"
@@ -0,0 +1,42 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/词法/逻辑位运算与优先级 {
+ r####"# 逻辑位运算与优先级
+
+## 逻辑运算符
+
+```
+&& || !
+```
+
+`!` 为一元前缀(逻辑非)。
+
+## 位运算符
+
+```
+& | ^ << >>
+```
+
+分别为按位与、按位或、按位异或、左移、右移。
+
+## 优先级
+
+中缀运算符的优先级如下(数值越大结合越紧);一元前缀运算符(`+ - ! √`)优先级高于全部中缀。
+
+| 运算符 | 优先级 |
+|--------|--------|
+| `\|\|` | 10 |
+| `&&` | 20 |
+| `==` `!=`(`≠`) | 30 |
+| `<` `>` `<=`(`≤`) `>=`(`≥`) | 40 |
+| `+` `-` | 50 |
+| `×` `÷` `%` | 60 |
+| `<<` `>>` | 70 |
+| `&` | 80 |
+| `^` | 90 |
+| `\|` | 100 |
+
+## 运算符成员分隔符
+
+`·`(U+00B7)是成员/方法分隔符,非算术运算符,词法化为独立的 `Dot` 词法单元,其词法与用途见 [[标识符]]。
+ "#### -> /lib/kvlang/spec/词法/逻辑位运算与优先级
+}
diff --git "a/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/01-\345\234\260\345\235\200\347\251\272\351\227\264.kv" "b/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/01-\345\234\260\345\235\200\347\251\272\351\227\264.kv"
new file mode 100644
index 00000000..eb52022f
--- /dev/null
+++ "b/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/01-\345\234\260\345\235\200\347\251\272\351\227\264.kv"
@@ -0,0 +1,33 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/kvspace模型/地址空间 {
+ r####"# 地址空间
+
+kvspace 是 kvlang 的第一性前置概念:它**既是寻址空间也是内存空间**。程序计数器 PC 是一条 kvspace 路径字符串,指令是路径上的值,变量是路径上的值,代码与数据统一在同一棵 KV 树上。本卷其余各章([[寻址与命名]]、[[键系统与数组访问]]、[[指令布局格式]]、[[系统变量]])均以本章界定的地址空间为基础。
+
+## 存储铁律
+
+kvspace 是文件系统风格的键值抽象。任一条目由 key 与 value 构成:
+
+- key **必须**是绝对、规范的字符串路径:以 `/` 开头,`/` 分隔层级;不得为相对路径。
+- value **必须**是一个 XValue 序列化后的字节串(TLV 编码,格式见 [[键系统与数组访问]])。
+- **不得**向 kvspace 直接写入裸基础类型字节;所有值必须经 XValue 编解码。违反此铁律的写入,读取方在解码非法字节时行为未定义。
+
+目录以尾随 `/` 标记:key `/a/` 是目录(其 value 为 `index`),key `/a` 是普通值。同一路径的有尾斜杠与无尾斜杠形态可独立共存。
+
+## 扩展存储
+
+kvspace 元存中的 value 分两类:**内联数据**(基础类型、容器元数据)与**扩展存储句柄**。句柄 value 的 ref=2(@ext,见 [[键系统与数组访问]]),其 body 只记录目标位置描述符,真实字节位于元存之外:
+
+| 扩展位置 | 典型数据 |
+|---------|---------|
+| 集群/本机共享内存 | 大张量、激活值 |
+| GPU 显存 | 计算张量 |
+| 文件系统 / 对象存储 | 模型权重、检查点、数据集、外部进程输出 |
+
+读取一个 ref=2 扩展句柄 value 时,运行时按 body 定位符前缀路由到对应兑现器还原真实字节(`runtime-rs/src/engine.rs`)。
+
+## 后端与前端
+
+kvspace 的 C ABI 由前端 dispatch 层(`kvspace` 仓 `src/frontend.c`)统一导出,运行期按连接串 scheme 选择后端:`shm://` 走 kvspace-c,`redis`/`fs`/`s3` 等走 kvspace-durable。三后端**必须**实现同一 ABI 与同一线格式(byte-identical),语义一致;一致性由 tutorial 三后端全绿判定(见 [[范围与一致性]])。ABI 符号与 XValue 线格式见 [[寻址与命名]] 与 [[键系统与数组访问]]。
+ "#### -> /lib/kvlang/spec/kvspace模型/地址空间
+}
diff --git "a/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/02-\347\273\223\346\236\204\345\237\237.kv" "b/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/02-\347\273\223\346\236\204\345\237\237.kv"
new file mode 100644
index 00000000..a33ad3b4
--- /dev/null
+++ "b/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/02-\347\273\223\346\236\204\345\237\237.kv"
@@ -0,0 +1,31 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/kvspace模型/结构域 {
+ r####"# 结构域
+
+kvspace 的路径中,只有以下前缀由语言核心赋予固定结构语义;其余 `/` 路径全部自由,由用户代码定义,核心不预设 schema。
+
+| 前缀 | 语义 |
+|------|------|
+| `/lib` | 函数与扩展指令的单一事实源:rwfunc 的 layout 产物(签名 + 指令树)、`.src` 源码副本、各 runtime 注册的 def rwir 路由头均落于此 |
+| `/vthread` | 虚线程运行时状态:每 vthread 一棵子树,栈帧、PC、状态等随身系统变量暴露执行现场 |
+| `/networld` | 与外部世界交互的名册域:本机与外部进程、文件等以 `/networld/{host}/…` 登记,供 rwir(经 def rwir 路由)定位与兑现 |
+
+`/lib` 与 `/vthread` 的前缀常量由运行时与 layout 各自定义(C 运行时 `runtime/src/runtime_internal.h` 的 `LIB_ROOT`/`VTHREAD_ROOT`,Rust layout `layout/src/keytree.rs` 的 `LIB_ROOT`/`VTHREAD_ROOT`)。
+
+### `/lib`
+
+`/lib` 是全局命名空间,无 `import`——lib 树本身即命名空间。`lib name { … }` 块声明包;跨包调用走全路径 `/lib/{pkg}·{func}`。多文件经引导拼接后统一 layout 进 `/lib`,已加载条目去重。函数在 `/lib` 下只读,帧调用经 extindex 复用同一份指令树(见 [[指令布局格式]])。
+
+### `/vthread`
+
+每个虚线程 `vid` 占一棵子树 `/vthread/{vid}/`,借用 Unix `/proc//` 思想:栈帧为其下的 KV 子树,`‥pc`、`‥status` 等系统变量(前缀 `‥`,见 [[系统变量]])暴露执行状态。PC 为路径字符串、帧根落 KV,故进程崩溃后可从 kvspace 续跑。
+
+### `/networld`
+
+`/networld` 是本机在网络命名空间下的身份域,`host` 取裸 hostname。外部进程执行、宿主文件系统读写等**不**经设备文件,而是登记在 `/networld/{host}/…` 下并由 rwir(经 def rwir 路由)兑现:例如外部进程的 stdout/stderr 捕获为扩展存储句柄,其逻辑定位符形如 `/networld/{host}/proc/{pid}/{stream}`(`runtime-rs/src/rwir/networld/`)。
+
+### 没有设备域
+
+kvspace 世界中没有终端、没有设备文件,只有 key 与 value。`print`/`println` 等 I/O 不是地址空间的一个域,也不是核心内建,而是 rwir(以 def rwir 路由头注册于 `/lib/`,见 [[指令布局格式]]),执行时直接作用于宿主 I/O。
+ "#### -> /lib/kvlang/spec/kvspace模型/结构域
+}
diff --git "a/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/03-\345\257\273\345\235\200\344\270\216\345\221\275\345\220\215.kv" "b/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/03-\345\257\273\345\235\200\344\270\216\345\221\275\345\220\215.kv"
new file mode 100644
index 00000000..07ffdf76
--- /dev/null
+++ "b/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/03-\345\257\273\345\235\200\344\270\216\345\221\275\345\220\215.kv"
@@ -0,0 +1,55 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/kvspace模型/寻址与命名 {
+ r####"# 寻址与命名
+
+本章界定 kvlang 如何在 [[地址空间]] 上寻址:PC 的形态、变量名与指针的关系、路径分隔符语义,以及访问 kvspace 的 C ABI。
+
+## PC 是路径字符串
+
+传统 VM 的程序计数器是一维线性整数(内存地址),跳转与调用是整数算术。kvlang 的 PC 是一条 kvspace 路径字符串,跳转与调用是路径拼接与子树导航。
+
+| 维度 | 传统 VM | kvlang |
+|------|---------|--------|
+| PC 类型 | `uint64` / 指令指针 | `string`(KV 路径) |
+| 指令获取 | 解引用内存地址 | 读 PC 路径处的 XValue |
+| 跳转 | 改寄存器 | PC 置为新路径 |
+| 调用 | 压返回地址、跳入口 | 建帧子树、帧根 extindex 指向 `/lib` 指令树 |
+| 栈帧 | 连续内存 | `/vthread/{vid}/…` KV 子树 |
+
+PC 落在 kvspace、帧根落在 kvspace,故执行现场可观测、可崩溃恢复。指令布局与帧机制见 [[指令布局格式]]。
+
+## 变量名即指针
+
+kvlang 没有取址运算符——**代码中变量的名字,本身就是该变量的指针**(一条 kvspace 路径)。指令槽里存的从来不是值,而是指针文本;求值恒经一次指针间接。指针有两种形态:
+
+| 形态 | 写法 | 语义 | 解析 |
+|------|------|------|------|
+| 相对指针 | 裸标识符 `x` | 相对当前栈帧 | 运行时与帧根拼接 |
+| 绝对指针 | `/counter` | kvspace 全局绝对路径 | 零拼接,直接读写 |
+
+局部变量的名字即相对指针。运行时解析公式:
+
+```
+绝对路径 = FrameRoot(PC) + "/" + 相对指针
+```
+
+`FrameRoot(PC)` 从 PC 截去末尾的 `/[coord]` 指令坐标段即得帧根(`layout/src/keytree.rs` 的 `frame_root`:PC 无 `/[` 坐标段则为非法)。这与 C 的 `rbp + offset` 同构:帧根对应帧基址,相对指针对应栈偏移,绝对指针对应固定地址。
+
+`/lib` 下的函数模板中只有相对指针,因此天然可重入:每次调用产生不同的帧根,同一份相对指针拼接出互不干扰的绝对指针——递归与尾调用无需额外机制。
+
+**参数不得同名**:变量名即指针,同一帧内两个同名参数将指向同一 kvspace 位置。读参列表内、写参列表内、以及读写列表之间均**不得**同名;layout 静态阻断,运行时兜底。
+
+## 路径分隔符
+
+kvspace 路径与 XValue 的 kindexpr 共用一套分隔符语义,每个分隔符承载固定含义(常量定义处:`kvspace/include/kvspace/const.h`、`kvspace-durable/src/const.rs`):
+
+| 分隔符 | 码位 | 语义 |
+|--------|------|------|
+| `/` | U+002F | 层级;目录以尾随 `/` 标记 |
+| `·` | U+00B7 | **两种独立含义,正交**(见 [[总体方案]]):①**memindex 标记**——值容器成员索引 `{key}·`(仅 stringkeymap/struct 用),以及成员访问 `obj·field`、`m·[i]`;②**包·函数命名分隔符**——`/lib/{pkg}·{func}` 中路径段名字的一部分,rwfunc 目录成员仍走 `/` 子路径,与 memindex 无关 |
+| `‥` | U+2025 | 运行时系统变量前缀(`X/‥pc`,见 [[系统变量]]) |
+| `…` | U+2026 | extindex 句柄 body 的首元素前缀 |
+
+标识符**不得**以 `‥` 开头,故用户代码永远造不出 `‥` 前缀段,系统变量命名空间与用户命名空间零交集(见 [[键系统与数组访问]] 的键形态三分)。
+ "#### -> /lib/kvlang/spec/kvspace模型/寻址与命名
+}
diff --git "a/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/04-CABI.kv" "b/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/04-CABI.kv"
new file mode 100644
index 00000000..f337b2e8
--- /dev/null
+++ "b/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/04-CABI.kv"
@@ -0,0 +1,26 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/kvspace模型/CABI {
+ r####"# C ABI
+
+访问 kvspace 的唯一 C ABI 由前端 dispatch 静态导出(`kvspace/include/kvspace/kvspace.h`)。读写采用**借用指针模型**:读返回指向后端常驻空间的指针,调用方不得释放;写返回 body 偏移指针供调用方直接填。核心符号:
+
+| 符号 | 语义 |
+|------|------|
+| `kvspaceGet` | 借用读:`*out` 指向后端常驻空间;`resolve=1` 穿透 link;不存在/空值 → `*out=NULL`、返回 0 |
+| `kvspaceWriteInPlace` | 就地写:key 已存在、kind 不变、body 长度不变;返回原 box body 偏移指针,违反前置条件即报错,绝不静默重分配 |
+| `kvspaceWriteNewPlace` | 新位置写:按 `(kindexpr, body_len)` 分配新 box、写好 head,返回 body 偏移指针;用于新建或 kind/尺寸变化 |
+| `kvspaceListLen` | 返回前缀下直接子项计数 |
+| `kvspaceListAt` | 取前缀下第 `idx` 个子项名,写入调用方自备缓冲;配合 `kvspaceListLen` 遍历 |
+| `kvspaceDel` | 批量删除给定 key 数组 |
+| `kvspaceDelTree` | 删除前缀子树 |
+| `kvspaceCp` / `kvspaceCpTree` / `kvspaceCpList` | 复制单值 / 子树 / 直接子项 |
+| `kvspaceMkindex` | 建目录,带 `capacity` 预留容量 |
+| `kvspaceMkindexExt` / `kvspaceRmindexExt` | 建立 / 撤销 extindex 叠加层 |
+| `kvspaceClear` | 清空 |
+| `kvspaceWatch` | 一次性等待某 key 变为目标值 |
+
+无句柄的编解码符号(前端静态实现,byte-identical):`kvspaceTlvEncode` / `kvspaceTlvEncodeMode` / `kvspaceDecodeHead`,以及构造器 `kvspaceNewPtr`(存目标完整 kindexpr + 目标 key)、`kvspaceNewChar` / `kvspaceNewBool` / `kvspaceNewInt64` / `kvspaceNewFloat64`。
+
+读写各带 `resolve` 参数:`resolve=1` 时透明穿透 ref=1 指针(link);`kvspaceListLen`/`kvspaceListAt` 另有 `expand_ext` 参数控制是否展开 extindex 子项。head 线格式与 kindexpr 编码见 [[键系统与数组访问]]。
+ "#### -> /lib/kvlang/spec/kvspace模型/CABI
+}
diff --git "a/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/05-\351\224\256\347\263\273\347\273\237\344\270\216\346\225\260\347\273\204\350\256\277\351\227\256.kv" "b/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/05-\351\224\256\347\263\273\347\273\237\344\270\216\346\225\260\347\273\204\350\256\277\351\227\256.kv"
new file mode 100644
index 00000000..9a177aec
--- /dev/null
+++ "b/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/05-\351\224\256\347\263\273\347\273\237\344\270\216\346\225\260\347\273\204\350\256\277\351\227\256.kv"
@@ -0,0 +1,40 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/kvspace模型/键系统与数组访问 {
+ r####"# 键系统与数组访问
+
+本章界定 kvspace 键的三种形态、XValue 的 kindexpr 类型表达与线格式、数组的两种物理存储形态及其访问方式。
+
+## 键形态三分
+
+任一 key 的形态唯一确定其性质与所有权:
+
+| 形态 | 例 | 性质 | 所有权 |
+|------|----|------|--------|
+| `X/名`(`/` + 普通名) | `/vthread/7/[3,0]`、`/lib/f/[1,0]` | 结构:帧、指令槽、目录 | 核心 |
+| `X·名`(`·` 中点键) | `/c0·next`、`m·[0]` | 用户数据成员 | 用户 |
+| `X/‥名`(`/` + `‥` 名) | `/vthread/7/‥pc` | 系统变量(影子元数据) | 核心 |
+
+标识符禁以 `‥` 开头,故三类零交集。系统变量清单见 [[系统变量]]。
+
+## kind 与 kindexpr
+
+| 概念 | 内容 | 例 |
+|------|------|----|
+| **kind** | 基础类型字符串(标量或元素类型),是 kindexpr 的叶子 | `uint8` `int32` `float64` `bool` `char/utf32` `stringkeymap` `rwir` `rwfunc` … |
+| **kindexpr** | 完整类型表达式(即 langtype 串):可选 `[dims]` + kind;ref 已独立为 head 字节字段,不再是 kindexpr 前缀 | `int8` `[10]int32` `[256,256]uint8` `[]char/utf8·int64` |
+
+kind 常量集中定义于 `kvspace/include/kvspace/const.h`(C)与 `kvspace-durable/src/const.rs`(Rust),两侧同名同值。剥掉 kindexpr 的所有前缀与 `[dims]` 修饰即得 kind。
+
+### kindexpr 文法
+
+kindexpr(即 langtype 串)**全前缀**书写,最左符号为最外层构造器,无优先级歧义(对齐 Go/Rust 的 `[]int`):
+
+```
+kindexpr ::= [ dims ] kind
+dims ::= '[' ']' # 变长一维
+ | '[' INT ( ',' INT )* ']' # 定长 / 多维(compact 连续布局)
+```
+
+维数与各维长度编码进 kindexpr 串本身;ref(存储位置)已独立为 head 中的 ref u8 字段(见 [[XValueHead线格式]]),不再是 kindexpr 前缀——storetype 物理字段携带对应的 ndim/dims 结构。完整签名类型表达式(并集 `A|B`、通配 `any`、动态维 `?`、map 键值 `key·value`)见 [[文法]] 与类型系统卷。**源码**类型标注可在最前写 `*`/`@` 前缀表示 ref(如 `*int64`、`@[256,256]uint8`),layout 解析时剥离前缀落成 head `ref` 独立字节;wire 层 langtype 串不含 `*`/`@` 前缀(见 [[总体方案]])。
+ "#### -> /lib/kvlang/spec/kvspace模型/键系统与数组访问
+}
diff --git "a/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/06-XValueHead\347\272\277\346\240\274\345\274\217.kv" "b/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/06-XValueHead\347\272\277\346\240\274\345\274\217.kv"
new file mode 100644
index 00000000..2a7df57e
--- /dev/null
+++ "b/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/06-XValueHead\347\272\277\346\240\274\345\274\217.kv"
@@ -0,0 +1,28 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/kvspace模型/XValueHead线格式 {
+ r####"# XValueHead 线格式
+
+XValue = head + body。head 由三正交字段(ref × storetype × langtype)与辅助字段构成,langtype kindexpr 串为语义类型真相(`kvspace/include/kvspace/kvspace.h`、`kvspace-c/src/xvalue.h`、`kvspace-durable/src/xvalue.rs`,三处 byte-identical):
+
+```
+head = [headlen u16 LE][ref u8][storetype u8][ro u8][vid u32 LE][body_len u32 LE]
+ [storetype 物理字段(变长,按 storetype)][langtype kindexpr 串(占至 headlen)]
+body = [body_len B raw]
+```
+
+| 字段 | 大小 | 含义 |
+|------|------|------|
+| `headlen` | 2B LE | head 总字节数;body 起于偏移 `headlen` |
+| `ref` | 1B | 存储位置:0=inline、1=ptr(body=目标 key 路径)、2=@ext(body=扩展世界定位符) |
+| `storetype` | 1B | 物理布局(codec 唯一分派):NONE/ATOM/ARRAYND/index/extindex |
+| `ro` | 1B | 1=只读,0=可写 |
+| `vid` | 4B LE | vthread id(默认 0) |
+| `body_len` | 4B LE | body 字节数 |
+| (storetype 物理字段) | 变 | ARRAYND:ndim u8 + dims[ndim] u32 LE;index/extindex:成员名 m×n 对齐字符串数组 dims=[len,cap,M](len=成员数、M align8、cap 预留容量);主槽 body 恒空 |
+| `langtype` | 变长 | kindexpr 串,占至 `headlen`(长度 = headlen − 当前偏移,无独立长度字段) |
+
+`langtype` 恒为 head 最后一段,无独立长度字段;body 起始偏移 = `headlen`。ref 与 storetype 各为独立 u8 字节,不再编码进 kindexpr 串。ARRAYND 的 ndim、dims 直接读自 storetype 物理字段,与 langtype 串内 `[dims]` 保持同步(由 codec 保证)。`char/*` kind 恒为 ARRAYND(ndim=1)。None 编码:storetype=NONE、langtype=""、body 空。
+
+指针(ref=1)的 head langtype = 目标完整 langtype(kindexpr,含 `[dims]`),storetype = 目标 storetype,body = 目标 key 路径;由 `kvspaceNewPtr(target_kindexpr, target)` 构造,Set 时据此单跳类型检查。
+ "#### -> /lib/kvlang/spec/kvspace模型/XValueHead线格式
+}
diff --git "a/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/07-\346\225\260\347\273\204\344\270\244\347\247\215\347\211\251\347\220\206\345\275\242\346\200\201.kv" "b/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/07-\346\225\260\347\273\204\344\270\244\347\247\215\347\211\251\347\220\206\345\275\242\346\200\201.kv"
new file mode 100644
index 00000000..ff271e50
--- /dev/null
+++ "b/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/07-\346\225\260\347\273\204\344\270\244\347\247\215\347\211\251\347\220\206\345\275\242\346\200\201.kv"
@@ -0,0 +1,53 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/kvspace模型/数组两种物理形态 {
+ r####"# 数组的两种物理形态
+
+理论上的数组(含多维)在 kvlang 有两种物理落盘形态:
+
+| 形态 | langtype | 触发写法 | 元素位置 | XValue 数 |
+|------|----------|---------|---------|----------|
+| **compact** | 元素 kind(`int64`…) | `[1,2,3]`、`[N]T`、`[d0,d1]T` | 连续打包进单个 XValue 的 body | 1 |
+| **stringkeymap** | `stringkeymap` | `{v0,v1,…}`、`array·scatter` 等 | 每元素落独立子 key `base·[i]` | N+1 |
+
+- **compact**:元素连续打包进一个 XValue,`raw_len = ∏dims × 元素字节宽`,head kind 即元素类型、ndim≥1。对齐 C `int[10]`、Go `[10]int`、Rust `[i32;10]`;多维即连续布局的 ndarray/tensor。要求元素定长同类型——含变长字符串字面量的 `[…]` 在 layout 阶段报错。支持 `arr[i]` 随机访问(下标读经 `xv·at` 在 body 内定位),可零拷贝整块读。
+- **stringkeymap**:head kind=`stringkeymap`、ndim≥1,body 只记形状;每个元素是独立子 key,成员名为**坐标段**。变长、可增长、允许变长元素——字符串数组、可追加数组走此形态。stringkeymap **必须** ndim≥1(无维度的键值容器应为 `struct`),且成员名**必须**是坐标段(`kvspace-durable/src/const.rs` 的 `ERR_MAP_NDIM`、`ERR_MAP_COORD`)。
+
+## 坐标段
+
+stringkeymap 元素的成员名是坐标段,物理 key 形如 `m·[i]`(一维)或 `m·[i,j]`(多维)——`·` 后紧跟方括号坐标,**不是** `m·0` 这类裸后缀。坐标段格式为 `[s0,s1,…]`:十进制、逗号分隔、无空格(`kvspace-durable/src/coord.rs` 的 `format_coord`)。
+
+- 结构判定 `is_coord`:`[` 开头、`]` 结尾、内部不含嵌套 `[`/`]`;判定不要求整数(允许含点或字符串坐标)。
+- 排序 `cmp_coord`(row-major):坐标段恒排在非坐标段之前;两个可按整数解析的坐标段按数值升序,否则字典序。
+- 访问:源码 `m·[i]` 对散 key 元素走 `kv·get`(member 名 `[i]`);compact 的 `arr[i]` 走 `xv·at`。二者由括号与形态区分。
+
+## 字面量括号即形态
+
+| 字面量 | 形态 | 约束 |
+|--------|------|------|
+| `[1, 2, 3]` | compact(head kind=元素类型) | 元素须定长同 kind;含变长字符串成员时 layout 报错 |
+| `{1, 2, 3}` | stringkeymap(散 key) | 变长 / 可增长;字符串数组必须走此形式 |
+| `{k = v; …}` | struct 或 stringkeymap | 由 `=` 键值对与散 key 数组区分;空 `{}` 须带类型标注 |
+
+## 形态转换
+
+| rwir | 方向 | 语义 |
+|------|------|------|
+| `array·scatter(arr) -> dst` | compact → stringkeymap | 连续数组拆成 `dst·[0]…dst·[N-1]` 独立 key |
+| `array·compact(arr) -> dst` | stringkeymap → compact | 读散 key 打包成连续数组 |
+| `array·append` / `array·slice` | 变长 | 作用于 compact 时先自动 scatter |
+
+## ref(存储位置维)与扩展句柄
+
+| ref | 语义 | body |
+|-----|------|------|
+| 0(inline) | 内联值 | 数据本体 |
+| 1(ptr) | kvspace 内软链接 | 目标 key 路径 |
+| 2(@ext) | 扩展存储句柄 | 元存外位置描述符 |
+
+ref=2 表示值本体在扩展世界(SHM/GPU/文件),head 中 langtype 记录形态(如 `[256,256]uint8`),body 记位置描述符。@ext 只表**单个值**存于扩展世界(compact 形态),与 storetype=index/extindex 无关。读取时按 body 前缀路由兑现(见 [[地址空间]] 扩展存储)。
+
+## memindex:定宽目录矩阵
+
+storetype=index/extindex 的 head 物理字段记成员名 m×n 对齐字符串数组,参数 `dims=[len, cap, M]`,`M` 向上 8 对齐;`len` 为当前项数、`cap` 为预留容量、`M` 为行宽;主槽 body 恒空。`kvspaceMkindex` 带 `capacity` 参数、构造器 `kvspaceXvalueNewIndexGrow(children, count, cap_hint, m_hint)`(`kvspace-c/src/xvalue.h`)据此保留容量与行宽,使增删可就地覆写、不重分配。
+ "#### -> /lib/kvlang/spec/kvspace模型/数组两种物理形态
+}
diff --git "a/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/08-\346\214\207\344\273\244\345\270\203\345\261\200\346\240\274\345\274\217.kv" "b/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/08-\346\214\207\344\273\244\345\270\203\345\261\200\346\240\274\345\274\217.kv"
new file mode 100644
index 00000000..ed4942dd
--- /dev/null
+++ "b/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/08-\346\214\207\344\273\244\345\270\203\345\261\200\346\240\274\345\274\217.kv"
@@ -0,0 +1,45 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/kvspace模型/指令布局格式 {
+ r####"# 指令布局格式
+
+本章界定函数经 layout 后在 `/lib` 下的 KV 布局:指令如何以坐标键落盘、签名与命名参数如何编码、调用如何经 extindex 复用指令树、参数如何经指针链解析。
+
+## 空间布局,非线性字节码
+
+传统 VM 编译产线性字节码,调用即压返回地址后跳入口。kvlang 的 layout 不产线性序列,而是**空间布局**:每条指令展开为一组 `[s0,s1]` 坐标键,可逐槽 `kv·get`/`kv·list` 寻址,无需反汇编器。函数体永不被复制——调用时经 extindex 令帧根指向 `/lib` 下同一份指令树(见下 [[调用extindex]] 调用机制)。
+
+## 坐标键 `[s0,s1]`
+
+函数 `/lib/{pkg}·{name}/` 目录下,每个槽以 `[s0,s1]` 坐标键寻址。约定:
+
+- `s0` = 行号:`[0,·]` 为签名行,`[1,·]` 起为指令行(指令 0 落 `[1,·]`)。
+- `s1` = 列:`0` 为 opcode 槽,负号 `-j` 为第 j 个读槽,正号 `+j` 为第 j 个写槽。
+
+入口 PC 为 `…/[1,0]`(`layout/src/keytree.rs` 的 `is_entry_pc`:PC 以 `/[1,0]` 结尾即入口)。
+
+### 签名行
+
+函数目录 `/lib/{pkg}·{name}/` 自身(主槽):storetype = index、langtype = `rwfunc`(裸种类名,**不含签名**),body = `[nr:u16 LE][nw:u16 LE][dynamic:u8]`(读参个数 `nr`、写参个数 `nw`、是否变参 `dynamic`)。各参数真实类型**不**写进主槽 langtype,而落在**签名行 `[0,x]` 子槽**:`x<0` 读参、`x>0` 写参、`[0,0]` 为锚点;每个 `[0,x]`(`x≠0`)是 storetype=ARRAYND、langtype=`def kindexpr` 的 xvalue,body 为该参数完整 kindexpr 串(见 [[总体方案]])。同理,`def rwir` 目录主槽 langtype = `def rwir`(裸种类名),body 同格式,签名行 `[0,x]` 亦为 `def kindexpr` 子槽,无实现指令行。
+
+- 命名参数 → 槽映射:`/lib/{pkg}·{name}/{param}` 是一个 char/utf32 值,内容为该参数的槽坐标串(如 `x` → `"[0,-1]"`、返回值 `R` → `"[0,1]"`)。读参映射到 `[0,-j]`、写参映射到 `[0,+j]`。
+
+### 指令行
+
+以 `id_val(x:int64) -> (R:int64) { int64·add(x, 0) -> R }` 为例,`/lib/id_val/` 下:
+
+```
+/lib/id_val/ storetype=index langtype=rwfunc body=[nr=1,nw=1,dyn=0] ← 主槽;langtype 为裸种类名,不含签名
+[0,0] (签名行锚点 s0=0)
+[0,-1] storetype=ARRAYND langtype=def kindexpr body="int64" ← 读参1 x 的类型
+[0,1] storetype=ARRAYND langtype=def kindexpr body="int64" ← 写参1 R 的类型
+x char/utf32→[0,-1] ← 命名读参 → 槽坐标(查表用)
+R char/utf32→[0,1] ← 命名写参 → 槽坐标(查表用)
+[1,0] rwir:int64·add ← 指令0 opcode
+[1,-1] rwir:x ← 指令0 读槽1
+[1,-2] int64:0 ← 指令0 读槽2(内联字面量)
+[1,1] rwir:R ← 指令0 写槽1
+```
+
+opcode 槽 langtype 为 `rwir`(可为 `rwfunc` 引用),body 记 opcode 名。读/写槽的值有两类:`rwir:name` 是对变量的引用(存名字文本,即相对指针),或内联字面量(如 `int64:0`、`char/utf32:"…"`)。opcode 槽永不存变量引用,故值拷贝 `=` 与函数调用 `call` 在 KV 层无歧义。
+ "#### -> /lib/kvlang/spec/kvspace模型/指令布局格式
+}
diff --git "a/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/09-\350\260\203\347\224\250extindex.kv" "b/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/09-\350\260\203\347\224\250extindex.kv"
new file mode 100644
index 00000000..84011802
--- /dev/null
+++ "b/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/09-\350\260\203\347\224\250extindex.kv"
@@ -0,0 +1,31 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/kvspace模型/调用extindex {
+ r####"# 调用:extindex 复用指令树
+
+调用一个函数时,运行时**不**拷贝指令,而是为本次调用建帧子树,令帧根成为指向 `/lib/{pkg}·{name}/` 指令树的 extindex 叠加层,再把实参 / 结果地址写进帧根下的 `[0,±j]` 槽:
+
+- `/lib` 下只有命名参数键(如 `x`、`R`),坐标键 `[0,-j]` / `[0,+j]` 不存在;故运行时向 `frameRoot/[0,±j]` 写入不与只读指令树冲突。
+- 所有帧共享 `/lib` 下同一份指令树,零拷贝;帧根下叠加各自的实参槽与局部变量。
+
+崩溃恢复由此自然成立:PC 是路径字符串、帧根落 KV、返回点落 KV——进程重启后可从 kvspace 续跑。
+
+## 参数解析:指针链
+
+指令读到 `rwir:x` 时,`x` 是相对当前帧的名字。运行时经指针链解析到实参真实位置:
+
+```
+1. 读 frameRoot/x → "[0,-1]" 名字 → 槽坐标
+2. 读 frameRoot/[0,-1] → 实参 key 路径 槽 → 实参地址
+3. 读该路径 → 值 解引用
+```
+
+第 1 跳的 `frameRoot/x` 由 `/lib` 指令树经 extindex 透出(layout 写入、只读),第 2 跳的 `frameRoot/[0,-1]` 由运行时在调用点写入。读参地址可指向调用方值以实现零拷贝重定向(见 [[系统变量]] 的 `‥rparam` / `‥wparam`)。
+
+## init 与标签
+
+- lib 内的裸指令收集为隐式 `init` 函数(无 `init` 关键字),同样以上述布局落 `/lib/{pkg}·init/`。
+- 具名块的标签落 `/lib/{pkg}·{name}/‥labels/{label}` → 指令序号(`layout/src/code.rs`、`layout/src/keytree.rs`)。
+
+签名类型表达式文法见 [[文法]];帧的系统变量见 [[系统变量]];坐标键与 kindexpr 的分隔符语义见 [[键系统与数组访问]]。
+ "#### -> /lib/kvlang/spec/kvspace模型/调用extindex
+}
diff --git "a/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/10-\347\263\273\347\273\237\345\217\230\351\207\217.kv" "b/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/10-\347\263\273\347\273\237\345\217\230\351\207\217.kv"
new file mode 100644
index 00000000..2d2f70ab
--- /dev/null
+++ "b/stdlib/kvlang/spec/02-kvspace\346\250\241\345\236\213/10-\347\263\273\347\273\237\345\217\230\351\207\217.kv"
@@ -0,0 +1,53 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/kvspace模型/系统变量 {
+ r####"# 系统变量
+
+运行时为它管理的对象附带**系统变量**(影子元数据),以 `{对象key}/‥{名}` 形式存放:宿主对象 `/` 下探一层、键名以 `‥`(U+2025)开头。标识符禁以 `‥` 开头,故所有 `‥` 前缀键均为核心保留,用户代码无法直接读写——类比 Unix 隐藏文件,默认视图不显示、引擎可见。
+
+系统变量(`X/‥名`,`/` + `‥` 前缀)与用户成员(`X·名`,`·` 中点键)正交,零交集(见 [[键系统与数组访问]] 键形态三分)。生命周期绑定:`X/‥*` 落在 X 的 `/` 子树内,删除 X 子树即连带清除其全部系统变量。
+
+## vthread 系统变量
+
+宿主 = `/vthread/{vid}`(常量:`runtime/src/keytree.c`、`layout/src/keytree.rs`):
+
+| 键 | 语义 |
+|----|------|
+| `‥pc` | 当前执行 PC(绝对路径字符串) |
+| `‥status` | 运行状态:`init` / `running` / `wait` / `paused`;进入终态时删除并 Notify 返回值 |
+| `‥status/msg` | 状态附带消息;错误时形如 `‥error/msg` 承载错误文本 |
+| `‥debugger` | 调试控制:空为正常,`paused` 为暂停;`debugger()` 内建写此键 |
+| `‥ctime` | 创建时刻 |
+
+## 帧系统变量
+
+宿主 = 帧根(rwfunc 帧或块帧的根路径):
+
+| 键 | 语义 |
+|----|------|
+| *(帧根 extindex)* | rwfunc 帧根经 extindex 指向 `/lib/{pkg}·{name}/` 只读指令树;块帧不建 extindex |
+| `‥lib` | rwfunc 帧的 lib 路径,用于识别 rwfunc 帧边界 |
+| `‥callpc` | 帧内执行进度(每 op 更新;块帧重入亦更新) |
+| `‥returnpc` | 返回地址(帧创建时固化;块帧仅首次设置,重入不覆写) |
+| `‥ro` | 只读参数名单,写槽检查用 |
+| `‥rparam/{name}` | 读参重定向:存调用方值的绝对路径,读参从此路径直读(零拷贝) |
+| `‥wparam/{name}` | 写参重定向:存调用方写目标的绝对路径,写参直写此路径 |
+
+调用点如何写实参 / 结果槽、如何经指针链解析读到重定向路径,见 [[指令布局格式]]。
+
+## 函数标签
+
+具名作用域的标签不落在帧上,而落在函数的 `/lib` 定义处:`/lib/{pkg}·{name}/‥labels/{label}` → 指令序号(`layout/src/keytree.rs`、`layout/src/code.rs`)。
+
+## 语法层保留名 `._`
+
+`._` 是源码层的丢弃槽占位符:写目标为 `._` 时不落 kvspace(帧槽键构造遇此名返回空路径)。它是语法占位符,**不**是 `‥` 系统变量,不落盘。
+
+## `debugger()`
+
+`debugger()` 内建对齐 V8/TypeScript 的 `debugger;` 语句:源码内联暂停点。非调试模式下为 no-op;调试模式下将 `‥status` 置 `paused`,由外部驱动改回 `running` 恢复执行。
+
+## 域与变量之别
+
+注意区分:[[地址空间]] 的结构**域**(`/lib`、`/vthread`、`/networld` 顶层树)与对象随身的 `‥` 系统**变量**是两种机制。域是路径前缀赋予的固定结构语义,系统变量是任一对象 `/` 子树内的影子元数据。
+ "#### -> /lib/kvlang/spec/kvspace模型/系统变量
+}
diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/01-\347\247\215\347\261\273\344\270\216\345\256\232\345\256\275\347\261\273\345\236\213.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/01-\347\247\215\347\261\273\344\270\216\345\256\232\345\256\275\347\261\273\345\236\213.kv"
new file mode 100644
index 00000000..9883c354
--- /dev/null
+++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/01-\347\247\215\347\261\273\344\270\216\345\256\232\345\256\275\347\261\273\345\236\213.kv"
@@ -0,0 +1,45 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/类型系统/种类与定宽类型 {
+ r####"# 种类与定宽类型
+
+kvlang 是**严格定宽类型语言**。
+每个变量、参数、返回值都有确定的种类(kind);无无类型变量,运行时种类不隐式改变。
+类型信息随值自描述:每个 XValue 的类别由 head 三个正交字段表达(见 [[总体方案]] 与 [[XValueHead线格式]]):
+- `ref`(存储位置):0=inline、1=ptr(软链)、2=@ext(单值在扩展世界);
+- `storetype`(物理布局,codec 视角,闭合集:NONE/ATOM/ARRAYND/index/extindex);
+- `langtype`(语义类型,即完整 kindexpr 串,变长,见 [[kindexpr签名类型表达式]])。
+
+## 锚例
+
+- 定宽构造与转换、float→int 截断、窄化回绕:`tutorial/01-basics/cast.kv`、`tutorial/01-basics/numtypes.kv`。
+- 算术保宽与混合提升:`tutorial/01-basics/type_narrowing.kv`。
+- 字符编码与索引:`tutorial/11-string/05-encodings.kv`、`06-convert.kv`、`02-char-ord.kv`。
+- 时间种类:`tutorial/01-basics/time.kv`、`tutorial/13-stdlib/time/`、`13-stdlib/duration/`。
+- 类型错误(bool 算术、跨种类比较、无符号取负、None、compact 变长串):`tutorial/error_cases/type_error/`、`error_cases/none_type_error/`。
+
+## 数值运算域
+
+1. **同种类算术产生同种类结果**,溢出按补码回绕:`int8(127)+int8(1)`=-128、`uint8(255)+uint8(1)`=0、`int32(100)×int32(100)`=10000(kind 保持 `int32`)。float32 运算不升 float64:`float32(16777216)+float32(1)`=16777216.0。
+2. **混合宽度整数向更宽种类提升**:`int8(100)×int16(2)`=200(结果 `int16`);`int8(7)%int16(3)`=1(结果 `int16`)。
+3. **任一侧浮点则提升为浮点**:`int8(120)÷float32(10)`=12.0(结果 `float32`);两整数 `÷` 为整除(`int8(120)÷int8(10)`=12)。
+4. **无符号取负** `-(uint8 值)` TypeError(对齐 C 警告 / Rust、Go 编译错误)。
+5. **bool 不参与算术**:`true + false` TypeError。
+6. **None 参与算术** TypeError;**None 参与分支条件** TypeError。
+7. **跨种类比较** TypeError(`int64(5) == "hello"` 报错);数值种类之间可跨宽度比较(`3 == 3.0` 为 true)。
+
+## bool 铁律
+
+`bool` 值**只能**为 `true`/`false`,**禁止**一切隐式布尔化:
+
+| 输入 | kvlang |
+|------|--------|
+| `true` / `false` | 合法 |
+| `0` / `1` 整数 | TypeError——须显式写 `!= 0` |
+| 非空字符串 | TypeError——须显式写 `!= ""` |
+| None | TypeError |
+
+分支条件(`if`/`while`/`br`)的条件槽**必须**是 `bool`。强制显式比较使控制流走向可被静态判定,不依赖运行时种类。
+
+逻辑运算 `&&`/`||`/`!` 的操作数**必须**是 `bool`,非 bool 即 TypeError;`bool(x)` 构造器只接受 `true`/`false`,其余种类 TypeError(对整数须写 `!= 0`)。
+"#### -> /lib/kvlang/spec/类型系统/种类与定宽类型
+}
diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/02-\347\247\215\347\261\273-\346\240\207\351\207\217\346\227\266\351\227\264\345\256\271\345\231\250.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/02-\347\247\215\347\261\273-\346\240\207\351\207\217\346\227\266\351\227\264\345\256\271\345\231\250.kv"
new file mode 100644
index 00000000..0e36255e
--- /dev/null
+++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/02-\347\247\215\347\261\273-\346\240\207\351\207\217\346\227\266\351\227\264\345\256\271\345\231\250.kv"
@@ -0,0 +1,52 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/类型系统/种类_标量时间容器 {
+ r####"# 种类(kind)
+
+**种类**是值的运行时类别。种类字符串是 kindexpr 的基(base)部分(见 [[kindexpr签名类型表达式]])。
+
+### 定宽数字种类
+
+kvlang 的数字种类**必须携带精确位宽**:
+
+| 类别 | 种类 |
+|------|------|
+| 有符号整数 | `int8` `int16` `int32` `int64` |
+| 无符号整数 | `uint8` `uint16` `uint32` `uint64` |
+| IEEE 754 浮点 | `float32` `float64` |
+
+整数按小端补码编码,浮点按 IEEE 754 编码。
+
+**铁律——无家族简写**。`int`、`uint`、`float`、`num`、`char` 这类不含位宽/编码的简写**不是**合法种类,在任何类型标注中均**不得**出现。位宽与字符编码是**开放集合**(未来可扩 `int4`、`fp8`、`fp16` 等),封闭的家族枚举必然漏项;多态**必须**靠 [[kindexpr签名类型表达式]] 的显式 `|` 枚举表达(如 `int8|int16|int32|int64`)。
+
+### bool 与字符种类
+
+| 种类 | 说明 |
+|------|------|
+| `bool` | 1 字节:`0`=false、`1`=true |
+| `char/utf32` | 码点序列,4B×N,定宽、可索引;**字符串字面量的默认种类** |
+| `char/ascii` | ASCII 字节序列,1B×N,定宽、可索引 |
+| `char/utf8` | UTF-8 字节序列,1B×N,变宽、**禁索引**(仅存储与交换) |
+
+字符三种编码的判定为前缀相等:某种类是字符种类当且仅当它以 `char/` 起始。定宽编码(`utf32`、`ascii`)**必须**支持 O(1) 码点索引;变宽编码 `utf8` 的按码点索引操作(`string·char`、`s[i]` 等)**必须**报 TypeError。单个字符标注为 `char/<编码>`(标量),字符串标注为 `[]char/<编码>`(序列);字符种类的值恒为一维序列。
+
+### 容器与结构种类
+
+| 种类 | 说明 |
+|------|------|
+| `stringkeymap` | map 容器,kindexpr 为 `key·value`(如 `[]char/utf8·int64`) |
+| `struct` | 结构原型实例的种类(见 [[容器]] 与结构声明) |
+| `index` | **storetype**:索引型节点(map/struct 值容器的 `{key}·` memindex、lib/rwfunc 目录节点);物理=m×n 对齐字符串数组,dims=[len,cap,M](M align8) |
+| `extindex` | **storetype**:可扩展索引型节点(vthread 运行栈等,cap 可增长);与 `ref`/`@ext` 无关,extindex 是 storetype 不是 ref=2 |
+
+容器的物理组成(值 + memindex)见 [[容器]]。
+
+### 时间种类
+
+| 种类 | 说明 |
+|------|------|
+| `time` | 时刻,由 `time·now()` 等产生 |
+| `duration` | 时长,由 `time/duration·*` 产生 |
+
+`time`/`duration` 是不透明标量种类,其运算由 time 标准库提供,字节布局不由本卷规定。
+"#### -> /lib/kvlang/spec/类型系统/种类_标量时间容器
+}
diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/03-\347\247\215\347\261\273-\344\273\243\347\240\201\344\270\216\347\211\271\346\256\212\345\200\274.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/03-\347\247\215\347\261\273-\344\273\243\347\240\201\344\270\216\347\211\271\346\256\212\345\200\274.kv"
new file mode 100644
index 00000000..b300d6c9
--- /dev/null
+++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/03-\347\247\215\347\261\273-\344\273\243\347\240\201\344\270\216\347\211\271\346\256\212\345\200\274.kv"
@@ -0,0 +1,22 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/类型系统/种类_代码与特殊值 {
+ r####"# 种类(kind)—— 代码节点与特殊值
+
+### 代码种类
+
+下列 langtype 描述 KV 树中的代码与目录节点(见 [[指令布局格式]]):
+
+- `rwir`:无 kvlang 实现体,指令名文本,storetype=ARRAYND 叶子;由 runtime 经 def rwir 路由直接兑现。
+- `def rwir`:**路由头**,仅存于 `/lib/`,是 rwir 统一调度入口,storetype=index(定义节点),**无 kvlang 实现体**;**不叫"扩展算子"**,**不得**出现在用户书写的类型标注中。每个 runtime 只声明 **myrwircaps**(该 runtime 能兑现的 rwir 能力集);rwir 若不在本 runtime myrwircaps 内须经 `/lib/` 的 def rwir 路由给能兑现它的其它 runtime。
+- `rwfunc`:有 kvlang 实现体(`/` 目录下的指令槽序列),storetype=index(静态定义)或 extindex(vthread 运行栈),可被任意 main-runtime 直接解释执行。
+
+**故有 def rwir 而无 def rwfunc**:rwfunc 有 kvlang 实现体(一串 rwir),任意 main-runtime 逐条解释即可,无需路由头;rwir 无实现体,不在本 runtime myrwircaps 内时必须路由,故需 def rwir。
+
+### None 与 ptr 不是种类
+
+- **None** 不是种类:它是 `storetype=NONE` 的空结构体 XValue。任何有名变量都有地址、都有 XValue;未赋值即 None。None 参与算术、比较、分支条件、类型构造一律 TypeError(见下文与 [[执行模型]])。
+- **ptr(软链接)** 不是种类:它是 head 的 `ref=1`(存储位置维),head 的 storetype/langtype 描述目标的完整形态,body 存目标 key 路径(见 [[容器]])。
+
+> ptr(`ref=1`)是 head 的 ref 字段(存储位置维);kvlang **源码**类型标注最前仍可书写 `*`/`@` 前缀(如 `*int64`、`@[256,256]uint8`),表 ref,layout 解析时剥离该前缀落成 head `ref` 独立字节;**wire 层 langtype 串不含 `*`/`@` 前缀**,存储位置一律经 head `ref` 字节表达。extindex 是 storetype(物理布局维),与 ref=2 无关(见 [[总体方案]])。
+"#### -> /lib/kvlang/spec/类型系统/种类_代码与特殊值
+}
diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/04-\346\236\204\351\200\240\345\231\250.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/04-\346\236\204\351\200\240\345\231\250.kv"
new file mode 100644
index 00000000..b7c4decf
--- /dev/null
+++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/04-\346\236\204\351\200\240\345\231\250.kv"
@@ -0,0 +1,26 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/类型系统/构造器 {
+ r####"# 构造器兼转换器
+
+十个定宽数字种类名与三个字符编码名**既是构造器也是转换器**——同名一元调用把实参转换为该种类:
+
+```kv
+f = float32(3) // kind=float32,值 3.0
+i = int8(0.1) // 0(float→int 向零截断)
+int8(300) -> w // 44(窄化 = 补码回绕)
+t = char/utf32(s) // 变宽 utf8 转定宽 utf32(转后可索引)
+u = char/ascii(t) // 非 ASCII 码点 → TypeError
+```
+
+转换规则(对齐 C / Go / Rust `as`):
+
+| 规则 | 语义 |
+|------|------|
+| float → int | 向零截断(`int32(3.9)`=3、`int32(-2.7)`=-2、`int64(0.5)`=0) |
+| 整数窄化 | 补码回绕(`int8(300)`=44、`uint8(-1)`=255、`int16(70000)`=4464、`int32(2147483648)`=-2147483648) |
+| float32 精度 | 收窄至单精度(`float32(3.141592653589793)`=3.1415927、`float32(16777217)`=16777216.0) |
+| None 输入 | TypeError(`int64(None)` 报错,不得静默产生 0) |
+
+构造器接受字面量与变量表达式(`42.9 -> x; int8(x)`)。种类构造的结果 XValue 以该种类名为 kindexpr 落盘,精度信息随值保留。
+"#### -> /lib/kvlang/spec/类型系统/构造器
+}
diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/05-kindexpr\347\255\276\345\220\215\347\261\273\345\236\213\350\241\250\350\276\276\345\274\217.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/05-kindexpr\347\255\276\345\220\215\347\261\273\345\236\213\350\241\250\350\276\276\345\274\217.kv"
new file mode 100644
index 00000000..ccf91c4f
--- /dev/null
+++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/05-kindexpr\347\255\276\345\220\215\347\261\273\345\236\213\350\241\250\350\276\276\345\274\217.kv"
@@ -0,0 +1,15 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/类型系统/kindexpr签名类型表达式 {
+ r####"# kindexpr 签名类型表达式
+
+**类型表达式**是函数(rwfunc)与 def rwir 签名中参数、返回值的类型标注语法。它既供人和工具读写,也逐字节落盘为运行时匹配的依据。同一套表达式贯穿 layout(静态校验)与 runtime(值匹配),故本卷统称 **kindexpr**。
+
+完整权威文法见 [[文法]](附录)的「类型表达式」小节;本章只界定其语义。
+
+## 锚例
+
+- 标量并集、多维形状、动态维、字符串标注:`tutorial/10-types/`(`01-typed-map.kv`~`05-tuple-key.kv`)。
+- 嵌套 mapexpr 与元组键落盘 round-trip:`tutorial/10-types/04-nested-type.kv`、`05-tuple-key.kv`。
+- 变参 `...`:`print`/`println`/`min`/`max` 全 tutorial 广泛使用。
+"#### -> /lib/kvlang/spec/类型系统/kindexpr签名类型表达式
+}
diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/06-\345\275\222\345\261\236\344\270\216\350\220\275\347\233\230.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/06-\345\275\222\345\261\236\344\270\216\350\220\275\347\233\230.kv"
new file mode 100644
index 00000000..20c85528
--- /dev/null
+++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/06-\345\275\222\345\261\236\344\270\216\350\220\275\347\233\230.kv"
@@ -0,0 +1,22 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/类型系统/归属与落盘 {
+ r####"# 归属与落盘
+
+| 归属 | 存放位置 | 种类 |
+|------|---------|------|
+| 用户函数签名 | `/lib/·` | `rwfunc` |
+| def rwir 路由头 | `/lib/` | `def rwir` |
+| native 算子签名 | C 注册表(不落盘) | —— |
+
+**铁律**:`rwfunc` 每个参数落盘的 kindexpr 与源码里的类型标注**逐字节相同**(同一文法,含 `...`);`def rwir` 源码不声明,其参数 kindexpr 由各 runtime 注册时按同一文法写入。签名**不写进 langtype 串**,也不塞进主槽 body,分两处存(详见 [[总体方案]]「签名不入 langtype 串」):
+
+1. **主槽计数头**:主槽(如 `/lib/pkg·funca`)body 只记 `[nr:u16 LE][nw:u16 LE][dynamic:u8]`——读参个数 `nr`、写参个数 `nw`、是否变参 `dynamic`(末位读参 `...`);**不含任何参数 kindexpr 串**。
+2. **签名行 `[0,x]` 各槽**:每个参数的 kindexpr 串落在签名行坐标 `[0,x]`(`x<0` 读参、`x>0` 写参、`[0,0]` 签名行锚点),每槽为一个 `def kindexpr` 类型的 xvalue,body 存该参数完整 kindexpr 串。
+
+故 rwfunc/def rwir 主槽的 langtype 就是裸种类名 `rwfunc`/`def rwir` 本身,不再是「签名 kindexpr 串」。native 算子的 kindexpr 内联在 C 注册表中,是唯一权威来源,运行时匹配**直接读 C 表、不回查 kvspace**;数值多类型算子在 C 表中融合为单条(如 `add(a:int8|…|float64, b:…)`)。
+
+## 强制类型标注
+
+`rwfunc` 签名中每个参数与每个返回值**必须**声明类型(`name:type_expr`)。缺标注的签名**拒绝装载**——layout 在语法检查期报错,指出该参数/返回值无类型标注。类型标注须通过 kindexpr 合法性校验(拒绝非种类名,见下)。`def rwir` 路由头由 runtime 注册(源码不声明),其参数类型在注册接口处按同一合法性规则校验。
+"#### -> /lib/kvlang/spec/类型系统/归属与落盘
+}
diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/07-\346\226\207\346\263\225\344\270\216\345\220\210\346\263\225\346\200\247.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/07-\346\226\207\346\263\225\344\270\216\345\220\210\346\263\225\346\200\247.kv"
new file mode 100644
index 00000000..66549b68
--- /dev/null
+++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/07-\346\226\207\346\263\225\344\270\216\345\220\210\346\263\225\346\200\247.kv"
@@ -0,0 +1,33 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/类型系统/文法与合法性 {
+ r####"# 文法与合法性
+
+类型表达式的构成(详见 [[文法]]):
+
+- **并集** `A|B`——以 `|` 拆分为若干 atom,表「A 或 B」。多态**必须**用显式并集表达。
+- **atom** = 形状(shape)或 map 表达式(mapexpr)。
+- **shape** = 可选维度 `dims` 后跟 `any` 或精确种类名。
+- **dims** = `[]`(无内容)或 `[dim,dim,…]`;`dim` 为整数或 `?`(动态维)。
+- **mapexpr** = `key·value`,`value` 递归为完整类型表达式(故 map 可无限嵌套)。
+- **key** = `[]char/<编码>`(字符串键)或 `[scalar,…]`(标量元组键);`scalar` 限 `bool` 与十个定宽数字种类。
+- **any** = 通配,匹配任意种类;是**唯一**简写。
+- **structref** = 以 `/` 起始的原型路径(如 `/lib/Point`),作为 atom 标注结构类型(见 [[容器]] 的 struct)。
+- **变参** `...`——见下。
+
+**合法性校验**(layout 与 runtime 一致):每个 atom 的基须为 `known` 种类名或 `any`;键须为 `[]char/<编码>` 或全标量元组。非法示例及拒因:
+
+| 非法 | 拒因 |
+|------|------|
+| `int` `float` `char` | 家族简写,非种类名 |
+| `int64*` | 后缀 `*` 位置非法;`*`/`@` 前缀**仅**可书写在源码类型标注最前,layout 剥离落 `ref` 字节,wire langtype 不含前缀 |
+| `char/utf8·int64` | map 键未加方括号 |
+| `[]int32·int64` | map 字符串键的编码非 `char/*` |
+| `[?]·int64` | map 键含维度 |
+| `[foo,int32]·int64` | 元组键含非标量元素 |
+| 裸 `[]` / 裸 `[?]` | 无基种类 |
+
+源码类型标注最前的 `*`/`@` 前缀(如 `*int64`、`@[256,256]uint8`)**合法**,layout 解析时剥离前缀落成 head `ref` 字节,再校验剩余 kindexpr;wire 层 langtype 串不含前缀(见 [[总体方案]])。
+
+`def rwir` 是路由头 langtype(仅落于 `/lib/`),**不得**作为类型标注书写;`rwfunc` 有 kvlang 实现体,可被任意 main-runtime 直接解释,**无需也没有** def rwfunc(见 [[种类与定宽类型]])。
+"#### -> /lib/kvlang/spec/类型系统/文法与合法性
+}
diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/08-\345\214\271\351\205\215\350\257\255\344\271\211\344\270\216\345\217\230\345\217\202.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/08-\345\214\271\351\205\215\350\257\255\344\271\211\344\270\216\345\217\230\345\217\202.kv"
new file mode 100644
index 00000000..b85adac4
--- /dev/null
+++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/08-\345\214\271\351\205\215\350\257\255\344\271\211\344\270\216\345\217\230\345\217\202.kv"
@@ -0,0 +1,48 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/类型系统/匹配语义与变参 {
+ r####"# 匹配语义与变参
+
+## 变参 `...`
+
+变参尾缀 `...` **仅**允许加在**末位读参**的类型表达式上(如 `A:any...`、`A:int64|float64...`),表「0..N 个同型实参」,用于 `print`/`println`/`min`/`max` 等 arity 开放的算子。
+
+- 非末位参数带 `...`:装载期错误。
+- 写参(返回值)带 `...`:装载期错误。
+
+匹配时,变参把所有尾随实参逐个按去掉 `...` 后的类型表达式判定。
+
+## 匹配语义
+
+一个值(种类 `k`、维数 `n`、维列表 `d`)匹配类型表达式 `E`:按 `|` 拆成若干 atom,**任一** atom 命中即匹配。单个 atom 的判定:
+
+1. atom 为 `any` → 命中。
+2. atom 含 `·`(mapexpr)→ 命中当且仅当 `k == stringkeymap`。键/值结构在**匹配期不再校验**(已在装载期校验合法性)。
+3. atom 有 `[` 前缀(shape)→ 先按维度段做形状匹配,再以剩余基种类匹配 `k`。
+4. atom 无 `[` 前缀(标量)→ 命中当且仅当 `n == 0` 且基种类等于 `k`(`any` 除外走精确字符串相等)。
+
+**形状匹配**(维度段 → `n`,`d`):
+
+| 维度段 | 命中条件 |
+|--------|---------|
+| 空(`[]`)或 `[?]` | 恰 `n == 1`,长度任意 |
+| `[d0,d1,…]` | 逗号项数 `== n`,且逐维:`?` 跳过、否则 `d[i] == di` |
+
+`[]` **等价** `[?]`——均为「恰一维、任意长」。字符串标注 `[]char/<编码>` 即一维字符序列。
+
+> 规范注记:`[]` 恒为「恰一维」是 normative 规则。runtime 匹配器(`runtime/src/kindexpr.c`)已一致;layout 匹配器(`layout/src/kindexpr.rs`)当前放宽为「任意 rank ≥1」,为已裁决待修的实现偏差,须收敛至「恰一维」。
+
+任一失配即 TypeError:装载期由 layout 报诊断,运行期写 vthread 错误并停机。
+
+XValue head 三正交维编码见 [[总体方案]](本卷只界定 langtype 作为 kindexpr 串的文法与匹配语义)。
+
+## 多态派发
+
+- **native 算子**(如 `+`)内建多态,签名只做类型检查;分派在 C 算子内部按实参种类完成。
+- **rwir 指令**(如 `numpy·add`)经 def rwir 路由到有对应 myrwircaps 的 runtime,按实参实际种类分派;高维形状由该 runtime 自行处理。
+- **用户函数**(rwfunc)以并集声明接受集,函数体内用种类分支处理各分支。
+
+## 语法冲突规避
+
+签名以 `,` 分隔参数,形状维度段内也用 `,` 分隔维。签名解析器**跟踪方括号深度**:见 `[` 进形状态、见 `]` 退出;形状态内的 `,` 归维、态外的 `,` 归参数。类型表达式内不出现 `(` `)` `:` `->` 空格,故与签名外层结构无歧义。
+"#### -> /lib/kvlang/spec/类型系统/匹配语义与变参
+}
diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/09-\346\225\260\347\273\204\345\275\242\346\200\201.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/09-\346\225\260\347\273\204\345\275\242\346\200\201.kv"
new file mode 100644
index 00000000..c1a4892d
--- /dev/null
+++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/09-\346\225\260\347\273\204\345\275\242\346\200\201.kv"
@@ -0,0 +1,28 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/类型系统/数组形态 {
+ r####"# 数组形态
+
+kvlang 的数组有**两种物理形态**:**compact**(稠密:全量元素连续打包进单个 XValue)与 **stringkeymap**(稀疏:散 key,每元素独立落库,未 set 的 key 不存在)。两形态由字面量括号选定,访问算子不同,但都被 `ndarray·*` 元数据算子统一观测。
+
+## 锚例
+
+- compact 建/读/写/求和:`tutorial/04-ndarray/continuous.kv`。
+- head 种类与 kindexpr、reinterpret:`tutorial/04-ndarray/xv_meta.kv`、`xv_reinterpret.kv`。
+- numel/dim/shape、xv·at/set:`tutorial/04-ndarray/xv_shape.kv`。
+- 多维下标写、reshape:`tutorial/04-ndarray/subscript_write.kv`。
+- stringkeymap 字面量与遍历:`tutorial/04-ndarray/sparse_literal.kv`、`string_array.kv`。
+- 两形态互转:`tutorial/04-ndarray/separated.kv`。
+- 多值坐标段:`tutorial/04-ndarray/geo_coord.kv`。
+- 括号规约错误(compact 容变长串):`tutorial/error_cases/type_error/compact_string_array.kv`。
+
+## 括号规约
+
+| 字面量 | 形态 | 落库 | 约束 |
+|--------|------|------|------|
+| `[e0, e1, …]` | compact | 元素连续打包进单个 XValue,head 的 langtype(kindexpr)= 元素种类(如 `[4]int64`),storetype=ARRAYND | 定长、同种类;元素**不得**为变长(字符串字面量禁入) |
+| `{v0, v1, …}` | stringkeymap | 每元素落 `base·i` 独立子 key,容器值 langtype=map kindexpr(如 `[]char/utf8·int64`),storetype=index,主槽 body 空,成员名索引落 `base·` memindex(m×n 对齐字符串数组) | 变长/可增长;字符串数组等变长集合用此形式 |
+
+- compact 字面量降级为 `array(…)` 构造。变长字符串元素进 compact `[…]` 在 layout 语法检查期报错(`compact array [...] cannot hold variable-length string element`)。
+- stringkeymap 字面量降级为 `map(…)` 构造,只作赋值右值或 `for-in` 源。
+"#### -> /lib/kvlang/spec/类型系统/数组形态
+}
diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/10-compact\345\275\242\346\200\201.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/10-compact\345\275\242\346\200\201.kv"
new file mode 100644
index 00000000..c4634903
--- /dev/null
+++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/10-compact\345\275\242\346\200\201.kv"
@@ -0,0 +1,46 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/类型系统/compact形态 {
+ r####"# compact 形态
+
+compact 数组是**单个 XValue**:head 的 langtype(kindexpr)形如 `[4]int64`(含维度+元素种类),storetype=ARRAYND,body 是连续的定宽元素字节。
+
+```kv
+a:[]int64 = [10, 20, 30, 40] // head kindexpr = [4]int64,body = 4×8 字节
+```
+
+- head 的 langtype = kindexpr 串形如 `[4]int64`(元素种类为 `int64`,**非** `array`);storetype=ARRAYND(见 `tutorial/04-ndarray/xv_meta.kv`)。
+- 字符串是 compact 的字符序列:`s:char/utf8 = "hi"` 的 kindexpr 为 `[2]char/utf8`。单个字符串是 compact;**字符串的数组**是变长集合,必须 stringkeymap。
+
+### compact 元素访问
+
+下标 `a[i]` 是 compact 元素访问:读降级为 `xv·at`,写(`a[i]=v` 或 `v -> a[i]`)降级为 `xv·set`。
+
+```kv
+a[1] -> e // 等价 xv·at(a, 1) -> e
+a[2] = 99 // 等价 xv·set(a, 2, 99) -> a
+99 -> a[0] // 右箭头下标写,等价 xv·set(a, 0, 99) -> a
+```
+
+`xv·at` / `xv·set` **仅接受 compact 数组**(维数非 0):对 stringkeymap 或标量报 TypeError。索引个数**必须**等于维数,按 row-major 折算扁平偏移;越界报 IndexError。写回保持 dims 不变。
+
+### 多维 compact(tensor)
+
+多维 compact 由 `xv·reshape` 从一维铺开:
+
+```kv
+m = xv·reshape([1, 2, 3, 4], 2, 2) // dims = [2,2]
+7 -> m[1, 0] // 多维下标写
+m[0, 1] -> x // 多维下标读
+```
+
+多维下标个数须等于维数(此例 2),按 row-major 折算(见 `tutorial/04-ndarray/subscript_write.kv`)。
+
+### head 观测与重解释
+
+| 算子 | 语义 |
+|------|------|
+| `xv·kindexpr(a)` | 返回 head 的 kindexpr 串(如 `[4]int64`) |
+| `xv·bodylen(a)` | 返回 body 字节数 |
+| `xv·reinterpret(a, "[]uint8")` | 原样保留 body 字节,只替换 kindexpr(`[3]int64` 24 字节 → `[24]uint8`) |
+"#### -> /lib/kvlang/spec/类型系统/compact形态
+}
diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/11-stringkeymap\345\275\242\346\200\201.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/11-stringkeymap\345\275\242\346\200\201.kv"
new file mode 100644
index 00000000..c95840cd
--- /dev/null
+++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/11-stringkeymap\345\275\242\346\200\201.kv"
@@ -0,0 +1,24 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/类型系统/stringkeymap形态 {
+ r####"# stringkeymap 形态
+
+stringkeymap 数组的**容器值**是一个 storetype=index 的 XValue(langtype 为 map kindexpr,如 `[]char/utf8·int64`;body 空,成员名索引落 `base·` memindex,dims=[len,cap,M]),**每个元素**是独立子 key `base·i`:
+
+```kv
+nums = {10, 20, 30, 40} // 每元素落 nums·0 … nums·3
+for (x in nums) { … } // 遍历散 key 元素
+names = {"apple", "banana", "cherry"} // 变长字符串数组必须 stringkeymap
+```
+
+散 key 元素以坐标段 `base·[i]` 访问(经 `kv·get`),或以 `for-in` / `kv·listlen` / `kv·listn` 遍历。坐标段支持多值键(含小数):`geo·[39.9,116.4] = "Beijing"`,物理以字符串格式落 key(见 `tutorial/04-ndarray/geo_coord.kv`)。
+
+## 两形态互转
+
+| 算子 | 语义 |
+|------|------|
+| `array·scatter(a)` | compact → stringkeymap(散 key) |
+| `array·compact(b)` | stringkeymap → compact |
+
+字面量初始化默认按括号定形态;`scatter`/`compact` 显式转换(见 `tutorial/04-ndarray/separated.kv`)。
+"#### -> /lib/kvlang/spec/类型系统/stringkeymap形态
+}
diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/12-\347\250\240\345\257\206vs\347\250\200\347\226\217.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/12-\347\250\240\345\257\206vs\347\250\200\347\226\217.kv"
new file mode 100644
index 00000000..68a5e482
--- /dev/null
+++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/12-\347\250\240\345\257\206vs\347\250\200\347\226\217.kv"
@@ -0,0 +1,25 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/类型系统/稠密vs稀疏 {
+ r####"# 稠密 compact vs 稀疏 stringkeymap:同一逻辑形状的两种落库
+
+同一个逻辑上的 `[1024,1024]int32` 二维数组,可按稀疏度选两种截然不同的物理存储:
+
+| 维度 | compact(稠密) | stringkeymap(稀疏) |
+|------|----------------|---------------------|
+| langtype | `[1024,1024]int32` | 坐标元组键 map,如 `[int32,int32]·int32` |
+| storetype | ARRAYND | index |
+| 落库 | 全量 1024×1024 元素连续打包进**单个** XValue 的 body(恒 1024×1024×4 = 4 MiB,未写元素亦占位) | 每个写过的坐标落一个独立子 key `base·[i,j]`;**未 set 的坐标子 key 根本不存在**,不占空间 |
+| 缺失元素 | 无「缺失」——全部就位(默认 0) | 读未写坐标返回 None(`kv·get` 缺失语义) |
+| 随机访问 | `a[i,j]` 按 row-major O(1) 偏移 | `base·[i,j]` / `kv·get` 按 key 查找 |
+| 适用 | 稠密张量、绝大多数元素有值、需连续内存与 O(1) 下标 | 稀疏矩阵、坐标空间极大而实际有值项稀少 |
+
+```kv
+dense:[]int32 = xv·reshape(array(…), 1024, 1024) // 4 MiB 稠密块,storetype=ARRAYND
+sparse:[int32,int32]·int32 = {} // 稀疏,storetype=index
+99 -> sparse·[3,7] // 仅此一项落子 key sparse·[3,7]
+sparse·[0,0] -> x // 未写坐标 → None(子 key 不存在)
+```
+
+两种落库共享 `ndarray·*` 观测(`numel` 对稀疏形态返回**实存成员数**,非坐标空间容量),并经下节 `array·scatter`/`array·compact` 互转。
+"#### -> /lib/kvlang/spec/类型系统/稠密vs稀疏
+}
diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/13-ndarray\345\205\203\346\225\260\346\215\256\347\256\227\345\255\220.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/13-ndarray\345\205\203\346\225\260\346\215\256\347\256\227\345\255\220.kv"
new file mode 100644
index 00000000..0a4bb121
--- /dev/null
+++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/13-ndarray\345\205\203\346\225\260\346\215\256\347\256\227\345\255\220.kv"
@@ -0,0 +1,20 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/类型系统/ndarray元数据算子 {
+ r####"# ndarray 元数据算子
+
+三个算子统一观测数组形状,对两形态均适用:
+
+| 算子 | 语义 |
+|------|------|
+| `ndarray·numel(a)` | 元素总数(compact 读 head array_len;stringkeymap 读成员数) |
+| `ndarray·dim(a)` | 维数(head ndim) |
+| `ndarray·shape(a)` | 各维长度,返回一维 `int64` compact 数组 |
+
+```kv
+a:[]int64 = [10, 20, 30, 40]
+ndarray·numel(a) -> n // 4
+ndarray·dim(a) -> d // 1
+ndarray·shape(a) -> s // [4];s[0] = 4
+```
+"#### -> /lib/kvlang/spec/类型系统/ndarray元数据算子
+}
diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/14-\345\256\271\345\231\250.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/14-\345\256\271\345\231\250.kv"
new file mode 100644
index 00000000..1d9f925e
--- /dev/null
+++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/14-\345\256\271\345\231\250.kv"
@@ -0,0 +1,40 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/类型系统/容器 {
+ r####"# 容器
+
+kvlang 的复合命名数据只有两种容器语义类型:**stringkeymap**(键-值映射)与 **struct**(异构命名成员)。kvlang **没有** `dict` 种类,也没有 `object` 或 `scope` 种类(见 [[总体方案]])。容器物理落 storetype=index,成员经 `{key}·` memindex 兄弟槽枚举(与 lib/rwfunc 目录节点用 `/` 子路径不同)。此外 **ptr**(软链接)是 ref=1 的值形态,指向另一 key。
+
+## 锚例
+
+- stringkeymap 字面量与访问:`tutorial/10-types/01-typed-map.kv`、`tutorial/05-dict/literal.kv`。
+- stringkeymap 与动态键、缺失返 None:`tutorial/10-types/02-string-map.kv`、`05-dict/kv_has_string_key.kv`。
+- 嵌套 map 与元组键签名:`tutorial/10-types/04-nested-type.kv`、`05-tuple-key.kv`。
+- struct 声明/实例化/默认值/多类型字段:`tutorial/12-struct/00-point.kv`、`01-fields.kv`。
+- 指针解引用、局部结构体、链表/树/图:`tutorial/12-struct/03-linked-list.kv`~`07-list-local.kv`。
+
+## 容器结构
+
+容器在 kvspace 中分两部分落库,`·`(U+00B7 中点)是值容器唯一的 memindex 标记(注:`/lib/{pkg}·{func}` 中的 `·` 是包·函数命名分隔符,与 memindex 无关,详见 [[总体方案]]):
+
+- **容器值**:落在裸 base 键,storetype=index,body 空;langtype 为 map kindexpr(如 `[]char/utf8·int64`)或 struct 原型路径(如 `/lib/Point`)。
+- **成员**:`base·name` 是独立子 key,各自持成员值。
+- **memindex**:落在 `base·` 键(尾中点),storetype=index,其 body 是成员名索引矩阵,是成员枚举的权威来源。
+
+memindex 的线格式为 dims = `[len, cap, M]` 的矩阵:`len` = 有效成员数、`cap` = 预留行数(`cap ≥ len`,满则翻倍扩容)、`M` = 成员名 UTF-8 字节最大长向上 8 对齐后的**行宽**;body 为 `cap × M` 字节,前 `len` 行是有序成员名(NUL 补齐),其余行全 NUL。容量内增删成员 body 长恒定、就地覆写。`M` 是行宽(行 stride),`cap` 是可翻倍的容量。
+
+## stringkeymap
+
+**stringkeymap** 是一等 map 类型,kindexpr 为 `key·value`(见 [[kindexpr签名类型表达式]]):`[]char/utf8·int64` 即 `map[string]int64`,value 可递归嵌套(`[]char/utf8·[]char/utf8·int64`)。
+
+```kv
+m:[]char/utf8·int64 = {} // 空 map 同样须带类型标注
+m·a = 10 // 命名成员写
+kv·set(m, "b", 20) // 动态键写
+kv·get(m, "a") -> x // 动态键读;缺失返回 None
+```
+
+## 空容器字面量须带类型标注
+
+`{}` 空 stringkeymap 字面量**必须**在赋值目标处带类型标注(如 `x:[]char/utf8·int64 = {}`);无标注时 layout 报错——空字面量本身无法推断 key/value 类型。
+"#### -> /lib/kvlang/spec/类型系统/容器
+}
diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/15-\346\210\220\345\221\230\350\256\277\351\227\256.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/15-\346\210\220\345\221\230\350\256\277\351\227\256.kv"
new file mode 100644
index 00000000..236fb718
--- /dev/null
+++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/15-\346\210\220\345\221\230\350\256\277\351\227\256.kv"
@@ -0,0 +1,22 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/类型系统/成员访问 {
+ r####"# 成员访问
+
+| 语法 | 语义 |
+|------|------|
+| `base·name` | 静态键成员读/写 |
+| `base·*k` | 动态键:变量 `k` 的值作成员名(用于局部容器) |
+| `kv·get(base, k)` / `kv·set(base, k, v)` | 动态字符串键读/写 |
+
+容器成员一律走 `·`(或 `kv·get`/`kv·set`),**不得**用 `[]`;`[]` 只索引 compact 数组(见 [[数组形态]])。
+
+### `base·name` 的 base 解析:按值优先、按名回退
+
+`base·name`(读写同规则)中 base 的解析:
+
+1. **按值解引用**:base 持有非空字符串值(路径指针)→ 成员键 = `值(base)·name`。如 `"/n1" -> p` 后 `p·next` 解析为 `/n1·next`。
+2. **按名回退**:base 无值(或非字符串)→ 成员键 = `解析(base)·name`;解析帧感知:裸名 → `帧根/base`,`/` 开头 → 直通。
+
+该规则让「局部结构体」(base 无值,按名)与「指针解引用」(base 存路径字符串,按值)共用一套语法。
+"#### -> /lib/kvlang/spec/类型系统/成员访问
+}
diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/16-ptr.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/16-ptr.kv"
new file mode 100644
index 00000000..7550fa17
--- /dev/null
+++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/16-ptr.kv"
@@ -0,0 +1,17 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/类型系统/ptr {
+ r####"# ptr(软链接)
+
+**ptr** 不是种类,而是 head 的 `ref=1`(存储位置维):ptr 值的 head storetype/langtype 描述**目标的完整形态**,body 存**目标 key 路径**。源码类型标注最前可写 `*` 前缀(如 `*int64`)表 ref,layout 剥离后落成 head `ref` 独立字节;wire 层 langtype 串不含前缀(见 [[总体方案]]);赋值(Set)时据 head 的 storetype/langtype 做单跳类型检查。
+
+跨函数共享的数据放绝对路径,指针变量存其路径字符串:
+
+```kv
+/n1 = Node{} // Node 为 struct 原型(含 val:int64、next:[]char/utf8 字段)
+/n1·val = 1
+/n1·next = "/n2" // next 存目标路径(指针)
+"/n1" -> p // 引号 = 路径串(指针)
+p·val -> v // 按值解引用:读 /n1·val
+```
+"#### -> /lib/kvlang/spec/类型系统/ptr
+}
diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/17-struct.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/17-struct.kv"
new file mode 100644
index 00000000..6e601ba0
--- /dev/null
+++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/17-struct.kv"
@@ -0,0 +1,24 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/类型系统/struct {
+ r####"# struct
+
+`struct` 声明注册一个原型节点于 `/lib/`(storetype=index,langtype 为原型路径如 `/lib/Point`),字段带类型标注与默认值:
+
+```kv
+struct Point {
+ x:float64=0.0
+ y:float64=0.0
+}
+```
+
+实例化 `Name{f=v}` 克隆原型子树、覆盖给定字段(其余取默认),并对每个字段做类型校验;实例是 struct 类型命名成员容器(storetype=index,成员在 `{key}·` memindex),成员经 `·` 访问。字段类型不符或写不存在的字段在 runtime 报 TypeError。
+
+```kv
+p = Point{x=3.0 y=4.0}
+p·x -> a // 3.0
+q = Point{} // 全取默认:0.0, 0.0
+```
+
+在签名中,结构类型以原型路径 `/lib/`(**structref** 类型表达式 atom)标注(见 [[kindexpr签名类型表达式]])。结构值可存进 map(int 键、struct 值)、以绝对路径指针连成链表/树/图(见 `tutorial/12-struct/`)。
+"#### -> /lib/kvlang/spec/类型系统/struct
+}
diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/18-\346\200\273\344\275\223\346\226\271\346\241\210.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/18-\346\200\273\344\275\223\346\226\271\346\241\210.kv"
new file mode 100644
index 00000000..07d5edd3
--- /dev/null
+++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/18-\346\200\273\344\275\223\346\226\271\346\241\210.kv"
@@ -0,0 +1,15 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/类型系统/总体方案 {
+ r####"# 类型系统总体方案:xvalue head 三正交维
+
+> **本卷为新方案,待敲定。** 敲定后据此重构 [[种类与定宽类型]]、[[kindexpr签名类型表达式]]、[[数组形态]]、[[容器]]。
+
+每个 XValue 落盘时,其类别由 head 三个**正交**字段表达,彻底取代旧的单一 `kind` 分类与 kindexpr 首字符 `*`/`@` 前缀。
+
+- **`ref`(存储位置)** — 值放在哪:inline / 指针 / 扩展世界。1 字节。
+- **`storetype`(物理布局,codec 视角)** — 字节怎么切。**闭合小集**,1 字节。
+- **`langtype`(语义类型,语言视角)** — 值是什么类型。**即旧的 kindexpr 串**,变长,保留高级语言的全部类型定义。
+
+**核心分层**:codec([[XValueHead线格式]] 的编解码层)**只按 `storetype` 这 1 字节分派切字节**,完全不解析 `langtype` 串(对它只是一段透传字节);body 对 codec 恒为不透明字节。语言层(layout/runtime 类型系统)只读 `langtype` kindexpr 串做类型检查、匹配、显示。这把 kvspace(寻址+内存空间,只认 storetype 1 字节)与 kvlang 类型系统(只认 langtype 串)彻底解耦。
+"#### -> /lib/kvlang/spec/类型系统/总体方案
+}
diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/19-head\345\255\227\346\256\265.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/19-head\345\255\227\346\256\265.kv"
new file mode 100644
index 00000000..f2e85819
--- /dev/null
+++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/19-head\345\255\227\346\256\265.kv"
@@ -0,0 +1,18 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/类型系统/head字段 {
+ r####"# 通用 head 字段(一切 xvalue 皆有,按序)
+
+| 字段 | 宽 | 义 |
+|------|----|----|
+| `headlen` | u16 LE | head 总字节数;body 起于偏移 `headlen` |
+| `ref` | u8 | 存储位置(见下) |
+| `storetype` | u8 | 物理布局(见下) |
+| `ro` | u8 | `1`=只读、`0`=可写 |
+| `vid` | u32 LE | vthread id(默认 0) |
+| `body_len` | u32 LE | body 字节数 |
+| (storetype 物理字段) | 变 | 按 storetype 追加,见下表 |
+| `langtype` | 变长 | kindexpr 串,占至 `headlen`(长度 = `headlen` − 当前偏移,无需独立长度字段) |
+
+`langtype` 恒为 head 最后一段(body 之前)。旧 1 字节 kindcode 方案作废——语义类型回归完整 kindexpr 串,方能承载 `[dims]`、map 的 `key·value`、struct 原型路径、def 族定义节点等高级定义。
+"#### -> /lib/kvlang/spec/类型系统/head字段
+}
diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/20-ref\345\255\230\345\202\250\344\275\215\347\275\256.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/20-ref\345\255\230\345\202\250\344\275\215\347\275\256.kv"
new file mode 100644
index 00000000..0e82b0b8
--- /dev/null
+++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/20-ref\345\255\230\345\202\250\344\275\215\347\275\256.kv"
@@ -0,0 +1,15 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/类型系统/ref存储位置 {
+ r####"# ref(存储位置维)
+
+只决定 body 语义与是否间接寻址;**不改变** storetype/langtype 描述——head 恒携带完整形态。
+
+| ref | body | 义 |
+|-----|------|----|
+| 0 inline | 值 raw 本体 | 就地落盘 |
+| 1 ptr | 目标 key 路径 | 软链接,单跳指向同型目标(head 的 storetype/langtype 即目标形态);`ptr → rwfunc` 即函数调用链 |
+| 2 @ext | 扩展句柄/定位符 | 单个值本体在扩展世界(fs 文件 / gpu tensordata),head 存元描述 |
+
+**源码书写与 wire 的分工**:kvlang **源码**里,指针/扩展引用仍以 `*`/`@` 前缀写在类型**最前**(`*int64`、`@[256,256]uint8`,见 tutorial 例),这是源码类型标注文法的一部分。layout 解析源码时把该前缀**剥离**并落成 head 的 `ref` 独立字节;故 **wire 层 langtype 串不含 `*`/`@` 前缀**,存储位置一律经 `ref` 字节表达。`ref=2` 只表**单值**存于扩展世界,与目录类型 `index`/`extindex` 无关。
+"#### -> /lib/kvlang/spec/类型系统/ref存储位置
+}
diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/21-storetype\347\211\251\347\220\206\345\270\203\345\261\200.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/21-storetype\347\211\251\347\220\206\345\270\203\345\261\200.kv"
new file mode 100644
index 00000000..39421155
--- /dev/null
+++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/21-storetype\347\211\251\347\220\206\345\270\203\345\261\200.kv"
@@ -0,0 +1,56 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/类型系统/storetype物理布局 {
+ r####"# storetype(物理布局维,codec 视角)
+
+决定 head 追加的物理字段与 body 切法。**codec 仅凭此 1 字节分派**。
+
+| storetype | 追加物理字段 | body(ref=0) | 承载的 langtype |
+|-----------|-------------|--------------|----------------|
+| `NONE` | 无 | 空 | None |
+| `ATOM` | 无 | 定宽 raw | 标量:bool、int/uint/float、单 char、time、duration |
+| `ARRAYND` | `ndim` u8 + `dims[ndim]` u32 LE | 稠密等宽元素数组 | 张量、`[]char/*` 字符串、rwir 指令行文本 |
+| `index` | 成员名 **m×n 对齐字符串数组**,`dims=[len,cap,M]`(len=成员数、M=对齐宽度 align8、cap 保留容量) | 见下(目录节点主槽 body 记计数头或空) | stringkeymap、struct(值容器);lib、rwfunc、def 族(目录/定义节点) |
+| `extindex` | 同 index,`cap` 可增长(栈帧/运行栈扩容) | 同上 | rwfunc(vthread 运行栈等可扩展目录) |
+
+数值 `dims` 供 codec O(1) 切字节,与 langtype 串内的 `[dims]` 语法一致(由 codec 保证同步)。index/extindex 的物理载体沿用今日敲定的 m×n 对齐字符串数组(每成员名 padding 至 M,`cap` 预留扩容),存成员/子项名。
+
+### 成员如何枚举:`/` 目录 vs `·` memindex
+
+storetype=index/extindex 只表「这是有成员的索引节点」,成员的**组织方式按 langtype 分两类**:
+
+| 类别 | langtype | 成员载体 | 例 |
+|------|----------|---------|----|
+| 目录节点 | lib、rwfunc、def rwir | **`/` 子路径**(kvspace 目录枚举) | `/lib/funca/[1,0]`、`/lib/funca/[1,1]` 为 `/lib/funca/` 的指令槽成员 |
+| 值容器 | stringkeymap、struct | **`{key}·` memindex 兄弟槽** | `p·` 存 `p` 的成员名索引 |
+
+`{key}·` 中的 **memindex `·`** 是值容器(stringkeymap/struct)唯一的成员索引标记;rwfunc/lib/def 族是真目录,成员即 `/` 子路径,绝不用 memindex `·`。
+
+**注意 `·` 的两种独立含义**——两者正交、勿混:
+
+1. **memindex 标记**:值容器主槽 `{key}` 的兄弟槽 `{key}·`,存该容器的成员名索引。**仅** stringkeymap/struct 用。
+2. **包·函数命名分隔符**:`/lib/{pkg}·{func}`(如 `/lib/time·now`)中的 `·` 只是路径名里分隔包名与函数名的字符,是 rwfunc 所在**目录的名字的一部分**,与 memindex 无关。故 `/lib/time·now/` 仍是纯 `/` 目录,其成员是 `/` 子路径而非兄弟 `·` 槽。
+
+两类值容器底层皆为同一 m×n 对齐字符串数组:目录节点由 kvspace 目录直接持有并按 `/` 枚举,值容器把它放在 `{key}·` 兄弟槽。
+
+### rwir 无实现体(叶子)vs rwfunc 有实现体(目录);def 族定义节点
+
+本质区别在「有无 kvlang 实现体」:
+
+| langtype | 有 kvlang 实现体? | 位置 | 谁实现 | 形态 |
+|----------|------------------|------|--------|------|
+| `rwir` | 无 | `/vthread//` 指令行 | runtime 直接兑现(经 def rwir 路由,myrwircaps) | ARRAYND 指令行叶子 |
+| `def rwir` | 无(仅签名,无指令行) | **仅 `/lib/`** | runtime 直接兑现 | index **定义节点**(有签名行 `[0,x]`,无实现指令行) |
+| `rwfunc` | **有**(一串 rwir 指令行) | `/lib/·/` | kvlang 指令序列自身 | index/extindex **目录**(签名行 `[0,x]` + 实现指令行 `[s0>0,·]`) |
+
+**def rwir 是路由头**(原 `defrwir`,现规范书写为带空格的 **`def rwir`**,见下「def 族」):它只存在于 `/lib/`,是每个 rwir 指令的统一声明入口。`/vthread/` 下执行的每条 rwir 都**引用** `/lib/` 的 def rwir——为「rwir 统一调度」而设。def rwir 没有 kvlang 实现体(无 `s0>0` 的实现指令行),由 runtime 直接兑现。
+
+**没有「扩展 rwir」这个说法**:def rwir 不专指扩展算子。每个 runtime 只声明自己的 **myrwircaps**(该 runtime 能兑现的 rwir 能力集),`/lib/` 的 def rwir 即这些能力对外的路由头。
+
+rwfunc 与之相反:它**有** kvlang 实现体——就是它 `/` 目录下的实现指令行子成员(`/lib/pkg·funca/[1,0]`…)。这正是 rwir/def rwir(无实现指令行、runtime 兑现)与 rwfunc(有实现指令行、`/` 目录)的本质区别。
+
+**为何有 def rwir 却无 def rwfunc**——根源在能力调度的不对称:
+
+- **rwfunc 可被任意 main-runtime 直接解释执行**:其实现体就是一串 rwir,main-runtime 逐条解释即可,不需路由头。故 rwfunc 无需、也没有 `def rwfunc`。
+- **rwir 若不在本 runtime 的 myrwircaps 内就执行不了**,必须依赖调度转发给**能兑现它的其它 runtime**。这份「按能力路由到其它 runtime」的需求,正由 `/lib/` 的 **def rwir 路由头**承载——这就是 def rwir 存在的根本原因。
+"#### -> /lib/kvlang/spec/类型系统/storetype物理布局
+}
diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/22-storetype-def\346\227\217\344\270\216\347\255\276\345\220\215\350\241\214.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/22-storetype-def\346\227\217\344\270\216\347\255\276\345\220\215\350\241\214.kv"
new file mode 100644
index 00000000..ced02590
--- /dev/null
+++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/22-storetype-def\346\227\217\344\270\216\347\255\276\345\220\215\350\241\214.kv"
@@ -0,0 +1,39 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/类型系统/storetype_def族与签名行 {
+ r####"# storetype——签名行、def 族与目录节点
+
+### 签名不入 langtype 串,而入签名行 `[0,x]` 槽
+
+rwfunc / def rwir 的**签名(各参数类型)不写进 langtype 串**,也不塞进主槽 body。分两处存:
+
+1. **主槽计数头**:目录节点主槽 `{fn}`(如 `/lib/pkg·funca`)的 body 只记 `[nr:u16 LE][nw:u16 LE][dynamic:u8]`——读参个数 `nr`、写参个数 `nw`、是否变参 `dynamic`(末位读参 `...`)。**不含任何参数 kindexpr 串**。
+2. **签名行 `[0,x]` 各槽**:每个参数的真实类型定义落在该目录的**签名行**坐标 `[0,x]`——`x<0` 为读参、`x>0` 为写参、`[0,0]` 为 opcode/签名行锚点(见 [[指令布局格式]] 的二元坐标 `[s0,s1]`:`s0=0` 即签名行)。每个 `[0,x]` 槽是一个 **`def kindexpr`** 类型的 xvalue,其 body 存该参数的完整 kindexpr 串(一个参数一槽)。
+
+于是 rwfunc/def rwir 主槽的 langtype 就是裸种类名 `rwfunc` / `def rwir` 本身,**不再是「签名 kindexpr 串」**。签名分散在 `[0,x]` 签名行槽里,实现指令行(若有)在 `[s0>0,·]`。
+
+### def 族:定义节点的 langtype(带空格书写)
+
+「某类型的定义节点」自身的 langtype 用 **`def `** 家族名,**中间保留空格**(读作「`base` 的定义」):
+
+| langtype | 落点 | 表示 |
+|----------|------|------|
+| `def rwir` | `/lib/` | 一条 rwir 的路由头/签名定义(原 `defrwir`,废连写) |
+| `def struct` | `/lib/` | 一个 struct 原型的定义节点(字段类型定义在其子槽) |
+| `def kindexpr` | 签名行 `[0,x]` 槽 | 一个参数的类型定义(body=该参数 kindexpr 串) |
+
+`def` 与 base 间的空格是**规范强制**:连写形式 `defrwir`/`defstruct`/`defkindexpr` 一律废除。
+
+### 目录节点即索引型容器
+
+KV 树中的目录路径(尾 `/`)本身是 xvalue,storetype ∈ {index, extindex},langtype 表达目录语义:
+
+| 路径 | langtype | storetype | 成员 |
+|------|----------|-----------|------|
+| `/lib/` | `lib` | index | `/lib/` 各包目录(`/` 子路径) |
+| `/lib/pkg·funca/` | `rwfunc` | index(静态函数定义目录) | 签名行 `[0,x]`(def kindexpr)+ 实现指令行 `[s0>0,·]` |
+| `/lib/` | `def rwir` | index(路由头,只有签名行) | 签名行 `[0,x]`(def kindexpr),无实现指令行 |
+| `/vthread/1/` | `rwfunc` | extindex(运行栈,可扩展) | `/vthread/1/<坐标>` 栈帧/指令 |
+
+同为 rwfunc,静态定义落 `index`、运行栈落 `extindex`——langtype 一致、物理载体按场景选。
+"#### -> /lib/kvlang/spec/类型系统/storetype_def族与签名行
+}
diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/23-langtype\350\257\255\344\271\211\347\261\273\345\236\213.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/23-langtype\350\257\255\344\271\211\347\261\273\345\236\213.kv"
new file mode 100644
index 00000000..56ea947e
--- /dev/null
+++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/23-langtype\350\257\255\344\271\211\347\261\273\345\236\213.kv"
@@ -0,0 +1,28 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/类型系统/langtype语义类型 {
+ r####"# langtype(语义类型维,语言视角)= kindexpr 串
+
+langtype 恢复为完整 kindexpr 串,逐字节即旧类型标注文法(见 [[kindexpr签名类型表达式]]),天然含 base 种类、`[dims]`、map 键值、struct 原型路径。各 langtype 的串形态与其落定的 storetype:
+
+| langtype(kindexpr 串例) | storetype | 说明 |
+|--------------------------|-----------|------|
+| `int64` `bool` `time` `duration` | ATOM | 定宽标量 |
+| `[]char/utf8` | ARRAYND(elem 1B) | **utf8 变宽 → 物理即 [n]uint8**;禁码点索引是 langtype 层规则,物理按字节切 |
+| `[]char/utf32` `[]char/ascii` | ARRAYND | 定宽,物理可 O(1) 码点索引 |
+| `[3,4]float32` | ARRAYND | 张量 |
+| `rwir`(指令行,`/vthread/`) | ARRAYND | 指令行叶子,**无实现体,由 runtime 经 def rwir 路由直接兑现(myrwircaps)** |
+| `def rwir`(路由头,仅 `/lib/`) | index | 定义节点:签名行 `[0,x]`,无实现指令行 |
+| `[]char/utf8·int64`(map) | index | **stringkeymap**,键值经 `·` mapexpr;成员在 `{key}·` |
+| `/lib/Point`(struct 原型路径) | index | 结构实例,字段固定;成员在 `{key}·` |
+| `def struct`(原型定义节点) | index | struct 原型自身;字段类型定义在其子槽 |
+| `rwfunc` | index / extindex | 函数即 `/` 目录:签名行 `[0,x]` + 实现指令行;主槽 body 只记 nr/nw/dynamic |
+| `def kindexpr`(签名行 `[0,x]` 槽) | ARRAYND | 单个参数类型定义,body=该参数 kindexpr 串 |
+| `lib`(包目录) | index | `/lib/` 及各 pkg 目录;成员为 `/` 子路径 |
+
+**def 族的来源**(`def` 不是 kvlang 关键字、不在 kv 源码书写):`def struct`(源码 `struct Name{}`,layout 落原型定义节点)、`def kindexpr`(源码参数标注 `x:int64`,layout 铺签名行时逐参生成)由 **layout** 产生;`def rwir`(`/lib/` 路由头)**由各 runtime 注册**——kv 源码不声明 rwir,layout 也不产生 def rwir(见 [[rwfunc布局与def_rwir]])。
+
+`object`/`scope` **彻底不存在**——无此种类名、无此关键字;异构命名容器一律是 `struct`(见 [[容器]])。容器**语义类型**只剩 `stringkeymap`、`struct`(口语称「map」指的即 stringkeymap,规范一律书写种类名 `stringkeymap`)。
+
+**一对多正是拆分的价值**:同为 rwfunc,静态函数定义落 `index`、vthread 运行栈落 `extindex`;语言层看到的是同一 langtype,物理层按场景选载体。
+"#### -> /lib/kvlang/spec/类型系统/langtype语义类型
+}
diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/24-wire\345\270\203\345\261\200\347\244\272\344\276\213.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/24-wire\345\270\203\345\261\200\347\244\272\344\276\213.kv"
new file mode 100644
index 00000000..fa765808
--- /dev/null
+++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/24-wire\345\270\203\345\261\200\347\244\272\344\276\213.kv"
@@ -0,0 +1,24 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/类型系统/wire布局示例 {
+ r####"# wire 布局示例
+
+通用前缀 `U = [headlen:u16][ref][storetype][ro][vid:u32][body_len:u32]`,其后按 storetype 追加物理字段,再接 langtype kindexpr 串(占至 headlen),末接 body:
+
+```
+None : U(store=NONE)[lang=""] | 空
+atom int64 : U(store=ATOM,body_len=8)[lang="int64"] | 8B raw
+[]char/utf8 : U(store=ARRAYND)[ndim=1][dims=n][lang="[]char/utf8"] | n 字节
+[3,4]f32 : U(store=ARRAYND)[ndim=2][dims=3,4][lang="[3,4]float32"] | 48B raw
+map : U(store=index)[count/cap…][lang="[]char/utf8·int64"] | 主槽空;成员在 {key}·
+struct 实例 : U(store=index)[count/cap…][lang="/lib/Point"] | 主槽空;成员在 {key}·
+def struct : U(store=index)[count/cap…][lang="def struct"] | Point 原型;字段定义在子槽
+/lib/ : U(store=index)[count/cap…][lang="lib"] | 成员为 /lib/ 子路径
+/lib/pkg·funca : U(store=index)[count/cap…][lang="rwfunc"] | body=[nr][nw][dyn];签名在 [0,x],实现在 [s0>0,·]
+/lib/ : U(store=index)[count/cap…][lang="def rwir"] | 路由头;body=[nr][nw][dyn];签名在 [0,x],无实现行
+签名行 [0,x]: U(store=ARRAYND)[lang="def kindexpr"] | body=该参数 kindexpr 串
+/vthread/1/ : U(store=extindex)[ext 元数据][lang="rwfunc"] | 运行栈,/vthread/1/<坐标> 子成员
+ptr→int64 : U(ref=1,store=ATOM)[lang="int64"] | body="/x/y"
+ptr→rwfunc : U(ref=1,store=index)[lang="rwfunc"] | body="/lib/pkg·funca"(调用链)
+```
+"#### -> /lib/kvlang/spec/类型系统/wire布局示例
+}
diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/25-\345\267\262\346\225\262\345\256\232.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/25-\345\267\262\346\225\262\345\256\232.kv"
new file mode 100644
index 00000000..34d88660
--- /dev/null
+++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/25-\345\267\262\346\225\262\345\256\232.kv"
@@ -0,0 +1,28 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/类型系统/已敲定 {
+ r####"# 已敲定
+
+- 三维正交:`ref` × `storetype` × `langtype`,codec 只认 storetype(1 字节)、语言层只认 langtype(kindexpr 串)。
+- **langtype = 旧 kindexpr 串**(变长),保留高级语言全部类型定义;1 字节 kindcode 方案作废。
+- storetype 集:`NONE`/`ATOM`/`ARRAYND`/`index`/`extindex`(index/extindex 是 storetype,非 langtype)。
+- 容器语义类型只剩 `stringkeymap`/`struct`(口语「map」= stringkeymap;`object`/`scope` **彻底删除**,无此种类/关键字);物理落 index。
+- 字符串:ascii/utf32 → ARRAYND;utf8 → ARRAYND(elem 1B)。
+- time/duration → ATOM;rwir 指令行 → ARRAYND 叶子(无实现体)。
+- **rwir vs rwfunc 的本质区别**:rwir 无实现指令行、由 runtime 直接兑现(myrwircaps);rwfunc 有 kvlang 实现指令行(`/` 目录下的 `[s0>0,·]`)→ 目录。
+- **def rwir 是路由头**(原 defrwir):仅存于 `/lib/`,是 rwir 统一调度入口;`/vthread/` 的每条 rwir 引用 `/lib/` 的 def rwir。**无「扩展 rwir」之说**,只有各 runtime 的 myrwircaps。
+- **签名不入 langtype 串**:rwfunc/def rwir 主槽 langtype 即裸名 `rwfunc`/`def rwir`;主槽 body 只记 `[nr][nw][dynamic]`;各参数真实类型落在签名行 `[0,x]` 槽(`x<0` 读参、`x>0` 写参、`[0,0]` 锚点),每槽为 `def kindexpr` xvalue(body=该参数 kindexpr 串)。
+- **def 族带空格书写**:`def rwir`、`def struct`、`def kindexpr`——`def` 与 base 间强制空格,连写形式废除。
+- **rwfunc/lib 是目录节点**:成员即 `/` 子路径;rwfunc 静态定义 → index、vthread 运行栈 → extindex。
+- **index/extindex 物理载体 = m×n 对齐字符串数组**(`dims=[len,cap,M]`,M align8、cap 扩容),沿用今日敲定方案,存成员/子项名。
+- **`·` 双义正交**:① memindex 标记 `{key}·` 仅 stringkeymap/struct 用;② `/lib/{pkg}·{func}` 里的 `·` 是包·函数命名分隔符(路径名一部分),与 memindex 无关,rwfunc 目录成员仍走 `/`。
+- 索引型容器(stringkeymap/struct)主槽 `{key}` body 恒空。
+- **源码 `*`/`@` 前缀保留**:kvlang 源码类型标注最前可写 `*`/`@`(表 ref),layout 剥离前缀落成 head `ref` 字节;wire 层 langtype 串不含前缀。
+- `headlen` u16 LE;`body_len` 保留为显式 u32 LE 字段;langtype 串占至 headlen,无独立长度字段。
+- `ref=2`(@ext)与 index/extindex 无关。
+- in-memory head struct 按 storetype 拆分——**属实现层,本规范只定 wire 与字段语义**。
+
+## 仍待敲定
+
+(本卷所有类型分歧已敲定。剩余仅实现层细节——如 index/extindex m×n 数组各字段精确偏移、签名行 `[0,x]` 坐标与 [[指令布局格式]] 二元坐标的具体编码、extindex 扩容策略——随 01-04 重构与 [[容器]] memindex 线格式对齐后落定,不属本卷规范分歧。)
+"#### -> /lib/kvlang/spec/类型系统/已敲定
+}
diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/26-\345\255\227\347\254\246\344\270\262\347\274\226\347\240\201.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/26-\345\255\227\347\254\246\344\270\262\347\274\226\347\240\201.kv"
new file mode 100644
index 00000000..de1a94dc
--- /dev/null
+++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/26-\345\255\227\347\254\246\344\270\262\347\274\226\347\240\201.kv"
@@ -0,0 +1,49 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/类型系统/字符串编码 {
+ r####"# 字符串编码
+
+char 种类([[种类与定宽类型]]、[[种类_标量时间容器]])承载三种编码:utf8、utf32、ascii。
+本章规定这三种编码在 **key/value 存储**、**用户 kv 代码**与 **string 标准库**三个层面的分工。
+
+## 一、存储与交换默认 utf8
+
+kvlang 体系内,**key 与 value 中的字符串默认 utf8**。
+
+- key 侧:字符串键(`[]char/utf8·value` 中 key 侧的 `[]char/`)与路径名,utf8 是默认。
+- value 侧:落到 KV 树的字符串值,未显式标注时以 utf8 承载。
+
+utf8 是变宽字节序列,**字节取向、空间高效**,适合作为持久/交换形态;utf8 **禁码点索引**(O(1) 索引须定宽编码)。
+
+## 二、utf32 开放给用户 kv 代码
+
+utf32 是码点序列(4B×N),**定宽、可索引**,供用户 kv 代码在需要处理字符串内容时显式使用:
+
+```
+// 存储读出的串默认 utf8;要逐码点处理,先显式转 utf32
+kv·get(d, "name") -> s8 // s8: []char/utf8
+char/utf32(s8) -> s32 // s32: []char/utf32,定宽可索引
+s32[0] -> c // O(1) 码点取
+```
+
+utf8 → utf32 的转换是**显式**的(编码纪律,见 [[字符串与空值布尔字面量]] 与 char 转换 builtin);跨编码不隐式混拼。
+
+## 三、string 标准库只处理定宽(utf32)
+
+string 包的处理函数(`string·len`、`string·find`、`string·slice`、`string·concat` 等)
+**通常只能处理定宽编码的字符串**——utf32(及 utf8 转换后的工作形态):
+
+- 传入 utf8 串必须先转 utf32 再交 string 包处理;
+- utf8 直接喂 string 包函数是 TypeError(变宽无法 O(1) 定位,函数不隐式转码)。
+
+> 例外:字节层面、与编码无关的操作(如原样搬运、`x` 编码无关比较)可接受 utf8;
+> 语义上按"string 包 = 定宽 utf32 工作面"理解,utf8 是它的存储/交换输入,先转后用。
+
+## 关系小结
+
+| 层面 | 默认编码 | 说明 |
+|------|---------|------|
+| key/value 存储与交换 | utf8 | 变宽字节序列,禁索引,空间高效 |
+| 用户 kv 代码处理 | utf32(显式) | 定宽可索引;utf8 先显式转 utf32 |
+| string 标准库 | utf32 | 只处理定宽;utf8 输入须先转 |
+ "#### -> /lib/kvlang/spec/类型系统/字符串编码
+}
diff --git "a/stdlib/kvlang/spec/04-layout\350\257\255\344\271\211/01-\346\214\207\344\273\244\346\236\266\346\236\204.kv" "b/stdlib/kvlang/spec/04-layout\350\257\255\344\271\211/01-\346\214\207\344\273\244\346\236\266\346\236\204.kv"
new file mode 100644
index 00000000..921b1600
--- /dev/null
+++ "b/stdlib/kvlang/spec/04-layout\350\257\255\344\271\211/01-\346\214\207\344\273\244\346\236\266\346\236\204.kv"
@@ -0,0 +1,50 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/layout语义/指令架构 {
+ r####"# 指令架构
+
+layout 把每个函数体布进 kvspace 的一棵子树:**指令即路径**,每条指令占据一个二维坐标 `[s0, s1]`。本章界定该坐标系、opcode 与读写槽的角色、三种赋值书写形态,以及槽值的 XValue 编码。二维坐标的线格式(TLV、head kindexpr)见 [[指令布局格式]](kvspace 模型卷);本章只界定 layout 产出的槽位语义。
+
+## 二维坐标系 `[s0, s1]`
+
+函数目录(`/lib/·/`,见 [[lib与rwir数据]])下,每条指令的每个槽是一个独立 KV key,key 名恒为坐标串 `[s0,s1]`。两轴含义:
+
+- **s0 轴(执行顺序轴)**——第几条指令。`s0 = 0` 保留给函数签名行;指令从 `s0 = 1` 起顺序编号(称 irseq)。
+- **s1 轴(参数轴)**——该槽的角色:
+
+| s1 | 角色 | 方向 |
+|----|------|------|
+| `s1 = 0` | **opcode**(操作码) | —— |
+| `s1 = -1, -2, …` | **读参**(read slot,输入) | 调用方 → 被调方 |
+| `s1 = +1, +2, …` | **写参**(write slot,输出) | 被调方 → 调用方 |
+
+铁律:
+
+- `[s0, 0]` **必须**是 opcode(操作符名或被调用的 rwir/rwfunc 名),**不得**放变量引用。
+- 读参在负轴、写参在正轴,符号即数据流方向:从负轴读入、在零轴执行、向正轴写出。
+- 参数数量**隐式编码**:runtime 沿 s1 轴向两侧扩展,遇空 key 即停,opcode 中不存 arity(见 [[执行模型]])。
+
+示例:`A + B -> C` 布为
+
+```
+[s0,0] = "+" opcode
+[s0,-1] = "A" 第 1 读参
+[s0,-2] = "B" 第 2 读参
+[s0,1] = "C" 第 1 写参
+```
+
+写参扇出(同一结果写入多个位置)以多个正轴槽表示:`a + b -> sum, backup` 布出 `[s0,1]="sum"`、`[s0,2]="backup"`。
+
+## 三种赋值书写形态
+
+赋值有三种等价书写,写槽约束完全一致:
+
+| 形态 | 写槽位置 | 例 |
+|------|---------|-----|
+| `expr -> writes` | 右 | `A + B -> C` |
+| `writes = expr` | 左 | `C = A + B` |
+
+`=` 与 `->` **不是**表达式,**不得**嵌套于条件或实参中;相等比较写作 `==`。两种方向记号写槽位置不同(`->` 右写、`=` 左写),同一次赋值只取一种方向。
+
+**写槽必须是位置(location)**:裸名(帧内变量)、绝对路径(`/abs`)、成员写(`base·field` / `base·*key`)、下标写(`arr[idx]`)。字面量出现在写槽位置是错误,layout 报诊断(见 [[诊断]])。
+ "#### -> /lib/kvlang/spec/layout语义/指令架构
+}
diff --git "a/stdlib/kvlang/spec/04-layout\350\257\255\344\271\211/02-\346\214\207\344\273\244\346\247\275\347\274\226\347\240\201.kv" "b/stdlib/kvlang/spec/04-layout\350\257\255\344\271\211/02-\346\214\207\344\273\244\346\247\275\347\274\226\347\240\201.kv"
new file mode 100644
index 00000000..5509ff2d
--- /dev/null
+++ "b/stdlib/kvlang/spec/04-layout\350\257\255\344\271\211/02-\346\214\207\344\273\244\346\247\275\347\274\226\347\240\201.kv"
@@ -0,0 +1,34 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/layout语义/指令槽编码 {
+ r####"# 指令槽编码
+
+## `=` 拷贝 opcode
+
+叶表达式写入写槽(拷贝)**必须**编码为显式 opcode `=`,被拷贝的值放读槽:
+
+```
+a -> b [s0,0]="=" [s0,-1]="a" [s0,1]="b"
+42 -> x [s0,0]="=" [s0,-1]=42 [s0,1]="x"
+```
+
+opcode 位恒为操作码,故拷贝(opcode=`=`)与零参函数调用(`greet() -> x`,opcode=`greet`)在 KV 层无歧义。
+
+## opcode 槽的 langtype
+
+opcode 槽 `[s0,0]` 的 langtype 由 layout 按 opcode 类别决定:
+
+- 控制流与拷贝原语(`return` / `goto` / `br` / `call` / `=`)——langtype `rwir`。
+- 其余(运算符、函数/rwir 调用目标)——langtype `rwir|rwfunc`。layout **不**静态判定该目标是否在本 runtime 的 myrwircaps 内(rwir)或为 rwfunc;判定推迟到 runtime 查 `/lib/` 分派(见 [[lib与rwir数据]])。
+
+## 读写槽的槽值编码
+
+读/写槽的槽值按内容编码为 XValue:
+
+- 字面量(整数、浮点、`true`/`false`、字符串、绝对路径)——按其类型编码为对应 kind 的 XValue(`int64` / `float64` / `bool` / `char/*` …);字符串字面量在 KV 传输层以 `"` 前缀区分于变量名。
+- 变量名、标签等引用——langtype `rwir`,body 即该名字符串。
+
+## 增量覆盖
+
+写函数前 layout **必须**先 `del_tree` 清除该函数子树,再重写:残留的旧槽会被 runtime 沿 s1 轴误读为真实参数。清除**仅限本函数子树**——多次 layout 各自覆盖其函数,**不得**整库删除,以支持增量布局(文件夹复制式合并)。
+ "#### -> /lib/kvlang/spec/layout语义/指令槽编码
+}
diff --git "a/stdlib/kvlang/spec/04-layout\350\257\255\344\271\211/03-\345\207\275\346\225\260.kv" "b/stdlib/kvlang/spec/04-layout\350\257\255\344\271\211/03-\345\207\275\346\225\260.kv"
new file mode 100644
index 00000000..50270079
--- /dev/null
+++ "b/stdlib/kvlang/spec/04-layout\350\257\255\344\271\211/03-\345\207\275\346\225\260.kv"
@@ -0,0 +1,57 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/layout语义/函数 {
+ r####"# 函数
+
+kvlang 源码只有一种命名单元:**rwfunc**(有指令体的用户函数),暴露 `(读参) -> (写参)` 箭头接口。函数**没有返回值**,只有读参与写参。rwir 是 runtime 兑现的原子能力,源码**不声明**、只调用;其 `def rwir` 路由头由各 runtime 注册到 `/lib`(见 [[rwfunc布局与def_rwir]])。
+
+## 读参与写参
+
+| 参数 | 布局槽位 | 方向 |
+|------|---------|------|
+| **读参** | `[0,-1], [0,-2], …` | 调用方 → 被调方 |
+| **写参** | `[0,+1], [0,+2], …` | 被调方 → 调用方 |
+
+`-> result` 是**写参的跨帧路径映射**,不是返回值:runtime 将子帧写参直写调用方目标位置(见 [[函数调用与内建]])。
+
+调用时**写参 arity 必须全部匹配**(对齐 Go/Rust):`f() -> s` 对多写参函数是错误;不需要的写参**必须**用 `_` 显式丢弃。
+
+## 参数类型必须标注
+
+每个读参与写参**必须**声明类型(`name:type_expr`,type_expr 见 [[kindexpr签名类型表达式]])。type_expr 最前可写 `*`/`@` 前缀(如 `*int64`、`@[256,256]uint8`)表示 ptr/ext 存储位置;layout 解析时剥离该前缀并落成 head `ref` 字节,wire 层 kindexpr 串不含前缀(见 [[总体方案]])。缺类型标注是错误:
+
+```
+error: func f: param "x" has no type annotation — every parameter must declare its type
+error: func f: return value "r" has no type annotation
+```
+
+末读参的 type_expr **可**加 `...` 声明变参(0..N 个同型实参)。变参**必须**是最后一个读参;写参**不得**变参。
+
+## 写参初值 None
+
+写参在被调方帧内初值为 **None**(strict null)。函数体内**必须**先显式初始化写参再参与运算——对 None 做算术在 runtime 被拒。惯例以拷贝置零值起步(`0 -> acc`),此后写参在体内可读可写,退出时经箭头映射回调用方。
+
+## 读参只读
+
+读参是单向输入绑定。函数体内把读参裸名放入写槽(含 `for … in` 的迭代变量)会破坏数据流方向,layout 报错拒绝装载:
+
+```
+error: func f: read param "A" cannot be used as write slot (read params are read-only)
+```
+
+**签名诚实原则**:函数体内被写的参数**必须**声明在写参侧。
+
+```
+// 非法:acc 被写却在读参侧
+rwfunc sum(arr:[]int64, acc:int64) -> (r:int64) { acc + arr[0] -> acc }
+// 合法:acc 在写参侧,体内可读可写
+rwfunc sum(arr:[]int64) -> (acc:int64) { acc + arr[0] -> acc }
+```
+
+判定规则(实现):写槽含 `/`、`[`、`·` 者视为路径/下标/成员写,不计入本检查;但 `kv·set(base, …)` 的 base 命中读参裸名同样拒绝(成员目录被改写)。
+
+## 参数同名规则
+
+- **定义时**:读参与写参**不得**同名——`rwfunc f(A:int64) -> (A:int64)` 非法,报 `param "A" appears in both read-params and write-params`。
+- **调用时**:同一变量**可**同时出现在读槽与写槽——`inc(x) -> x` 合法,读写独立解析、互不冲突。
+ "#### -> /lib/kvlang/spec/layout语义/函数
+}
diff --git "a/stdlib/kvlang/spec/04-layout\350\257\255\344\271\211/04-\345\207\275\346\225\260\345\206\231\346\247\275\344\270\216\345\270\203\345\261\200.kv" "b/stdlib/kvlang/spec/04-layout\350\257\255\344\271\211/04-\345\207\275\346\225\260\345\206\231\346\247\275\344\270\216\345\270\203\345\261\200.kv"
new file mode 100644
index 00000000..132b8da7
--- /dev/null
+++ "b/stdlib/kvlang/spec/04-layout\350\257\255\344\271\211/04-\345\207\275\346\225\260\345\206\231\346\247\275\344\270\216\345\270\203\345\261\200.kv"
@@ -0,0 +1,35 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/layout语义/函数写槽与布局 {
+ r####"# 函数写槽与布局
+
+## 写槽校验
+
+写槽(`->` 右 / `=` 左)解析时,非法写槽产生警告(`warn`,不拒装载):
+
+- 字面量(数字/引号串开头)出现在写槽位置 → `unexpected token … in write slot position`。
+- 写槽后紧跟 `(`(同行函数调用)→ `function call … on same line as write slot`。
+
+合法写槽:裸名、`/abs`、`base·名`、`base·*key`、`arr[idx]`。
+
+## rwfunc 布局
+
+rwfunc 布进 `/lib/·/`:
+
+1. `[0,0]`——签名行锚点,langtype `rwfunc`,body `[nr:u16 LE][nw:u16 LE][dynamic:u8]`(读参数/写参数/是否变参);各参数类型落在签名行 `[0,x]` 槽(`x<0` 读参、`x>0` 写参),每槽为 `def kindexpr` xvalue,body 即该参数 kindexpr 串(见 [[总体方案]])。
+2. `/lib/·.src`——源码副本(kind `char`)。
+3. 每个命名参数——`funcDir/` 存 Ptr(kind `char`),指向其槽坐标串(读参 `[0,-j]`、写参 `[0,+j]`)。
+4. 指令体从 `[1,0]` 起(`[0,*]` 为签名行占用)。
+
+写参不需要值的调用以 `_` 接收,`_` 写入帧内 `_` 槽、不影响语义。
+
+## rwfunc 声明位置
+
+rwfunc 应包裹在 `lib pkg { }` 内。裸顶层 rwfunc **可**声明,但产生提示(`info`)并登记到 `/lib/`(无 pkg):
+
+```
+info: rwfunc outside lib block — registering under /lib/; consider wrapping in 'lib pkgname { }'
+```
+
+裸顶层 rwfunc 名与 native builtin 同名是错误(`function "…" shadows builtin`)——须包裹进 lib 或改名。
+ "#### -> /lib/kvlang/spec/layout语义/函数写槽与布局
+}
diff --git "a/stdlib/kvlang/spec/04-layout\350\257\255\344\271\211/05-\346\216\247\345\210\266\346\265\201.kv" "b/stdlib/kvlang/spec/04-layout\350\257\255\344\271\211/05-\346\216\247\345\210\266\346\265\201.kv"
new file mode 100644
index 00000000..97dafb30
--- /dev/null
+++ "b/stdlib/kvlang/spec/04-layout\350\257\255\344\271\211/05-\346\216\247\345\210\266\346\265\201.kv"
@@ -0,0 +1,44 @@
+// 欢迎加入kvspace世界
+lib kvlang/spec/layout语义/控制流 {
+ r####"# 控制流
+
+kvlang 的结构化控制流有 `if`/`else`/`while`/`for … in`/具名 block/`break`/`continue`/`return`。它们**只能**出现在 rwfunc 体内;顶层出现是错误:
+
+```
+error: top-level while is not supported — wrap in main()
+```
+
+`return` **无参数**——输出经写参传递;`return x` 报错。
+
+## 降级为 goto/br(lower)
+
+layout 的 lower 阶段把结构化控制流降级为两条控制原语加具名作用域块(ScopeStmt):
+
+- `goto(label)`——无条件跳转。
+- `br(cond, then_label, else_label)`——按 cond 二路分支。
+- `break` → `goto` 到循环 exit 块;`continue` → `goto` 到循环 cond 块。
+
+每个 `if`/`while`/`for` 展开为一组具名块(如 `_while_2`、`_do_3`、`_exit_4`、`_if_5`、`_then_6`、`_else_7`、`_merge_8`)。`else if` 链按嵌套 `if` 展开。开放路径尾部补 `return`(layout 保证每块以终结符 `return`/`goto`/`br` 收尾)。
+
+## 布局为线性 irseq
+
+lower 之后,layout 把**所有**块体展平进函数目录下的**单一线性指令序列** `[1,0]…[N,0]`——**不建 scope 子目录**。goto/br 的跳转目标在布局时解析为**整数 irseq**(目标块首指令的 s0 序号),写入其读槽。
+
+标签到 irseq 的映射另存于 `/lib/·/‥labels/