From 6aaef8d1b33f39cee9e784dd8932dd236ae8b23f Mon Sep 17 00:00:00 2001 From: "peng.li24" <734991033@qq.com> Date: Sun, 23 Aug 2026 14:33:28 +0000 Subject: [PATCH] =?UTF-8?q?refactor:=20type=5Fexpr=20=E2=86=92=20kindexpr?= =?UTF-8?q?=EF=BC=88XValue=20header=20=E7=BB=9F=E4=B8=80=E4=B8=BA=E5=8D=95?= =?UTF-8?q?=E4=B8=80=20kindexpr=20=E4=B8=B2=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - layout/src/type_expr.rs → kindexpr.rs;runtime/src/type_expr.c → kindexpr.c。 - kvkind.rs 新增 defrwir/defrwfunc kind。 - head 格式:ref/ndim/dims 全并入 kindexpr 串。 Co-Authored-By: Claude --- layout/src/code.rs | 2 +- layout/src/ffi.rs | 18 ++--- layout/src/{type_expr.rs => kindexpr.rs} | 20 +++--- layout/src/kvkind.rs | 67 ++++++++++++++++--- layout/src/lib.rs | 2 +- layout/src/parser.rs | 8 +-- .../{type_expr_test.rs => kindexpr_test.rs} | 0 runtime/CMakeLists.txt | 2 +- runtime/include/kvlang_rwirext.h | 6 +- runtime/src/builtin.c | 52 +++++++------- runtime/src/const.h | 2 + runtime/src/{type_expr.c => kindexpr.c} | 8 +-- runtime/src/kvcpu.c | 18 ++--- runtime/src/runtime_internal.h | 33 ++++++--- runtime/src/xvalue.c | 55 ++++++++++++--- 15 files changed, 192 insertions(+), 101 deletions(-) rename layout/src/{type_expr.rs => kindexpr.rs} (89%) rename layout/tests/{type_expr_test.rs => kindexpr_test.rs} (100%) rename runtime/src/{type_expr.c => kindexpr.c} (95%) diff --git a/layout/src/code.rs b/layout/src/code.rs index 510feb14..11c30770 100644 --- a/layout/src/code.rs +++ b/layout/src/code.rs @@ -154,7 +154,7 @@ pub fn write_rwir_decl(kv: &mut Kv, decl: &RwirDecl) { if !decl.pkg.is_empty() { opcode = format!("{}{}{opcode}", decl.pkg, keytree::MEMBER_SEP); } - let v = kvkind::new_rwir(decl.sig.num_reads(), decl.sig.num_writes(), &decl.sig.kindexp_list().join("\n")); + let v = kvkind::new_defrwir(decl.sig.num_reads(), decl.sig.num_writes(), &decl.sig.kindexp_list().join("\n")); let _ = kv.set(&[(keytree::rwir(&opcode), v)]); } diff --git a/layout/src/ffi.rs b/layout/src/ffi.rs index 9aa3ec92..28bb6cbe 100644 --- a/layout/src/ffi.rs +++ b/layout/src/ffi.rs @@ -102,16 +102,14 @@ extern "C" { fn kvspaceNewFloat64(v: f64, out: *mut *mut u8, out_len: *mut u32) -> c_int; } -/// XValueHead 解码结果(与 kvspace-durable 的 kvspaceHead_t 布局一致)。 +/// XValueHead 解码结果(与 kvspace-durable 的 kvspaceHead_t 布局一致)。kindexpr 为唯一类型真相。 #[repr(C)] pub struct kvspaceHead_t { - pub kind: [u8; 32], - pub is_ptr: u8, - pub array_len: i32, + pub kindexpr: [u8; 256], + pub ro: u8, + pub vid: u32, pub body_len: i32, pub body_offset: i32, - pub ndim: i32, - pub dims: [i32; 8], } // ── 内部助手 ───────────────────────────────────────────────────────── @@ -286,13 +284,11 @@ pub fn tlv_encode_ptr(kind: &str, raw: &[u8], array_len: i32) -> Vec { /// 解码 XValueHead。 pub fn decode_head(data: &[u8]) -> kvspaceHead_t { let mut h = kvspaceHead_t { - kind: [0u8; 32], - is_ptr: 0, - array_len: 0, + kindexpr: [0u8; 256], + ro: 0, + vid: 0, body_len: 0, body_offset: 0, - ndim: 0, - dims: [0i32; 8], }; unsafe { kvspaceDecodeHead(data.as_ptr(), data.len() as u32, &mut h); diff --git a/layout/src/type_expr.rs b/layout/src/kindexpr.rs similarity index 89% rename from layout/src/type_expr.rs rename to layout/src/kindexpr.rs index 98c96754..1861b8a5 100644 --- a/layout/src/type_expr.rs +++ b/layout/src/kindexpr.rs @@ -1,4 +1,4 @@ -//! 签名类型表达式(runtime篇-07,修订:无家族简写):语法校验 + 值匹配。 +//! 签名 kindexpr(runtime篇-07,修订:无家族简写):语法校验 + 值匹配。 //! //! type = atom ("|" atom)* //! atom = [dims] ( any | kind ) @@ -68,7 +68,7 @@ pub fn strip_variadic(expr: &str) -> &str { } /// 类型表达式语法校验(装载期)。允许末参尾缀 `...` 变参。 -pub fn valid_type_expr(expr: &str) -> bool { +pub fn valid_kindexpr(expr: &str) -> bool { let e = strip_variadic(expr); !e.is_empty() && e.split('|').all(valid_atom) } @@ -119,7 +119,7 @@ fn match_atom(s: &str, kind: &str, ndim: i32, dims: &[i32]) -> bool { /// 单值(kind/ndim/dims)是否匹配类型表达式:任一 atom 命中即 true。 /// 变参 `...` 按单元素判定(去尾缀后匹配),重复由派发循环处理。 -pub fn match_type(expr: &str, kind: &str, ndim: i32, dims: &[i32]) -> bool { +pub fn match_kindexpr(expr: &str, kind: &str, ndim: i32, dims: &[i32]) -> bool { let e = strip_variadic(expr); !e.is_empty() && e.split('|').any(|atom| match_atom(atom, kind, ndim, dims)) } @@ -139,7 +139,7 @@ mod tests { "bool|char/utf8", "index|objindex", "any...", "int64|float64...", "[]float32...", ] { - assert!(valid_type_expr(e), "{e} should be valid"); + assert!(valid_kindexpr(e), "{e} should be valid"); } } @@ -149,9 +149,9 @@ mod tests { assert!(!is_variadic("any")); assert_eq!(strip_variadic("int64|float64..."), "int64|float64"); // 变参 kindexp 按单元素匹配 - assert!(match_type("any...", "int64", 0, &[])); - assert!(match_type("int64|float64...", "float64", 0, &[])); - assert!(!match_type("int64...", "bool", 0, &[])); + assert!(match_kindexpr("any...", "int64", 0, &[])); + assert!(match_kindexpr("int64|float64...", "float64", 0, &[])); + assert!(!match_kindexpr("int64...", "bool", 0, &[])); } #[test] @@ -162,7 +162,7 @@ mod tests { "*int64", "@int64", "int64*", "float64|", "int ", "float32,float64", "int", "uint", "float", "num", "char", "int4", "fp8", "fp16", "string", "charbyte", ] { - assert!(!valid_type_expr(e), "{e} should be invalid"); + assert!(!valid_kindexpr(e), "{e} should be invalid"); } } @@ -189,8 +189,8 @@ mod tests { ("index|objindex", "index", 0, &[], true), ]; for (expr, kind, ndim, dims, want) in cases { - let got = match_type(expr, kind, ndim, dims); - assert_eq!(got, want, "match_type({expr}, {kind}, ndim={ndim}, dims={dims:?})"); + let got = match_kindexpr(expr, kind, ndim, dims); + assert_eq!(got, want, "match_kindexpr({expr}, {kind}, ndim={ndim}, dims={dims:?})"); } } } diff --git a/layout/src/kvkind.rs b/layout/src/kvkind.rs index 10fd58b2..43c4855f 100644 --- a/layout/src/kvkind.rs +++ b/layout/src/kvkind.rs @@ -22,6 +22,8 @@ pub const KIND_EXT_INDEX: &str = "extindex"; // 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_SCOPE: &str = "scope"; // ── 通用 XValue 字节访问器 ─────────────────────────────────────────── @@ -35,24 +37,62 @@ pub fn head(data: &[u8]) -> ffi::kvspaceHead_t { ffi::decode_head(data) } -pub fn kind(data: &[u8]) -> String { +/// 解析 head 的 kindexpr 内容 → (ref, dims, base kind)。 +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(']') { + Some(end) => ( + r, + rest[1..end] + .split(',') + .filter(|d| !d.is_empty()) + .map(|d| d.parse().unwrap_or(0)) + .collect(), + rest[end + 1..].to_string(), + ), + None => (r, Vec::new(), rest.to_string()), + } + } else { + (r, Vec::new(), rest.to_string()) + } +} + +/// 读 head 的 kindexpr 内容(去 NUL)。 +pub fn kindexpr(data: &[u8]) -> String { if data.is_empty() { return String::new(); } let h = ffi::decode_head(data); - let end = h.kind.iter().position(|&b| b == 0).unwrap_or(h.kind.len()); - String::from_utf8_lossy(&h.kind[..end]).into_owned() + let end = h.kindexpr.iter().position(|&b| b == 0).unwrap_or(h.kindexpr.len()); + String::from_utf8_lossy(&h.kindexpr[..end]).into_owned() +} + +pub fn kind(data: &[u8]) -> String { + if data.is_empty() { + return String::new(); + } + parse_kindexpr(&kindexpr(data)).2 } pub fn is_ptr(data: &[u8]) -> bool { - !data.is_empty() && ffi::decode_head(data).is_ptr != 0 + !data.is_empty() && parse_kindexpr(&kindexpr(data)).0 == 1 } pub fn array_len(data: &[u8]) -> i32 { if data.is_empty() { return 0; } - ffi::decode_head(data).array_len + let dims = parse_kindexpr(&kindexpr(data)).1; + if dims.is_empty() { + 1 + } else { + dims.iter().product() + } } /// 从 data 截取 body 字节。 @@ -81,16 +121,25 @@ pub fn is_char_kind(k: &str) -> bool { k.starts_with("char/") } -// ── kvlang 自有 kind:rwir ────────────────────────────────────────── +// ── kvlang 自有 kind:rwir / defrwir ──────────────────────────────── // // body = [2B nr LE][2B nw LE][sig],array_len=1。 +// rwir=槽值(引用串/opcode),defrwir=定义(签名)。 -pub fn new_rwir(nr: i32, nw: i32, sig: &str) -> Vec { +fn rwir_body(nr: i32, nw: i32, sig: &str) -> Vec { let mut raw = Vec::with_capacity(4 + sig.len()); raw.extend_from_slice(&(nr as u16).to_le_bytes()); raw.extend_from_slice(&(nw as u16).to_le_bytes()); raw.extend_from_slice(sig.as_bytes()); - ffi::tlv_encode(KIND_RWIR, &raw, 1) + raw +} + +pub fn new_rwir(nr: i32, nw: i32, sig: &str) -> Vec { + ffi::tlv_encode(KIND_RWIR, &rwir_body(nr, nw, sig), 1) +} + +pub fn new_defrwir(nr: i32, nw: i32, sig: &str) -> Vec { + ffi::tlv_encode(KIND_DEF_RWIR, &rwir_body(nr, nw, sig), 1) } // ── kvlang 自有 kind:rwfunc ──────────────────────────────────────── @@ -102,7 +151,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_RWFUNC, &raw, num_insts) + ffi::tlv_encode(KIND_DEF_RWFUNC, &raw, num_insts) } /// rwfunc body 访问器(layout 读回签名时用)。 diff --git a/layout/src/lib.rs b/layout/src/lib.rs index e3f1ff95..0977472d 100644 --- a/layout/src/lib.rs +++ b/layout/src/lib.rs @@ -11,7 +11,7 @@ pub mod ast; pub mod scanner; pub mod parser; pub mod builtin; -pub mod type_expr; +pub mod kindexpr; pub mod lower; pub mod code; pub mod capi; diff --git a/layout/src/parser.rs b/layout/src/parser.rs index 6fbe4921..85557af3 100644 --- a/layout/src/parser.rs +++ b/layout/src/parser.rs @@ -415,7 +415,7 @@ impl Parser { fn check_param_types(&mut self, sig: &FuncSig) { for param in &sig.params { - if !crate::type_expr::valid_type_expr(¶m.ty) { + if !crate::kindexpr::valid_kindexpr(¶m.ty) { self.errors.push(Diagnostic { pos: Pos { line: 0, col: 0 }, message: format!("func {}: param {:?}: {} (got {:?})", sig.name, param.name, type_error(¶m.ty), param.ty), @@ -428,7 +428,7 @@ impl Parser { } } for ret in &sig.returns { - if !crate::type_expr::valid_type_expr(&ret.ty) { + if !crate::kindexpr::valid_kindexpr(&ret.ty) { self.errors.push(Diagnostic { pos: Pos { line: 0, col: 0 }, message: format!("func {}: return value {:?}: {} (got {:?})", sig.name, ret.name, type_error(&ret.ty), ret.ty), @@ -471,7 +471,7 @@ impl Parser { fn check_variadic(&mut self, sig: &FuncSig) { let last = sig.params.len().saturating_sub(1); for (i, p) in sig.params.iter().enumerate() { - if crate::type_expr::is_variadic(&p.ty) && i != last { + if crate::kindexpr::is_variadic(&p.ty) && i != last { self.errors.push(Diagnostic { pos: Pos { line: 0, col: 0 }, message: format!("func {}: variadic param {:?} must be the last read-param", sig.name, p.name), @@ -484,7 +484,7 @@ impl Parser { } } for r in &sig.returns { - if crate::type_expr::is_variadic(&r.ty) { + if crate::kindexpr::is_variadic(&r.ty) { self.errors.push(Diagnostic { pos: Pos { line: 0, col: 0 }, message: format!("func {}: write-param {:?} cannot be variadic", sig.name, r.name), diff --git a/layout/tests/type_expr_test.rs b/layout/tests/kindexpr_test.rs similarity index 100% rename from layout/tests/type_expr_test.rs rename to layout/tests/kindexpr_test.rs diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index 86805104..6fcf7ca2 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -23,7 +23,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${BIN_DIR}") add_library(kvlang_runtime SHARED src/strbuf.c src/xvalue.c src/kv.c src/keytree.c src/rwir.c src/vthread.c src/logx.c src/builtin.c src/kvcpu.c src/runtime.c src/rwirext.c - src/type_expr.c) + src/kindexpr.c) target_include_directories(kvlang_runtime PUBLIC include src) target_compile_definitions(kvlang_runtime PRIVATE _GNU_SOURCE) diff --git a/runtime/include/kvlang_rwirext.h b/runtime/include/kvlang_rwirext.h index c74a0a49..83124eea 100644 --- a/runtime/include/kvlang_rwirext.h +++ b/runtime/include/kvlang_rwirext.h @@ -41,11 +41,11 @@ char *kvlang_rwirextResolveReadPath(void *kvspace, const char *pc, int idx); /* 解析写参 idx 为 KV 路径(路径 → 直接返回;变量 → 帧槽路径)。 */ char *kvlang_rwirextResolveWrite(void *kvspace, const char *pc, int idx); -/* 签名类型表达式(runtime篇-07)——供扩展做实参类型判定。 */ +/* 签名 kindexpr(runtime篇-07)——供扩展做实参类型判定。 */ /* 语法校验:type = atom("|"atom)*, atom = [dims](family|kind), * dims="[]"|"["dim(","dim)*"]", dim=int|"?"。 */ -bool kvlang_rwirextTypeValid(const char *expr); +bool kvlang_rwirextKindexprValid(const char *expr); /* 值判定:kind 为实际落盘 kind 串,ndim 为秩(标量 0),dims 为各维长(标量传 * NULL)。 */ -bool kvlang_rwirextTypeMatch(const char *expr, const char *kind, int32_t ndim, +bool kvlang_rwirextKindexprMatch(const char *expr, const char *kind, int32_t ndim, const int32_t *dims); diff --git a/runtime/src/builtin.c b/runtime/src/builtin.c index 45f55fa4..014e413d 100644 --- a/runtime/src/builtin.c +++ b/runtime/src/builtin.c @@ -858,7 +858,8 @@ int kvlangBuiltinXvDim(kvlangFrame_t *f) { free(fr); } else if (n > 0) { kvspaceHead_t h; kvlangXvalueHead(&in[0], &h); - ndim = h.ndim; + kvlang_kindexpr_t kx; kvlang_kindexpr_parse(h.kindexpr, &kx); + ndim = kx.ndim; } kvlangXvalue_t r; kvlangXvalueNewInt64(&r, ndim); int rc = write_result(f, &r); kvlangXvalueFree(&r); free_inputs(in, n); @@ -875,8 +876,9 @@ int kvlangBuiltinXvShape(kvlangFrame_t *f) { free(fr); } else if (n > 0 && !kvlangXvalueNone(&in[0])) { kvspaceHead_t h; kvlangXvalueHead(&in[0], &h); - ndim = h.ndim; - for (int i = 0; i < ndim && i < 8; i++) dims[i] = h.dims[i]; + kvlang_kindexpr_t kx; kvlang_kindexpr_parse(h.kindexpr, &kx); + ndim = kx.ndim; + for (int i = 0; i < ndim && i < 8; i++) dims[i] = kx.dims[i]; } uint8_t raw[64]; uint32_t raw_len = 0; for (int i = 0; i < ndim; i++) { @@ -891,12 +893,12 @@ int kvlangBuiltinXvShape(kvlangFrame_t *f) { } /* 计算多维下标 (i0..i_{n-1}) 的 row-major 扁平索引,越界返回 -1。 */ -static int64_t flat_index(const kvspaceHead_t *h, const kvlangXvalue_t *in, int nidx) { +static int64_t flat_index(const kvlang_kindexpr_t *kx, const kvlangXvalue_t *in, int nidx) { int64_t flat = 0; for (int i = 0; i < nidx; i++) { int64_t idx = kvlangXvalueAsInt64(&in[i + 1]); - if (idx < 0 || idx >= h->dims[i]) return -1; - flat = flat * h->dims[i] + idx; + if (idx < 0 || idx >= kx->dims[i]) return -1; + flat = flat * kx->dims[i] + idx; } return flat; } @@ -921,9 +923,10 @@ int kvlangBuiltinXvAt(kvlangFrame_t *f) { const char *k = kvlangXvalueKind(&in[0]); int sz = kvlangXvalueElemSize(k); kvspaceHead_t h; kvspaceDecodeHead(in[0].data, in[0].len, &h); - if (sz <= 0 || h.ndim == 0) { free_inputs(in, n); return set_err(f, "TypeError: xv.at requires a compact array, got %s", k); } - if (nidx != h.ndim) { free_inputs(in, n); return set_err(f, "IndexError: xv.at: %d-dim array needs %d indices, got %d", h.ndim, h.ndim, nidx); } - int64_t flat = flat_index(&h, in, nidx); + kvlang_kindexpr_t kx; kvlang_kindexpr_parse(h.kindexpr, &kx); + if (sz <= 0 || kx.ndim == 0) { free_inputs(in, n); return set_err(f, "TypeError: xv.at requires a compact array, got %s", k); } + if (nidx != kx.ndim) { free_inputs(in, n); return set_err(f, "IndexError: xv.at: %d-dim array needs %d indices, got %d", kx.ndim, kx.ndim, nidx); } + int64_t flat = flat_index(&kx, in, nidx); if (flat < 0) { free_inputs(in, n); return set_err(f, "IndexError: xv.at: index out of bounds"); } const uint8_t *body = in[0].data + h.body_offset; kvlangXvalue_t e; kvlangXvalueNewTlv(&e, k, body + flat * sz, (uint32_t)sz, 1); @@ -939,9 +942,10 @@ int kvlangBuiltinXvSet(kvlangFrame_t *f) { const char *k = kvlangXvalueKind(&in[0]); int sz = kvlangXvalueElemSize(k); kvspaceHead_t h; kvspaceDecodeHead(in[0].data, in[0].len, &h); - if (sz <= 0 || h.ndim == 0) { free_inputs(in, n); return set_err(f, "TypeError: xv.set requires a compact array, got %s", k); } - if (nidx != h.ndim) { free_inputs(in, n); return set_err(f, "IndexError: xv.set: %d-dim array needs %d indices, got %d", h.ndim, h.ndim, nidx); } - int64_t flat = flat_index(&h, in, nidx); + kvlang_kindexpr_t kx; kvlang_kindexpr_parse(h.kindexpr, &kx); + if (sz <= 0 || kx.ndim == 0) { free_inputs(in, n); return set_err(f, "TypeError: xv.set requires a compact array, got %s", k); } + if (nidx != kx.ndim) { free_inputs(in, n); return set_err(f, "IndexError: xv.set: %d-dim array needs %d indices, got %d", kx.ndim, kx.ndim, nidx); } + int64_t flat = flat_index(&kx, in, nidx); if (flat < 0) { free_inputs(in, n); return set_err(f, "IndexError: xv.set: index out of bounds"); } const uint8_t *body = in[0].data + h.body_offset; uint8_t *nb = malloc((size_t)h.body_len); @@ -950,7 +954,7 @@ int kvlangBuiltinXvSet(kvlangFrame_t *f) { const uint8_t *vb = in[nidx + 1].data + vh.body_offset; int c = vh.body_len < sz ? vh.body_len : sz; memcpy(nb + flat * sz, vb, (size_t)c); - kvlangXvalue_t nv; kvlangXvalueNewTlvDims(&nv, k, nb, (uint32_t)h.body_len, h.dims, h.ndim); + kvlangXvalue_t nv; kvlangXvalueNewTlvDims(&nv, k, nb, (uint32_t)h.body_len, kx.dims, kx.ndim); int rc = write_result(f, &nv); kvlangXvalueFree(&nv); free(nb); free_inputs(in, n); return rc; @@ -964,7 +968,8 @@ int kvlangBuiltinXvReshape(kvlangFrame_t *f) { const char *k = kvlangXvalueKind(&in[0]); if (kvlangXvalueElemSize(k) <= 0) { free_inputs(in, n); return set_err(f, "TypeError: xv.reshape requires a compact array, got %s", k); } kvspaceHead_t h; kvspaceDecodeHead(in[0].data, in[0].len, &h); - if (h.ndim < 1) { free_inputs(in, n); return set_err(f, "TypeError: xv.reshape requires a compact array, got scalar %s", k); } + kvlang_kindexpr_t kx; kvlang_kindexpr_parse(h.kindexpr, &kx); + if (kx.ndim < 1) { free_inputs(in, n); return set_err(f, "TypeError: xv.reshape requires a compact array, got scalar %s", k); } if (ndims > X_MAX_NDIM) { free_inputs(in, n); return set_err(f, "IndexError: xv.reshape: at most %d dims, got %d", X_MAX_NDIM, ndims); } int32_t dims[X_MAX_NDIM]; int64_t numel = 1; for (int i = 0; i < ndims; i++) { @@ -972,20 +977,11 @@ int kvlangBuiltinXvReshape(kvlangFrame_t *f) { if (dims[i] < 0) { free_inputs(in, n); return set_err(f, "IndexError: xv.reshape: negative dim %d", dims[i]); } numel *= dims[i]; } - if (numel != h.array_len) { free_inputs(in, n); return set_err(f, "IndexError: xv.reshape: cannot reshape %d elements into %lld", h.array_len, (long long)numel); } - /* 原地改写:数组 head 形状段恒 X_MAX_NDIM×4=32B,改写 dims+ndim+padding,body 不搬 */ - uint8_t *data = in[0].data; - int32_t dims_off = 1 + (int32_t)data[0] + 2; - data[dims_off - 1] = (uint8_t)ndims; - memset(data + dims_off, 0, (size_t)(X_MAX_NDIM * 4)); - for (int i = 0; i < ndims; i++) { - uint32_t v = (uint32_t)dims[i]; - data[dims_off + i * 4] = (uint8_t)v; - data[dims_off + i * 4 + 1] = (uint8_t)(v >> 8); - data[dims_off + i * 4 + 2] = (uint8_t)(v >> 16); - data[dims_off + i * 4 + 3] = (uint8_t)(v >> 24); - } - int rc = write_result(f, &in[0]); + if (numel != kx.array_len) { free_inputs(in, n); return set_err(f, "IndexError: xv.reshape: cannot reshape %d elements into %lld", kx.array_len, (long long)numel); } + const uint8_t *body = in[0].data + h.body_offset; + kvlangXvalue_t nv; kvlangXvalueNewTlvDims(&nv, k, body, (uint32_t)h.body_len, dims, ndims); + int rc = write_result(f, &nv); + kvlangXvalueFree(&nv); free_inputs(in, n); return rc; } diff --git a/runtime/src/const.h b/runtime/src/const.h index 196551c5..5a3f0429 100644 --- a/runtime/src/const.h +++ b/runtime/src/const.h @@ -26,6 +26,8 @@ #define KVSPACE_KIND_EXT_INDEX "extindex" #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_SCOPE "scope" #define KVSPACE_KIND_TIME "time" #define KVSPACE_KIND_DURATION "duration" diff --git a/runtime/src/type_expr.c b/runtime/src/kindexpr.c similarity index 95% rename from runtime/src/type_expr.c rename to runtime/src/kindexpr.c index 51aa06c5..7509a724 100644 --- a/runtime/src/type_expr.c +++ b/runtime/src/kindexpr.c @@ -1,6 +1,6 @@ #include "runtime_internal.h" -/* ── 签名类型表达式(runtime篇-07,修订:无家族简写)────────────────── +/* ── 签名 kindexpr(runtime篇-07,修订:无家族简写)────────────────── * type = atom ("|" atom)* * atom = [dims] ( any | kind ) * dims = "[]" | "[" dim ("," dim)* "]" @@ -78,7 +78,7 @@ static bool valid_atom(const char *s, size_t len) { } /* 末参变参标记:A:any... 表 0..N 个同型实参。 */ -bool kvlang_rwirextTypeVariadic(const char *expr) { +bool kvlang_rwirextKindexprVariadic(const char *expr) { if (!expr) return false; size_t n = strlen(expr); return n >= 3 && memcmp(expr + n - 3, "...", 3) == 0; @@ -91,7 +91,7 @@ static size_t effective_len(const char *expr) { } /* 类型表达式语法校验(装载期)。允许末参尾缀 "..." 变参。 */ -bool kvlang_rwirextTypeValid(const char *expr) { +bool kvlang_rwirextKindexprValid(const char *expr) { if (!expr || !*expr) return false; size_t total = effective_len(expr); if (total == 0) return false; @@ -151,7 +151,7 @@ static bool match_atom(const char *s, size_t len, const char *kind, int32_t ndim /* 单值(kind/ndim/dims)是否匹配类型表达式:任一 atom 命中即 true。 * 变参 "..." 按单元素判定(去尾缀后匹配),重复由派发循环处理。 */ -bool kvlang_rwirextTypeMatch(const char *expr, const char *kind, int32_t ndim, const int32_t *dims) { +bool kvlang_rwirextKindexprMatch(const char *expr, const char *kind, int32_t ndim, const int32_t *dims) { if (!expr || !kind) return false; const char *end = expr + effective_len(expr); const char *p = expr; diff --git a/runtime/src/kvcpu.c b/runtime/src/kvcpu.c index d868d756..01c84e56 100644 --- a/runtime/src/kvcpu.c +++ b/runtime/src/kvcpu.c @@ -43,7 +43,7 @@ static int check_read_types(kvlangKv_t *kv, const char *vtid, const char *pc, if (!nl) break; *nl = 0; s = nl + 1; } - bool var_last = rn > 0 && kvlang_rwirextTypeVariadic(reads[rn - 1]); + bool var_last = rn > 0 && kvlang_rwirextKindexprVariadic(reads[rn - 1]); int min_args = var_last ? rn - 1 : rn; char *fr = kvlangKeytreeFrameRoot(pc); int rc = 0; @@ -62,12 +62,13 @@ static int check_read_types(kvlangKv_t *kv, const char *vtid, const char *pc, rc = -1; break; } - if (!exp[0] || !kvlang_rwirextTypeValid(exp)) continue; /* 动态/非法 kindexp 跳过 */ + if (!exp[0] || !kvlang_rwirextKindexprValid(exp)) continue; /* 动态/非法 kindexp 跳过 */ kvlangXvalue_t v; kvlangXvalueZero(&v); kvlangBuiltinResolveReadValue(kv, fr, args[i].name, &args[i].val, &v); const char *k = kvlangXvalueKind(&v); kvspaceHead_t h; kvlangXvalueHead(&v, &h); - bool ok = kvlang_rwirextTypeMatch(exp, k, h.ndim, h.dims); + kvlang_kindexpr_t kx; kvlang_kindexpr_parse(h.kindexpr, &kx); + bool ok = kvlang_rwirextKindexprMatch(exp, k, kx.ndim, kx.dims); char kbuf[40]; snprintf(kbuf, sizeof kbuf, "%s", k[0] ? k : "None"); kvlangXvalueFree(&v); if (!ok) { @@ -256,14 +257,14 @@ 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_RWFUNC)) { + if (kvlangXvalueNone(&sig) || !kvlangXvalueKindIs(&sig, KVSPACE_KIND_DEF_RWFUNC)) { /* 按 xvalue 的 kind 精确区分缺 rwir 还是缺 rwfunc: * 到这里说明 opcode 已被 is_ext_rwir 判否(/lib/ 非 rwir)。 */ char *rk = kvlangKeytreeRwir(fn); kvlangXvalue_t rv; kvlangXvalueZero(&rv); kvlangKvGetOne(kv, rk, &rv); char msg[256]; - if (!kvlangXvalueNone(&rv) && kvlangXvalueKindIs(&rv, KVSPACE_KIND_RWIR)) + if (!kvlangXvalueNone(&rv) && kvlangXvalueKindIs(&rv, KVSPACE_KIND_DEF_RWIR)) snprintf(msg, sizeof msg, "NameError: rwir 未注册/签名不匹配: %s", fn); else if (!kvlangXvalueNone(&sig)) snprintf(msg, sizeof msg, "NameError: %s 不是 rwfunc (kind=%s)", fn, kvlangXvalueKind(&sig)); @@ -328,8 +329,9 @@ static char *handle_call(kvlangKv_t *kv, const char *pc, kvlangRwirInst_t *inst) /* 写字面量到 rk(拷贝,避免 double-free) */ kvspaceHead_t ah; kvspaceDecodeHead(arg->val.data, arg->val.len, &ah); int32_t abl; const uint8_t *ab = kvlangXvalueBody(&arg->val, &ah, &abl); + kvlang_kindexpr_t akx; kvlang_kindexpr_parse(ah.kindexpr, &akx); pairs[np].key = strdup(rk); - kvspaceTlvEncode(kvlangXvalueKind(&arg->val), ab, (uint32_t)abl, ah.dims, ah.ndim, + kvspaceTlvEncode(kvlangXvalueKind(&arg->val), ab, (uint32_t)abl, akx.dims, akx.ndim, &pairs[np].val.data, &pairs[np].val.len); np++; } @@ -425,7 +427,7 @@ bool is_ext_rwir(kvlangKv_t *kv, const char *opcode) { char *rk = kvlangKeytreeRwir(opcode); kvlangXvalue_t v; kvlangXvalueZero(&v); kvlangKvGetOne(kv, rk, &v); - bool r = !kvlangXvalueNone(&v) && kvlangXvalueKindIs(&v, KVSPACE_KIND_RWIR); + bool r = !kvlangXvalueNone(&v) && kvlangXvalueKindIs(&v, KVSPACE_KIND_DEF_RWIR); kvlangXvalueFree(&v); free(rk); return r; } @@ -476,7 +478,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_RWFUNC)) { + if (kvlangXvalueNone(&sig) || !kvlangXvalueKindIs(&sig, KVSPACE_KIND_DEF_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); diff --git a/runtime/src/runtime_internal.h b/runtime/src/runtime_internal.h index 405a29f9..8e46e18d 100644 --- a/runtime/src/runtime_internal.h +++ b/runtime/src/runtime_internal.h @@ -11,13 +11,11 @@ /* ── kvspace-durable C ABI ─────────────────────────────────────────── */ typedef struct { - uint8_t kind[32]; - uint8_t is_ptr; - int32_t array_len; - int32_t body_len; - int32_t body_offset; - int32_t ndim; /* 0=标量,N=N 维数组(唯一「是否数组」标志) */ - int32_t dims[8]; /* kind+ndim+dims 即完整 kindexp */ + uint8_t kindexpr[256]; /* NUL 终止(含 ref 前缀与 [dims],去 padding) */ + 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; extern void *kvspaceConnect(const char *dsn); @@ -56,6 +54,19 @@ extern int kvspaceNewFloat64(double v, uint8_t **out, uint32_t *out_len); #define MAX_STACK_DEPTH 256 #define X_MAX_NDIM 8 +/* ── 派生 head:解析 kindexpr 得到(不落盘) ───────────────────────── */ + +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; +} kvlang_kindexpr_t; + +void kvlang_kindexpr_parse(const uint8_t *kindexpr, kvlang_kindexpr_t *out); + /* ── 基础类型 ──────────────────────────────────────────────────────── */ typedef struct { uint8_t *data; uint32_t len; } kvlangXvalue_t; @@ -94,10 +105,10 @@ bool kvlangXvalueIsIntKind(const char *kind); bool kvlangXvalueIsUintKind(const char *kind); bool kvlangXvalueIsFloatKind(const char *kind); bool kvlangXvalueIsNumKind(const char *kind); -/* 签名类型表达式(runtime篇-07)校验/匹配 */ -bool kvlang_rwirextTypeValid(const char *expr); -bool kvlang_rwirextTypeMatch(const char *expr, const char *kind, int32_t ndim, const int32_t *dims); -bool kvlang_rwirextTypeVariadic(const char *expr); +/* 签名 kindexpr(runtime篇-07)校验/匹配 */ +bool kvlang_rwirextKindexprValid(const char *expr); +bool kvlang_rwirextKindexprMatch(const char *expr, const char *kind, int32_t ndim, const int32_t *dims); +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); diff --git a/runtime/src/xvalue.c b/runtime/src/xvalue.c index 44f25d03..a382d382 100644 --- a/runtime/src/xvalue.c +++ b/runtime/src/xvalue.c @@ -16,13 +16,36 @@ void kvlangXvalueSetBytes(kvlangXvalue_t *v, uint8_t *data, uint32_t len) { v->data = data; v->len = len; } +/* 解析 kindexpr 内容 → (ref, dims, base kind)。kindexpr 为 NUL 终止串。 */ +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) { + int32_t d = 0; + while (kx[i] >= '0' && kx[i] <= '9') { d = d * 10 + (kx[i] - '0'); i++; } + out->dims[out->ndim++] = d; + if (kx[i] == ',') i++; + } + if (kx[i] == ']') i++; + } + out->kind = (const char *)(kx + i); + out->kind_len = (int32_t)strlen((const char *)(kx + i)); + out->array_len = 1; + for (int d = 0; d < out->ndim; d++) out->array_len *= out->dims[d]; +} + /* head 编解码统一委托给链接的 kvspace .so(kvspace-c / kvspace-durable 同一 ABI), * runtime 不再私持 TLV head 布局,杜绝多份手写偏移不一致。 */ static int kvlangXvalueDecodeHeadRaw(const uint8_t *d, uint32_t len, kvspaceHead_t *h) { memset(h, 0, sizeof(*h)); if (!d || len == 0) return -1; kvspaceDecodeHead(d, len, h); - return h->kind[0] ? 0 : -1; + return h->kindexpr[0] ? 0 : -1; } /* array_len → dims:char/* 恒一维(含空串/单字符);其余标量(≤1)=0 维、多元素=1 维。 */ @@ -58,28 +81,37 @@ const char *kvlangXvalueKind(const kvlangXvalue_t *v) { char *b = buf[idx]; idx = (idx + 1) & 15; if (kvlangXvalueNone(v)) { b[0] = 0; return b; } - uint8_t kl = v->data[0]; + kvspaceHead_t h; + if (kvlangXvalueHead(v, &h) < 0) { b[0] = 0; return b; } + kvlang_kindexpr_t kx; kvlang_kindexpr_parse(h.kindexpr, &kx); + int32_t kl = kx.kind_len; if (kl > 32) kl = 32; - memcpy(b, v->data + 1, kl); + memcpy(b, kx.kind, (size_t)kl); b[kl] = 0; return b; } bool kvlangXvalueKindIs(const kvlangXvalue_t *v, const char *kind) { if (kvlangXvalueNone(v)) return kind[0] == 0; - uint8_t kl = v->data[0]; - return (size_t)kl == strlen(kind) && memcmp(v->data + 1, kind, kl) == 0; + kvspaceHead_t h; + if (kvlangXvalueHead(v, &h) < 0) return false; + kvlang_kindexpr_t kx; kvlang_kindexpr_parse(h.kindexpr, &kx); + return (size_t)kx.kind_len == strlen(kind) && memcmp(kx.kind, kind, (size_t)kx.kind_len) == 0; } bool kvlangXvalueIsPtr(const kvlangXvalue_t *v) { if (kvlangXvalueNone(v)) return false; - return v->len > 2 + v->data[0] && v->data[1 + v->data[0]] == 1; + kvspaceHead_t h; + if (kvlangXvalueHead(v, &h) < 0) return false; + kvlang_kindexpr_t kx; kvlang_kindexpr_parse(h.kindexpr, &kx); + return kx.ref == 1; } int32_t kvlangXvalueArrayLen(const kvlangXvalue_t *v) { if (kvlangXvalueNone(v)) return 0; kvspaceHead_t h; kvlangXvalueDecodeHeadRaw(v->data, v->len, &h); - return h.array_len; + kvlang_kindexpr_t kx; kvlang_kindexpr_parse(h.kindexpr, &kx); + return kx.array_len; } const uint8_t *kvlangXvalueBody(const kvlangXvalue_t *v, const kvspaceHead_t *h, int32_t *out_len) { @@ -176,7 +208,9 @@ bool kvlangXvalueAsBool(const kvlangXvalue_t *v) { uint32_t kvlangXvalueChar32At(const kvlangXvalue_t *v, int32_t idx) { kvspaceHead_t h; const uint8_t *b = v_body(v, &h); - if (!b || idx < 0 || idx >= h.array_len) return 0; + if (!b) return 0; + kvlang_kindexpr_t kx; kvlang_kindexpr_parse(h.kindexpr, &kx); + if (idx < 0 || idx >= kx.array_len) return 0; return rd32(b + idx * 4); } @@ -237,8 +271,9 @@ 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 (h.is_ptr) { + if (kx.ref == 1) { kvlangStrbuf_t b; kvlangStrbufInit(&b); kvlangStrbufPutn(&b, "\xE2\x86\x92", 3); kvlangStrbufPutn(&b, (const char *)body, (size_t)blen); @@ -346,7 +381,7 @@ void kvlangXvalueNewRwir(kvlangXvalue_t *v, int32_t nr, int32_t nw, const char * raw[0] = nr & 0xFF; raw[1] = (nr >> 8) & 0xFF; raw[2] = nw & 0xFF; raw[3] = (nw >> 8) & 0xFF; memcpy(raw + 4, sig, sl); - kvlangXvalueNewTlv(v, KVSPACE_KIND_RWIR, raw, (uint32_t)(4 + sl), 1); + kvlangXvalueNewTlv(v, KVSPACE_KIND_DEF_RWIR, raw, (uint32_t)(4 + sl), 1); free(raw); }