Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,9 @@ kvtut*

# runtime-rs 测试 shm 产物
kvlangtest*

# shm 测试残留(相对路径 DSN 标记 + slotsboxmalloc 后端文件)
/tut
/wptest
*.sbo.data
*.sbo.head
6 changes: 3 additions & 3 deletions deps.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"kvspace": "v0.2.12",
"kvspace-c": "v0.2.12",
"kvspace-durable": "v0.2.12",
"kvspace": "v0.2.13",
"kvspace-c": "v0.2.13",
"kvspace-durable": "v0.2.13",
"blockmalloc": "v0.1.4",
"slotsboxmalloc": "v0.1.5"
}
20 changes: 6 additions & 14 deletions layout/src/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -401,28 +401,20 @@ pub fn write_func(kv: &mut Kv, pkg: &str, fn_: &mut Func) {
keytree::lib_src(pkg, &fn_.sig.name),
ffi::new_char_byte(fn_.full_text().as_bytes()),
));
// 签名行:每个参数的类型定义落 [0,x] 槽(def langtype),x<0 读参、x>0 写参。
// 运行期 call 会用实参绑定覆盖同坐标的帧槽,静态类型定义仅供 layout 类型检查/dump。
// 命名参数键 funcDir/<name>:Ptr,body=帧坐标 [0,±k](k<0 读参、k>0 写参),
// target_langtype=该参类型——类型随参数名承载。func dir 根不落 [0,±k] 静态槽:
// 那些坐标是 runtime call 期写入的帧本地实参地址,若 layout 提前落在 func dir 根,
// 建帧 extindex 时会把它们当只读扩展节点,令 call 期同坐标绑定触发 ext-write 保护。
for (i, p) in fn_.sig.params.iter().enumerate() {
let slot = format!("[0,-{}]", i + 1);
pairs.push((
format!("{func_dir}/{slot}"),
kvkind::new_def_langtype(&param_types[i]),
));
pairs.push((
format!("{func_dir}/{}", p.name),
ffi::new_ptr(kvkind::KIND_CHAR, &slot),
ffi::new_ptr(&param_types[i], &format!("[0,-{}]", i + 1)),
));
}
for (i, r) in fn_.sig.returns.iter().enumerate() {
let slot = format!("[0,{}]", i + 1);
pairs.push((
format!("{func_dir}/{slot}"),
kvkind::new_def_langtype(&param_types[nr as usize + i]),
));
pairs.push((
format!("{func_dir}/{}", r.name),
ffi::new_ptr(kvkind::KIND_CHAR, &slot),
ffi::new_ptr(&param_types[nr as usize + i], &format!("[0,{}]", i + 1)),
));
}
let _ = kv.set(&pairs);
Expand Down
2 changes: 1 addition & 1 deletion runtime-rs/src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ fn storetype_from_langtype(kx: &str) -> u8 {
if base == "extindex" {
return STORETYPE_EXTINDEX;
}
if matches!(base, "index" | "rwfunc" | "defrwir")
if matches!(base, "index" | "rwfunc" | "def rwir")
|| base.starts_with('/')
|| base.contains('\u{b7}')
{
Expand Down
24 changes: 20 additions & 4 deletions runtime-rwirext_example/go/json/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -646,14 +646,30 @@ type op struct {

var myrwircaps []op

func cstrArr(n int) (**C.char, []*C.char) {
if n == 0 {
return nil, nil
}
arr := make([]*C.char, n)
for i := range arr {
arr[i] = cstr("any")
}
return (**C.char)(unsafe.Pointer(&arr[0])), arr
}

func register(c unsafe.Pointer) {
for _, o := range myrwircaps {
sig := strings.TrimSuffix(strings.Repeat("any\n", o.nr+o.nw), "\n")
co := cstr(o.name)
cs := cstr(sig)
C.kvlangRwirextRegister(c, co, C.int32_t(o.nr), C.int32_t(o.nw), cs)
rp, ra := cstrArr(o.nr)
wp, wa := cstrArr(o.nw)
C.kvlangDefRwir(c, co, rp, C.int32_t(o.nr), wp, C.int32_t(o.nw))
C.free(unsafe.Pointer(co))
C.free(unsafe.Pointer(cs))
for _, p := range ra {
C.free(unsafe.Pointer(p))
}
for _, p := range wa {
C.free(unsafe.Pointer(p))
}
}
}

Expand Down
15 changes: 11 additions & 4 deletions runtime-rwirext_example/py/numpy/numpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,10 @@ def _bind():
for fn in ("kvlangRwirextParams", "kvlangRwirextResolveRead", "kvlangRwirextResolveReadPath",
"kvlangRwirextResolveWrite", "kvlangRwirextNextPc"):
getattr(_rt, fn).restype = ctypes.c_void_p
_rt.kvlangRwirextRegister.restype = ctypes.c_int
_rt.kvlangRwirextRegister.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int32, ctypes.c_int32, ctypes.c_char_p]
_rt.kvlangDefRwir.restype = ctypes.c_int
_rt.kvlangDefRwir.argtypes = [ctypes.c_void_p, ctypes.c_char_p,
ctypes.POINTER(ctypes.c_char_p), ctypes.c_int32,
ctypes.POINTER(ctypes.c_char_p), ctypes.c_int32]
_rt.kvlangRwirextParams.argtypes = [ctypes.c_void_p, ctypes.c_char_p]
_rt.kvlangRwirextResolveRead.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int]
_rt.kvlangRwirextResolveReadPath.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int]
Expand Down Expand Up @@ -288,9 +290,14 @@ def read_arg(self, pc, i):

# ── 注册五大类 ─────────────────────────────────────────────────
def register(self):
def _arr(lst):
return (ctypes.c_char_p * len(lst))(*[s.encode() for s in lst])
for op, (nr, _) in OPS.items():
_rt.kvlangRwirextRegister(self.kv, op.encode(), nr, 1, ("\n".join(["any"] * (nr + 1))).encode())
_rt.kvlangRwirextRegister(self.kv, b"numpy.print", 1, 0, b"any...")
rp = _arr(["any"] * nr)
wp = _arr(["any"])
_rt.kvlangDefRwir(self.kv, op.encode(), rp, nr, wp, 1)
rp = _arr(["any..."])
_rt.kvlangDefRwir(self.kv, b"numpy.print", rp, 1, None, 0)

def _handle(self, op, nr, fn, pc):
params = _s(_rt.kvlangRwirextParams(self.kv, pc.encode())).split("\n")
Expand Down
14 changes: 5 additions & 9 deletions runtime/src/kvcpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -403,15 +403,11 @@ static char *handle_call(kvlangKv_t *kv, const char *pc, kvlangRwirInst_t *inst)
const uint8_t *sbody = sig.data + h.body_offset;
int nr = sbody[0] | (sbody[1] << 8);
int nw = sbody[2] | (sbody[3] << 8);
int dyn = h.body_len >= 5 ? sbody[4] : 0;

{ /* 读参类型校验:reads[0]=函数名,实参从 reads[1] 起。
* 读参 langtype 逐条落签名行 [0,-i] 槽(def langtype),主槽 body 仅计数头。 */
char *ds = join_read_sig(kv, func_dir.p, nr);
int crc = check_read_types(kv, vtid, pc, fn, ds, nr, dyn, inst->reads + 1, inst->nr - 1);
free(ds);
if (crc != 0) goto fail;
}

/* rwfunc 不做派发期位置化读参校验:类型随命名参数键 funcDir/<name>(Ptr 的
* target_langtype)承载,函数体在帧内按名解析、各 native 算子在使用点自校验操作数
* kind。位置化的有序签名校验(join_read_sig+check_read_types)是 rwir 的需求——
* 跨 runtime 队列按位置收参,故仅 def rwir 路由路径保留(见本文件 m->def_sig)。 */

char *caller_fr = kvlangKeytreeFrameRoot(pc);
int d = kvlangKeytreeFrameNum(pc);
Expand Down
27 changes: 19 additions & 8 deletions stdlib/kvlang/spec/00-导言/01-范围与一致性.kv
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,41 @@ lib kvlang/spec/导言/范围与一致性 {

## 本规范的地位

本规范是 kvlang 语言的**唯一事实源**。语言核心的任何设计或实现调整,一律**规范驱动**:先改本规范的相应条款及其锚定示例,再改实现,直至锚例在三后端全绿。规范与实现不符时,以规范为准,实现视为缺陷。
本规范是 kvlang 语言的**唯一事实源**。语言核心的任何设计或实现调整,一律**规范驱动**:先改本规范的相
应条款及其锚定示例,再改实现,直至锚例在三后端全绿。规范与实现不符时,以规范为准,实现视为缺陷。

规范以 kvlang 自身书写(`.kv`),layout&run 后落进 `/lib/kvlang/spec/…`——规范即 KV 树里的数据,可被 kvlang 自解析与自校验。
规范以 kvlang 自身书写(`.kv`),layout&run 后落进 `/lib/kvlang/spec/…`——规范即 KV 树里的数据,可被
kvlang 自解析与自校验。

## 范围

本规范界定 kvlang 语言本体:

- **词法**(卷 01)——源码表示、词法单元、注释、标识符、字面量、运算符。
- **kvspace 模型**(卷 02)——地址空间、寻址与命名、键系统与数组访问、指令布局格式、系统变量。kvspace 既是寻址空间也是内存空间,是 kvlang 的第一性前置概念,故前置于语义两卷。
- **类型系统**(卷 03)——种类与定宽类型、langtype 签名类型表达式、数组形态、容器。类型跨 layout 与 runtime 两阶段,故独立成卷。
- **layout 语义**(卷 04)——静态语义:语法检查与布局。layout 是 **o0 编译器**:做检查、布局与降级,**不做任何优化**(一旦优化即丢失高层语义,使扩展编译器无法按原语义在异构硬件上优化),可报诊断。
- **kvspace 模型**(卷 02)——地址空间、寻址与命名、键系统与数组访问、指令布局格式、系统变量。kvspace
既是寻址空间也是内存空间,是 kvlang 的第一性前置概念,故前置于语义两卷。
- **类型系统**(卷 03)——种类与定宽类型、langtype 签名类型表达式、数组形态、容器。类型跨 layout 与
runtime 两阶段,故独立成卷。
- **layout 语义**(卷 04)——静态语义:语法检查与布局。layout 是 **o0 编译器**:做检查、布局与降级,
**不做任何优化**(一旦优化即丢失高层语义,使扩展编译器无法按原语义在异构硬件上优化),可报诊断。
- **runtime 语义**(卷 05)——动态语义:纯解释执行。
- **编译器语义**(卷 06)——扩展编译器与核心的契约:前端算子/后端算子两层表示、后端绑定、算子版本化与 runtime 高版本优先。编译器本体不属语言核心(是计算引擎类扩展的组成),本卷只界定其与核心的契约。流水线上编译器介于 layout 与 runtime 之间(layout o0 → 编译器优化 → runtime 解释)。
- **编译器语义**(卷 06)——扩展编译器与核心的契约:前端算子/后端算子两层表示、后端绑定、算子版本化与
runtime 高版本优先。编译器本体不属语言核心(是计算引擎类扩展的组成),本卷只界定其与核心的契约。流
水线上编译器介于 layout 与 runtime 之间(layout o0 → 编译器优化 → runtime 解释)。

附录给出唯一权威文法;设计理由卷为非规范(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)。
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)全部通过、输出逐字节一致,即为符合。
**tutorial 套件即一致性测试。** 一个实现是否符合本规范,由 `tutorial/` 下的可运行 `.kv` 示例判定:三
后端(shm / fs / redis)全部通过、输出逐字节一致,即为符合。

本规范每条 normative 条款应锚定至 tutorial 中至少一条示例。修改语言的流程恒为:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ lib kvlang/spec/导言/规范用语与阅读约定 {
- **应 / 不应**(should / should not)——存在正当理由时可偏离,但须权衡后果。
- **可**(may)——纯可选。

未加此类限定词的陈述句为**事实性描述**(语言如此这般),同样是 normative 的。设计动机、历史与取舍一律归入非规范的**设计理由**卷,不混入正文条款。
未加此类限定词的陈述句为**事实性描述**(语言如此这般),同样是 normative 的。设计动机、历史与取舍一
律归入非规范的**设计理由**卷,不混入正文条款。

## 阅读约定

Expand Down
15 changes: 10 additions & 5 deletions stdlib/kvlang/spec/01-词法/01-源码结构.kv
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,24 @@ lib kvlang/spec/词法/源码结构 {

## 源码表示

kvlang 源文件是一段 **UTF-8 字节序列**。词法分析按字节推进:ASCII 字节触发语法结构,其余多字节序列(如中文、`é`)作为普通字符原样穿过,出现在标识符、字符串与路径内部。
kvlang 源文件是一段 **UTF-8 字节序列**。词法分析按字节推进:ASCII 字节触发语法结构,其余多字节序列
(如中文、`é`)作为普通字符原样穿过,出现在标识符、字符串与路径内部。

一处**行**由换行符 `\n`(U+000A)界定;`\r`(U+000D)在词法阶段被直接跳过,不产生任何词法单元,故 `\r\n` 与 `\n` 等价。位置以 1 起始的 `line`、`col` 计。
一处**行**由换行符 `\n`(U+000A)界定;`\r`(U+000D)在词法阶段被直接跳过,不产生任何词法单元,故
`\r\n` 与 `\n` 等价。位置以 1 起始的 `line`、`col` 计。

## 空白与语句分隔

空格 ` ` 与制表符 `\t` 是词法单元之间的分隔符,本身不产生词法单元;除用于分隔相邻词法单元外不具意义。
空格 ` ` 与制表符 `\t` 是词法单元之间的分隔符,本身不产生词法单元;除用于分隔相邻词法单元外不具意
义。

**语句分隔**由换行符 `\n` 与分号 `;` 表达,二者语义等价,均产生一个 `Newline` 词法单元。词法器执行两条归并规则:
**语句分隔**由换行符 `\n` 与分号 `;` 表达,二者语义等价,均产生一个 `Newline` 词法单元。词法器执行两
条归并规则:

- 连续的语句分隔(多个换行/分号、含其间空白)**折叠**为单个 `Newline`;
- 词法单元流开头的语句分隔被**抑制**,不产生 `Newline`。

字符串与原始字符串字面量内部的物理换行**不**产生 `Newline`(它是字面量内容的一部分),但行号仍随之前进。
字符串与原始字符串字面量内部的物理换行**不**产生 `Newline`(它是字面量内容的一部分),但行号仍随之前
进。
"#### -> /lib/kvlang/spec/词法/源码结构
}
11 changes: 8 additions & 3 deletions stdlib/kvlang/spec/01-词法/02-词法单元.kv
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,18 @@ kvlang 只有 **7 个词法关键字**,它们在词法阶段即被识别,不
return if else for while break continue
```

其余在语言中具有特殊含义的词(`lib`、`rwir`、`rwfunc`、`in`、`any`、`None`、`true`、`false`、种类名如 `int64`/`float32`/`struct` 等)**不是**词法关键字:它们一律词法化为 `Ident`,其含义由 layout 阶段依上下文赋予。这类词称为**上下文词**。
其余在语言中具有特殊含义的词(`lib`、`rwir`、`rwfunc`、`in`、`any`、`None`、`true`、`false`、种类名
如 `int64`/`float32`/`struct` 等)**不是**词法关键字:它们一律词法化为 `Ident`,其含义由 layout 阶段
依上下文赋予。这类词称为**上下文词**。

`def` **不是** kvlang 关键字,kv 源码中永不出现:`def rwir`/`def struct`/`def langtype` 是 head 的 langtype 元层「定义节点」标记,只在 layout 之后(`def struct`、`def langtype`)或 runtime 注册时(`def rwir`)产生,与源码词法无关(见 [[langtype语义类型]])。
`def` **不是** kvlang 关键字,kv 源码中永不出现:`def rwir`/`def struct`/`def langtype` 是 head 的
langtype 元层「定义节点」标记,只在 layout 之后(`def struct`、`def langtype`)或 runtime 注册时
(`def rwir`)产生,与源码词法无关(见 [[langtype语义类型]])。

## 最长匹配

词法分析遵循**最长匹配**(maximal munch):在每个位置,词法器取能构成合法词法单元的最长字符序列。特别地:
词法分析遵循**最长匹配**(maximal munch):在每个位置,词法器取能构成合法词法单元的最长字符序列。特
别地:

- 以数字开头的序列必为数值字面量,不会被识别为标识符;
- `-` 后紧跟 `>` 构成 `->`,`<` 后紧跟 `<` 构成 `<<`,依此类推——双字符运算符优先于其单字符成分。
Expand Down
6 changes: 4 additions & 2 deletions stdlib/kvlang/spec/01-词法/03-注释.kv
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ kvlang 有两种注释,语法与 Rust 一致。**不存在** `#` 注释。
x = 42 // 这是行注释
```

行注释不消费其后的换行符,故一行末尾的行注释之后仍产生一个 `Newline` 语句分隔。行注释不嵌套:其内部的 `//`、`/*` 均无特殊含义。
行注释不消费其后的换行符,故一行末尾的行注释之后仍产生一个 `Newline` 语句分隔。行注释不嵌套:其内部
的 `//`、`/*` 均无特殊含义。

## 块注释

Expand All @@ -37,6 +38,7 @@ x = 42 // 这是行注释

## 注释的地位

注释被词法化为 `Comment` 词法单元,在词法流中保留,但对程序语义无贡献——layout 阶段将其忽略。注释不是语句分隔符:其内部的换行不产生 `Newline`(块注释),行注释后的换行照常产生 `Newline`。
注释被词法化为 `Comment` 词法单元,在词法流中保留,但对程序语义无贡献——layout 阶段将其忽略。注释不是
语句分隔符:其内部的换行不产生 `Newline`(块注释),行注释后的换行照常产生 `Newline`。
"#### -> /lib/kvlang/spec/词法/注释
}
11 changes: 8 additions & 3 deletions stdlib/kvlang/spec/01-词法/04-标识符.kv
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ lib kvlang/spec/词法/标识符 {
## 锚例

- `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`。
- `tutorial/01-basics/kv_tree.kv`——绝对路径 `/tmp/kvt`、子键路径 `/tmp/kvt·data`、层级路径
`/tmp/kvt/a`,以及成员/方法 `kv·set`、`kv·get`。

## 标识符

Expand All @@ -25,9 +26,13 @@ println("值 =", 变量数)

此决策使 kvlang 与 C99、Go、Python、Rust、TypeScript 在「允许 Unicode 标识符」上对齐。

7 个词法关键字(`return if else for while break continue`)为保留字,不得用作标识符;其余上下文词(`lib`、`None`、`true`、`false`、种类名等)不保留,但用作普通标识符会遮蔽其上下文含义,不应如此使用。
7 个词法关键字(`return if else for while break continue`)为保留字,不得用作标识符;其余上下文词
(`lib`、`None`、`true`、`false`、种类名等)不保留,但用作普通标识符会遮蔽其上下文含义,不应如此使
用。

> 实现说明(非规范):当前词法器以「最长非分隔符字节串」切分标识符,未逐字符校验上述字母表,故比本节所述更宽松。分隔符集合为空白、`; , ( ) { } [ ] :`、成员分隔符 `·`,以及运算符字符 `+ - * % ! = < > & | ^`。
> 实现说明(非规范):当前词法器以「最长非分隔符字节串」切分标识符,未逐字符校验上述字母表,故比本节
所述更宽松。分隔符集合为空白、`; , ( ) { } [ ] :`、成员分隔符 `·`,以及运算符字符
`+ - * % ! = < > & | ^`。

## 成员分隔符

Expand Down
Loading
Loading