Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions boot.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1586,6 +1586,30 @@ local function initialise()
local r
local fn = P.F["shen.initialise"]
if fn then r = fn() end
-- Initialise the Shen Batteries feature registry from capabilities detected
-- by native extension installers. The Batteries module loader asks the
-- port for `(shen.x.features.current)` before loading a module; leaving the
-- registry unbound makes that query fail even though the extension API is
-- otherwise available. Keep this derived from backend globals so
-- SHEN_X_SHA256=pure (and ports without native backends) advertise no host
-- capability while retaining the portable implementation.
if P.F["shen.x.features.current"] then
local detected = {}
local function add_backend(global, feature)
local backend = P.GLOBALS[global]
if backend == R.intern("host") then
detected[#detected + 1] = R.intern(feature)
end
end
add_backend("shen.x.*sha256-backend*", "shen.x/sha256-host")
add_backend("shen.x.*zmq-backend*", "shen.x/zmq-host")
-- The community extension's `features.initialise` additionally hooks the
-- legacy macro registration API (`shen.set-lambda-form-entry`), which is
-- not present in the refreshed 41.2 kernel. Seed its backing global
-- directly; `features.current` is the stable API consumed by Batteries
-- and `features.add` can still extend this list later.
P.GLOBALS["shen.x.features.*features*"] = R.from_table(detected)
end
-- Register the lua.* interop entries in Shen's own arity/lambda-form
-- tables (needs the *property-vector* the kernel just created).
require("lua_interop").post_initialise()
Expand Down
1 change: 1 addition & 0 deletions scripts/run-tests.lua
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ local specs = {
"test/engine_spec.lua",
"test/error_robustness_spec.lua",
"test/eval_order_spec.lua",
"test/features_spec.lua",
"test/interop_spec.lua",
"test/io_spec.lua",
"test/jit_spec.lua",
Expand Down
40 changes: 40 additions & 0 deletions test/features_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
-- Shen Batteries feature bridge (including shen-extensions capabilities).
--
-- luajit test/features_spec.lua
local shen = require("shen")
shen.boot{ quiet = true }
local R = require("runtime")
local P = shen.prims

local npass, nfail = 0, 0
local function check(cond, name)
if cond then npass = npass + 1
else nfail = nfail + 1; io.write("FAIL: ", name, "\n") end
end

local function names(xs)
local out = {}
while R.is_cons(xs) do
out[tostring(xs[1])] = true
xs = xs[2]
end
return out
end

local ok, current = pcall(shen.call, "shen.x.features.current")
check(ok, "features.current is callable after boot")
if ok then
local have = names(current)
local backend = P.GLOBALS["shen.x.*sha256-backend*"]
if backend == R.intern("host") then
check(have["shen.x/sha256-host"] == true,
"host SHA-256 backend is advertised to Batteries")
else
check(have["shen.x/sha256-host"] ~= true,
"non-host SHA-256 backend is not advertised as host")
end
check(not have["shen.x/zmq-host"], "unsupported ZMQ backend is not advertised")
end

io.write(string.format("features_spec: %d pass, %d fail\n", npass, nfail))
os.exit(nfail == 0 and 0 or 1)
Loading