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/builtin.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -170,7 +170,7 @@ fn native_rwir_set() -> &'static [&'static str] {
"kv.get", "kv.set", "kv.del", "kv.deltree", "kv.list", "kv.mkindex",
"kv.extindex", "kv.rmindexext", "kv.watch",
// xv.* 形状内省与多维元素访问
"xv.numel", "xv.dim", "xv.shape", "xv.at", "xv.set",
"xv.numel", "xv.dim", "xv.shape", "xv.at", "xv.set", "xv.reshape",
]
}

Expand Down
7 changes: 7 additions & 0 deletions layout/src/lower.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -536,6 +536,10 @@ fn infer_inst(inst: &Instruction, tm: &mut HashMap<String, String>) {
Some(e) => e,
None => return,
};
// kv.set 成员形(3 读:base, key, val)是 void 无写槽,但 base 仍须推断为 obj/map(供 for-in / 成员访问)
if e.op == "kv.set" && e.args.len() >= 3 && !e.args[0].val.contains('/') {
tm.entry(e.args[0].val.clone()).or_insert_with(|| "obj".to_string());
}
if inst.writes.is_empty() {
return;
}
Expand DownExpand Up@@ -650,6 +654,9 @@ fn infer_op_type(opcode: &str, reads: &[String], tm: &mut HashMap<String, String
}
return if !reads.is_empty() { slot_type(&reads[0], tm) } else { String::new() };
}
"xv.reshape" => {
return if !reads.is_empty() { slot_type(&reads[0], tm) } else { String::new() };
}
_ => {}
}
String::new()
Expand Down
20 changes: 13 additions & 7 deletions layout/src/parser.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -539,19 +539,24 @@ impl Parser {
});
};
let check = |p: &mut Self, inst: &Instruction, ro: &std::collections::HashSet<String>, fname: &str| {
for (i, w) in inst.writes.iter().enumerate() {
// 写槽命中读参(非路径/索引/成员)
for w in inst.writes.iter() {
if w.contains('/') || w.contains('[') || w.contains(keytree::MEMBER_SEP) {
continue;
}
if let Some(e) = &inst.expr {
if e.op == "set" && i == 0 && !e.args.is_empty() && w == &e.args[0].val {
continue;
}
}
if ro.contains(w) {
bad(p, w, fname);
}
}
// kv.set 成员形(3 读:base, key, val)改写 base 的成员目录,命中读参即拒绝
if let Some(e) = &inst.expr {
if e.op == "kv.set" && e.args.len() >= 3 {
let base = &e.args[0].val;
if !base.contains('/') && ro.contains(base) {
bad(p, base, fname);
}
}
}
};
let fname = func.sig.name.clone();
walk_read_only(self, &func.body, &ro, &fname, &check);
Expand DownExpand Up@@ -1357,8 +1362,9 @@ impl Parser {
ast::str_lit(&field)
};
let e = inst.expr.take();
// base.key = v 脱糖为 kv.set(base, key, val):kv.set 是 void(副作用写成员),无写槽
inst.expr = Some(ast::call("kv.set", vec![ast::leaf(&base), key, e.unwrap_or(ast::leaf(""))]));
inst.writes = vec![base];
inst.writes = Vec::new();
inst.write_types = Vec::new();
}

Expand Down
55 changes: 44 additions & 11 deletions runtime/src/builtin.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,7 +6,7 @@ typedef int (*kvlangBuiltinFn)(kvlangFrame_t *f);

/* collection 模块 handler(builtin_coll.c) */
int kvlangBuiltinArray(kvlangFrame_t *f), kvlangBuiltinXvNumel(kvlangFrame_t *f), kvlangBuiltinXvDim(kvlangFrame_t *f), kvlangBuiltinXvShape(kvlangFrame_t *f),
kvlangBuiltinXvAt(kvlangFrame_t *f), kvlangBuiltinXvSet(kvlangFrame_t *f),
kvlangBuiltinXvAt(kvlangFrame_t *f), kvlangBuiltinXvSet(kvlangFrame_t *f), kvlangBuiltinXvReshape(kvlangFrame_t *f),
kvlangBuiltinScatter(kvlangFrame_t *f), kvlangBuiltinCompact(kvlangFrame_t *f),
kvlangBuiltinAppend(kvlangFrame_t *f), kvlangBuiltinSlice(kvlangFrame_t *f), kvlangBuiltinObj(kvlangFrame_t *f), kvlangBuiltinMap(kvlangFrame_t *f), kvlangBuiltinStringSet(kvlangFrame_t *f),
kvlangBuiltinStringChar(kvlangFrame_t *f), kvlangBuiltinStringOrd(kvlangFrame_t *f), kvlangBuiltinStringCmp(kvlangFrame_t *f),
Expand DownExpand Up@@ -593,7 +593,7 @@ static const struct { const char *op; kvlangBuiltinFn fn; } builtins[] = {
{"array.append", kvlangBuiltinAppend}, {"array.slice", kvlangBuiltinSlice},
{"obj", kvlangBuiltinObj}, {"map", kvlangBuiltinMap},
{"xv.numel", kvlangBuiltinXvNumel}, {"xv.dim", kvlangBuiltinXvDim}, {"xv.shape", kvlangBuiltinXvShape},
{"xv.at", kvlangBuiltinXvAt}, {"xv.set", kvlangBuiltinXvSet},
{"xv.at", kvlangBuiltinXvAt}, {"xv.set", kvlangBuiltinXvSet}, {"xv.reshape", kvlangBuiltinXvReshape},
{"string.set", kvlangBuiltinStringSet}, {"string.char", kvlangBuiltinStringChar}, {"string.ord", kvlangBuiltinStringOrd},
{"string.cmp", kvlangBuiltinStringCmp}, {"string.find", kvlangBuiltinStringFind}, {"string.len", kvlangBuiltinStringLen},
{"string.slice", kvlangBuiltinStringSlice}, {"string.concat", kvlangBuiltinStringConcat},
Expand DownExpand Up@@ -934,6 +934,7 @@ int kvlangBuiltinXvAt(kvlangFrame_t *f) {
int kvlangBuiltinXvSet(kvlangFrame_t *f) {
int nidx = f->inst->nr - 2;
if (nidx < 1) return set_err(f, "TypeError: xv.set requires array, indices, value");
if (f->inst->nw == 0) return set_err(f, "TypeError: xv.set requires a write param (-> a)");
kvlangXvalue_t in[MAX_PARAMS]; int n = read_inputs(f, in, MAX_PARAMS);
const char *k = kvlangXvalueKind(&in[0]);
int sz = kvlangXvalueElemSize(k);
Expand All@@ -950,13 +951,43 @@ int kvlangBuiltinXvSet(kvlangFrame_t *f) {
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);
char *fr = kvlangKeytreeFrameRoot(f->pc);
char *key = kvlangBuiltinResolveWriteSlot(f->kv, fr, f->inst->reads[0].name);
free(fr);
kvlangKvPair_t p = { key, nv };
char err[256]; kvlangKvSet(f->kv, &p, 1, err, sizeof err);
free(key); kvlangXvalueFree(&nv); free(nb); free_inputs(in, n);
next_pc(f); return 0;
int rc = write_result(f, &nv);
kvlangXvalueFree(&nv); free(nb); free_inputs(in, n);
return rc;
}

int kvlangBuiltinXvReshape(kvlangFrame_t *f) {
int ndims = f->inst->nr - 1;
if (ndims < 1) return set_err(f, "TypeError: xv.reshape requires array and >=1 dims");
if (f->inst->nw == 0) return set_err(f, "TypeError: xv.reshape requires a write param (-> a)");
kvlangXvalue_t in[MAX_PARAMS]; int n = read_inputs(f, in, MAX_PARAMS);
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); }
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++) {
dims[i] = (int32_t)kvlangXvalueAsInt64(&in[i + 1]);
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]);
free_inputs(in, n);
return rc;
}

int kvlangBuiltinScatter(kvlangFrame_t *f) {
Expand DownExpand Up@@ -1001,9 +1032,10 @@ int kvlangBuiltinCompact(kvlangFrame_t *f) {

int kvlangBuiltinAppend(kvlangFrame_t *f) {
if (f->inst->nr < 2) return set_err(f, "TypeError: array.append requires array and element");
if (f->inst->nw == 0) return set_err(f, "TypeError: array.append requires a write param (-> arr)");
kvlangXvalue_t in[2]; int n = read_inputs(f, in, 2);
char *fr = kvlangKeytreeFrameRoot(f->pc);
char *base = kvlangBuiltinResolveWriteSlot(f->kv, fr, f->inst->reads[0].name);
char *base = kvlangBuiltinResolveWriteSlot(f->kv, fr, f->inst->writes[0].name);
ensure_scattered(f, base);
int len = separated_len(f->kv, base);
kvlangStrbuf_t k; kvlangStrbufInit(&k); kvlangStrbufPrintf(&k, "%s[%d]", base, len);
Expand All@@ -1015,9 +1047,10 @@ int kvlangBuiltinAppend(kvlangFrame_t *f) {

int kvlangBuiltinSlice(kvlangFrame_t *f) {
if (f->inst->nr < 3) return set_err(f, "TypeError: array.slice requires array, start, end");
if (f->inst->nw == 0) return set_err(f, "TypeError: array.slice requires a write param (-> arr)");
kvlangXvalue_t in[3]; int n = read_inputs(f, in, 3);
char *fr = kvlangKeytreeFrameRoot(f->pc);
char *base = kvlangBuiltinResolveWriteSlot(f->kv, fr, f->inst->reads[0].name);
char *base = kvlangBuiltinResolveWriteSlot(f->kv, fr, f->inst->writes[0].name);
ensure_scattered(f, base);
int al = separated_len(f->kv, base);
int lo = (int)kvlangXvalueAsInt64(&in[1]), hi = (int)kvlangXvalueAsInt64(&in[2]);
Expand Down
1 change: 1 addition & 0 deletions runtime/src/runtime_internal.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -87,6 +87,7 @@ extern int kvspaceNewFloat64(double v, uint8_t **out, uint32_t *out_len);

#define MAX_PARAMS 128
#define MAX_STACK_DEPTH 256
#define X_MAX_NDIM 8

/* ── 基础类型 ──────────────────────────────────────────────────────── */

Expand Down
2 changes: 1 addition & 1 deletion tutorial/04-ndarray/xv_shape.kv
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,7 +12,7 @@ rwfunc main() -> () {
println("shape0=", s[0])
xv.at(a, 1) -> e
println("at1=", e)
xv.set(a, 1, 99)
xv.set(a, 1, 99) -> a
println("set1=", a[1])
}
main()
Loading