From 0644f199024e12fea47d402dfc4c9e568d122683 Mon Sep 17 00:00:00 2001 From: "peng.li24" <734991033@qq.com> Date: Mon, 17 Aug 2026 18:18:14 +0000 Subject: [PATCH] =?UTF-8?q?refactor:=20Go=20=E5=BD=92=E6=A1=A3=20oldhero/?= =?UTF-8?q?=EF=BC=8Crwirext=20=E6=8B=86=20go/py/rust=EF=BC=8Cruntime=20?= =?UTF-8?q?=E5=88=87=20CMake?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Go 实现整体移入 oldhero/(ast/cmd/keytree/kvcpu/logx/lower/parser/rwir/rwirext/stdlib/symbol/vthread/go.mod)。 - runtime-rwirext 拆为 go/json、py/numpy、rust/term 三语言。 - runtime 从 Makefile 切 CMake(KVSPACE_LIB 选后端,产物输出 bin/)。 - 根 Makefile 统一编排 runtime/term/run/layout/json/oldhero/all/clean。 - layout/build.rs 依赖路径从 CARGO_MANIFEST_DIR 推导,去 hardcode。 - 新增 .clang-format(LLVM),.gitignore 加 /bin/。 - 子模块 deepx-design 指针更新。 Co-Authored-By: Claude --- .gitignore | 2 + CMakeLists.txt | 48 -- Makefile | 49 +- cmd/kvlang/main.cppx | 26 - deepx-design | 2 +- keytree/const.h | 42 -- keytree/dev.h | 11 - keytree/entry.h | 10 - keytree/frame.h | 13 - keytree/keytree_stub.cppx | 1 - keytree/member.h | 10 - keytree/sys.h | 11 - keytree/vthread.h | 11 - kvcpu/cpu.h | 35 -- kvcpu/kvcpu_stub.cppx | 181 ------- layout/build.rs | 18 +- logx/logx.h | 33 -- logx/logx_stub.cppx | 1 - {ast => oldhero/ast}/ast.go | 4 +- {ast => oldhero/ast}/astfile.go | 0 {ast => oldhero/ast}/dump.go | 0 {ast => oldhero/ast}/escape.go | 0 {ast => oldhero/ast}/format.go | 0 {cmd => oldhero/cmd}/kvlang/format.go | 6 +- {cmd => oldhero/cmd}/kvlang/help.go | 0 {cmd => oldhero/cmd}/kvlang/input.go | 0 {cmd => oldhero/cmd}/kvlang/layout.go | 10 +- {cmd => oldhero/cmd}/kvlang/layoutandrun.go | 12 +- {cmd => oldhero/cmd}/kvlang/main.go | 0 {cmd => oldhero/cmd}/kvlang/ps.go | 4 +- {cmd => oldhero/cmd}/kvlang/run.go | 14 +- {cmd => oldhero/cmd}/kvlang/stdlib.go | 16 +- {cmd => oldhero/cmd}/kvlang/util.go | 0 {cmd => oldhero/cmd}/kvlang/vet.go | 8 +- go.mod => oldhero/go.mod | 4 +- go.sum => oldhero/go.sum | 0 .../hardcode_check.py | 2 +- {keytree => oldhero/keytree}/const.go | 0 {keytree => oldhero/keytree}/entry.go | 0 {keytree => oldhero/keytree}/frame.go | 0 {keytree => oldhero/keytree}/member.go | 0 {keytree => oldhero/keytree}/sys.go | 0 {keytree => oldhero/keytree}/vthread.go | 0 {kvcpu => oldhero/kvcpu}/controlflow.go | 12 +- {kvcpu => oldhero/kvcpu}/cpu.go | 0 {kvcpu => oldhero/kvcpu}/debug.go | 4 +- {kvcpu => oldhero/kvcpu}/execute.go | 14 +- {kvcpu => oldhero/kvcpu}/sched.go | 0 {layout => oldhero/layout}/layout.go | 16 +- {logx => oldhero/logx}/logx.go | 2 +- {lower => oldhero/lower}/infer.go | 6 +- {lower => oldhero/lower}/lower.go | 4 +- {lower => oldhero/lower}/specialize.go | 6 +- {parser => oldhero/parser}/inst.go | 6 +- {parser => oldhero/parser}/parser.go | 6 +- {parser => oldhero/parser}/scanner.go | 2 +- {parser => oldhero/parser}/stmt.go | 2 +- {rwir => oldhero/rwir}/builtin/arith.go | 4 +- {rwir => oldhero/rwir}/builtin/array.go | 6 +- {rwir => oldhero/rwir}/builtin/bit.go | 4 +- {rwir => oldhero/rwir}/builtin/call.go | 2 +- {rwir => oldhero/rwir}/builtin/cast.go | 4 +- {rwir => oldhero/rwir}/builtin/cmp.go | 4 +- {rwir => oldhero/rwir}/builtin/coerce.go | 0 {rwir => oldhero/rwir}/builtin/debugger.go | 6 +- {rwir => oldhero/rwir}/builtin/dict.go | 6 +- {rwir => oldhero/rwir}/builtin/helper.go | 6 +- {rwir => oldhero/rwir}/builtin/kvop.go | 6 +- {rwir => oldhero/rwir}/builtin/logic.go | 4 +- {rwir => oldhero/rwir}/builtin/math.go | 4 +- {rwir => oldhero/rwir}/builtin/num.go | 0 .../rwir}/builtin/random/random.go | 0 {rwir => oldhero/rwir}/builtin/random_op.go | 6 +- {rwir => oldhero/rwir}/builtin/resolve.go | 4 +- {rwir => oldhero/rwir}/builtin/rwirs.go | 4 +- {rwir => oldhero/rwir}/builtin/string.go | 8 +- {rwir => oldhero/rwir}/builtin/time.go | 4 +- {rwir => oldhero/rwir}/builtin/utf8/utf8.go | 0 {rwir => oldhero/rwir}/control.go | 0 {rwir => oldhero/rwir}/ext/ext.go | 6 +- {rwir => oldhero/rwir}/frame.go | 0 {rwir => oldhero/rwir}/pc.go | 0 {rwir => oldhero/rwir}/rwir.go | 0 {rwirext => oldhero/rwirext}/term/cmd/main.go | 2 +- {rwirext => oldhero/rwirext}/term/file.go | 0 {rwirext => oldhero/rwirext}/term/serve.go | 8 +- {stdlib => oldhero/stdlib}/embed.go | 0 {stdlib => oldhero/stdlib}/math.kv | 0 {symbol => oldhero/symbol}/symbol.go | 0 {vthread => oldhero/vthread}/vthread.go | 2 +- runtime-rwirext/build.rs | 8 - .../go}/json/cmd/main.go | 9 +- runtime-rwirext/go/json/go.mod | 3 + runtime-rwirext/go/json/json.go | 491 ++++++++++++++++++ runtime-rwirext/py/numpy/numpy_ext.py | 140 +++++ runtime-rwirext/py/numpy/numpy_rwext.py | 93 ++++ runtime-rwirext/py/numpy/test.kv | 10 + runtime-rwirext/py/numpy/test_numpy.py | 60 +++ runtime-rwirext/{ => rust/term}/.gitignore | 0 runtime-rwirext/{ => rust/term}/Cargo.lock | 0 runtime-rwirext/{ => rust/term}/Cargo.toml | 5 +- runtime-rwirext/{ => rust/term}/Makefile | 0 runtime-rwirext/rust/term/build.rs | 8 + .../{src/lib.rs => rust/term/src/main.rs} | 17 +- runtime/.clang-format | 1 + runtime/CMakeLists.txt | 49 ++ runtime/Makefile | 31 -- runtime/include/kvlang_rwext.h | 19 + runtime/src/rwext.c | 82 +++ runtime/test/main.c | 7 - rwir/builtin/builtin.h | 35 -- rwir/builtin/rwir_builtin_stub.cppx | 1 - rwir/control.h | 18 - rwir/frame.h | 12 - rwir/instruction.h | 41 -- rwir/pc.h | 19 - rwir/rwir_stub.cppx | 1 - rwir/tensor.h | 17 - rwirext/json/json.go | 255 --------- vthread/vthread.h | 54 -- vthread/vthread_stub.cppx | 1 - 121 files changed, 1149 insertions(+), 1102 deletions(-) delete mode 100644 CMakeLists.txt delete mode 100644 cmd/kvlang/main.cppx delete mode 100644 keytree/const.h delete mode 100644 keytree/dev.h delete mode 100644 keytree/entry.h delete mode 100644 keytree/frame.h delete mode 100644 keytree/keytree_stub.cppx delete mode 100644 keytree/member.h delete mode 100644 keytree/sys.h delete mode 100644 keytree/vthread.h delete mode 100644 kvcpu/cpu.h delete mode 100644 kvcpu/kvcpu_stub.cppx delete mode 100644 logx/logx.h delete mode 100644 logx/logx_stub.cppx rename {ast => oldhero/ast}/ast.go (99%) rename {ast => oldhero/ast}/astfile.go (100%) rename {ast => oldhero/ast}/dump.go (100%) rename {ast => oldhero/ast}/escape.go (100%) rename {ast => oldhero/ast}/format.go (100%) rename {cmd => oldhero/cmd}/kvlang/format.go (96%) rename {cmd => oldhero/cmd}/kvlang/help.go (100%) rename {cmd => oldhero/cmd}/kvlang/input.go (100%) rename {cmd => oldhero/cmd}/kvlang/layout.go (97%) rename {cmd => oldhero/cmd}/kvlang/layoutandrun.go (95%) rename {cmd => oldhero/cmd}/kvlang/main.go (100%) rename {cmd => oldhero/cmd}/kvlang/ps.go (96%) rename {cmd => oldhero/cmd}/kvlang/run.go (95%) rename {cmd => oldhero/cmd}/kvlang/stdlib.go (93%) rename {cmd => oldhero/cmd}/kvlang/util.go (100%) rename {cmd => oldhero/cmd}/kvlang/vet.go (95%) rename go.mod => oldhero/go.mod (75%) rename go.sum => oldhero/go.sum (100%) rename hardcode_check.py => oldhero/hardcode_check.py (98%) rename {keytree => oldhero/keytree}/const.go (100%) rename {keytree => oldhero/keytree}/entry.go (100%) rename {keytree => oldhero/keytree}/frame.go (100%) rename {keytree => oldhero/keytree}/member.go (100%) rename {keytree => oldhero/keytree}/sys.go (100%) rename {keytree => oldhero/keytree}/vthread.go (100%) rename {kvcpu => oldhero/kvcpu}/controlflow.go (95%) rename {kvcpu => oldhero/kvcpu}/cpu.go (100%) rename {kvcpu => oldhero/kvcpu}/debug.go (98%) rename {kvcpu => oldhero/kvcpu}/execute.go (98%) rename {kvcpu => oldhero/kvcpu}/sched.go (100%) rename {layout => oldhero/layout}/layout.go (99%) rename {logx => oldhero/logx}/logx.go (99%) rename {lower => oldhero/lower}/infer.go (99%) rename {lower => oldhero/lower}/lower.go (99%) rename {lower => oldhero/lower}/specialize.go (96%) rename {parser => oldhero/parser}/inst.go (99%) rename {parser => oldhero/parser}/parser.go (99%) rename {parser => oldhero/parser}/scanner.go (99%) rename {parser => oldhero/parser}/stmt.go (99%) rename {rwir => oldhero/rwir}/builtin/arith.go (99%) rename {rwir => oldhero/rwir}/builtin/array.go (99%) rename {rwir => oldhero/rwir}/builtin/bit.go (97%) rename {rwir => oldhero/rwir}/builtin/call.go (97%) rename {rwir => oldhero/rwir}/builtin/cast.go (99%) rename {rwir => oldhero/rwir}/builtin/cmp.go (99%) rename {rwir => oldhero/rwir}/builtin/coerce.go (100%) rename {rwir => oldhero/rwir}/builtin/debugger.go (96%) rename {rwir => oldhero/rwir}/builtin/dict.go (95%) rename {rwir => oldhero/rwir}/builtin/helper.go (98%) rename {rwir => oldhero/rwir}/builtin/kvop.go (97%) rename {rwir => oldhero/rwir}/builtin/logic.go (97%) rename {rwir => oldhero/rwir}/builtin/math.go (99%) rename {rwir => oldhero/rwir}/builtin/num.go (100%) rename {rwir => oldhero/rwir}/builtin/random/random.go (100%) rename {rwir => oldhero/rwir}/builtin/random_op.go (92%) rename {rwir => oldhero/rwir}/builtin/resolve.go (98%) rename {rwir => oldhero/rwir}/builtin/rwirs.go (98%) rename {rwir => oldhero/rwir}/builtin/string.go (99%) rename {rwir => oldhero/rwir}/builtin/time.go (99%) rename {rwir => oldhero/rwir}/builtin/utf8/utf8.go (100%) rename {rwir => oldhero/rwir}/control.go (100%) rename {rwir => oldhero/rwir}/ext/ext.go (97%) rename {rwir => oldhero/rwir}/frame.go (100%) rename {rwir => oldhero/rwir}/pc.go (100%) rename {rwir => oldhero/rwir}/rwir.go (100%) rename {rwirext => oldhero/rwirext}/term/cmd/main.go (93%) rename {rwirext => oldhero/rwirext}/term/file.go (100%) rename {rwirext => oldhero/rwirext}/term/serve.go (97%) rename {stdlib => oldhero/stdlib}/embed.go (100%) rename {stdlib => oldhero/stdlib}/math.kv (100%) rename {symbol => oldhero/symbol}/symbol.go (100%) rename {vthread => oldhero/vthread}/vthread.go (99%) delete mode 100644 runtime-rwirext/build.rs rename {rwirext => runtime-rwirext/go}/json/cmd/main.go (58%) create mode 100644 runtime-rwirext/go/json/go.mod create mode 100644 runtime-rwirext/go/json/json.go create mode 100644 runtime-rwirext/py/numpy/numpy_ext.py create mode 100644 runtime-rwirext/py/numpy/numpy_rwext.py create mode 100644 runtime-rwirext/py/numpy/test.kv create mode 100644 runtime-rwirext/py/numpy/test_numpy.py rename runtime-rwirext/{ => rust/term}/.gitignore (100%) rename runtime-rwirext/{ => rust/term}/Cargo.lock (100%) rename runtime-rwirext/{ => rust/term}/Cargo.toml (70%) rename runtime-rwirext/{ => rust/term}/Makefile (100%) create mode 100644 runtime-rwirext/rust/term/build.rs rename runtime-rwirext/{src/lib.rs => rust/term/src/main.rs} (90%) create mode 100644 runtime/.clang-format create mode 100644 runtime/CMakeLists.txt delete mode 100644 runtime/Makefile delete mode 100644 rwir/builtin/builtin.h delete mode 100644 rwir/builtin/rwir_builtin_stub.cppx delete mode 100644 rwir/control.h delete mode 100644 rwir/frame.h delete mode 100644 rwir/instruction.h delete mode 100644 rwir/pc.h delete mode 100644 rwir/rwir_stub.cppx delete mode 100644 rwir/tensor.h delete mode 100644 rwirext/json/json.go delete mode 100644 vthread/vthread.h delete mode 100644 vthread/vthread_stub.cppx diff --git a/.gitignore b/.gitignore index 6e26fcc6..75153e2b 100644 --- a/.gitignore +++ b/.gitignore @@ -57,3 +57,5 @@ appendonly.aof *.kvfail *.kv.skip tutorial/test_failures.csv + +/bin/ diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index b8ab2c4e..00000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,48 +0,0 @@ -cmake_minimum_required(VERSION 3.20) -project(kvlang VERSION 0.1.0 LANGUAGES CXX) - -# ── C++ standard ───────────────────────────────────── -set(CMAKE_CXX_STANDARD 23) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) -# .cppx = 避开 Go 编译器的 C++ 源文件(Go 在包目录看到 .cpp 会走 CGo) -set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS cpp;cxx;cc;cppx) - -# ── Compiler warnings ──────────────────────────────── -if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") - add_compile_options(-Wall -Wextra -Wpedantic -Werror) -elseif(MSVC) - add_compile_options(/W4 /WX) -endif() - -# ── kvlang library (C++ runtime) ───────────────────── -# C++ only implements the runtime: read from kvspace → kvcpu execute. -# Go handles the toolchain (parse/lower/layout). - -file(GLOB_RECURSE KV_SOURCES - "device/*.cppx" - "keytree/*.cppx" - "kvcpu/*.cppx" - "logx/*.cppx" - "op/*.cppx" - "op/builtin/*.cppx" - "op/dispatch/*.cppx" - "vthread/*.cppx" - "vtype/*.cppx" -) - -add_library(kvlang_lib ${KV_SOURCES}) - -# All module directories are include paths (headers use #include "module/file.h") -target_include_directories(kvlang_lib PUBLIC ${CMAKE_SOURCE_DIR}) - -# ── CLI executable ─────────────────────────────────── -add_executable(kvlang cmd/kvlang/main.cppx) -target_link_libraries(kvlang PRIVATE kvlang_lib) - -# ── Tests (optional) ───────────────────────────────── -option(BUILD_TESTS "Build tests" OFF) -if(BUILD_TESTS) - enable_testing() - # add_subdirectory(tests) -endif() diff --git a/Makefile b/Makefile index f374e7a9..1bb75831 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,42 @@ -.PHONY: build test vet clean kvspace install +# kvlang 统一构建:产物全部输出到 bin/,各组件独立编译。 +# make runtime C runtime 库(libkvlang_runtime.so,经 CMake) +# make term Rust term 扩展(term 可执行文件,独立进程) +# make run 测试执行器(run,链接 runtime) +# make layout Rust layout(layout_file) +# make json Go json 扩展(json-rwirext 可执行文件) +# make oldhero Go 旧 runtime(kvlang,兼容保留) +# make all 全部 +# make clean 清理 bin/ 与各构建目录 -export GOPROXY ?= https://goproxy.cn,direct -PREFIX ?= ~/.local +BIN := bin +KVSPACE_LIB ?= kvspace-c -build: - go mod tidy - go build -ldflags="-s -w" -o kvlang ./cmd/kvlang/ - install -d $(PREFIX)/bin - install kvlang $(PREFIX)/bin/kvlang +.PHONY: all runtime term run layout json oldhero clean -vet: - go vet ./... +all: runtime term run layout json + +runtime: + cmake -S runtime -B build/runtime -DCMAKE_BUILD_TYPE=Release -DKVSPACE_LIB=$(KVSPACE_LIB) + cmake --build build/runtime --target kvlang_runtime -j + +term: + cargo build --release --manifest-path runtime-rwirext/rust/term/Cargo.toml + cp runtime-rwirext/rust/term/target/release/term $(BIN)/ + +run: runtime + cmake --build build/runtime --target run -j + +layout: + KVLANG_KVSPACE_LIB=$(KVSPACE_LIB) cargo build --release --manifest-path layout/Cargo.toml --example layout_file + cp layout/target/release/examples/layout_file $(BIN)/ + +json: + cd runtime-rwirext/go/json && go build -o ../../../bin/json-rwirext ./cmd/ + +oldhero: + cd oldhero && go build -ldflags="-s -w" -o ../bin/kvlang ./cmd/kvlang/ clean: - go clean - rm -f kvlang + rm -rf $(BIN) build + cargo clean --manifest-path layout/Cargo.toml + cargo clean --manifest-path runtime-rwirext/rust/term/Cargo.toml diff --git a/cmd/kvlang/main.cppx b/cmd/kvlang/main.cppx deleted file mode 100644 index 73714fe6..00000000 --- a/cmd/kvlang/main.cppx +++ /dev/null @@ -1,26 +0,0 @@ -// kvlang C++ CLI — entry point for "run" command. -// -// Usage: kvlang run -// -// This is the C++ counterpart to cmd/kvlang/main.go (Go toolchain CLI) -// and cmd/kvlang/main.rs (Rust runtime CLI). - -#include -#include - -int main(int argc, char* argv[]) { - if (argc < 2) { - std::cerr << "usage: kvlang run \n"; - return 1; - } - - std::string_view cmd = argv[1]; - if (cmd == "run") { - // TODO: parse → lower → layout → execute - std::cout << "[cpp] run: not yet implemented\n"; - return 0; - } - - std::cerr << "unknown command: " << cmd << "\n"; - return 1; -} diff --git a/deepx-design b/deepx-design index 81641980..93c7d4ec 160000 --- a/deepx-design +++ b/deepx-design @@ -1 +1 @@ -Subproject commit 816419809687034050b67375688c7f30137baf31 +Subproject commit 93c7d4eca430ca8a73d3032e53f3ba634725ea03 diff --git a/keytree/const.h b/keytree/const.h deleted file mode 100644 index 5a950640..00000000 --- a/keytree/const.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once -#include -#include - -// KV path constants — single source of truth for all KV tree paths. -// Keep in sync with keytree/const.go, keytree/const.rs. - -namespace kvlang::keytree { - -// ── /sys ────────────────────────────────────────── -inline constexpr std::string_view SysRoot = "/sys"; -inline constexpr std::string_view SysVM = "/sys/vm"; -inline constexpr std::string_view SysVT = "/sys/vthread"; -inline constexpr std::string_view SysLib = "/sys/lib"; - -// ── /lib ────────────────────────────────────────── -inline constexpr std::string_view LibRoot = "/lib"; - -// ── /vthread ────────────────────────────────────── -inline constexpr std::string_view VTRoot = "/vthread"; - -// ── Frame keys ──────────────────────────────────── -inline constexpr std::string_view FramePC = ".pc"; -inline constexpr std::string_view FrameStatus = ".status"; -inline constexpr std::string_view FrameRetVal = ".retval"; -inline constexpr std::string_view FrameErr = ".err"; -inline constexpr std::string_view FrameDebug = ".debugger"; -inline constexpr std::string_view FrameX = ".x"; // local variable prefix -inline constexpr std::string_view FrameRParam = ".rparam"; // read params -inline constexpr std::string_view FrameWParam = ".wparam"; // write params - -// Path builder helpers -std::string vt_path(std::string_view vtid); -std::string vt_pc(std::string_view vtid); -std::string vt_status(std::string_view vtid); -std::string lib_func(std::string_view pkg, std::string_view name); -std::string lib_func_src(std::string_view pkg, std::string_view name); -std::string frame_local(std::string_view frame_root, std::string_view slot); -std::string frame_rparam(std::string_view frame_root, std::string_view name); -std::string frame_wparam(std::string_view frame_root, std::string_view name); - -} // namespace kvlang::keytree diff --git a/keytree/dev.h b/keytree/dev.h deleted file mode 100644 index 0d976146..00000000 --- a/keytree/dev.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once -#include -#include - -namespace kvlang::keytree { - -// Device paths -std::string dev_terminal(std::string_view vm_id); -std::string dev_ws(std::string_view vm_id); - -} // namespace kvlang::keytree diff --git a/keytree/entry.h b/keytree/entry.h deleted file mode 100644 index 76dcc434..00000000 --- a/keytree/entry.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once -#include -#include - -namespace kvlang::keytree { - -// Entry point paths -std::string entry_main(std::string_view pkg); - -} // namespace kvlang::keytree diff --git a/keytree/frame.h b/keytree/frame.h deleted file mode 100644 index f75bf653..00000000 --- a/keytree/frame.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include -#include -#include - -namespace kvlang::keytree { - -// Frame coordinate encoding -std::string frame_coord(int row, int col); -std::string frame_root(std::string_view vtid); -std::string frame_link_base(std::string_view pc); - -} // namespace kvlang::keytree diff --git a/keytree/keytree_stub.cppx b/keytree/keytree_stub.cppx deleted file mode 100644 index 15719b2a..00000000 --- a/keytree/keytree_stub.cppx +++ /dev/null @@ -1 +0,0 @@ -#include "const.h" diff --git a/keytree/member.h b/keytree/member.h deleted file mode 100644 index eaa670bd..00000000 --- a/keytree/member.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once -#include -#include - -namespace kvlang::keytree { - -// Member access paths within frames -std::string member_path(std::string_view base, std::string_view member); - -} // namespace kvlang::keytree diff --git a/keytree/sys.h b/keytree/sys.h deleted file mode 100644 index a0305bf0..00000000 --- a/keytree/sys.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once -#include -#include - -namespace kvlang::keytree { - -// System-level paths -std::string sys_vm_error(std::string_view vm_id); -std::string sys_vt_list(); - -} // namespace kvlang::keytree diff --git a/keytree/vthread.h b/keytree/vthread.h deleted file mode 100644 index 7c872621..00000000 --- a/keytree/vthread.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once -#include -#include - -namespace kvlang::keytree { - -// VThread paths -std::string vthread_root(std::string_view vtid); -std::string vthread_call(std::string_view vtid, int depth); - -} // namespace kvlang::keytree diff --git a/kvcpu/cpu.h b/kvcpu/cpu.h deleted file mode 100644 index adf83cf7..00000000 --- a/kvcpu/cpu.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once -#include -#include -#include - -// KV Virtual CPU — identical API to kvcpu/cpu.go and kvcpu/cpu.rs. -// -// Usage: -// auto cpu = kvlang::kvcpu::CPU::create(kv, vm_id); -// cpu->execute(pc); - -namespace kvlang::kvcpu { - -class KVSpace; // forward decl (kvspace-cpp) - -// ── CPU interface ──────────────────────────────────── - -class CPU { -public: - virtual ~CPU() = default; - - // Fetch-Decode-Execute loop starting at pc. - virtual void execute(std::string_view pc) = 0; - - // Step one instruction (for debugging). - virtual void step(std::string_view pc) = 0; - - // Check if debugger is active for the current vthread. - [[nodiscard]] virtual bool debugger_active() const = 0; -}; - -// Factory -std::unique_ptr create_cpu(KVSpace& kv, std::string_view vm_id); - -} // namespace kvlang::kvcpu diff --git a/kvcpu/kvcpu_stub.cppx b/kvcpu/kvcpu_stub.cppx deleted file mode 100644 index ac8093cc..00000000 --- a/kvcpu/kvcpu_stub.cppx +++ /dev/null @@ -1,181 +0,0 @@ -// kvlang::kvcpu — C++ virtual CPU implementation -// Links against libkvspace-c.so. Mounts SHM that Go layout wrote. -#include "cpu.h" -#include -#include -#include -#include -#include -#include -#include -#include - -namespace kvlang::kvcpu { - -// ── KVSpace thin wrapper ──────────────────────────────────────────────────── -class KVSpace { - kvspace_t *kv; -public: - KVSpace(kvspace_t *k) : kv(k) {} - xvalue_head_t get(std::string_view key) { - int32_t len; uint8_t *d = kvspace_get(kv, key.data(), 1, &len); - if (!d) return {}; - auto h = xvalue_decode_head(d, len); free(d); return h; - } - void set(std::string_view key, const char *kind, const uint8_t *raw, int32_t rl) { - int32_t kl = strlen(kind); - int32_t tl = 1 + kl + 8 + rl; - auto buf = std::make_unique(tl); - buf[0] = kl; memcpy(&buf[1], kind, kl); - int32_t al = 1; - memcpy(&buf[1+kl], &al, 4); memcpy(&buf[1+kl+4], &rl, 4); - memcpy(&buf[1+kl+8], raw, rl); - kvspace_set(kv, key.data(), buf.get(), tl); - } - void setStr(std::string_view key, std::string_view val) { - set(key, "string", (const uint8_t *)val.data(), val.size()); - } - static void close(kvspace_t *k) { kvspace_close(k); } -}; - -// ── Instruction ───────────────────────────────────────────────────────────── -struct Inst { - std::string opcode; - std::vector> reads, writes; // (name, raw_val) -}; - -static int extractAddr0(std::string_view seg) { - auto s = seg.substr(1, seg.size() - 2); // strip [ ] - auto c = s.find(','); return c == s.npos ? 0 : std::stoi(std::string(s.substr(0, c))); -} -static std::string nextPC(std::string_view pc) { - auto lb = pc.rfind('['); - if (lb == pc.npos) return std::string(pc); - auto rb = pc.find(']', lb); - if (rb == pc.npos) return std::string(pc); - auto inner = pc.substr(lb + 1, rb - lb - 1); - auto comma = inner.find(','); - if (comma == std::string_view::npos) return std::string(pc); - int off = std::stoi(std::string(inner.substr(comma + 1))); - return std::string(pc.substr(0, lb)) + "[" + std::string(inner.substr(0, comma)) + "," + std::to_string(off + 1) + "]"; -} - -static Inst decode(KVSpace &kv, std::string_view pc) { - Inst inst; - auto last = pc.rfind("/["); - if (last == pc.npos) return inst; - int addr0 = extractAddr0(pc.substr(last + 1)); - auto prefix = pc.substr(0, last); - - // opcode: [addr0, 0] - auto opk = std::string(prefix) + "[" + std::to_string(addr0) + ",0]"; - auto op = kv.get(opk); - inst.opcode = op.kind_len > 0 ? std::string(op.kind, op.kind_len) : ""; - if (inst.opcode == "string" && op.raw_len > 0) - inst.opcode = std::string((const char *)op.raw, op.raw_len); - - // params: [addr0, -1], [-2], ... and [addr0, 1], [2], ... - for (int i = 1; i <= 128; i++) { - auto rk = std::string(prefix) + "[" + std::to_string(addr0) + ",-" + std::to_string(i) + "]"; - auto rv = kv.get(rk); - if (rv.kind_len > 0) - inst.reads.push_back({rk, std::string((const char *)rv.raw, rv.raw_len)}); - auto wk = std::string(prefix) + "[" + std::to_string(addr0) + "," + std::to_string(i) + "]"; - auto wv = kv.get(wk); - if (wv.kind_len > 0) - inst.writes.push_back({wk, std::string((const char *)wv.raw, wv.raw_len)}); - } - return inst; -} - -// ── CPU Impl ──────────────────────────────────────────────────────────────── -class CPUImpl : public CPU { - KVSpace kv; - std::string vm_id; - - std::string vtidFromPC(std::string_view pc) { - auto s = pc.substr(1); // skip / - auto v = s.find("vthread/"); - if (v == s.npos) return ""; - s = s.substr(v + 8); - auto slash = s.find('/'); - return slash == s.npos ? std::string(s) : std::string(s.substr(0, slash)); - } - - // ── native ops ─────────────────────────────────────────────────────── - int execArith(const Inst &inst, int64_t (*fn)(int64_t, int64_t)) { - if (inst.reads.size() < 2 || inst.writes.empty()) return -1; - int64_t a = 0, b = 0; - memcpy(&a, inst.reads[0].second.data(), std::min(sizeof(a), inst.reads[0].second.size())); - memcpy(&b, inst.reads[1].second.data(), std::min(sizeof(b), inst.reads[1].second.size())); - int64_t r = fn(a, b); - kv.set(inst.writes[0].first, "int64", (const uint8_t *)&r, 8); - return 0; - } - int execCmp(const Inst &inst, bool (*fn)(int64_t, int64_t)) { - if (inst.reads.size() < 2 || inst.writes.empty()) return -1; - int64_t a = 0, b = 0; - memcpy(&a, inst.reads[0].second.data(), std::min(sizeof(a), inst.reads[0].second.size())); - memcpy(&b, inst.reads[1].second.data(), std::min(sizeof(b), inst.reads[1].second.size())); - uint8_t r = fn(a, b); - kv.set(inst.writes[0].first, "bool", &r, 1); - return 0; - } - int execPrint(const Inst &inst, bool nl) { - for (auto &r : inst.reads) { printf("%s", r.second.c_str()); if (nl) printf("\n"); } - return 0; - } - -public: - CPUImpl(kvspace_t *k, std::string_view vid) : kv(k), vm_id(vid) {} - - void execute(std::string_view pc) override { - std::string cur(pc); - auto vtid = vtidFromPC(cur); - auto vt_root = "/vthread/" + vtid; - for (;;) { - auto sv = kv.get(vt_root + "/status"); - std::string status((const char *)sv.raw, sv.raw_len); - if (status == "done" || status == "error") break; - auto pv = kv.get(vt_root + "/pc"); - if (pv.kind_len == 0) break; - cur = std::string((const char *)pv.raw, pv.raw_len); - try { step(cur); } catch (...) { break; } - } - } - - void step(std::string_view pc) override { - auto vtid = vtidFromPC(pc); - auto vt_root = "/vthread/" + vtid; - auto inst = decode(kv, pc); - if (inst.opcode.empty()) { kv.setStr(vt_root + "/status", "done"); return; } - - if (inst.opcode == "add") execArith(inst, [](auto a,auto b){return a+b;}); - else if (inst.opcode == "sub") execArith(inst, [](auto a,auto b){return a-b;}); - else if (inst.opcode == "mul") execArith(inst, [](auto a,auto b){return a*b;}); - else if (inst.opcode == "div") execArith(inst, [](auto a,auto b){return b? a/b : 0;}); - else if (inst.opcode == "mod") execArith(inst, [](auto a,auto b){return b? a%b : 0;}); - else if (inst.opcode == "eq") execCmp(inst, [](auto a,auto b){return a==b;}); - else if (inst.opcode == "neq") execCmp(inst, [](auto a,auto b){return a!=b;}); - else if (inst.opcode == "lt") execCmp(inst, [](auto a,auto b){return ab;}); - else if (inst.opcode == "le") execCmp(inst, [](auto a,auto b){return a<=b;}); - else if (inst.opcode == "ge") execCmp(inst, [](auto a,auto b){return a>=b;}); - else if (inst.opcode == "print" || inst.opcode == "println") execPrint(inst, inst.opcode == "println"); - - kv.setStr(vt_root + "/pc", nextPC(pc)); - } - - bool debugger_active() const override { return false; } -}; - -// ── Factory ───────────────────────────────────────────────────────────────── -std::unique_ptr create_cpu(KVSpace &kv, std::string_view vm_id) { - (void)kv; (void)vm_id; - throw std::runtime_error("not implemented — use raw kvspace_t* overload"); -} -std::unique_ptr create_cpu(kvspace_t *kv, std::string_view vm_id) { - return std::make_unique(kv, vm_id); -} - -} // namespace kvlang::kvcpu diff --git a/layout/build.rs b/layout/build.rs index fce9492c..2883091b 100644 --- a/layout/build.rs +++ b/layout/build.rs @@ -1,17 +1,23 @@ // 链接 kvspace 动态库(cdylib)。布局侧只通过 extern "C" ABI 调用。 // 默认链接 kvspace-durable;KVLANG_KVSPACE_LIB=kvspace-c 时链接 kvspace-c(SHM,durable 兼容 ABI)。 +// 依赖路径从 CARGO_MANIFEST_DIR 推导(array2d 工作区根),不 hardcode 绝对路径。 fn main() { + println!("cargo:rerun-if-env-changed=KVLANG_KVSPACE_LIB"); let lib = std::env::var("KVLANG_KVSPACE_LIB").unwrap_or_else(|_| "kvspace_durable".into()); - let (lib_dir, extra_rpath) = if lib == "kvspace-c" { - ("/home/peng.li24/github.com/array2d/kvspace/build", true) + let root = format!("{}/../..", env!("CARGO_MANIFEST_DIR")); // array2d 工作区根 + let (lib_dir, extra) = if lib == "kvspace-c" { + (format!("{root}/kvspace/build"), true) } else { - ("/home/peng.li24/github.com/array2d/kvspace-durable/target/release", false) + (format!("{root}/kvspace-durable/target/release"), false) }; println!("cargo:rustc-link-search=native={lib_dir}"); println!("cargo:rustc-link-lib=dylib={lib}"); + // --disable-new-dtags 使 rpath 转 DT_RPATH(传递),让 kvspace-c → blockmalloc/slotsboxmalloc + // 的传递依赖能被 layout 的 rpath 找到。 println!("cargo:rustc-link-arg=-Wl,-rpath,{lib_dir}"); - if extra_rpath { - println!("cargo:rustc-link-arg=-Wl,-rpath,/home/peng.li24/github.com/array2d/blockmalloc/build"); - println!("cargo:rustc-link-arg=-Wl,-rpath,/home/peng.li24/github.com/array2d/slotsboxmalloc/build"); + println!("cargo:rustc-link-arg=-Wl,--disable-new-dtags"); + if extra { + println!("cargo:rustc-link-arg=-Wl,-rpath,{root}/blockmalloc/build"); + println!("cargo:rustc-link-arg=-Wl,-rpath,{root}/slotsboxmalloc/build"); } } diff --git a/logx/logx.h b/logx/logx.h deleted file mode 100644 index f618e265..00000000 --- a/logx/logx.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once -#include -#include -#include - -// Logging — identical API to logx/logx.go and logx/logx.rs. - -namespace kvlang::logx { - -enum class Level { debug, info, warn, error, fatal }; - -void set_level(Level lv); -Level get_level(); - -void debug(std::string_view fmt, auto&&... args) { /* TODO */ } -void info(std::string_view fmt, auto&&... args) { /* TODO */ } -void warn(std::string_view fmt, auto&&... args) { /* TODO */ } -void error(std::string_view fmt, auto&&... args) { /* TODO */ } -[[noreturn]] void fatal(std::string_view fmt, auto&&... args); - -// Diagnostic printing (from parser) -struct Diagnostic { - int line, col; - std::string message; - bool warn, info; - std::string source_line; - std::string src_file; - std::string src_name; -}; -void diag(const Diagnostic& d); -bool has_errors(const std::vector& diags); - -} // namespace kvlang::logx diff --git a/logx/logx_stub.cppx b/logx/logx_stub.cppx deleted file mode 100644 index b742dcba..00000000 --- a/logx/logx_stub.cppx +++ /dev/null @@ -1 +0,0 @@ -#include "logx.h" diff --git a/ast/ast.go b/oldhero/ast/ast.go similarity index 99% rename from ast/ast.go rename to oldhero/ast/ast.go index 7ec674c5..fe5296b2 100644 --- a/ast/ast.go +++ b/oldhero/ast/ast.go @@ -5,8 +5,8 @@ package ast import ( "strings" - "kvlang/keytree" - "kvlang/symbol" + "oldhero/keytree" + "oldhero/symbol" ) // Stmt 表示函数体中的一条语句。 diff --git a/ast/astfile.go b/oldhero/ast/astfile.go similarity index 100% rename from ast/astfile.go rename to oldhero/ast/astfile.go diff --git a/ast/dump.go b/oldhero/ast/dump.go similarity index 100% rename from ast/dump.go rename to oldhero/ast/dump.go diff --git a/ast/escape.go b/oldhero/ast/escape.go similarity index 100% rename from ast/escape.go rename to oldhero/ast/escape.go diff --git a/ast/format.go b/oldhero/ast/format.go similarity index 100% rename from ast/format.go rename to oldhero/ast/format.go diff --git a/cmd/kvlang/format.go b/oldhero/cmd/kvlang/format.go similarity index 96% rename from cmd/kvlang/format.go rename to oldhero/cmd/kvlang/format.go index 73e1ddef..de88a2b1 100644 --- a/cmd/kvlang/format.go +++ b/oldhero/cmd/kvlang/format.go @@ -6,9 +6,9 @@ import ( "os" "strings" - "kvlang/ast" - "kvlang/logx" - "kvlang/parser" + "oldhero/ast" + "oldhero/logx" + "oldhero/parser" ) func cmdFormat(args []string) { diff --git a/cmd/kvlang/help.go b/oldhero/cmd/kvlang/help.go similarity index 100% rename from cmd/kvlang/help.go rename to oldhero/cmd/kvlang/help.go diff --git a/cmd/kvlang/input.go b/oldhero/cmd/kvlang/input.go similarity index 100% rename from cmd/kvlang/input.go rename to oldhero/cmd/kvlang/input.go diff --git a/cmd/kvlang/layout.go b/oldhero/cmd/kvlang/layout.go similarity index 97% rename from cmd/kvlang/layout.go rename to oldhero/cmd/kvlang/layout.go index 587595e1..31e17d10 100644 --- a/cmd/kvlang/layout.go +++ b/oldhero/cmd/kvlang/layout.go @@ -7,12 +7,12 @@ import ( "path/filepath" "strings" - "kvlang/ast" + "oldhero/ast" "github.com/array2d/kvspace-go" - "kvlang/layout" - "kvlang/logx" - "kvlang/lower" - "kvlang/parser" + "oldhero/layout" + "oldhero/logx" + "oldhero/lower" + "oldhero/parser" ) // cmdLayout 将 .kv 文件加载进 kvspace,不执行。多文件拼接为单源解析。 diff --git a/cmd/kvlang/layoutandrun.go b/oldhero/cmd/kvlang/layoutandrun.go similarity index 95% rename from cmd/kvlang/layoutandrun.go rename to oldhero/cmd/kvlang/layoutandrun.go index a30046b3..7ebd282e 100644 --- a/cmd/kvlang/layoutandrun.go +++ b/oldhero/cmd/kvlang/layoutandrun.go @@ -4,13 +4,13 @@ import ( "io" "strings" - "kvlang/ast" - "kvlang/keytree" + "oldhero/ast" + "oldhero/keytree" "github.com/array2d/kvspace-go" - "kvlang/layout" - "kvlang/logx" - "kvlang/lower" - "kvlang/parser" + "oldhero/layout" + "oldhero/logx" + "oldhero/lower" + "oldhero/parser" ) // cmdLayoutAndRun 先 layout 再 run(fix-039:替代旧 run 机制)。 diff --git a/cmd/kvlang/main.go b/oldhero/cmd/kvlang/main.go similarity index 100% rename from cmd/kvlang/main.go rename to oldhero/cmd/kvlang/main.go diff --git a/cmd/kvlang/ps.go b/oldhero/cmd/kvlang/ps.go similarity index 96% rename from cmd/kvlang/ps.go rename to oldhero/cmd/kvlang/ps.go index 2fd05785..4f9004fc 100644 --- a/cmd/kvlang/ps.go +++ b/oldhero/cmd/kvlang/ps.go @@ -8,8 +8,8 @@ import ( "sort" "strconv" - "kvlang/keytree" - "kvlang/vthread" + "oldhero/keytree" + "oldhero/vthread" "github.com/array2d/kvspace-go" ) diff --git a/cmd/kvlang/run.go b/oldhero/cmd/kvlang/run.go similarity index 95% rename from cmd/kvlang/run.go rename to oldhero/cmd/kvlang/run.go index 799de799..bb1fd96b 100644 --- a/cmd/kvlang/run.go +++ b/oldhero/cmd/kvlang/run.go @@ -8,14 +8,14 @@ import ( "strings" "time" - "kvlang/rwirext/term" - "kvlang/keytree" - "kvlang/kvcpu" + "oldhero/rwirext/term" + "oldhero/keytree" + "oldhero/kvcpu" "github.com/array2d/kvspace-go" - "kvlang/layout" - "kvlang/rwir/builtin" - "kvlang/logx" - "kvlang/vthread" + "oldhero/layout" + "oldhero/rwir/builtin" + "oldhero/logx" + "oldhero/vthread" ) // cmdRun 解析参数并路由:内联 / {lib}.{func} / 文件 / 管道。 diff --git a/cmd/kvlang/stdlib.go b/oldhero/cmd/kvlang/stdlib.go similarity index 93% rename from cmd/kvlang/stdlib.go rename to oldhero/cmd/kvlang/stdlib.go index 9d3c1397..f4caa641 100644 --- a/cmd/kvlang/stdlib.go +++ b/oldhero/cmd/kvlang/stdlib.go @@ -4,15 +4,15 @@ import ( "context" "strings" - "kvlang/keytree" - "kvlang/kvcpu" + "oldhero/keytree" + "oldhero/kvcpu" "github.com/array2d/kvspace-go" - "kvlang/layout" - "kvlang/logx" - "kvlang/lower" - "kvlang/parser" - "kvlang/stdlib" - "kvlang/vthread" + "oldhero/layout" + "oldhero/logx" + "oldhero/lower" + "oldhero/parser" + "oldhero/stdlib" + "oldhero/vthread" ) // layoutAndRunStdlib 在 runtime 启动时 layout 内置 lib 源码到 /lib/,并 run 各 lib 的 init。 diff --git a/cmd/kvlang/util.go b/oldhero/cmd/kvlang/util.go similarity index 100% rename from cmd/kvlang/util.go rename to oldhero/cmd/kvlang/util.go diff --git a/cmd/kvlang/vet.go b/oldhero/cmd/kvlang/vet.go similarity index 95% rename from cmd/kvlang/vet.go rename to oldhero/cmd/kvlang/vet.go index 689a25a0..25159d59 100644 --- a/cmd/kvlang/vet.go +++ b/oldhero/cmd/kvlang/vet.go @@ -6,10 +6,10 @@ import ( "os" "strings" - "kvlang/ast" - "kvlang/logx" - "kvlang/lower" - "kvlang/parser" + "oldhero/ast" + "oldhero/logx" + "oldhero/lower" + "oldhero/parser" ) func cmdVet(args []string) { diff --git a/go.mod b/oldhero/go.mod similarity index 75% rename from go.mod rename to oldhero/go.mod index ed50c20b..9edd9fea 100644 --- a/go.mod +++ b/oldhero/go.mod @@ -1,4 +1,4 @@ -module kvlang +module oldhero go 1.24.4 @@ -10,4 +10,4 @@ require ( github.com/redis/go-redis/v9 v9.7.0 // indirect ) -replace github.com/array2d/kvspace-go v0.1.0 => ../kvspace-go +replace github.com/array2d/kvspace-go v0.1.0 => ../../kvspace-go diff --git a/go.sum b/oldhero/go.sum similarity index 100% rename from go.sum rename to oldhero/go.sum diff --git a/hardcode_check.py b/oldhero/hardcode_check.py similarity index 98% rename from hardcode_check.py rename to oldhero/hardcode_check.py index d4eac4b0..6aec115a 100644 --- a/hardcode_check.py +++ b/oldhero/hardcode_check.py @@ -2,7 +2,7 @@ """检查 symbol.Table 之外的算子 hardcode。语法 token(arrow、成员访问)除外。""" import argparse, os, re, sys -ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +ROOT = os.path.dirname(os.path.abspath(__file__)) SYMBOLS = {s.strip("\"'") for s in ''' "+" "-" "*" "×" "/" "÷" "%" "=" diff --git a/keytree/const.go b/oldhero/keytree/const.go similarity index 100% rename from keytree/const.go rename to oldhero/keytree/const.go diff --git a/keytree/entry.go b/oldhero/keytree/entry.go similarity index 100% rename from keytree/entry.go rename to oldhero/keytree/entry.go diff --git a/keytree/frame.go b/oldhero/keytree/frame.go similarity index 100% rename from keytree/frame.go rename to oldhero/keytree/frame.go diff --git a/keytree/member.go b/oldhero/keytree/member.go similarity index 100% rename from keytree/member.go rename to oldhero/keytree/member.go diff --git a/keytree/sys.go b/oldhero/keytree/sys.go similarity index 100% rename from keytree/sys.go rename to oldhero/keytree/sys.go diff --git a/keytree/vthread.go b/oldhero/keytree/vthread.go similarity index 100% rename from keytree/vthread.go rename to oldhero/keytree/vthread.go diff --git a/kvcpu/controlflow.go b/oldhero/kvcpu/controlflow.go similarity index 95% rename from kvcpu/controlflow.go rename to oldhero/kvcpu/controlflow.go index 5fc1f1fb..b1c14fe0 100644 --- a/kvcpu/controlflow.go +++ b/oldhero/kvcpu/controlflow.go @@ -4,13 +4,13 @@ import ( "context" "fmt" - "kvlang/keytree" + "oldhero/keytree" "github.com/array2d/kvspace-go" - "kvlang/layout" - "kvlang/logx" - "kvlang/rwir" - "kvlang/rwir/builtin" - "kvlang/vthread" + "oldhero/layout" + "oldhero/logx" + "oldhero/rwir" + "oldhero/rwir/builtin" + "oldhero/vthread" ) // handleControl 分发控制流原语(call / return / br / goto)。 diff --git a/kvcpu/cpu.go b/oldhero/kvcpu/cpu.go similarity index 100% rename from kvcpu/cpu.go rename to oldhero/kvcpu/cpu.go diff --git a/kvcpu/debug.go b/oldhero/kvcpu/debug.go similarity index 98% rename from kvcpu/debug.go rename to oldhero/kvcpu/debug.go index ecd13ba6..1dbf6b83 100644 --- a/kvcpu/debug.go +++ b/oldhero/kvcpu/debug.go @@ -11,9 +11,9 @@ import ( "strings" "time" - "kvlang/keytree" + "oldhero/keytree" "github.com/array2d/kvspace-go" - "kvlang/rwir" + "oldhero/rwir" ) // debugFuncName 从帧根目录的 extindex 目标路径提取函数名。 diff --git a/kvcpu/execute.go b/oldhero/kvcpu/execute.go similarity index 98% rename from kvcpu/execute.go rename to oldhero/kvcpu/execute.go index b9d012a7..3c47fafd 100644 --- a/kvcpu/execute.go +++ b/oldhero/kvcpu/execute.go @@ -9,13 +9,13 @@ import ( "time" "github.com/array2d/kvspace-go" - "kvlang/keytree" - "kvlang/layout" - "kvlang/symbol" - "kvlang/logx" - "kvlang/rwir" - "kvlang/rwir/builtin" - "kvlang/vthread" + "oldhero/keytree" + "oldhero/layout" + "oldhero/symbol" + "oldhero/logx" + "oldhero/rwir" + "oldhero/rwir/builtin" + "oldhero/vthread" ) // MaxStackDepth 允许的最大调用栈深度(P6)。 diff --git a/kvcpu/sched.go b/oldhero/kvcpu/sched.go similarity index 100% rename from kvcpu/sched.go rename to oldhero/kvcpu/sched.go diff --git a/layout/layout.go b/oldhero/layout/layout.go similarity index 99% rename from layout/layout.go rename to oldhero/layout/layout.go index d6504958..cc7a1f67 100644 --- a/layout/layout.go +++ b/oldhero/layout/layout.go @@ -26,15 +26,15 @@ import ( "strconv" "strings" - "kvlang/ast" - "kvlang/keytree" - "kvlang/symbol" + "oldhero/ast" + "oldhero/keytree" + "oldhero/symbol" "github.com/array2d/kvspace-go" - "kvlang/lower" - "kvlang/rwir" - "kvlang/rwir/builtin" - "kvlang/rwir/ext" - "kvlang/vthread" + "oldhero/lower" + "oldhero/rwir" + "oldhero/rwir/builtin" + "oldhero/rwir/ext" + "oldhero/vthread" ) // WriteBody 将 []Stmt 写入 /lib/// 下的结构化 KV(编译后指令)。 diff --git a/logx/logx.go b/oldhero/logx/logx.go similarity index 99% rename from logx/logx.go rename to oldhero/logx/logx.go index 0e43385c..04540538 100644 --- a/logx/logx.go +++ b/oldhero/logx/logx.go @@ -21,7 +21,7 @@ import ( "os" "strings" - "kvlang/parser" + "oldhero/parser" ) type level int diff --git a/lower/infer.go b/oldhero/lower/infer.go similarity index 99% rename from lower/infer.go rename to oldhero/lower/infer.go index f581221a..0fef53ca 100644 --- a/lower/infer.go +++ b/oldhero/lower/infer.go @@ -17,9 +17,9 @@ package lower import ( "strings" - "kvlang/ast" - "kvlang/symbol" - "kvlang/rwir" + "oldhero/ast" + "oldhero/symbol" + "oldhero/rwir" ) // InferTypes 为单个函数体中的所有中间变量推断类型。 diff --git a/lower/lower.go b/oldhero/lower/lower.go similarity index 99% rename from lower/lower.go rename to oldhero/lower/lower.go index 996990f9..0ef3b55a 100644 --- a/lower/lower.go +++ b/oldhero/lower/lower.go @@ -14,8 +14,8 @@ package lower import ( "fmt" - "kvlang/ast" - "kvlang/rwir" + "oldhero/ast" + "oldhero/rwir" ) // File 将文件中所有函数降级。 diff --git a/lower/specialize.go b/oldhero/lower/specialize.go similarity index 96% rename from lower/specialize.go rename to oldhero/lower/specialize.go index 98a55f38..ab8171d1 100644 --- a/lower/specialize.go +++ b/oldhero/lower/specialize.go @@ -1,9 +1,9 @@ package lower import ( - "kvlang/ast" - "kvlang/rwir/builtin" - "kvlang/symbol" + "oldhero/ast" + "oldhero/rwir/builtin" + "oldhero/symbol" ) // Specialize 将多态数值 op(add/+、eq/== 等)按读参类型特化为 /lib/{kind}/{op}。 diff --git a/parser/inst.go b/oldhero/parser/inst.go similarity index 99% rename from parser/inst.go rename to oldhero/parser/inst.go index 32dae346..abc778ca 100644 --- a/parser/inst.go +++ b/oldhero/parser/inst.go @@ -9,10 +9,10 @@ import ( "strings" "strconv" - "kvlang/keytree" + "oldhero/keytree" - "kvlang/ast" - "kvlang/symbol" + "oldhero/ast" + "oldhero/symbol" ) // parseInst 直接在 token 流上解析一条指令(Pratt 递归下降)。 diff --git a/parser/parser.go b/oldhero/parser/parser.go similarity index 99% rename from parser/parser.go rename to oldhero/parser/parser.go index 7111437c..41a31344 100644 --- a/parser/parser.go +++ b/oldhero/parser/parser.go @@ -21,9 +21,9 @@ import ( "os" "strings" - "kvlang/ast" - "kvlang/keytree" - "kvlang/symbol" + "oldhero/ast" + "oldhero/keytree" + "oldhero/symbol" ) // ParseFile 打开并解析 .kv 源文件。 diff --git a/parser/scanner.go b/oldhero/parser/scanner.go similarity index 99% rename from parser/scanner.go rename to oldhero/parser/scanner.go index 19de57c2..9165c089 100644 --- a/parser/scanner.go +++ b/oldhero/parser/scanner.go @@ -6,7 +6,7 @@ import ( "fmt" "strings" - "kvlang/symbol" + "oldhero/symbol" ) // Pos 携带 Token 在源码中的起始位置。 diff --git a/parser/stmt.go b/oldhero/parser/stmt.go similarity index 99% rename from parser/stmt.go rename to oldhero/parser/stmt.go index 42ae72c9..9a8642e7 100644 --- a/parser/stmt.go +++ b/oldhero/parser/stmt.go @@ -7,7 +7,7 @@ package parser import ( - "kvlang/ast" + "oldhero/ast" ) // parseBody 消费 Token 直到 RBrace 或 EOF,返回语句列表。 diff --git a/rwir/builtin/arith.go b/oldhero/rwir/builtin/arith.go similarity index 99% rename from rwir/builtin/arith.go rename to oldhero/rwir/builtin/arith.go index e850242d..f811b6ee 100644 --- a/rwir/builtin/arith.go +++ b/oldhero/rwir/builtin/arith.go @@ -4,8 +4,8 @@ import ( "fmt" "github.com/array2d/kvspace-go" - "kvlang/rwir" - "kvlang/vthread" + "oldhero/rwir" + "oldhero/vthread" ) func init() { diff --git a/rwir/builtin/array.go b/oldhero/rwir/builtin/array.go similarity index 99% rename from rwir/builtin/array.go rename to oldhero/rwir/builtin/array.go index 96bbbd11..7bc296ba 100644 --- a/rwir/builtin/array.go +++ b/oldhero/rwir/builtin/array.go @@ -7,10 +7,10 @@ import ( "strconv" "strings" - "kvlang/keytree" + "oldhero/keytree" "github.com/array2d/kvspace-go" - "kvlang/rwir" - "kvlang/vthread" + "oldhero/rwir" + "oldhero/vthread" ) func init() { diff --git a/rwir/builtin/bit.go b/oldhero/rwir/builtin/bit.go similarity index 97% rename from rwir/builtin/bit.go rename to oldhero/rwir/builtin/bit.go index 3007a1e7..6330517c 100644 --- a/rwir/builtin/bit.go +++ b/oldhero/rwir/builtin/bit.go @@ -4,8 +4,8 @@ import ( "fmt" "github.com/array2d/kvspace-go" - "kvlang/rwir" - "kvlang/vthread" + "oldhero/rwir" + "oldhero/vthread" ) func init() { diff --git a/rwir/builtin/call.go b/oldhero/rwir/builtin/call.go similarity index 97% rename from rwir/builtin/call.go rename to oldhero/rwir/builtin/call.go index 15cbf9e9..62a1cef9 100644 --- a/rwir/builtin/call.go +++ b/oldhero/rwir/builtin/call.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "kvlang/rwir" + "oldhero/rwir" "github.com/array2d/kvspace-go" ) diff --git a/rwir/builtin/cast.go b/oldhero/rwir/builtin/cast.go similarity index 99% rename from rwir/builtin/cast.go rename to oldhero/rwir/builtin/cast.go index c59a032c..0eb9208a 100644 --- a/rwir/builtin/cast.go +++ b/oldhero/rwir/builtin/cast.go @@ -4,8 +4,8 @@ import ( "fmt" "github.com/array2d/kvspace-go" - "kvlang/rwir" - "kvlang/vthread" + "oldhero/rwir" + "oldhero/vthread" ) func init() { diff --git a/rwir/builtin/cmp.go b/oldhero/rwir/builtin/cmp.go similarity index 99% rename from rwir/builtin/cmp.go rename to oldhero/rwir/builtin/cmp.go index 4570b429..ce1d4bcb 100644 --- a/rwir/builtin/cmp.go +++ b/oldhero/rwir/builtin/cmp.go @@ -5,8 +5,8 @@ import ( "strconv" "github.com/array2d/kvspace-go" - "kvlang/rwir" - "kvlang/vthread" + "oldhero/rwir" + "oldhero/vthread" ) func init() { diff --git a/rwir/builtin/coerce.go b/oldhero/rwir/builtin/coerce.go similarity index 100% rename from rwir/builtin/coerce.go rename to oldhero/rwir/builtin/coerce.go diff --git a/rwir/builtin/debugger.go b/oldhero/rwir/builtin/debugger.go similarity index 96% rename from rwir/builtin/debugger.go rename to oldhero/rwir/builtin/debugger.go index acfe42b9..b7a072ca 100644 --- a/rwir/builtin/debugger.go +++ b/oldhero/rwir/builtin/debugger.go @@ -4,9 +4,9 @@ import ( "encoding/json" "time" - "kvlang/keytree" - "kvlang/rwir" - "kvlang/vthread" + "oldhero/keytree" + "oldhero/rwir" + "oldhero/vthread" "github.com/array2d/kvspace-go" ) diff --git a/rwir/builtin/dict.go b/oldhero/rwir/builtin/dict.go similarity index 95% rename from rwir/builtin/dict.go rename to oldhero/rwir/builtin/dict.go index 5d26241e..5fa0948c 100644 --- a/rwir/builtin/dict.go +++ b/oldhero/rwir/builtin/dict.go @@ -1,10 +1,10 @@ package builtin import ( - "kvlang/keytree" + "oldhero/keytree" "github.com/array2d/kvspace-go" - "kvlang/rwir" - "kvlang/vthread" + "oldhero/rwir" + "oldhero/vthread" ) func init() { diff --git a/rwir/builtin/helper.go b/oldhero/rwir/builtin/helper.go similarity index 98% rename from rwir/builtin/helper.go rename to oldhero/rwir/builtin/helper.go index d29342dd..2c8b79fc 100644 --- a/rwir/builtin/helper.go +++ b/oldhero/rwir/builtin/helper.go @@ -3,10 +3,10 @@ package builtin import ( "fmt" - "kvlang/keytree" + "oldhero/keytree" "github.com/array2d/kvspace-go" - "kvlang/rwir" - "kvlang/vthread" + "oldhero/rwir" + "oldhero/vthread" ) func requireBinary(inputs []kvspace.XValue) error { diff --git a/rwir/builtin/kvop.go b/oldhero/rwir/builtin/kvop.go similarity index 97% rename from rwir/builtin/kvop.go rename to oldhero/rwir/builtin/kvop.go index afd0117a..b7f3fcf5 100644 --- a/rwir/builtin/kvop.go +++ b/oldhero/rwir/builtin/kvop.go @@ -5,10 +5,10 @@ import ( "strconv" "strings" - "kvlang/keytree" + "oldhero/keytree" "github.com/array2d/kvspace-go" - "kvlang/rwir" - "kvlang/vthread" + "oldhero/rwir" + "oldhero/vthread" ) func init() { diff --git a/rwir/builtin/logic.go b/oldhero/rwir/builtin/logic.go similarity index 97% rename from rwir/builtin/logic.go rename to oldhero/rwir/builtin/logic.go index 30e19763..7506039c 100644 --- a/rwir/builtin/logic.go +++ b/oldhero/rwir/builtin/logic.go @@ -2,8 +2,8 @@ package builtin import ( "github.com/array2d/kvspace-go" - "kvlang/rwir" - "kvlang/vthread" + "oldhero/rwir" + "oldhero/vthread" ) func init() { diff --git a/rwir/builtin/math.go b/oldhero/rwir/builtin/math.go similarity index 99% rename from rwir/builtin/math.go rename to oldhero/rwir/builtin/math.go index fa90405b..443d0c8f 100644 --- a/rwir/builtin/math.go +++ b/oldhero/rwir/builtin/math.go @@ -5,8 +5,8 @@ import ( "math" "github.com/array2d/kvspace-go" - "kvlang/rwir" - "kvlang/vthread" + "oldhero/rwir" + "oldhero/vthread" ) func init() { diff --git a/rwir/builtin/num.go b/oldhero/rwir/builtin/num.go similarity index 100% rename from rwir/builtin/num.go rename to oldhero/rwir/builtin/num.go diff --git a/rwir/builtin/random/random.go b/oldhero/rwir/builtin/random/random.go similarity index 100% rename from rwir/builtin/random/random.go rename to oldhero/rwir/builtin/random/random.go diff --git a/rwir/builtin/random_op.go b/oldhero/rwir/builtin/random_op.go similarity index 92% rename from rwir/builtin/random_op.go rename to oldhero/rwir/builtin/random_op.go index 0e644ef4..6e0ffeee 100644 --- a/rwir/builtin/random_op.go +++ b/oldhero/rwir/builtin/random_op.go @@ -2,9 +2,9 @@ package builtin import ( "github.com/array2d/kvspace-go" - "kvlang/rwir" - "kvlang/vthread" - rand "kvlang/rwir/builtin/random" + "oldhero/rwir" + "oldhero/vthread" + rand "oldhero/rwir/builtin/random" ) func init() { diff --git a/rwir/builtin/resolve.go b/oldhero/rwir/builtin/resolve.go similarity index 98% rename from rwir/builtin/resolve.go rename to oldhero/rwir/builtin/resolve.go index ae872dc2..5e1cf394 100644 --- a/rwir/builtin/resolve.go +++ b/oldhero/rwir/builtin/resolve.go @@ -1,9 +1,9 @@ package builtin import ( - "kvlang/keytree" + "oldhero/keytree" "github.com/array2d/kvspace-go" - "kvlang/rwir" + "oldhero/rwir" ) func isAbsolute(param string) bool { return len(param) > 0 && param[0] == '/' } diff --git a/rwir/builtin/rwirs.go b/oldhero/rwir/builtin/rwirs.go similarity index 98% rename from rwir/builtin/rwirs.go rename to oldhero/rwir/builtin/rwirs.go index 17ddb8fb..6b0d42b6 100644 --- a/rwir/builtin/rwirs.go +++ b/oldhero/rwir/builtin/rwirs.go @@ -5,8 +5,8 @@ import ( "strings" "github.com/array2d/kvspace-go" - "kvlang/keytree" - "kvlang/symbol" + "oldhero/keytree" + "oldhero/symbol" ) // nativeRwir 内置算子注册项。 diff --git a/rwir/builtin/string.go b/oldhero/rwir/builtin/string.go similarity index 99% rename from rwir/builtin/string.go rename to oldhero/rwir/builtin/string.go index 6014d7a6..1066db18 100644 --- a/rwir/builtin/string.go +++ b/oldhero/rwir/builtin/string.go @@ -3,11 +3,11 @@ package builtin import ( "fmt" - "kvlang/keytree" + "oldhero/keytree" "github.com/array2d/kvspace-go" - "kvlang/logx" - "kvlang/rwir" - "kvlang/vthread" + "oldhero/logx" + "oldhero/rwir" + "oldhero/vthread" ) func init() { diff --git a/rwir/builtin/time.go b/oldhero/rwir/builtin/time.go similarity index 99% rename from rwir/builtin/time.go rename to oldhero/rwir/builtin/time.go index 57f74681..5a348845 100644 --- a/rwir/builtin/time.go +++ b/oldhero/rwir/builtin/time.go @@ -4,8 +4,8 @@ import ( "time" "github.com/array2d/kvspace-go" - "kvlang/rwir" - "kvlang/vthread" + "oldhero/rwir" + "oldhero/vthread" ) func init() { diff --git a/rwir/builtin/utf8/utf8.go b/oldhero/rwir/builtin/utf8/utf8.go similarity index 100% rename from rwir/builtin/utf8/utf8.go rename to oldhero/rwir/builtin/utf8/utf8.go diff --git a/rwir/control.go b/oldhero/rwir/control.go similarity index 100% rename from rwir/control.go rename to oldhero/rwir/control.go diff --git a/rwir/ext/ext.go b/oldhero/rwir/ext/ext.go similarity index 97% rename from rwir/ext/ext.go rename to oldhero/rwir/ext/ext.go index 11dc8e3a..61877222 100644 --- a/rwir/ext/ext.go +++ b/oldhero/rwir/ext/ext.go @@ -7,7 +7,7 @@ // 2. Register/Serve 两行转发(注册签名、常驻监控 .todo、批量执行、交还 PC); // 3. Exec 按 opcode 分发到具体 handler。 // -// 参考实现见 rwirext/json 与 rwirext/term。 +// 参考实现见 runtime-rwirext/go/json 与 rwirext/term。 package ext import ( @@ -16,8 +16,8 @@ import ( "time" "github.com/array2d/kvspace-go" - "kvlang/keytree" - "kvlang/rwir" + "oldhero/keytree" + "oldhero/rwir" ) // Op 定义一个 rwir:opcode + 签名 + 读写参数量。 diff --git a/rwir/frame.go b/oldhero/rwir/frame.go similarity index 100% rename from rwir/frame.go rename to oldhero/rwir/frame.go diff --git a/rwir/pc.go b/oldhero/rwir/pc.go similarity index 100% rename from rwir/pc.go rename to oldhero/rwir/pc.go diff --git a/rwir/rwir.go b/oldhero/rwir/rwir.go similarity index 100% rename from rwir/rwir.go rename to oldhero/rwir/rwir.go diff --git a/rwirext/term/cmd/main.go b/oldhero/rwirext/term/cmd/main.go similarity index 93% rename from rwirext/term/cmd/main.go rename to oldhero/rwirext/term/cmd/main.go index a17af56f..6d8b849c 100644 --- a/rwirext/term/cmd/main.go +++ b/oldhero/rwirext/term/cmd/main.go @@ -6,7 +6,7 @@ import ( "github.com/array2d/kvspace-go" _ "github.com/array2d/kvspace-go/redis" - "kvlang/rwirext/term" + "oldhero/rwirext/term" ) func main() { diff --git a/rwirext/term/file.go b/oldhero/rwirext/term/file.go similarity index 100% rename from rwirext/term/file.go rename to oldhero/rwirext/term/file.go diff --git a/rwirext/term/serve.go b/oldhero/rwirext/term/serve.go similarity index 97% rename from rwirext/term/serve.go rename to oldhero/rwirext/term/serve.go index f3b0ded8..ad300f49 100644 --- a/rwirext/term/serve.go +++ b/oldhero/rwirext/term/serve.go @@ -8,10 +8,10 @@ import ( "strings" "github.com/array2d/kvspace-go" - "kvlang/keytree" - "kvlang/rwir" - "kvlang/rwir/builtin" - "kvlang/rwir/ext" + "oldhero/keytree" + "oldhero/rwir" + "oldhero/rwir/builtin" + "oldhero/rwir/ext" ) type op struct { diff --git a/stdlib/embed.go b/oldhero/stdlib/embed.go similarity index 100% rename from stdlib/embed.go rename to oldhero/stdlib/embed.go diff --git a/stdlib/math.kv b/oldhero/stdlib/math.kv similarity index 100% rename from stdlib/math.kv rename to oldhero/stdlib/math.kv diff --git a/symbol/symbol.go b/oldhero/symbol/symbol.go similarity index 100% rename from symbol/symbol.go rename to oldhero/symbol/symbol.go diff --git a/vthread/vthread.go b/oldhero/vthread/vthread.go similarity index 99% rename from vthread/vthread.go rename to oldhero/vthread/vthread.go index 0cfe1956..4980f1dc 100644 --- a/vthread/vthread.go +++ b/oldhero/vthread/vthread.go @@ -33,7 +33,7 @@ import ( "strconv" "time" - "kvlang/keytree" + "oldhero/keytree" "github.com/array2d/kvspace-go" ) diff --git a/runtime-rwirext/build.rs b/runtime-rwirext/build.rs deleted file mode 100644 index 88d8180e..00000000 --- a/runtime-rwirext/build.rs +++ /dev/null @@ -1,8 +0,0 @@ -fn main() { - let rt = "/home/peng.li24/github.com/array2d/kvlang/runtime/build"; - let dual = "/home/peng.li24/github.com/array2d/kvspace-durable/target/release"; - println!("cargo:rustc-link-search=native={rt}"); - println!("cargo:rustc-link-lib=dylib=kvlang_runtime"); - println!("cargo:rustc-link-arg=-Wl,-rpath,{rt}"); - println!("cargo:rustc-link-arg=-Wl,-rpath,{dual}"); -} diff --git a/rwirext/json/cmd/main.go b/runtime-rwirext/go/json/cmd/main.go similarity index 58% rename from rwirext/json/cmd/main.go rename to runtime-rwirext/go/json/cmd/main.go index caa54567..276043c3 100644 --- a/rwirext/json/cmd/main.go +++ b/runtime-rwirext/go/json/cmd/main.go @@ -4,17 +4,12 @@ package main import ( "flag" - "github.com/array2d/kvspace-go" - _ "github.com/array2d/kvspace-go/redis" - "kvlang/rwirext/json" + "runtime-rwirext/go/json" ) func main() { dsn := flag.String("kvspace", "redis://127.0.0.1:6379", "kvspace DSN") flag.Parse() - kv := kvspace.Conn(*dsn) - defer kv.DisConn() - - json.Serve(kv) + json.Serve(*dsn) } diff --git a/runtime-rwirext/go/json/go.mod b/runtime-rwirext/go/json/go.mod new file mode 100644 index 00000000..33bd067f --- /dev/null +++ b/runtime-rwirext/go/json/go.mod @@ -0,0 +1,3 @@ +module runtime-rwirext/go/json + +go 1.24.4 diff --git a/runtime-rwirext/go/json/json.go b/runtime-rwirext/go/json/json.go new file mode 100644 index 00000000..73b07080 --- /dev/null +++ b/runtime-rwirext/go/json/json.go @@ -0,0 +1,491 @@ +// Package json 是 rwirext 扩展运行时(json.to/json.from)。经 C runtime 的 +// rwext_* ABI 与 kvspace 交互(不依赖 kvspace-go)。独立进程常驻 serve。 +package json + +/* +#cgo CFLAGS: -I${SRCDIR}/../../../runtime/include +#cgo LDFLAGS: -L${SRCDIR}/../../../bin -lkvlang_runtime -Wl,-rpath,${SRCDIR}/../../../bin +#cgo LDFLAGS: -Wl,-rpath-link,${SRCDIR}/../../../../kvspace/build +#cgo LDFLAGS: -Wl,-rpath-link,${SRCDIR}/../../../../blockmalloc/build +#cgo LDFLAGS: -Wl,-rpath-link,${SRCDIR}/../../../../slotsboxmalloc/build +#cgo LDFLAGS: -Wl,-rpath-link,${SRCDIR}/../../../../kvspace-durable/target/release +#include "kvlang_rwext.h" +#include +*/ +import "C" + +import ( + "bytes" + "encoding/binary" + "encoding/json" + "math" + "sort" + "strconv" + "strings" + "time" + "unsafe" +) + +// ── cgo 封装 ──────────────────────────────────────────────────────── + +func cstr(s string) *C.char { return C.CString(s) } + +func gostr(s *C.char) string { + if s == nil { + return "" + } + defer C.free(unsafe.Pointer(s)) + return C.GoString(s) +} + +func list(c *C.rwext_conn, prefix string) []string { + cp := cstr(prefix) + defer C.free(unsafe.Pointer(cp)) + s := C.rwext_list(c, cp) + if s == nil { + return nil + } + defer C.free(unsafe.Pointer(s)) + str := C.GoString(s) + if str == "" { + return nil + } + return strings.Split(str, "\n") +} + +func get(c *C.rwext_conn, key string) string { + ck := cstr(key) + defer C.free(unsafe.Pointer(ck)) + return gostr(C.rwext_get(c, ck)) +} + +func getTLV(c *C.rwext_conn, key string) []byte { + ck := cstr(key) + defer C.free(unsafe.Pointer(ck)) + var out *C.uint8_t + var outLen C.uint32_t + C.rwext_get_tlv(c, ck, &out, &outLen) + if out == nil { + return nil + } + defer C.free(unsafe.Pointer(out)) + return C.GoBytes(unsafe.Pointer(out), C.int(outLen)) +} + +func setTLV(c *C.rwext_conn, key string, tlv []byte) { + ck := cstr(key) + defer C.free(unsafe.Pointer(ck)) + buf := C.CBytes(tlv) + defer C.free(buf) + C.rwext_set_tlv(c, ck, (*C.uint8_t)(buf), C.uint32_t(len(tlv))) +} + +func setChar(c *C.rwext_conn, key, val string) { + ck := cstr(key) + cv := cstr(val) + defer C.free(unsafe.Pointer(ck)) + defer C.free(unsafe.Pointer(cv)) + C.rwext_set(c, ck, cv) +} + +func mkindex(c *C.rwext_conn, path string) { + cp := cstr(path) + defer C.free(unsafe.Pointer(cp)) + C.rwext_mkindex(c, cp) +} + +func resolveRead(c *C.rwext_conn, pc string, idx int) string { + cp := cstr(pc) + defer C.free(unsafe.Pointer(cp)) + return gostr(C.rwext_resolve_read(c, cp, C.int(idx))) +} + +func resolveWrite(c *C.rwext_conn, pc string, idx int) string { + cp := cstr(pc) + defer C.free(unsafe.Pointer(cp)) + return gostr(C.rwext_resolve_write(c, cp, C.int(idx))) +} + +func nextPC(pc string) string { + cp := cstr(pc) + defer C.free(unsafe.Pointer(cp)) + return gostr(C.rwext_next_pc(cp)) +} + +func params(c *C.rwext_conn, pc string) []string { + cp := cstr(pc) + defer C.free(unsafe.Pointer(cp)) + return strings.Split(gostr(C.rwext_params(c, cp)), "\n") +} + +// ── TLV 编解码(kindexp:kl|kind|ref|arr_flag|ndim|dims|raw_len|raw)─── + +func u32(v uint32) []byte { + b := make([]byte, 4) + binary.LittleEndian.PutUint32(b, v) + return b +} + +func parseTLV(data []byte) (kind string, raw []byte, arrLen int) { + if len(data) < 4 { + return "", nil, 0 + } + kl := int(data[0]) + kind = string(data[1 : 1+kl]) + o := 1 + kl + arrFlag := data[o+1] + ndim := int(data[o+2]) + rawOff := o + 3 + 4*ndim + if rawOff+4 > len(data) { + return kind, nil, 1 + } + rawLen := int(binary.LittleEndian.Uint32(data[rawOff : rawOff+4])) + raw = data[rawOff+4 : rawOff+4+rawLen] + if arrFlag == 0 { + arrLen = 1 + } else { + arrLen = 1 + for i := 0; i < ndim; i++ { + arrLen *= int(binary.LittleEndian.Uint32(data[o+3+4*i : o+3+4*i+4])) + } + } + return kind, raw, arrLen +} + +func constructTLV(kind string, raw []byte, arrLen int) []byte { + var b bytes.Buffer + b.WriteByte(byte(len(kind))) + b.WriteString(kind) + b.WriteByte(0) // ref + if arrLen > 1 { + b.WriteByte(1) // arr_flag + b.WriteByte(1) // ndim + b.Write(u32(uint32(arrLen))) + } else { + b.WriteByte(0) + b.WriteByte(0) + } + b.Write(u32(uint32(len(raw)))) + b.Write(raw) + return b.Bytes() +} + +// ── JSON 值 ↔ TLV ─────────────────────────────────────────────────── + +func readInt(raw []byte) int64 { + var v int64 + switch len(raw) { + case 1: + v = int64(int8(raw[0])) + case 2: + v = int64(int16(binary.LittleEndian.Uint16(raw))) + case 4: + v = int64(int32(binary.LittleEndian.Uint32(raw))) + case 8: + v = int64(binary.LittleEndian.Uint64(raw)) + } + return v +} + +func elemSize(kind string) int { + switch kind { + case "int8", "uint8", "bool": + return 1 + case "int16", "uint16": + return 2 + case "int32", "uint32", "float32": + return 4 + case "int64", "uint64", "float64": + return 8 + } + return 0 +} + +func utf32ToString(raw []byte) string { + var b strings.Builder + for i := 0; i+4 <= len(raw); i += 4 { + b.WriteRune(rune(binary.LittleEndian.Uint32(raw[i : i+4]))) + } + return b.String() +} + +func tlvToJSONValue(kind string, raw []byte, arrLen int) interface{} { + es := elemSize(kind) + switch kind { + case "bool": + if arrLen > 1 { + arr := make([]interface{}, arrLen) + for i := 0; i < arrLen; i++ { + arr[i] = raw[i] != 0 + } + return arr + } + return raw[0] != 0 + case "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64": + if arrLen > 1 { + arr := make([]interface{}, arrLen) + for i := 0; i < arrLen; i++ { + arr[i] = readInt(raw[i*es : i*es+es]) + } + return arr + } + return readInt(raw[:es]) + case "float32", "float64": + if arrLen > 1 { + arr := make([]interface{}, arrLen) + for i := 0; i < arrLen; i++ { + arr[i] = float64From(raw[i*es : i*es+es]) + } + return arr + } + return float64From(raw[:es]) + case "char/utf8", "char/ascii": + return string(raw) + case "char/utf32": + return utf32ToString(raw) + default: + return string(raw) + } +} + +func float64From(raw []byte) float64 { + if len(raw) == 4 { + return float64(math.Float32frombits(binary.LittleEndian.Uint32(raw))) + } + return math.Float64frombits(binary.LittleEndian.Uint64(raw)) +} + +func jsonValueToTLV(v interface{}) []byte { + switch t := v.(type) { + case json.Number: + if i, err := t.Int64(); err == nil { + return constructTLV("int64", u64(uint64(i)), 1) + } + f, _ := t.Float64() + return constructTLV("float64", u64bits(f), 1) + case bool: + b := byte(0) + if t { + b = 1 + } + return constructTLV("bool", []byte{b}, 1) + case string: + return constructTLV("char/utf8", []byte(t), 1) + default: + return nil + } +} + +func jsonArrayToTLV(arr []interface{}) []byte { + if len(arr) == 0 { + return nil + } + switch arr[0].(type) { + case json.Number: + allInt := true + for _, e := range arr { + if _, err := e.(json.Number).Int64(); err != nil { + allInt = false + break + } + } + if allInt { + raw := make([]byte, 0, len(arr)*8) + for _, e := range arr { + i, _ := e.(json.Number).Int64() + raw = append(raw, u64(uint64(i))...) + } + return constructTLV("int64", raw, len(arr)) + } + raw := make([]byte, 0, len(arr)*8) + for _, e := range arr { + f, _ := e.(json.Number).Float64() + raw = append(raw, u64bits(f)...) + } + return constructTLV("float64", raw, len(arr)) + case bool: + raw := make([]byte, len(arr)) + for i, e := range arr { + if e.(bool) { + raw[i] = 1 + } + } + return constructTLV("bool", raw, len(arr)) + default: + return nil + } +} + +func u64(v uint64) []byte { + b := make([]byte, 8) + binary.LittleEndian.PutUint64(b, v) + return b +} + +func u64bits(f float64) []byte { + bits := *(*uint64)(unsafe.Pointer(&f)) + return u64(bits) +} + +// ── KV 子树 ↔ map[string]any ─────────────────────────────────────── + +func splitArrayName(name string) (base string, idx int, ok bool) { + lt := strings.LastIndex(name, "[") + if lt <= 0 || !strings.HasSuffix(name, "]") { + return "", 0, false + } + i, err := strconv.Atoi(name[lt+1 : len(name)-1]) + if err != nil { + return "", 0, false + } + return name[:lt], i, true +} + +func buildMap(c *C.rwext_conn, root string) map[string]any { + m := map[string]any{} + scat := map[string][]int{} + for _, child := range list(c, root+"/") { + if child == "" { + continue + } + if base, idx, ok := splitArrayName(child); ok { + scat[base] = append(scat[base], idx) + continue + } + // 目录:list(child+"/") 非空 → 递归 + if len(list(c, root+"/"+child+"/")) > 0 { + m[child] = buildMap(c, root+"/"+child) + continue + } + kind, raw, arrLen := parseTLV(getTLV(c, root+"/"+child)) + m[child] = tlvToJSONValue(kind, raw, arrLen) + } + for base, idxs := range scat { + sort.Ints(idxs) + arr := make([]interface{}, len(idxs)) + for i, idx := range idxs { + kind, raw, arrLen := parseTLV(getTLV(c, root+"/"+base+"["+strconv.Itoa(idx)+"]")) + arr[i] = tlvToJSONValue(kind, raw, arrLen) + } + m[base] = arr + } + return m +} + +func writeMap(c *C.rwext_conn, root string, m map[string]any) { + for k, v := range m { + childPath := root + "/" + k + switch t := v.(type) { + case map[string]any: + mkindex(c, childPath+"/") + writeMap(c, childPath, t) + case []interface{}: + setTLV(c, childPath, jsonArrayToTLV(t)) + default: + setTLV(c, childPath, jsonValueToTLV(v)) + } + } +} + +func fromJSON(data []byte) map[string]any { + dec := json.NewDecoder(bytes.NewReader(data)) + dec.UseNumber() + var m map[string]any + if err := dec.Decode(&m); err != nil { + return nil + } + return m +} + +// ── rwir handoff ─────────────────────────────────────────────────── + +type op struct { + name string + nr int + nw int +} + +var ops = []op{ + {"json.to", 1, 1}, + {"json.from", 1, 1}, +} + +func register(c *C.rwext_conn) { + for _, o := range ops { + sig := "rwir " + o.name + "(a:any) -> (b:any)" + co := cstr(o.name) + cs := cstr(sig) + C.rwext_register(c, co, C.int32_t(o.nr), C.int32_t(o.nw), cs) + C.free(unsafe.Pointer(co)) + C.free(unsafe.Pointer(cs)) + } +} + +func doTo(c *C.rwext_conn, pc string, readNames, writeNames []string) { + root := readNames[0] + if !strings.HasPrefix(root, "/") { + root = resolveRead(c, pc, 0) + } + data, _ := json.Marshal(buildMap(c, root)) + dest := resolveWrite(c, pc, 0) + setChar(c, dest, string(data)) +} + +func doFrom(c *C.rwext_conn, pc string, readNames, writeNames []string) { + src := resolveRead(c, pc, 0) + root := writeNames[0] + if !strings.HasPrefix(root, "/") { + root = resolveWrite(c, pc, 0) + } + writeMap(c, root, fromJSON([]byte(src))) +} + +func serveOp(c *C.rwext_conn, o op) { + base := "/lib/" + o.name + for _, child := range list(c, base+"/") { + if !strings.HasPrefix(child, ".todo<") || !strings.HasSuffix(child, ">") { + continue + } + vid := child[6 : len(child)-1] + todo := base + "/" + child + pcid := get(c, todo) + pc, id := pcid, "" + if i := strings.LastIndex(pcid, "|"); i >= 0 { + pc, id = pcid[:i], pcid[i+1:] + } + + ps := params(c, pc) + opcode := ps[0] + readNames := ps[1 : 1+o.nr] + writeNames := ps[1+o.nr : 1+o.nr+o.nw] + if opcode == "json.to" { + doTo(c, pc, readNames, writeNames) + } else { + doFrom(c, pc, readNames, writeNames) + } + + nxt := nextPC(pc) + setChar(c, "/vthread/"+vid+"/‥pc", nxt) + setChar(c, base+"/.done<"+vid+">", id) + ck := cstr(todo) + C.rwext_del(c, ck) + C.free(unsafe.Pointer(ck)) + } +} + +// Serve 常驻循环:注册 + 监控 .todo + 批量执行 + 交还 PC。 +func Serve(dsn string) { + cd := cstr(dsn) + defer C.free(unsafe.Pointer(cd)) + c := C.rwext_connect(cd) + if c == nil { + return + } + register(c) + for { + for _, o := range ops { + serveOp(c, o) + } + time.Sleep(50 * time.Millisecond) + } +} diff --git a/runtime-rwirext/py/numpy/numpy_ext.py b/runtime-rwirext/py/numpy/numpy_ext.py new file mode 100644 index 00000000..cd3daea8 --- /dev/null +++ b/runtime-rwirext/py/numpy/numpy_ext.py @@ -0,0 +1,140 @@ +"""numpy 扩展:把 numpy ndarray 的 buffer 建立在 kvspace-c SHM 上(零拷贝)。 + +kvspace 存 tensor 为 XValue 数组(float64/int64 等)。`tensor_view` 直接解析 +TLV 头拿到 SHM 里 raw data 的地址,用 numpy 在该地址上建立 ndarray——读写 ndarray +即读写 kvspace,无拷贝。 +""" + +import ctypes +import struct + +import numpy as np + +_lib = None + +_KIND_CTYPE = { + "float64": ctypes.c_double, + "float32": ctypes.c_float, + "int64": ctypes.c_int64, + "int32": ctypes.c_int32, + "int16": ctypes.c_int16, + "int8": ctypes.c_int8, + "uint64": ctypes.c_uint64, + "uint32": ctypes.c_uint32, + "uint16": ctypes.c_uint16, + "uint8": ctypes.c_uint8, +} + +_NP_DTYPE = { + "float64": np.float64, + "float32": np.float32, + "int64": np.int64, + "int32": np.int32, + "int16": np.int16, + "int8": np.int8, + "uint64": np.uint64, + "uint32": np.uint32, + "uint16": np.uint16, + "uint8": np.uint8, +} + + +def _load(): + global _lib + if _lib is None: + _lib = ctypes.CDLL("libkvspace-c.so") + _lib.kvsc_open.argtypes = [ctypes.c_char_p, ctypes.c_size_t] + _lib.kvsc_open.restype = ctypes.c_void_p + _lib.kvsc_close.argtypes = [ctypes.c_void_p] + _lib.kvsc_get.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int, ctypes.POINTER(ctypes.c_int32)] + _lib.kvsc_get.restype = ctypes.POINTER(ctypes.c_uint8) + _lib.kvsc_set.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.POINTER(ctypes.c_uint8), ctypes.c_int32] + _lib.kvsc_set.restype = ctypes.c_int + _lib.kvsc_del.argtypes = [ctypes.c_void_p, ctypes.c_char_p] + _lib.kvsc_del.restype = ctypes.c_int + return _lib + + +class NumpyExt: + """kvspace-c SHM 上的 numpy tensor 容器。""" + + def __init__(self, dsn: str): + if not dsn.startswith("shm://"): + raise ValueError(f"numpy 扩展走 shm 后端(大 data 零拷贝),got {dsn}") + self.path = dsn[len("shm://"):] + self.lib = _load() + # data_size = 8 * 64^4 = 128MB,与 kvlang runtime 默认一致 + self.kv = self.lib.kvsc_open(self.path.encode(), 8 * 64 ** 4) + if not self.kv: + raise RuntimeError(f"kvsc_open failed: {self.path}") + + def close(self): + if self.kv: + self.lib.kvsc_close(self.kv) + self.kv = None + + def __enter__(self): + return self + + def __exit__(self, *exc): + self.close() + + # ---- tensor 写入 ---- + + def tensor_alloc(self, key: str, arr: np.ndarray): + """把 numpy 数组写到 kvspace(float64/int64 等定长数组)。""" + arr = np.ascontiguousarray(arr) + kind = _dtype_to_kind(arr.dtype) + raw = arr.tobytes() + n = arr.size + if n > 1: + tlv = (struct.pack(" np.ndarray | None: + """零拷贝视图:返回的 ndarray 的 buffer 直接指向 kvspace SHM 的 raw data。""" + out_len = ctypes.c_int32() + d = self.lib.kvsc_get(self.kv, key.encode(), 1, ctypes.byref(out_len)) + if not d: + return None + kl = d[0] + kind = bytes(d[1:1 + kl]).decode() + o = 1 + kl + ref = d[o] + arr_flag = d[o + 1] + ndim = d[o + 2] + if ref != 0 or kind not in _KIND_CTYPE: + return None + raw_off = o + 3 + 4 * ndim + raw_len = int.from_bytes(bytes(d[raw_off:raw_off + 4]), "little") + base = ctypes.cast(d, ctypes.c_void_p).value + elem = _KIND_CTYPE[kind] + n = raw_len // ctypes.sizeof(elem) + ptr = ctypes.cast(base + raw_off + 4, ctypes.POINTER(elem)) + if arr_flag == 0: + shape = () + else: + shape = tuple( + int.from_bytes(bytes(d[o + 3 + 4 * i: o + 3 + 4 * i + 4]), "little") + for i in range(ndim) + ) + arr = np.ctypeslib.as_array(ptr, shape=(n,)) + return arr.reshape(shape) if shape else arr[0] + + +def _dtype_to_kind(dt) -> str: + for kind, npdt in _NP_DTYPE.items(): + if np.dtype(dt) == np.dtype(npdt): + return kind + raise ValueError(f"unsupported dtype: {dt}") diff --git a/runtime-rwirext/py/numpy/numpy_rwext.py b/runtime-rwirext/py/numpy/numpy_rwext.py new file mode 100644 index 00000000..217cb02a --- /dev/null +++ b/runtime-rwirext/py/numpy/numpy_rwext.py @@ -0,0 +1,93 @@ +"""numpy rwir 扩展:注册 numpy.add/mul,serve handoff,ndarray 零拷贝。 + +- 手递协议复用 C runtime 的 rwext_* ABI(rwext_connect/register/list/get/set/del/params/next_pc)。 +- tensor 数据本体用 numpy_ext.NumpyExt(kvspace-c SHM 零拷贝 view)。 +""" + +import ctypes +import time + +from numpy_ext import NumpyExt + +_rwext = ctypes.CDLL("libkvlang_runtime.so") +_rwext.rwext_connect.argtypes = [ctypes.c_char_p] +_rwext.rwext_connect.restype = ctypes.c_void_p +_rwext.rwext_register.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int32, ctypes.c_int32, ctypes.c_char_p] +_rwext.rwext_register.restype = ctypes.c_int +_rwext.rwext_list.argtypes = [ctypes.c_void_p, ctypes.c_char_p] +_rwext.rwext_list.restype = ctypes.c_void_p +_rwext.rwext_get.argtypes = [ctypes.c_void_p, ctypes.c_char_p] +_rwext.rwext_get.restype = ctypes.c_void_p +_rwext.rwext_set.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_char_p] +_rwext.rwext_set.restype = ctypes.c_int +_rwext.rwext_del.argtypes = [ctypes.c_void_p, ctypes.c_char_p] +_rwext.rwext_del.restype = ctypes.c_int +_rwext.rwext_params.argtypes = [ctypes.c_void_p, ctypes.c_char_p] +_rwext.rwext_params.restype = ctypes.c_void_p +_rwext.rwext_next_pc.argtypes = [ctypes.c_char_p] +_rwext.rwext_next_pc.restype = ctypes.c_void_p + +_libc = ctypes.CDLL(None) +_libc.free.argtypes = [ctypes.c_void_p] + +OPS = { + "numpy.add": (2, 1), + "numpy.mul": (2, 1), +} + + +def _s(p): + if not p: + return "" + s = ctypes.string_at(p).decode() + _libc.free(p) + return s + + +def serve(dsn: str): + kv = NumpyExt(dsn) # 零拷贝 buffer(kvspace-c SHM) + conn = _rwext.rwext_connect(dsn.encode()) + if not conn: + raise RuntimeError("rwext_connect failed") + + for op, (nr, nw) in OPS.items(): + sig = f"rwir {op}(a:path, b:path) -> (c:path)" + _rwext.rwext_register(conn, op.encode(), nr, nw, sig.encode()) + + while True: + for op, (nr, nw) in OPS.items(): + base = f"/lib/{op}" + children = _s(_rwext.rwext_list(conn, f"{base}/".encode())) + for child in children.split("\n"): + if not child.startswith(".todo<") or not child.endswith(">"): + continue + vid = child[6:-1] + todo = f"{base}/{child}" + pcid = _s(_rwext.rwext_get(conn, todo.encode())) + pc, _, pid = pcid.rpartition("|") + + params = _s(_rwext.rwext_params(conn, pc.encode())).split("\n") + opcode = params[0] + reads = params[1:1 + nr] + writes = params[1 + nr:1 + nr + nw] + + a = kv.tensor_view(reads[0]) + b = kv.tensor_view(reads[1]) + if opcode == "numpy.add": + c = a + b + elif opcode == "numpy.mul": + c = a * b + else: + continue + kv.tensor_alloc(writes[0], c) + + nxt = _s(_rwext.rwext_next_pc(pc.encode())) + _rwext.rwext_set(conn, f"/vthread/{vid}/‥pc".encode(), nxt.encode()) + _rwext.rwext_set(conn, f"{base}/.done<{vid}>".encode(), pid.encode()) + _rwext.rwext_del(conn, todo.encode()) + time.sleep(0.05) + + +if __name__ == "__main__": + import sys + serve(sys.argv[1] if len(sys.argv) > 1 else "shm:///tmp/numpy_rwext") diff --git a/runtime-rwirext/py/numpy/test.kv b/runtime-rwirext/py/numpy/test.kv new file mode 100644 index 00000000..f956c965 --- /dev/null +++ b/runtime-rwirext/py/numpy/test.kv @@ -0,0 +1,10 @@ +# numpy.add 外部 rwir 测试(走 shm) +# 期望输出: +# c = [ 5.0 , 7.0 , 9.0 ] +rwfunc main() -> () { + [1.0, 2.0, 3.0] -> /t/a + [4.0, 5.0, 6.0] -> /t/b + numpy.add(/t/a, /t/b) -> /t/c + println("c =", /t/c) +} +main() diff --git a/runtime-rwirext/py/numpy/test_numpy.py b/runtime-rwirext/py/numpy/test_numpy.py new file mode 100644 index 00000000..295cecec --- /dev/null +++ b/runtime-rwirext/py/numpy/test_numpy.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +"""numpy 扩展验证:ndarray buffer 建立在 kvspace-c SHM 上(零拷贝)。 + +验证点: + 1. tensor_alloc 写 float64 数组到 kvspace; + 2. tensor_view 返回的 ndarray 直接指向 SHM 的 raw data; + 3. 原地改 ndarray 后,从 kvspace 重新 view 能看到改动(证明 buffer 即 kvspace)。 +""" + +import numpy as np + +from numpy_ext import NumpyExt + + +def main(): + dsn = "shm:///tmp/numpy_test" + with NumpyExt(dsn) as kv: + # 1. 分配两个 float64 数组 + a = np.array([1.0, 2.0, 3.0], dtype=np.float64) + b = np.array([4.0, 5.0, 6.0], dtype=np.float64) + kv.tensor_alloc("/t/a", a) + kv.tensor_alloc("/t/b", b) + + # 2. 零拷贝视图 + va = kv.tensor_view("/t/a") + vb = kv.tensor_view("/t/b") + assert va is not None and vb is not None + assert list(va) == [1.0, 2.0, 3.0], f"a = {list(va)}" + assert list(vb) == [4.0, 5.0, 6.0], f"b = {list(vb)}" + print(f"a = {list(va)}") + print(f"b = {list(vb)}") + + # 3. 原地改 ndarray(直接写 SHM buffer) + va[0] = 100.0 + va[2] = 300.0 + + # 4. 重新 view 读回,证明改动落在 kvspace + va2 = kv.tensor_view("/t/a") + assert list(va2) == [100.0, 2.0, 300.0], f"a2 = {list(va2)}" + print(f"a (改后) = {list(va2)} ← 零拷贝写回 kvspace 生效") + + # 5. numpy 计算 c = a + b,写回 kvspace + c = va2 + vb + kv.tensor_alloc("/t/c", c) + vc = kv.tensor_view("/t/c") + assert list(vc) == [104.0, 7.0, 306.0], f"c = {list(vc)}" + print(f"c = a + b = {list(vc)}") + + # 6. int64 数组同样支持 + iv = np.array([10, 20, 30], dtype=np.int64) + kv.tensor_alloc("/t/i", iv) + vi = kv.tensor_view("/t/i") + assert list(vi) == [10, 20, 30] + print(f"i = {list(vi)}") + + print("PASS: ndarray buffer 建立在 kvspace-c SHM 上") + + +if __name__ == "__main__": + main() diff --git a/runtime-rwirext/.gitignore b/runtime-rwirext/rust/term/.gitignore similarity index 100% rename from runtime-rwirext/.gitignore rename to runtime-rwirext/rust/term/.gitignore diff --git a/runtime-rwirext/Cargo.lock b/runtime-rwirext/rust/term/Cargo.lock similarity index 100% rename from runtime-rwirext/Cargo.lock rename to runtime-rwirext/rust/term/Cargo.lock diff --git a/runtime-rwirext/Cargo.toml b/runtime-rwirext/rust/term/Cargo.toml similarity index 70% rename from runtime-rwirext/Cargo.toml rename to runtime-rwirext/rust/term/Cargo.toml index 2f73ec92..61464394 100644 --- a/runtime-rwirext/Cargo.toml +++ b/runtime-rwirext/rust/term/Cargo.toml @@ -3,8 +3,9 @@ name = "kvlang-rwext-term" version = "0.1.0" edition = "2021" -[lib] -crate-type = ["cdylib", "rlib"] +[[bin]] +name = "term" +path = "src/main.rs" [dependencies] libc = "0.2" diff --git a/runtime-rwirext/Makefile b/runtime-rwirext/rust/term/Makefile similarity index 100% rename from runtime-rwirext/Makefile rename to runtime-rwirext/rust/term/Makefile diff --git a/runtime-rwirext/rust/term/build.rs b/runtime-rwirext/rust/term/build.rs new file mode 100644 index 00000000..29a3158b --- /dev/null +++ b/runtime-rwirext/rust/term/build.rs @@ -0,0 +1,8 @@ +// 链接 C runtime(libkvlang_runtime.so)。产物统一在 kvlang/bin/, +// 依赖路径从 CARGO_MANIFEST_DIR 推导,不 hardcode 绝对路径。 +fn main() { + let bin = format!("{}/../../../bin", env!("CARGO_MANIFEST_DIR")); // kvlang/bin + println!("cargo:rustc-link-search=native={bin}"); + println!("cargo:rustc-link-lib=dylib=kvlang_runtime"); + println!("cargo:rustc-link-arg=-Wl,-rpath,$ORIGIN"); +} diff --git a/runtime-rwirext/src/lib.rs b/runtime-rwirext/rust/term/src/main.rs similarity index 90% rename from runtime-rwirext/src/lib.rs rename to runtime-rwirext/rust/term/src/main.rs index 95530e76..7b655e45 100644 --- a/runtime-rwirext/src/lib.rs +++ b/runtime-rwirext/rust/term/src/main.rs @@ -1,5 +1,5 @@ //! term 扩展 runtime:第一个通过 C ABI(kvlang_rwext)嵌入 C runtime 的扩展。 -//! 用 Rust 实现,注册 print/println/cerr,常驻 serve 循环执行外部 rwir。 +//! 用 Rust 实现,独立进程常驻 serve,注册 print/println/cerr 并执行外部 rwir。 use std::ffi::{c_char, c_int, CStr, CString}; use std::time::Duration; @@ -119,17 +119,12 @@ fn serve(conn: Conn) { } } -#[no_mangle] -pub extern "C" fn rwext_term_start(dsn: *const c_char) { - let dsn = if dsn.is_null() { - "redis://127.0.0.1:6379".to_string() - } else { - unsafe { CStr::from_ptr(dsn) }.to_string_lossy().into_owned() - }; +fn main() { + let dsn = std::env::args().nth(1).unwrap_or_else(|| "redis://127.0.0.1:6379".to_string()); let c = unsafe { rwext_connect(cs(&dsn).as_ptr()) }; if c.is_null() { - return; + eprintln!("term: rwext_connect failed: {dsn}"); + std::process::exit(1); } - let conn = Conn(c); - std::thread::spawn(move || serve(conn)); + serve(Conn(c)); } diff --git a/runtime/.clang-format b/runtime/.clang-format new file mode 100644 index 00000000..9b3aa8b7 --- /dev/null +++ b/runtime/.clang-format @@ -0,0 +1 @@ +BasedOnStyle: LLVM diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt new file mode 100644 index 00000000..8d12cd91 --- /dev/null +++ b/runtime/CMakeLists.txt @@ -0,0 +1,49 @@ +cmake_minimum_required(VERSION 3.10) +project(kvlang-runtime C) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +# ── 依赖路径(相对 kvlang,不 hardcode 绝对路径)──────────────── +get_filename_component(ARRAY2D "${CMAKE_SOURCE_DIR}/../.." ABSOLUTE) +set(KVSPACE_C_DIR "${ARRAY2D}/kvspace/build") +set(KVSPACE_DURABLE_DIR "${ARRAY2D}/kvspace-durable/target/release") +set(BLOCKMALLOC_DIR "${ARRAY2D}/blockmalloc/build") +set(SLOTSBOXMALLOC_DIR "${ARRAY2D}/slotsboxmalloc/build") + +# ── kvspace 后端(kvspace-c 或 kvspace_durable,均导出同一 C ABI)──── +set(KVSPACE_LIB "kvspace-c" CACHE STRING "kvspace 后端库:kvspace-c / kvspace_durable") + +# ── 输出统一到 bin/ ────────────────────────────────────────────── +set(BIN_DIR "${CMAKE_SOURCE_DIR}/../bin") +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${BIN_DIR}") +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/rwext.c) +target_include_directories(kvlang_runtime PUBLIC include src) +target_compile_definitions(kvlang_runtime PRIVATE _GNU_SOURCE) + +if(KVSPACE_LIB STREQUAL "kvspace-c") + target_link_directories(kvlang_runtime PRIVATE ${KVSPACE_C_DIR} ${BLOCKMALLOC_DIR} ${SLOTSBOXMALLOC_DIR}) + target_link_libraries(kvlang_runtime PRIVATE kvspace-c blockmalloc slotsboxmalloc) + set_target_properties(kvlang_runtime PROPERTIES + BUILD_RPATH "${KVSPACE_C_DIR};${BLOCKMALLOC_DIR};${SLOTSBOXMALLOC_DIR}") +else() + target_link_directories(kvlang_runtime PRIVATE ${KVSPACE_DURABLE_DIR}) + target_link_libraries(kvlang_runtime PRIVATE kvspace_durable) + set_target_properties(kvlang_runtime PROPERTIES BUILD_RPATH "${KVSPACE_DURABLE_DIR}") +endif() +target_link_libraries(kvlang_runtime PRIVATE m pthread) +# --export-dynamic 供 term 扩展找符号;--disable-new-dtags 使 rpath 转 DT_RPATH(传递), +# 让 run → runtime → kvspace-c → blockmalloc/slotsboxmalloc 的传递依赖能被 run/runtime 的 rpath 找到。 +set_target_properties(kvlang_runtime PROPERTIES LINK_FLAGS "-Wl,--export-dynamic -Wl,--disable-new-dtags") + +# ── 测试执行器 run:只链接 runtime(term 扩展是独立进程)────────── +add_executable(run test/main.c) +target_link_libraries(run PRIVATE kvlang_runtime) +set_target_properties(run PROPERTIES + LINK_FLAGS "-Wl,--disable-new-dtags" + BUILD_RPATH "${BIN_DIR};${KVSPACE_C_DIR};${BLOCKMALLOC_DIR};${SLOTSBOXMALLOC_DIR};${KVSPACE_DURABLE_DIR}") diff --git a/runtime/Makefile b/runtime/Makefile deleted file mode 100644 index 5073c9d0..00000000 --- a/runtime/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -CC = cc -CFLAGS = -std=gnu11 -O2 -Wall -fPIC -D_GNU_SOURCE -Iinclude -Isrc -DUAL = /home/peng.li24/github.com/array2d/kvspace-durable/target/release -KVS = /home/peng.li24/github.com/array2d/kvspace/build -BLK = /home/peng.li24/github.com/array2d/blockmalloc/build -SBO = /home/peng.li24/github.com/array2d/slotsboxmalloc/build -SRCS = 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/rwext.c -OBJS = $(SRCS:.c=.o) -TARGET = build/libkvlang_runtime.so - -# 链接哪个 kvspace 库由 KVLANG_KVSPACE_LIB 控制(kvspace-c 或 kvspace_durable,均导出同一 ABI) -KVLANG_KVSPACE_LIB ?= kvspace_durable -ifeq ($(KVLANG_KVSPACE_LIB), kvspace-c) - KVS_LINK = -L$(KVS) -lkvspace-c -L$(BLK) -lblockmalloc -L$(SBO) -lslotsboxmalloc \ - -Wl,-rpath,$(KVS) -Wl,-rpath,$(BLK) -Wl,-rpath,$(SBO) -else - KVS_LINK = -L$(DUAL) -lkvspace_durable -Wl,-rpath,$(DUAL) -endif - -all: $(TARGET) - -$(TARGET): $(OBJS) - mkdir -p build - $(CC) -shared -o $@ $(OBJS) $(KVS_LINK) -lm -pthread -Wl,--export-dynamic - -%.o: %.c - $(CC) $(CFLAGS) -c $< -o $@ - -clean: - rm -f $(OBJS) $(TARGET) diff --git a/runtime/include/kvlang_rwext.h b/runtime/include/kvlang_rwext.h index ae4ac174..51ed2a75 100644 --- a/runtime/include/kvlang_rwext.h +++ b/runtime/include/kvlang_rwext.h @@ -24,6 +24,15 @@ int rwext_set(rwext_conn *c, const char *key, const char *val); /* 删 key */ int rwext_del(rwext_conn *c, const char *key); +/* 读 key 的原始 TLV 字节(含类型信息,malloc,调用方 free);None → out=NULL */ +int rwext_get_tlv(rwext_conn *c, const char *key, uint8_t **out, uint32_t *out_len); + +/* 写原始 TLV 字节 */ +int rwext_set_tlv(rwext_conn *c, const char *key, const uint8_t *val, uint32_t val_len); + +/* 递归建目录索引 */ +int rwext_mkindex(rwext_conn *c, const char *path); + /* 从 pc 解码指令;若 opcode ∈ {print,println,cerr},resolve 全部 reads 并 display, * 以自身 sep(print 无分隔、println/cerr 空格分隔)连接返回(malloc); * 非己方指令返回 NULL(调用方应停止 RunSeq)。 @@ -33,3 +42,13 @@ char *rwext_print_line(rwext_conn *c, const char *pc, int *rawnl, int *cerr); /* 当前指令的下一条 PC(malloc) */ char *rwext_next_pc(const char *pc); + +/* 解码指令,返回 opcode + 读参名 + 写参名(\n 分隔:首行 opcode,接 nr 行读参名,接 nw 行写参名,malloc)。 + * 供 numpy/tensor 扩展按路径零拷贝读 raw 数据。 */ +char *rwext_params(rwext_conn *c, const char *pc); + +/* 解析读参 idx 为字符串(变量 → 帧槽值;路径 → 该路径下的值)。 */ +char *rwext_resolve_read(rwext_conn *c, const char *pc, int idx); + +/* 解析写参 idx 为 KV 路径(路径 → 直接返回;变量 → 帧槽路径)。 */ +char *rwext_resolve_write(rwext_conn *c, const char *pc, int idx); diff --git a/runtime/src/rwext.c b/runtime/src/rwext.c index 708b92ef..f064f595 100644 --- a/runtime/src/rwext.c +++ b/runtime/src/rwext.c @@ -62,6 +62,32 @@ int rwext_del(rwext_conn *c, const char *key) { return kv_del(c->kv, key, err, sizeof err); } +int rwext_get_tlv(rwext_conn *c, const char *key, uint8_t **out, uint32_t *out_len) { + if (out) *out = NULL; + if (out_len) *out_len = 0; + xval_t v; xv_zero(&v); + kv_get_one(c->kv, key, &v); + if (xv_none(&v)) { xv_free(&v); return 0; } + uint8_t *b = malloc(v.len); + if (!b) { xv_free(&v); return -1; } + memcpy(b, v.data, v.len); + *out = b; *out_len = v.len; + xv_free(&v); + return 0; +} + +int rwext_set_tlv(rwext_conn *c, const char *key, const uint8_t *val, uint32_t val_len) { + xval_t v = { (uint8_t *)val, val_len }; + kv_pair_t p = { (char *)key, v }; + char err[256]; + return kv_set(c->kv, &p, 1, err, sizeof err); +} + +int rwext_mkindex(rwext_conn *c, const char *path) { + char err[256]; + return kv_mkindex(c->kv, path, err, sizeof err); +} + char *rwext_print_line(rwext_conn *c, const char *pc, int *rawnl, int *cerr) { if (rawnl) *rawnl = 0; if (cerr) *cerr = 0; @@ -102,3 +128,59 @@ char *rwext_next_pc(const char *pc) { rwir_next_pc(pc, &b); return sb_detach(&b); } + +char *rwext_params(rwext_conn *c, const char *pc) { + char *fr = kt_frame_root(pc); + if (!fr) return strdup(""); + char *lb = kt_stack(fr); + rwir_inst_t inst; + char err[256]; + if (rwir_decode(c->kv, lb, pc, &inst, err, sizeof err) != 0) { + free(fr); free(lb); return strdup(""); + } + free(lb); + sbuf_t b; sb_init(&b); + sb_puts(&b, inst.opcode ? inst.opcode : ""); + for (int i = 0; i < inst.nr; i++) { sb_putc(&b, '\n'); sb_puts(&b, inst.reads[i].name ? inst.reads[i].name : ""); } + for (int i = 0; i < inst.nw; i++) { sb_putc(&b, '\n'); sb_puts(&b, inst.writes[i].name ? inst.writes[i].name : ""); } + free(fr); + rwir_inst_free(&inst); + return sb_detach(&b); +} + +/* 解析读参 idx 为字符串(变量 → 帧槽值;路径 → 该路径下的值)。 */ +char *rwext_resolve_read(rwext_conn *c, const char *pc, int idx) { + char *fr = kt_frame_root(pc); + if (!fr) return strdup(""); + char *lb = kt_stack(fr); + rwir_inst_t inst; + char err[256]; + if (rwir_decode(c->kv, lb, pc, &inst, err, sizeof err) != 0 || idx < 0 || idx >= inst.nr) { + free(fr); free(lb); return strdup(""); + } + free(lb); + xval_t v; xv_zero(&v); + bi_resolve_read_value(c->kv, fr, inst.reads[idx].name, &inst.reads[idx].val, &v); + char *s = xv_none(&v) ? strdup("") : xv_value_string(&v); + xv_free(&v); + free(fr); + rwir_inst_free(&inst); + return s; +} + +/* 解析写参 idx 为 KV 路径(路径 → 直接返回;变量 → 帧槽路径)。 */ +char *rwext_resolve_write(rwext_conn *c, const char *pc, int idx) { + char *fr = kt_frame_root(pc); + if (!fr) return strdup(""); + char *lb = kt_stack(fr); + rwir_inst_t inst; + char err[256]; + if (rwir_decode(c->kv, lb, pc, &inst, err, sizeof err) != 0 || idx < 0 || idx >= inst.nw) { + free(fr); free(lb); return strdup(""); + } + free(lb); + char *s = bi_resolve_write_slot(c->kv, fr, inst.writes[idx].name); + free(fr); + rwir_inst_free(&inst); + return s; +} diff --git a/runtime/test/main.c b/runtime/test/main.c index 56978d4c..cae0cb72 100644 --- a/runtime/test/main.c +++ b/runtime/test/main.c @@ -1,19 +1,12 @@ #include "kvlang_runtime.h" #include #include -#include - -extern void rwext_term_start(const char *dsn); int main(int argc, char **argv) { if (argc < 2) { fprintf(stderr, "usage: %s funcname [arg...]\n", argv[0]); return 2; } const char *dsn = getenv("KVSPACE") ? getenv("KVSPACE") : "redis://127.0.0.1:6379"; kvlang_rt *rt = kvlang_rt_connect(dsn); if (!rt) { fprintf(stderr, "connect failed\n"); return 1; } - if (!getenv("KVLANG_NOTERM")) { - rwext_term_start(dsn); - usleep(200000); - } char *ret = NULL; char err[512]; int rc = kvlang_rt_execute(rt, argv[1], (const char *const *)(argv + 2), argc - 2, &ret, err, sizeof err); diff --git a/rwir/builtin/builtin.h b/rwir/builtin/builtin.h deleted file mode 100644 index e9c63c03..00000000 --- a/rwir/builtin/builtin.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -// Builtin operation dispatch table — identical API to op/builtin/builtin.go. - -namespace kvlang::op::builtin { - -class VThread; // forward decl - -// Builtin handler: takes reads + write slot, returns new PC ("" = continue). -using BuiltinFunc = std::function& reads, - std::string_view write, - VThread& vt -)>; - -// Register a builtin by opcode name. -void register_builtin(std::string_view opcode, BuiltinFunc handler); - -// Look up a builtin. Returns nullptr if not found. -[[nodiscard]] const BuiltinFunc* lookup(std::string_view opcode); - -// Execute a builtin by opcode. Returns new PC, or "" if not a builtin. -[[nodiscard]] std::string dispatch( - std::string_view opcode, - const std::vector& reads, - std::string_view write, - VThread& vt -); - -} // namespace kvlang::op::builtin diff --git a/rwir/builtin/rwir_builtin_stub.cppx b/rwir/builtin/rwir_builtin_stub.cppx deleted file mode 100644 index 0c0b9104..00000000 --- a/rwir/builtin/rwir_builtin_stub.cppx +++ /dev/null @@ -1 +0,0 @@ -#include "builtin.h" diff --git a/rwir/control.h b/rwir/control.h deleted file mode 100644 index b7e5ce77..00000000 --- a/rwir/control.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include "instruction.h" - -// Control flow opcodes — goto, br, label, call, return. - -namespace kvlang::op { - -struct GotoInst { - std::string label; -}; - -struct BrInst { - std::string cond_slot; // KV path to condition value - std::string true_label; - std::string false_label; -}; - -} // namespace kvlang::op diff --git a/rwir/frame.h b/rwir/frame.h deleted file mode 100644 index 8418f3f5..00000000 --- a/rwir/frame.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include -#include - -// Frame-level instruction helpers. - -namespace kvlang::op { - -[[nodiscard]] std::string frame_root(std::string_view pc); -[[nodiscard]] std::string link_base(std::string_view frame_root); - -} // namespace kvlang::op diff --git a/rwir/instruction.h b/rwir/instruction.h deleted file mode 100644 index 6c54eadf..00000000 --- a/rwir/instruction.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once -#include -#include -#include -#include - -// Opcode instruction types — identical to op/instruction.go and op/instruction.rs. - -namespace kvlang::op { - -// ── Core instruction ───────────────────────────────── - -struct Instruction { - std::string opcode; // e.g. "copy", "add", "/lib/pkg.fn" - std::vector reads; // read slots (KV paths) - std::string write; // write slot (KV path, "" if none) - std::string label; // block label - std::string comment; // source comment - - [[nodiscard]] bool is_call() const; - [[nodiscard]] bool is_return() const; - [[nodiscard]] bool is_goto() const; - [[nodiscard]] bool is_label() const; - [[nodiscard]] bool is_terminator() const; -}; - -// ── Decode from KV store ───────────────────────────── - -class KVSpace; // forward decl (kvspace-cpp) -Instruction decode(KVSpace& kv, std::string_view link_base, std::string_view pc); - -// ── Constants ──────────────────────────────────────── - -inline constexpr std::string_view OpCopy = "copy"; -inline constexpr std::string_view OpCall = "call"; -inline constexpr std::string_view OpReturn = "return"; -inline constexpr std::string_view OpGoto = "goto"; -inline constexpr std::string_view OpBr = "br"; -inline constexpr std::string_view OpNop = "nop"; - -} // namespace kvlang::op diff --git a/rwir/pc.h b/rwir/pc.h deleted file mode 100644 index 30a8f4de..00000000 --- a/rwir/pc.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include -#include - -// Program counter (PC) utilities. PC is a KV path string. - -namespace kvlang::op { - -// Split PC into frame root + instruction coordinate. -struct PC { - std::string frame_root; - int row = 0; - int col = 0; -}; - -[[nodiscard]] PC decode_pc(std::string_view pc); -[[nodiscard]] std::string next_pc(std::string_view pc); - -} // namespace kvlang::op diff --git a/rwir/rwir_stub.cppx b/rwir/rwir_stub.cppx deleted file mode 100644 index de1a264b..00000000 --- a/rwir/rwir_stub.cppx +++ /dev/null @@ -1 +0,0 @@ -#include "instruction.h" diff --git a/rwir/tensor.h b/rwir/tensor.h deleted file mode 100644 index 3ffb3895..00000000 --- a/rwir/tensor.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include -#include -#include - -// Tensor operation opcodes. - -namespace kvlang::op { - -struct TensorOp { - std::string opcode; // e.g. "tensor.add", "tensor.matmul" - std::vector input_paths; - std::string output_path; - std::vector shape; -}; - -} // namespace kvlang::op diff --git a/rwirext/json/json.go b/rwirext/json/json.go deleted file mode 100644 index 924cb2c4..00000000 --- a/rwirext/json/json.go +++ /dev/null @@ -1,255 +0,0 @@ -// Package json 是 rwirext 扩展运行时(另一个是 term)。 -// -// 一个 rwirext 只需做三件事: -// 1. 用 ext.Ext 声明己方 rwir(opcode + 签名 + 读写参数量); -// 2. Register/Serve 两行转发(注册签名、常驻监控 .todo、批量执行、交还 PC); -// 3. exec 按 opcode 分发到具体 handler。 -// -// 中央 kvlang runtime 把控制权交给扩展运行时,扩展运行时批量执行己方 rwir -// 直到遇到非己方指令,再把最终 PC 写回 /vthread//pc。livebyte 的 agent -// 扩展照此模板实现即可:声明 op 集合与 exec 分发,其余由框架负责。 -package json - -import ( - "bytes" - "context" - "encoding/json" - "sort" - "strconv" - "strings" - - "github.com/array2d/kvspace-go" - "kvlang/keytree" - "kvlang/rwir" - "kvlang/rwir/builtin" - "kvlang/rwir/ext" -) - -// rt 声明 json 扩展运行时:json.to / json.from 两个 rwir。 -var rt = ext.Ext{ - Ops: []ext.Op{ - {Name: "json.to", Sig: "rwir json.to(rootkey:charbyte) -> (dest:[]charbyte)", Nr: 1, Nw: 1}, - {Name: "json.from", Sig: "rwir json.from(src:[]charbyte) -> (rootkey:charbyte)", Nr: 1, Nw: 1}, - }, - Exec: exec, -} - -func Register(kv kvspace.KVSpace) { rt.Register(kv) } -func Serve(kv kvspace.KVSpace) { rt.Serve(kv) } - -func exec(_ context.Context, kv kvspace.KVSpace, pc string, inst *rwir.Rwir) { - if inst.Opcode == "json.to" { - doTo(kv, pc, inst) - } else { - doFrom(kv, pc, inst) - } -} - -// doTo 序列化:rootkey 子树 → map[string]any → json.Marshal → 写回写参 dest。 -func doTo(kv kvspace.KVSpace, pc string, inst *rwir.Rwir) { - if len(inst.Reads) == 0 || len(inst.Writes) == 0 { - return - } - root := rootKey(kv, keytree.FrameRoot(pc), inst.Reads[0]) - data, _ := json.Marshal(buildMap(kv, root)) - writeKey := builtin.ResolveWriteSlot(kv, keytree.FrameRoot(pc), inst.Writes[0].Name) - kv.Set([]kvspace.KVPair{{Key: writeKey, Val: kvspace.NewCharByte(data...)}}) -} - -// doFrom 反序列化:JSON → map[string]any → 递归写回 rootkey(写参)子树。 -func doFrom(kv kvspace.KVSpace, pc string, inst *rwir.Rwir) { - if len(inst.Reads) == 0 || len(inst.Writes) == 0 { - return - } - src := builtin.ResolveReadValue(kv, keytree.FrameRoot(pc), inst.Reads[0]) - root := builtin.ResolveWriteSlot(kv, keytree.FrameRoot(pc), inst.Writes[0].Name) - writeMap(kv, root, fromJSON([]byte(src.ValueString()))) -} - -// rootKey 解析读参为 KV 路径:/ 开头直接用,否则取变量的字符串值。 -func rootKey(kv kvspace.KVSpace, framePath string, r rwir.Param) string { - if strings.HasPrefix(r.Name, "/") { - return r.Name - } - return builtin.ResolveReadValue(kv, framePath, r).ValueString() -} - -// buildMap 递归把 root 下的子树读成 map[string]any。 -// 目录→嵌套 map;散 key 数组(name[0]..name[N-1])→ JSON 数组;叶子→Go 值。 -func buildMap(kv kvspace.KVSpace, root string) map[string]any { - m := map[string]any{} - scat := map[string][]int{} - for _, child := range kv.List(root+"/", false, false) { - if strings.HasSuffix(child, "/") { - name := strings.TrimSuffix(child, "/") - m[name] = buildMap(kv, root+"/"+name) - continue - } - if base, idx, ok := splitArrayName(child); ok { - scat[base] = append(scat[base], idx) - continue - } - m[child] = toJSONValue(kvspace.GetOne(kv, root+"/"+child)) - } - for base, idxs := range scat { - sort.Ints(idxs) - arr := make([]interface{}, len(idxs)) - for i, idx := range idxs { - arr[i] = toJSONValue(kvspace.GetOne(kv, root+"/"+base+"["+strconv.Itoa(idx)+"]")) - } - m[base] = arr - } - return m -} - -// writeMap 递归把 map[string]any 写回 root 下的 KV 子树。 -// map→目录;[]any→连续数组;其余→叶子。 -func writeMap(kv kvspace.KVSpace, root string, m map[string]any) { - for k, v := range m { - childPath := root + "/" + k - switch t := v.(type) { - case map[string]any: - kvspace.MkIndexRecursive(kv, childPath+"/") - writeMap(kv, childPath, t) - case []interface{}: - kv.Set([]kvspace.KVPair{{Key: childPath, Val: fromJSONArray(t)}}) - default: - kv.Set([]kvspace.KVPair{{Key: childPath, Val: fromJSONValue(v)}}) - } - } -} - -// splitArrayName 解析散 key 数组元素名 name[i] → (name, i, ok)。 -func splitArrayName(name string) (base string, idx int, ok bool) { - lt := strings.LastIndex(name, "[") - if lt <= 0 || !strings.HasSuffix(name, "]") { - return "", 0, false - } - i, err := strconv.Atoi(name[lt+1 : len(name)-1]) - if err != nil { - return "", 0, false - } - return name[:lt], i, true -} - -// toJSONValue 把叶子/数组 XValue 转成 Go 值。charbyte→字符串;多元素→[]any。 -func toJSONValue(v kvspace.XValue) interface{} { - if kvspace.IsNone(v) { - return nil - } - n := int(v.ArrayLen()) - if kvspace.IsCharKind(v.Kind()) { - return v.ValueString() - } - if n > 1 && kvspace.ElemSize(v.Kind()) > 0 { - arr := make([]interface{}, n) - for i := 0; i < n; i++ { - arr[i] = elemJSON(v, i) - } - return arr - } - return elemJSON(v, 0) -} - -// elemJSON 按具体类型读取第 idx 个元素(标量或数组元素)为 Go 值。 -func elemJSON(v kvspace.XValue, idx int) interface{} { - switch t := v.(type) { - case kvspace.Bool: - return t.At(idx) - case kvspace.Int8: - return t.At(idx) - case kvspace.Int16: - return t.At(idx) - case kvspace.Int32: - return t.At(idx) - case kvspace.Int64: - return t.At(idx) - case kvspace.Uint8: - return t.At(idx) - case kvspace.Uint16: - return t.At(idx) - case kvspace.Uint32: - return t.At(idx) - case kvspace.Uint64: - return t.At(idx) - case kvspace.Float32: - return t.At(idx) - case kvspace.Float64: - return t.At(idx) - default: - return v.ValueString() - } -} - -// fromJSON 解析 JSON 字节为 map[string]any(UseNumber 保留整数/浮点区分)。 -func fromJSON(data []byte) map[string]any { - dec := json.NewDecoder(bytes.NewReader(data)) - dec.UseNumber() - var m map[string]any - if err := dec.Decode(&m); err != nil { - return nil - } - return m -} - -// fromJSONArray 把 JSON 数组打包为连续数组 XValue(统一元素类型)。 -func fromJSONArray(arr []interface{}) kvspace.XValue { - if len(arr) == 0 { - return kvspace.None{} - } - switch arr[0].(type) { - case json.Number: - ints := make([]int64, len(arr)) - for i, e := range arr { - n, ok := e.(json.Number) - if !ok { - return kvspace.None{} - } - iv, err := n.Int64() - if err != nil { - floats := make([]float64, len(arr)) - for j, e := range arr { - n, ok := e.(json.Number) - if !ok { - return kvspace.None{} - } - f, _ := n.Float64() - floats[j] = f - } - return kvspace.NewFloat64(floats...) - } - ints[i] = iv - } - return kvspace.NewInt64(ints...) - case bool: - bs := make([]bool, len(arr)) - for i, e := range arr { - b, ok := e.(bool) - if !ok { - return kvspace.None{} - } - bs[i] = b - } - return kvspace.NewBool(bs...) - default: - return kvspace.None{} - } -} - -// fromJSONValue 把 JSON 标量值构造为 XValue。 -func fromJSONValue(v interface{}) kvspace.XValue { - switch t := v.(type) { - case json.Number: - if i, err := t.Int64(); err == nil { - return kvspace.NewInt64(i) - } - f, _ := t.Float64() - return kvspace.NewFloat64(f) - case string: - return kvspace.NewCharByte([]byte(t)...) - case bool: - return kvspace.NewBool(t) - default: - return kvspace.None{} - } -} diff --git a/vthread/vthread.h b/vthread/vthread.h deleted file mode 100644 index 6786625b..00000000 --- a/vthread/vthread.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -// Virtual thread management — identical API to vthread/vthread.go and vthread/vthread.rs. - -namespace kvlang::vthread { - -class KVSpace; // forward decl (kvspace-cpp) - -// ── VThread state ──────────────────────────────────── - -struct VThreadState { - std::string pc; // current program counter (KV path) - std::string status; // "running" | "done" | "error" | "waiting" -}; - -// ── API ────────────────────────────────────────────── - -// Read current PC and status from KV. -VThreadState get(KVSpace& kv, std::string_view vtid); - -// Write PC and status to KV. -void set(KVSpace& kv, std::string_view vtid, std::string_view pc, std::string_view status); - -// Mark vthread as done with return value. -void set_done(KVSpace& kv, std::string_view vtid, std::string_view ret_val); - -// Mark vthread as error. -void set_error(KVSpace& kv, std::string_view vtid, std::string_view pc, std::string_view err_msg); - -// Allocate a new vthread ID. -[[nodiscard]] std::string alloc_vtid(KVSpace& kv); - -// Create a new vthread for a function call. -// Returns the new vtid. -[[nodiscard]] std::string create_vthread( - KVSpace& kv, - std::string_view func_name, - const std::vector& reads, - const std::vector& writes -); - -// Block until vthread completes. Returns the return value, or nullopt on timeout. -[[nodiscard]] std::optional wait_done( - KVSpace& kv, - std::string_view vtid, - std::chrono::milliseconds timeout -); - -} // namespace kvlang::vthread diff --git a/vthread/vthread_stub.cppx b/vthread/vthread_stub.cppx deleted file mode 100644 index 96c05a14..00000000 --- a/vthread/vthread_stub.cppx +++ /dev/null @@ -1 +0,0 @@ -#include "vthread.h"