Skip to content

Commit f0b1dcb

Browse files
authored
Merge pull request #275 from array2d/layout-langtype
layout: kindexpr→langtype 归并 + spec 06
2 parents d2aed8b + 5fa818e commit f0b1dcb

26 files changed

Lines changed: 409 additions & 218 deletions

layout/src/ast.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,15 +109,21 @@ impl FuncSig {
109109
self.params.iter().map(|p| p.name.clone()).collect()
110110
}
111111

112-
/// 参数 kindexp 列表(读参在前、写参在后,源文法逐字节),落盘于 rwir/rwfunc body。
113-
pub fn kindexp_list(&self) -> Vec<String> {
112+
/// 参数 langtype 列表(读参在前、写参在后),落盘于 rwir/rwfunc body。
113+
/// 末读参尾缀 `...` 是签名层变参标记:此处剥离,langtype 串保持纯净(变参落 dynamic 字节)。
114+
pub fn langtype_list(&self) -> Vec<String> {
114115
self.params
115116
.iter()
116117
.chain(self.returns.iter())
117-
.map(|p| p.ty.clone())
118+
.map(|p| p.ty.strip_suffix("...").unwrap_or(&p.ty).to_string())
118119
.collect()
119120
}
120121

122+
/// 末读参是否变参(源尾缀 `...`)→ 落成主槽 body 的 dynamic 字节。
123+
pub fn dynamic(&self) -> bool {
124+
self.params.last().is_some_and(|p| p.ty.ends_with("..."))
125+
}
126+
121127
pub fn num_reads(&self) -> i32 {
122128
self.params.len() as i32
123129
}
@@ -185,7 +191,7 @@ impl RwirDecl {
185191
#[derive(Clone)]
186192
pub struct Field {
187193
pub name: String,
188-
pub ty: String, // kindexpr(字段类型)
194+
pub ty: String, // langtype(字段类型)
189195
pub default: Option<Expr>, // 默认值字面量(None = 未给)
190196
}
191197

layout/src/capi.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -183,12 +183,12 @@ pub extern "C" fn kvlangLayoutDump(
183183
}
184184
}
185185

186-
// ── kindexpr 解析 ABI ──────────────────────────────────────────────────
187-
// kindexpr 语法唯一事实源在 layout(kindexpr.rs);解析能力导出为 C ABI,
186+
// ── langtype 解析 ABI ──────────────────────────────────────────────────
187+
// langtype 语法唯一事实源在 layout(langtype.rs);解析能力导出为 C ABI,
188188
// 供 runtime 之外的消费方(扩展宿主 term/numpy/json、byteseek…)读取 XValue head 时
189189
// 复用,杜绝各处手写 head 结构/解析造成的 ABI 漂移(#70 遗留的旧 kind[32] 结构即此类)。
190190

191-
/// kindexpr 解析结果(repr(C),内存布局 = i32,i32,[i32;8],i32,[u8;64])。
191+
/// langtype 解析结果(repr(C),内存布局 = i32,i32,[i32;8],i32,[u8;64])。
192192
#[repr(C)]
193193
pub struct kvlangKindexpr {
194194
pub ref_: i32, // 0=内联 1=指针(*) 2=扩展句柄(@)
@@ -198,18 +198,18 @@ pub struct kvlangKindexpr {
198198
pub kind: [u8; 64], // base kind,NUL 终止(如 "float64"、"char/utf8"、"rwir|rwfunc")
199199
}
200200

201-
/// 解析 XValue head 的 kindexpr 内容(NUL 终止串,含 */@ 前缀与 [dims])。
201+
/// 解析 XValue head 的 langtype 内容(NUL 终止串,含 */@ 前缀与 [dims])。
202202
/// 成功返回 0,失败(空指针/空串)返回 -1。
203203
#[no_mangle]
204-
pub extern "C" fn kvlangKindexprParse(kindexpr: *const c_char, out: *mut kvlangKindexpr) -> i32 {
205-
if kindexpr.is_null() || out.is_null() {
204+
pub extern "C" fn kvlangKindexprParse(langtype: *const c_char, out: *mut kvlangKindexpr) -> i32 {
205+
if langtype.is_null() || out.is_null() {
206206
return -1;
207207
}
208-
let s = cstr(kindexpr);
208+
let s = cstr(langtype);
209209
if s.is_empty() {
210210
return -1;
211211
}
212-
let (dims, kind) = kvkind::parse_kindexpr(s);
212+
let (dims, kind) = kvkind::parse_langtype(s);
213213
let out = unsafe { &mut *out };
214214
out.ref_ = 0;
215215
out.ndim = dims.len() as i32;

layout/src/code.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -390,12 +390,12 @@ pub fn write_func(kv: &mut Kv, pkg: &str, fn_: &mut Func) {
390390

391391
let nr = fn_.sig.num_reads();
392392
let nw = fn_.sig.num_writes();
393-
let param_types: Vec<String> = fn_.sig.kindexp_list();
393+
let param_types: Vec<String> = fn_.sig.langtype_list();
394394

395395
let mut pairs: Vec<(String, Vec<u8>)> = Vec::new();
396396
pairs.push((
397397
format!("{func_dir}/[0,0]"),
398-
kvkind::new_rwfunc(seq.len() as i32, nr, nw, &param_types),
398+
kvkind::new_rwfunc(seq.len() as i32, nr, nw, fn_.sig.dynamic(), &param_types),
399399
));
400400
pairs.push((
401401
keytree::lib_src(pkg, &fn_.sig.name),
@@ -465,7 +465,7 @@ pub fn write_struct_decl(kv: &mut Kv, decl: &StructDecl) {
465465
/// 字段默认值 XValue:head kind = 字段类型,body = 默认字面量(未给则零值)。
466466
/// 标量+char 直接编码;带 dims / structref 仅记录类型(空 body),嵌套 struct 待定。
467467
fn field_default(ty: &str, default: Option<&Expr>) -> Vec<u8> {
468-
let (dims, base) = kvkind::parse_kindexpr(ty);
468+
let (dims, base) = kvkind::parse_langtype(ty);
469469
let s = default.map(|e| e.val.clone()).unwrap_or_default();
470470
if base.starts_with("char/") {
471471
return ffi::new_char(&base, &s);
@@ -501,7 +501,8 @@ pub fn write_rwir_decl(kv: &mut Kv, decl: &RwirDecl) {
501501
let v = kvkind::new_defrwir(
502502
decl.sig.num_reads(),
503503
decl.sig.num_writes(),
504-
&decl.sig.kindexp_list().join("\n"),
504+
decl.sig.dynamic(),
505+
&decl.sig.langtype_list().join("\n"),
505506
);
506507
let _ = kv.set(&[(keytree::rwir(&opcode), v)]);
507508
}

layout/src/ffi.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ extern "C" {
108108
fn kvspaceDecodeHead(data: *const u8, data_len: u32, out: *mut kvspaceHead_t) -> c_int;
109109

110110
fn kvspaceNewPtr(
111-
target_kindexpr: *const c_char,
111+
target_langtype: *const c_char,
112112
target: *const c_char,
113113
out: *mut *mut u8,
114114
out_len: *mut u32,
@@ -190,7 +190,7 @@ impl Kv {
190190
Kv { h }
191191
}
192192

193-
/// 写:pairs 的值为预编码 TLV;逐条解 head 取 (kindexpr, body),经 WriteNewPlace
193+
/// 写:pairs 的值为预编码 TLV;逐条解 head 取 (langtype, body),经 WriteNewPlace
194194
/// 向 kvspace 要 body 偏移指针后直接写入 body 字节(新建/换 kind/换尺寸唯一原语)。
195195
pub fn set(&mut self, pairs: &[(String, Vec<u8>)]) -> Result<(), String> {
196196
for (key, tlv) in pairs {
@@ -379,8 +379,8 @@ pub fn decode_head(data: &[u8]) -> kvspaceHead_t {
379379

380380
// ── 标准标量构造器 ───────────────────────────────────────────────────
381381

382-
pub fn new_ptr(target_kindexpr: &str, target: &str) -> Vec<u8> {
383-
let ck = CString::new(target_kindexpr).expect("no NUL");
382+
pub fn new_ptr(target_langtype: &str, target: &str) -> Vec<u8> {
383+
let ck = CString::new(target_langtype).expect("no NUL");
384384
let ct = CString::new(target).expect("no NUL");
385385
call_codec(|out, out_len| unsafe { kvspaceNewPtr(ck.as_ptr(), ct.as_ptr(), out, out_len) })
386386
}

layout/src/kvkind.rs

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ pub fn head(data: &[u8]) -> ffi::kvspaceHead_t {
3838
ffi::decode_head(data)
3939
}
4040

41-
/// 解析 kindexpr 内容 → (dims, base kind)。kindexpr 无前缀(ref/ptr 归 head.ref)。
42-
pub fn parse_kindexpr(kx: &str) -> (Vec<i32>, String) {
41+
/// 解析 langtype 内容 → (dims, base kind)。langtype 无前缀(ref/ptr 归 head.ref)。
42+
pub fn parse_langtype(kx: &str) -> (Vec<i32>, String) {
4343
if kx.starts_with('[') {
4444
match kx.find(']') {
4545
Some(end) => (
@@ -57,8 +57,8 @@ pub fn parse_kindexpr(kx: &str) -> (Vec<i32>, String) {
5757
}
5858
}
5959

60-
/// 读 head 的 kindexpr 内容(去 NUL)。
61-
pub fn kindexpr(data: &[u8]) -> String {
60+
/// 读 head 的 langtype 内容(去 NUL)。
61+
pub fn langtype(data: &[u8]) -> String {
6262
if data.is_empty() {
6363
return String::new();
6464
}
@@ -75,7 +75,7 @@ pub fn kind(data: &[u8]) -> String {
7575
if data.is_empty() {
7676
return String::new();
7777
}
78-
parse_kindexpr(&kindexpr(data)).1
78+
parse_langtype(&langtype(data)).1
7979
}
8080

8181
pub fn is_ptr(data: &[u8]) -> bool {
@@ -86,7 +86,7 @@ pub fn array_len(data: &[u8]) -> i32 {
8686
if data.is_empty() {
8787
return 0;
8888
}
89-
let dims = parse_kindexpr(&kindexpr(data)).0;
89+
let dims = parse_langtype(&langtype(data)).0;
9090
if dims.is_empty() {
9191
1
9292
} else {
@@ -104,7 +104,7 @@ pub fn body<'a>(data: &'a [u8], h: &ffi::kvspaceHead_t) -> &'a [u8] {
104104
&data[off..off + len]
105105
}
106106

107-
/// 指针目标 key(Ptr 的 body 即目标 key 路径;head 去 * 为目标完整 kindexpr)。
107+
/// 指针目标 key(Ptr 的 body 即目标 key 路径;head 去 * 为目标完整 langtype)。
108108
pub fn ptr_target(data: &[u8]) -> String {
109109
let h = ffi::decode_head(data);
110110
String::from_utf8_lossy(body(data, &h)).into_owned()
@@ -122,7 +122,7 @@ pub fn display(data: &[u8]) -> String {
122122
if data.is_empty() {
123123
return "None".to_string();
124124
}
125-
let (_, k) = parse_kindexpr(&kindexpr(data));
125+
let (_, k) = parse_langtype(&langtype(data));
126126
if k.is_empty() {
127127
return "None".to_string();
128128
}
@@ -187,21 +187,23 @@ fn plain_value(k: &str, b: &[u8]) -> String {
187187
.map(|c| char::from_u32(le_u32(c)).unwrap_or('\u{FFFD}'))
188188
.collect(),
189189
"index" => format!("({})", count_names(b)),
190-
// kvlang 自有 kind:body = [2B nr][2B nw][sig];槽值/调用目标 nr=nw=0,取 sig 即可。
190+
// kvlang 自有 kind:body = [2B nr][2B nw][1B dynamic][sig];槽值/调用目标 nr=nw=0,取 sig 即可。
191191
"rwir" | "rwir|rwfunc" | "rwfunc" | "defrwir" => {
192-
let (nr, nw) = if b.len() >= 4 {
192+
let (nr, nw, dynamic) = if b.len() >= 5 {
193193
(
194194
u16::from_le_bytes([b[0], b[1]]),
195195
u16::from_le_bytes([b[2], b[3]]),
196+
b[4] != 0,
196197
)
197198
} else {
198-
(0, 0)
199+
(0, 0, false)
199200
};
200-
let sig = String::from_utf8_lossy(&b[4.min(b.len())..]).into_owned();
201+
let sig = String::from_utf8_lossy(&b[5.min(b.len())..]).into_owned();
202+
let var = if dynamic { "..." } else { "" };
201203
if nr == 0 && nw == 0 {
202204
sig
203205
} else {
204-
format!("(nr={nr},nw={nw}) {sig}")
206+
format!("(nr={nr},nw={nw}{var}) {sig}")
205207
}
206208
}
207209
_ => String::from_utf8_lossy(b).into_owned(),
@@ -214,34 +216,35 @@ pub fn is_char_kind(k: &str) -> bool {
214216

215217
// ── kvlang 自有 kind:rwir / defrwir ────────────────────────────────
216218
//
217-
// body = [2B nr LE][2B nw LE][sig],array_len=1。
218-
// rwir=槽值(引用串/opcode),defrwir=定义(签名)。
219+
// body = [2B nr LE][2B nw LE][1B dynamic][sig],array_len=1。
220+
// rwir=槽值(引用串/opcode),defrwir=定义(签名)。dynamic=末读参变参(arity,非 langtype)。
219221

220-
fn rwir_body(nr: i32, nw: i32, sig: &str) -> Vec<u8> {
221-
let mut raw = Vec::with_capacity(4 + sig.len());
222+
fn rwir_body(nr: i32, nw: i32, dynamic: bool, sig: &str) -> Vec<u8> {
223+
let mut raw = Vec::with_capacity(5 + sig.len());
222224
raw.extend_from_slice(&(nr as u16).to_le_bytes());
223225
raw.extend_from_slice(&(nw as u16).to_le_bytes());
226+
raw.push(dynamic as u8);
224227
raw.extend_from_slice(sig.as_bytes());
225228
raw
226229
}
227230

228231
pub fn new_rwir(nr: i32, nw: i32, sig: &str) -> Vec<u8> {
229-
ffi::tlv_encode(KIND_RWIR, &rwir_body(nr, nw, sig), 1)
232+
ffi::tlv_encode(KIND_RWIR, &rwir_body(nr, nw, false, sig), 1)
230233
}
231234

232-
/// 调用目标(看起来像函数调用的 opcode)→ kindexpr `rwir|rwfunc` 并列。
235+
/// 调用目标(看起来像函数调用的 opcode)→ langtype `rwir|rwfunc` 并列。
233236
/// 静态无法判定是扩展 rwir 还是用户 rwfunc,交 runtime 查 /lib/<op> 的 XValue kind 分派。
234237
pub fn new_rwir_union(sig: &str) -> Vec<u8> {
235-
ffi::tlv_encode(KIND_RWIR_OR_RWFUNC, &rwir_body(0, 0, sig), 1)
238+
ffi::tlv_encode(KIND_RWIR_OR_RWFUNC, &rwir_body(0, 0, false, sig), 1)
236239
}
237240

238-
pub fn new_defrwir(nr: i32, nw: i32, sig: &str) -> Vec<u8> {
239-
ffi::tlv_encode(KIND_DEF_RWIR, &rwir_body(nr, nw, sig), 1)
241+
pub fn new_defrwir(nr: i32, nw: i32, dynamic: bool, sig: &str) -> Vec<u8> {
242+
ffi::tlv_encode(KIND_DEF_RWIR, &rwir_body(nr, nw, dynamic, sig), 1)
240243
}
241244

242245
// ── struct 原型(对齐 runtime kvlangBuiltinMemindex)─────────────────
243246
//
244-
// /lib/Name kind=struct,body="name:kindexpr\n..."(字段声明类型,供实例化类型校验)
247+
// /lib/Name kind=struct,body="name:langtype\n..."(字段声明类型,供实例化类型校验)
245248
// /lib/Name· kind=index,body=[4B count LE][name\n...](字段名唯一权威)
246249

247250
pub fn new_struct(fields: &[(String, String)]) -> Vec<u8> {
@@ -261,12 +264,19 @@ pub fn new_memindex(names: &[String]) -> Vec<u8> {
261264

262265
// ── kvlang 自有 kind:rwfunc ────────────────────────────────────────
263266
//
264-
// body = [2B nr LE][2B nw LE][param_types 以 \n 连接],array_len=num_insts。
265-
266-
pub fn new_rwfunc(num_insts: i32, nr: i32, nw: i32, param_types: &[String]) -> Vec<u8> {
267-
let mut raw = Vec::with_capacity(4 + param_types.iter().map(|s| s.len()).sum::<usize>());
267+
// body = [2B nr LE][2B nw LE][1B dynamic][param_types 以 \n 连接],array_len=num_insts。
268+
269+
pub fn new_rwfunc(
270+
num_insts: i32,
271+
nr: i32,
272+
nw: i32,
273+
dynamic: bool,
274+
param_types: &[String],
275+
) -> Vec<u8> {
276+
let mut raw = Vec::with_capacity(5 + param_types.iter().map(|s| s.len()).sum::<usize>());
268277
raw.extend_from_slice(&(nr as u16).to_le_bytes());
269278
raw.extend_from_slice(&(nw as u16).to_le_bytes());
279+
raw.push(dynamic as u8);
270280
raw.extend_from_slice(param_types.join("\n").as_bytes());
271281
ffi::tlv_encode(KIND_RWFUNC, &raw, num_insts)
272282
}
@@ -287,10 +297,10 @@ pub fn rwfunc_num_writes(body: &[u8]) -> i32 {
287297
}
288298

289299
pub fn rwfunc_param_types(body: &[u8]) -> Vec<String> {
290-
if body.len() <= 4 {
300+
if body.len() <= 5 {
291301
return Vec::new();
292302
}
293-
String::from_utf8_lossy(&body[4..])
303+
String::from_utf8_lossy(&body[5..])
294304
.split('\n')
295305
.map(|s| s.to_string())
296306
.collect()

0 commit comments

Comments
 (0)