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 layout/src/code.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -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)]);
}

Expand Down
18 changes: 7 additions & 11 deletions layout/src/ffi.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -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],
}

// ── 内部助手 ─────────────────────────────────────────────────────────
Expand DownExpand Up@@ -286,13 +284,11 @@ pub fn tlv_encode_ptr(kind: &str, raw: &[u8], array_len: i32) -> Vec<u8> {
/// 解码 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);
Expand Down
20 changes: 10 additions & 10 deletions layout/src/type_expr.rs → layout/src/kindexpr.rs
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
//! 签名类型表达式(runtime篇-07,修订:无家族简写):语法校验 + 值匹配。
//! 签名 kindexpr(runtime篇-07,修订:无家族简写):语法校验 + 值匹配。
//!
//! type = atom ("|" atom)*
//! atom = [dims] ( any | kind )
Expand DownExpand Up@@ -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)
}
Expand DownExpand Up@@ -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))
}
Expand All@@ -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");
}
}

Expand All@@ -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]
Expand All@@ -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");
}
}

Expand All@@ -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:?})");
}
}
}
67 changes: 58 additions & 9 deletions layout/src/kvkind.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -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 字节访问器 ───────────────────────────────────────────
Expand All@@ -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<i32>, 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 字节。
Expand DownExpand Up@@ -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<u8> {
fn rwir_body(nr: i32, nw: i32, sig: &str) -> Vec<u8> {
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<u8> {
ffi::tlv_encode(KIND_RWIR, &rwir_body(nr, nw, sig), 1)
}

pub fn new_defrwir(nr: i32, nw: i32, sig: &str) -> Vec<u8> {
ffi::tlv_encode(KIND_DEF_RWIR, &rwir_body(nr, nw, sig), 1)
}

// ── kvlang 自有 kind:rwfunc ────────────────────────────────────────
Expand All@@ -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 读回签名时用)。
Expand Down
2 changes: 1 addition & 1 deletion layout/src/lib.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -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;
Expand Down
8 changes: 4 additions & 4 deletions layout/src/parser.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -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(&param.ty) {
if !crate::kindexpr::valid_kindexpr(&param.ty) {
self.errors.push(Diagnostic {
pos: Pos { line: 0, col: 0 },
message: format!("func {}: param {:?}: {} (got {:?})", sig.name, param.name, type_error(&param.ty), param.ty),
Expand All@@ -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),
Expand DownExpand Up@@ -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),
Expand All@@ -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),
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion runtime/CMakeLists.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -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)

Expand Down
6 changes: 3 additions & 3 deletions runtime/include/kvlang_rwirext.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -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);
Loading
Loading