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
38 changes: 1 addition & 37 deletions layout/src/builtin.rs
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
//! builtin 辅助(对齐 rwir/builtin 中 lower/layout 依赖的部分:
//! NumOp/IsNumKind/WiderNumKind/OpKind/TryParseNumber/IsNativeRwir/IsGlobalRwir)。
//! NumOp/IsNumKind/WiderNumKind/OpKind/TryParseNumber)。

use super::ffi;

Expand DownExpand Up@@ -149,39 +149,3 @@ pub fn try_parse_number(s: &str) -> Option<Vec<u8>> {
}
None
}

// ── native / global rwir 判定(layout 命名空间用) ───────────────────

/// VM 原生 rwir 中不带 `.` 的 opcode(带 `.` 的由 MemberSep 检查兜底)。
fn native_rwir_set() -> &'static [&'static str] {
&[
// 单字 builtin
"array", "obj", "map", "debugger",
// cast kind
"bool", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64",
"float32", "float64", "char/utf8", "char/ascii", "char/utf32",
// 数值 op word + glyph
"add", "+", "sub", "-", "mul", "×", "div", "÷", "mod", "%",
"eq", "==", "neq", "!=", "≠", "lt", "<", "gt", ">", "le", "<=", "≤", "ge", ">=", "≥",
"and", "&&", "or", "||", "not", "!",
"bitand", "&", "bitor", "|", "bitxor", "^", "shl", "<<", "shr", ">>",
"sqrt", "√", "neg", "abs", "sign", "max", "min", "pow", "exp", "log",
// kv.* 树操作
"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.reshape",
]
}

pub fn is_native_rwir(opcode: &str) -> bool {
native_rwir_set().contains(&opcode)
}

fn global_rwir_set() -> &'static [&'static str] {
&["print", "println", "cerr", "input", "json.to", "json.from"]
}

pub fn is_global_rwir(opcode: &str) -> bool {
global_rwir_set().contains(&opcode)
}
42 changes: 24 additions & 18 deletions layout/src/code.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,11 +30,23 @@ pub fn compile(kv: &mut Kv, src: &str) -> Result<(), String> {
return Err("parse: error-level diagnostics — refusing to load".to_string());
}

// 用户函数名 → 有效包名。layout 只对这些名字加包前缀(正向识别用户函数),
// 其余 opcode(native / 扩展 rwir)原样落盘,由 runtime 查 /lib/<op> 的 XValue kind 判定。
let mut user_pkg: HashMap<String, String> = HashMap::new();
for func in &file.funcs {
let p = if func.pkg.is_empty() { file.package.clone() } else { func.pkg.clone() };
user_pkg.insert(func.sig.name.clone(), p);
}
for decl in &file.rwir_decls {
let p = if decl.pkg.is_empty() { file.package.clone() } else { decl.pkg.clone() };
user_pkg.insert(decl.sig.name.clone(), p);
}

let mut any_code = false;
for func in &file.funcs {
let pkg = if func.pkg.is_empty() { file.package.clone() } else { func.pkg.clone() };
let mut lowered = lower::lower_func(func);
write_func(kv, &pkg, &mut lowered);
write_func(kv, &pkg, &mut lowered, &user_pkg);
any_code = true;
}
for decl in &file.rwir_decls {
Expand All@@ -53,7 +65,7 @@ pub fn compile(kv: &mut Kv, src: &str) -> Result<(), String> {
pkg: String::new(),
};
let mut lowered = lower::lower_func(&init_fn);
write_func(kv, "", &mut lowered);
write_func(kv, "", &mut lowered, &user_pkg);
any_code = true;
}

Expand DownExpand Up@@ -100,7 +112,7 @@ pub fn vet(src: &str) -> Result<(), String> {
}

/// 写函数到 /lib/:签名(rwfunc)、源码、参数 Ptr、指令体。
pub fn write_func(kv: &mut Kv, pkg: &str, fn_: &mut Func) {
pub fn write_func(kv: &mut Kv, pkg: &str, fn_: &mut Func, user_pkg: &HashMap<String, String>) {
let mut type_map = lower::infer_types(fn_);
lower::specialize(fn_, &type_map);
let func_dir = keytree::lib_func(pkg, &fn_.sig.name);
Expand DownExpand Up@@ -133,7 +145,7 @@ pub fn write_func(kv: &mut Kv, pkg: &str, fn_: &mut Func) {
}
let _ = kv.set(&pairs);

write_body(kv, pkg, &fn_.sig.name, &fn_.body, &mut type_map, 1);
write_body(kv, pkg, &fn_.sig.name, &fn_.body, &mut type_map, 1, user_pkg);
}

/// 写用户声明的 rwir(无体)到 /lib/<opcode>。
Expand All@@ -147,11 +159,11 @@ pub fn write_rwir_decl(kv: &mut Kv, decl: &RwirDecl) {
}

/// 将 body 写入 /lib/<pkg>/<name>/ 下。offset 起始 idx(顶层函数=1)。
fn write_body(kv: &mut Kv, pkg: &str, name: &str, body: &[Stmt], type_map: &mut HashMap<String, String>, offset: i32) {
fn write_body(kv: &mut Kv, pkg: &str, name: &str, body: &[Stmt], type_map: &mut HashMap<String, String>, offset: i32, user_pkg: &HashMap<String, String>) {
let prefix = keytree::lib_func(pkg, name);
let mut idx = offset;
for st in body {
write_stmt(kv, st, &prefix, &mut idx, type_map, pkg);
write_stmt(kv, st, &prefix, &mut idx, type_map, pkg, user_pkg);
}
}

Expand All@@ -162,6 +174,7 @@ fn write_stmt(
idx: &mut i32,
type_map: &mut HashMap<String, String>,
pkg: &str,
user_pkg: &HashMap<String, String>,
) {
match st {
Stmt::Instruction(s) => {
Expand All@@ -173,9 +186,7 @@ fn write_stmt(
}
let (mut opcode, reads) = s.flat();
if !pkg.is_empty()
&& !builtin::is_native_rwir(&opcode)
&& !builtin::is_global_rwir(&opcode)
&& !is_control_op(&opcode)
&& user_pkg.get(&opcode).map_or(false, |p| p == pkg)
&& !opcode.contains(keytree::MEMBER_SEP)
&& !opcode.starts_with("/lib/")
&& symbol::lookup(&opcode).word != "assign"
Expand DownExpand Up@@ -207,7 +218,7 @@ fn write_stmt(
let scope_prefix = format!("{prefix}/{}", s.label);
let mut scope_idx = 0;
for child in &s.body {
write_stmt_scope(kv, child, &scope_prefix, &mut scope_idx, type_map, pkg, prefix);
write_stmt_scope(kv, child, &scope_prefix, &mut scope_idx, type_map, pkg, prefix, user_pkg);
}
}
_ => {}
Expand All@@ -222,6 +233,7 @@ fn write_stmt_scope(
type_map: &mut HashMap<String, String>,
pkg: &str,
func_prefix: &str,
user_pkg: &HashMap<String, String>,
) {
match st {
Stmt::Instruction(s) => {
Expand All@@ -233,9 +245,7 @@ fn write_stmt_scope(
}
let (mut opcode, reads) = s.flat();
if !pkg.is_empty()
&& !builtin::is_native_rwir(&opcode)
&& !builtin::is_global_rwir(&opcode)
&& !is_control_op(&opcode)
&& user_pkg.get(&opcode).map_or(false, |p| p == pkg)
&& !opcode.contains(keytree::MEMBER_SEP)
&& !opcode.starts_with("/lib/")
&& symbol::lookup(&opcode).word != "assign"
Expand DownExpand Up@@ -267,7 +277,7 @@ fn write_stmt_scope(
let child_prefix = format!("{func_prefix}/{}", s.label);
let mut child_idx = 0;
for child in &s.body {
write_stmt_scope(kv, child, &child_prefix, &mut child_idx, type_map, pkg, func_prefix);
write_stmt_scope(kv, child, &child_prefix, &mut child_idx, type_map, pkg, func_prefix, user_pkg);
}
}
_ => {}
Expand DownExpand Up@@ -304,10 +314,6 @@ fn count_direct_insts(body: &[Stmt]) -> i32 {
body.iter().filter(|st| matches!(st, Stmt::Instruction(_))).count() as i32
}

fn is_control_op(op: &str) -> bool {
matches!(op, "call" | "return" | "br" | "goto")
}

fn is_literal(s: &str) -> bool {
if s.is_empty() {
return false;
Expand Down
6 changes: 3 additions & 3 deletions layout/src/type_expr.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -17,7 +17,7 @@ fn known_kind(k: &str) -> bool {
"bool" | "int8" | "int16" | "int32" | "int64" | "uint8" | "uint16" | "uint32" | "uint64"
| "float32" | "float64" | "char/utf32" | "char/utf8" | "char/ascii" | "objindex"
| "strkeymapindex" | "index" | "extindex" | "rwir" | "rwfunc" | "scope" | "time"
| "duration" | "json"
| "duration"
)
}

Expand DownExpand Up@@ -132,11 +132,11 @@ mod tests {
fn valid() {
for e in [
"int64", "uint8", "float32", "bool", "any",
"char/utf8", "char/utf32", "char/ascii", "objindex", "strkeymapindex", "json", "index",
"char/utf8", "char/utf32", "char/ascii", "objindex", "strkeymapindex", "index",
"[]float32", "[2]float32", "[2,3]float32", "[2,3,4]float64",
"[?,768]float32", "[?,?]int8",
"int64|float64", "[2,3]float32|float32", "[]float32|[]float64",
"bool|char/utf8", "index|objindex", "json|strkeymapindex",
"bool|char/utf8", "index|objindex",
"any...", "int64|float64...", "[]float32...",
] {
assert!(valid_type_expr(e), "{e} should be valid");
Expand Down
31 changes: 31 additions & 0 deletions runtime-rwirext_example/go/json/edge_test.go
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
package json

import (
"encoding/json"
"fmt"
"testing"
)

func TestEdgeKeys(t *testing.T) {
c := rtConn(t)
defer disconnect(c)
cases := []string{
`{"a.b":1}`, // 点号 key(应拒绝)
`{"a/b":1}`, // 斜杠 key(应拒绝)
`{"a[b]":1}`, // 方括号 key(应拒绝)
`{"a\nb":1}`, // 换行 key(应拒绝)
`{"0":"zero","1":"one"}`, // 数字字符串 key(合法)
`{"":1}`, // 空 key(应拒绝)
`{"a":"v.b/c\nx"}`, // 值含特殊字符(应允许)
}
for i, in := range cases {
root := "/rt/edge" + fmt.Sprint(i)
err := writeMap(c, root, fromJSON([]byte(in)))
status := "OK "
if err != nil {
status = "REJ "
}
out, _ := json.Marshal(buildMap(c, root))
fmt.Printf("[%s] in: %s\n err: %v\n out: %s\n", status, in, err, out)
}
}
Loading
Loading