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
2 changes: 1 addition & 1 deletion runtime-rwirext_example/go/json/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ package json
// 后端(kvspace-c=shm / kvspace_durable=redis|fs)由 Makefile 经 CGO_LDFLAGS 注入,
// 对齐 term 的 KVLANG_KVSPACE_LIB;扩展宿主自连 kvspace,不经 runtime。
#cgo CFLAGS: -I${SRCDIR}/../../../runtime/include
#cgo LDFLAGS: -L${SRCDIR}/../../../bin -lkvlang_runtime -L${SRCDIR}/../../../layout/target/release -lkvlang_layout -Wl,-rpath,${SRCDIR}/../../../bin -Wl,-rpath,${SRCDIR}/../../../layout/target/release
#cgo LDFLAGS: -L${SRCDIR}/../../../bin -lkvlang_runtime -L${SRCDIR}/../../../layout/target/release -lkvlanglayout -Wl,-rpath,${SRCDIR}/../../../bin -Wl,-rpath,${SRCDIR}/../../../layout/target/release
#include "kvlang_rwirext.h"
#include <stdint.h>
#include <stdlib.h>
Expand Down
2 changes: 1 addition & 1 deletion stdlib/kvlang/spec/01-词法/08-运算符基础.kv
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ x = 42 // 左写、右读
- `/`(U+002F)**不是**除号。它只用于绝对路径字面量与注释(`//`、`/*`);出现在其他位置的裸 `/` 不承
载算术除法语义。

一元 `+`、`-` 作前缀;`√`(U+221A,平方根)亦为一元前缀运算符。`&` 亦兼一元前缀(取址
一元 `+`、`-` 作前缀;`√`(U+221A,平方根)亦为一元前缀运算符。`&` 亦兼一元前缀(**绝对地址**
`&x ≡ kv·abs(x)`);其中缀身份(按位与)与前缀身份靠位置区分,同 C,详见 [[逻辑位运算与优先级]]。

## 比较运算符
Expand Down
19 changes: 11 additions & 8 deletions stdlib/kvlang/spec/01-词法/09-逻辑位运算与优先级.kv
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,23 @@ lib kvlang/spec/词法/逻辑位运算与优先级 {
分别为按位与、按位或、按位异或、左移、右移。

`&` 一符二用,靠位置区分(同 C):操作数之后为中缀**按位与**;表达式起始或运算符之后为一元前缀
**取址**(见下「取址运算符 `&`」)。
**绝对地址**(见下「绝对地址运算符 `&`」)。

## 取址运算符 `&`
## 绝对地址运算符 `&`

一元前缀 `&loc` 求值为 `loc` 所在节点的绝对 KV 路径字符串,等价 `kv·abs(loc)`。操作数须为位置
(location):帧内裸名、容器/成员链(`x`、`list·1`、`base·field`)。
一元前缀 `&loc` 求值为指向 `loc` 所在节点的**指针**(ref=1 Ptr:head 的 langtype = 目标 kindexpr、
body = 目标绝对路径),等价 `kv·abs(loc)`——故它是**绝对地址运算符**,不是 C 式取址(kvspace 无进程私有
内存地址)。操作数须为位置(location):帧内裸名、容器/成员链(`x`、`list·1`、`base·field`)。

产物是普通路径串,与指针惯例同型(可 `-> p` 存指针、`+ "·n"` 拼子节点、赋给 `next` 字段);与
`*T` ref 标注互补——`&` 造路径,`*` 标注该路径所指目标的形态(见 [[ptr]])。
产物是**指针值**(不是 `char` 路径串):可 `-> p` 存进 `*T` 变量、可 `p·field` 经指针访问成员;需要目
标整值时用 `*p` 解引用。与 `*T` ref 标注互补——`&` 造指针,`*T` 标注该指针所指目标的形态(见
[[ptr]])。

```
list·1 -> x
&x -> p // p = x 的绝对路径串,等价 kv·abs(x)
p + "·next" -> q
&x -> p // p = 指向 x 的 Ptr(ref=1),等价 kv·abs(x)
*p -> q // 解引用:取 x 的整值
p·field -> v // 经指针访问成员(自动解引用,见 [[ptr]])
```

## 优先级
Expand Down
4 changes: 2 additions & 2 deletions stdlib/kvlang/spec/02-kvspace模型/03-寻址与命名.kv
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ PC 落在 kvspace、帧根落在 kvspace,故执行现场可观测、可崩溃
## 变量名即指针

**代码中变量的名字,本身就是该变量的指针**(一条 kvspace 路径)kvspace/kvlang是路径寻址,而不是64位寻址。指令槽里存的从来不是值,而是指针文
本;求值恒经一次指针间接。`&x`(`≡ kv·abs(x)`)是取址语法糖,取到的是 kvspace 路径串,**不是**私有内
存地址(见 [[运算符基础]])。指针有两种形态:
本;求值恒经一次指针间接。`&x`(`≡ kv·abs(x)`)是**绝对地址运算符**,产指向该节点的 Ptr(ref=1,
body=绝对路径),**不是** C 式取址的私有内存地址(见 [[运算符基础]])。指针有两种形态:

| 形态 | 写法 | 语义 | 解析 |
|------|------|------|------|
Expand Down
17 changes: 12 additions & 5 deletions stdlib/kvlang/spec/03-类型系统/07-文法与合法性.kv
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ lib kvlang/spec/类型系统/文法与合法性 {
空 `[]` **等价** `[.]`(恰一维、任意长)——字符串标注 `[]char/<编码>` 即此形。一个 dims 内**至多一
个**变元量词(`?`/`*`/`+`),其余须为定长元(整数或 `.`)——保证匹配 O(n) 确定、无回溯(见 [[匹配语
义与变参]])。
- **mapexpr** = `memitemkeylangtype·memitemvaluelangtype`——`·`(U+00B7 中点)连接**两条各自独立的
langtype**:左侧是 item **键**类型、右侧是 item **值/body** 类型。值类型递归为完整类型表达式(故
map 可无限嵌套)。map 声明形如 `memheadname:memitemkeylangtype·memitemvaluelangtype={}`,术语与形态
详见 [[map容器]]。
- **memitemkey**(键类型,三选一,各自独立可校验):
- **mapexpr** = `memitemkey_langtype_formatter·memitemvalue_langtype`——`·`(U+00B7 中点)连接**两条各
自独立**的类型表达式:左侧是 item **键**的格式器、右侧是 item **值/body** 类型。值类型递归为完整类型
表达式(故 map 可无限嵌套)。map 声明形如
`memheadname:memitemkey_langtype_formatter·memitemvalue_langtype={}`,术语与形态详见 [[map容器]]。
- **memitemkey_langtype_formatter**(键侧格式器,三选一,各自独立可校验):key 只在**路径系统**里、无
XValue body,故键侧描述的不是「值的类型」而是「把 key 值格式化成路径段字符串的格式器」——其输出即访问
键(见 [[map容器]]):
- **裸标量** `scalar`——如 `int64`、`float64`、`bool`;`scalar` 限 `bool` 与十个定宽数字种类。
- **字符串键** `[]char/<编码>`——等价 Go `map[string]V`。
- **标量元组键** `[scalar,…]`——括号内是**种类名序列**(如 `[float64,float64]`),元素须全为标量。
Expand All @@ -51,6 +53,10 @@ lib kvlang/spec/类型系统/文法与合法性 {
+ 尾随种类**(`[2]float64`)是 shape 的 `dims`——1 维、长度 2 的 float64 数组(见 [[数组形态]])。二者
语义差别巨大(定长异构位置元组 vs 一维定长向量),layout 与 runtime **不得**将元组键与数组形状互相塌
缩或推断转换。

**形状不可作键**:`b:[2]int32·[]char/utf8` 非法——形状 `[2]int32` 是 value/body 的 langtype(描述连续
打包的元素),而键无 body;表达「两个 int32 的 key」只能用元组键 `[int32,int32]`,其 formatter 产出
`b·[1,2]`(见 [[map容器]])。
- **any** = 通配,匹配任意种类;是**唯一**简写。
- **structref** = 以 `/` 起始的原型路径(如 `/lib/Point`),作为 atom 标注结构类型(见 [[struct]])。

Expand Down Expand Up @@ -83,6 +89,7 @@ structref 放行——裸名已被隐式展开为 `/lib/<name>`,正是靠「
| `char/utf8·int64` | `char/*` 只能作 `[]char/*` 字符串键,不可裸作键(裸键仅限标量 `scalar`,如 `int64·int64` 合法) |
| `[]int32·int64` | map 字符串键的编码非 `char/*` |
| `[.]·int64` | map 键含维度 |
| `[2]int32·int64` | 数组形状不可作键(键无 body;要表达两个 int32 的 key 用 `[int32,int32]`) |
| `[foo,int32]·int64` | 元组键含非标量元素 |
| 裸 `[]` / 裸 `[.]` | 无基种类 |
| `[*,+]int64`、`[?,*]int64` | 一个 dims 含多于一个变元量词(`?`/`*`/`+`) |
Expand Down
37 changes: 28 additions & 9 deletions stdlib/kvlang/spec/03-类型系统/14-map容器.kv
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,37 @@ lib kvlang/spec/类型系统/map容器 {
一个 map 的 kvlang 代码形式:

```
memheadname : memitemkeylangtype · memitemvaluelangtype = {}
memheadname : memitemkey_langtype_formatter · memitemvalue_langtype = {}
```

| 位置 | 名称 | 含义 |
|------|------|------|
| `:` 之前 | **memheadname** | map 的名字(头名,命名整族成员) |
| `:` 与 `·` 之间 | **memitemkeylangtype** | item **键**的 langtype(独立 langtype) |
| `·` 之后 | **memitemvaluelangtype** | item **值/body** 的 langtype(独立 langtype,可递归嵌套) |
| `:` 与 `·` 之间 | **memitemkey_langtype_formatter** | item **键**的 langtype——键侧是**格式器**(见下),不是值类型 |
| `·` 之后 | **memitemvalue_langtype** | item **值/body** 的 langtype(独立 langtype,可递归嵌套) |

`·`(U+00B7 中点)连接 item 的键类型与值类型两条**各自独立**的 langtype。**通过 item 的 key 访问 item
body**:写 `memheadname·<memitemkey 的字符串形式>` 即取到该 item 的 body(memitemvalue)。
`·`(U+00B7 中点)连接 item 的键侧与值侧两条**各自独立**的类型表达式。**通过 item 的 key 访问 item
body**:写 `memheadname·<memitemkey 的字符串形式>` 即取到该 item 的 body(memitemvalue)。

**memitemkey** 是 key-eligible langtype,三选一:**裸标量**(`int64`)、**字符串键**
`[]char/<编码>`、**标量元组键** `[scalar,…]`。memitemkey 逐字落键——访问键就是 memitemkey 值按其
langtype 的**字面量本身**,kvspace 与 kvlangruntime 均**不得**加壳、归一化或改键(逐字铁律与
`[float64,float64]`(元组键)≠ `[2]float64`(数组形状)的区分见 [[文法与合法性]])。
### 键侧是 formatter,不是值类型

**memitemkey_langtype_formatter**:memitemkey 侧不是「值的类型」,而是**把 key 值格式化成路径段字符串的
格式器**——因为 memitemkey 永远活在**路径系统**里(`memhead·<key 文本>`),**从不进入任何 XValue 的
body**。key 侧没有 body 可承载类型,key 的类型完全是字符串层面的事,故必须由 formatter 规定「什么值的
key 格式化成什么字面量文本」:

| memitemkey 类型 | formatter 输出(= 访问键) | 例 |
|-----------------|---------------------------|-----|
| 裸标量(`bool` + 十个定宽数字种类) | 该标量的字面量文本 | `b·200` |
| 标量元组 `[scalar,…]` | `[v0,v1,…]`(逗号分隔、无空格) | `a·[3.252,235124.23]` |
| `[]char/<编码>` | 字符串本身(裸名) | `m·a` / `kv·set(m,"a",v)` |

**不得**用数组形状 `[N]T` / `[d0,d1]T` 作键:形状描述「一段连续打包进 body 的等宽元素」,属 **value 的
langtype**;key 无 body、纯路径文本,形状对它没有意义。故 `b:[2]int32·[]char/utf8 = {}` 报错,而表达同
样「两个 int32」的元组键 `b2:[int32,int32]·[]char/utf8 = {}` 合法(formatter 产出 `b2·[1,2]`)。

`a:int32·int32 = {}`(裸标量键,访问键 `a·200`)与 `a:[int32]·int32 = {}`(一元元组键,访问键
`a·[200]`)是**两个不同的 formatter**,不得互相转换(逐字铁律见 [[文法与合法性]])。

## 例子

Expand All @@ -41,6 +56,10 @@ b·200 = 7 // 访问键就是 200,禁止写成 b·[200]

a:[float64,float64]·int32 = {} // 标量元组键 map([float64,float64] ≠ [2]float64)
a·[342.124,23.2345] = 1 // 访问键就是元组字面量本身

b2:[int32,int32]·[]char/utf8 = {} // 元组键 + 字符串值(两元素都是标量,合法)
b2·[1,2] = "x" // 访问键 = formatter 输出 "[1,2]"
// b:[2]int32·[]char/utf8 = {} // 非法:数组形状 [2]int32 不是键(键无 body 可承载)
```

memitemvalue 可递归嵌套(`[]char/utf8·[]char/utf8·int64` 即 `map[string]map[string]int64`)。
Expand Down
7 changes: 4 additions & 3 deletions stdlib/kvlang/spec/03-类型系统/15-成员访问.kv
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ lib kvlang/spec/类型系统/成员访问 {
由 runtime-c 沿 Ptr 解引用取被指向值作键;省略 `*` 非法(不自动解引用)。这是**显式** deref、非自动改
键(运行期语义见 [[成员访问]](runtime 卷))。

`base` 即 map 的 memheadname(或 struct 实例名)。访问键**逐字即 memitemkey 值**:kvspace 与
kvlangruntime 均不得归一化、改写或自动加壳(详见 [[文法与合法性]] 的逐字铁律,术语见 [[map容器]])。裸
标量键 `base·200` 与 1 元元组键 `base·[200]` 是**不同** memitemkey,不得互转。
`base` 即 map 的 memheadname(或 struct 实例名)。访问键**逐字即键侧 formatter 的输出**(memitemkey 只
在路径系统、无 body,见 [[map容器]]):kvspace 与 kvlangruntime 均不得归一化、改写或自动加壳(详见
[[文法与合法性]] 的逐字铁律)。裸标量键 `base·200` 与 1 元元组键 `base·[200]` 是**不同** formatter,
不得互转。

容器成员一律走 `·`(或 `kv·get`/`kv·set`)作**索引**,**不得**用 `[]` 索引运算符;`[]` 只索引 compact
数组(见 [[数组形态]])。注意:元组键 `base·[…]` 里的 `[…]` 是 **memitemkey 值字面量**、不是索引运算
Expand Down
6 changes: 3 additions & 3 deletions stdlib/kvlang/spec/03-类型系统/16-ptr.kv
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ lib kvlang/spec/类型系统/ptr {

| 形态 | 语义 |
|------|------|
| `&x` | 取地址 → ref=1 Ptr(`&x ≡ kv·abs(x)`,返回绝对路径串) |
| `&x` | **绝对地址** → ref=1 Ptr(`≡ kv·abs(x)`,body = 目标绝对路径) |
| `p`(`*T` 变量读值) | 得地址值本身(不穿透) |
| `*p` | 解引用 → 读 body 目标地址的值 |
| `None` | **空指针**(唯一的空指针字面量;即键不存在=无值) |
Expand Down Expand Up @@ -41,13 +41,13 @@ p·val -> v // 成员访问经指针自动解引用:读 /n1·val
if (p != None) { … } // 空指针判定
```

`&` 对**裸名** `&x` 取帧槽地址(`≡ kv·abs(x)`)、对**成员链** `&t·2` 取成员路径地址(`≡
`&` 对**裸名** `&x` 产帧槽的绝对地址(`≡ kv·abs(x)`)、对**成员链** `&t·2` 产成员路径的绝对地址(`≡
kv·abs(t, "2")`),均产 ref=1 Ptr、body 为目标 key 路径。

成员访问 `p·field` 经指针**自动解引用**(对齐 Go/Rust 的 `p.field`);需要「指针指向的整值」(如指针
指向标量)时用显式 `*p`。二者不冲突:`*p` 取整值、`p·field` 取成员。

嵌套指针(`**T`)不在本模型内:wire 层 langtype 串不含 `*`、ref 仅单字节,无法表达层数。链表/树/取址
嵌套指针(`**T`)不在本模型内:wire 层 langtype 串不含 `*`、ref 仅单字节,无法表达层数。链表/树/绝对地址
皆一层指针,已覆盖;C 里 `**` 的「out 参数传地址」由 kvlang 写参取代——要直写调用方对象就写
`-> (r:*T)`(地址写参),`-> (r:T)` 是值写参(copy-in / copy-out),无需 `**`。
"#### -> /lib/kvlang/spec/类型系统/ptr
Expand Down
7 changes: 4 additions & 3 deletions stdlib/kvlang/spec/设计理由/02-一切皆明文.kv
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,12 @@ def rwir 路由)、读写哪个 slot。调度层的绝对耗时在 tensor 计
字符串 PC 直接带来崩溃恢复能力:进程崩溃后,PC 路径已持久化在 kvspace,重启后从该路径继续执行,无需
重放或检查点协议。整数 PC 做不到这点,因为整数脱离了进程上下文就失去意义。

## 为什么 `&` 取的是路径而非私有地址
## 为什么 `&` 是绝对地址运算符而非取址运算符

传统语言的 `&` 取址产生的是私有内存地址,只在当前进程内有意义,且与内存布局深度绑定。kvlang 的"变量
名"本身就是该变量的 kvspace 路径——路径在任何连接到同一 kvspace 的节点上都有意义。故 kvlang 保留 `&x`
(`≡ kv·abs(x)`),但它的产物是**路径指针**、不是私有地址:没有进程私有地址空间,也没有内存布局意义
上的"取址"(见 [[寻址与命名]]、[[运算符基础]])。
(`≡ kv·abs(x)`),但它的产物是**指向该节点的 Ptr**(ref=1,body=绝对路径)、不是私有地址:没有进程私
有地址空间,也没有 C 式取址的内存布局含义,故规范称它为**绝对地址运算符**(见 [[寻址与命名]]、
[[运算符基础]])。
"#### -> /lib/kvlang/spec/设计理由/一切皆明文
}
8 changes: 4 additions & 4 deletions stdlib/kvlang/spec/附录/03-类型表达式文法.kv
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ type_expr = [ ref_prefix ] atom { "|" atom } (* ref 前缀可选;layout
ref_prefix = "*" | "@" (* * → ref=1(kvspace 内间接);@ → ref=2(扩展世界,值在 kvspace 之外,runtime-c 不可直达、由支持 @ 的 rwir 兑现)。签名位置可写:`T` 值传、`*T` 址传、`@T` 扩展存储;值容器(map/struct)无值本体可拷,必须带 `*`/`@`,见 [[函数]] *)
atom = shape | mapexpr | structref
shape = [ dims ] ( any | kind )
mapexpr = memitemkey "·" memitemvalue (* stringkeymap;`·` 连接两条独立 langtype:左=item 键类型、右=item 值类型。声明形如 memheadname:memitemkey·memitemvalue={},见 [[map容器]] *)
mapexpr = memitemkey "·" memitemvalue (* stringkeymap;`·` 左=item 键侧的**格式器**(memitemkey_langtype_formatter)、右=item 值类型。声明形如 memheadname:memitemkey_langtype_formatter·memitemvalue_langtype={},见 [[map容器]] *)
memitemvalue = type_expr (* item 值/body 类型,递归为完整 type_expr,故 map 可无限嵌套 *)
memitemkey = scalar (* 裸标量键:访问键即该标量字面量本身,如 b·200;禁止包成 [200](见 [[文法与合法性]]) *)
| "[]" char_enc (* 字符串键,等价 Go map[string]V *)
| "[" scalar { "," scalar } "]" (* 标量元组键:括号内是种类名序列,访问键即括号元组字面量本身,如 a·[342.124,23.2345] *)
memitemkey = scalar (* 裸标量键:键只在路径系统、无 body,故这是"格式器"——输出该标量字面量本身,如 b·200;禁止包成 [200](见 [[文法与合法性]]) *)
| "[]" char_enc (* 字符串键(格式器输出裸名字符串),等价 Go map[string]V *)
| "[" scalar { "," scalar } "]" (* 标量元组键(格式器输出 `[v0,v1,…]`),如 a·[342.124,23.2345];与数组形状 [2]float64 不同——形状不可作键 *)
structref = path (* struct 原型路径,如 /lib/Point *)
char_enc = "char/utf8" | "char/utf32" | "char/ascii"
scalar = "bool"
Expand Down
2 changes: 1 addition & 1 deletion stdlib/kvlang/spec/附录/05-表达式.kv
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ primary = literal | ident | path
| struct_literal
| map_literal

prefix_unary = "-" | "!" | "√" | "&" | "*" (* √ = sqrt(U+221A);&x ≡ kv·abs(x) 取址;*p 解引用 *)
prefix_unary = "-" | "!" | "√" | "&" | "*" (* √ = sqrt(U+221A);&x ≡ kv·abs(x) 绝对地址(产 ref=1 Ptr);*p 解引用 *)

infix_primary = binary_op expr

Expand Down
2 changes: 1 addition & 1 deletion stdlib/kvlang/spec/附录/07-内建函数.kv
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ builtin_call = ( "abs" | "neg" | "sign" | "pow" | "sqrt" | "exp" | "log"
(* ÷ : 两侧 int → 整除(C 风格);任一侧 float → 浮除 *)
(* s[i] 读返单字符字符串,越界返 "";s[i]="X" 单字符替换写回新串 *)
(* + 作用在 string∧string → 拼接 *)
(* &x kv·abs(x) 的语法糖(一元前缀取址,返回 x 的绝对路径串);与中缀按位与 a & b 靠位置区分 *)
(* &x kv·abs(x):一元前缀**绝对地址**运算符,产指向 x 的 Ptr(ref=1,body=绝对路径);与中缀按位与 a & b 靠位置区分 *)
```
"## -> /lib/kvlang/spec/附录/内建函数
}
Loading