Lets app/api/foo.prg keep its idiomatic `FUNCTION Main()` shape while
multiple such files compile into one binary. fnode auto-renames each
library file's Main into a unique symbol derived from the basename:
app/api/hello.prg -> HELLO__MAIN
app/api/admin-stats.prg -> ADMIN_STATS__MAIN (hyphen -> underscore)
Three moving parts:
cmd/fnode/main.go
parseOne for every PRG, then rename Main on every file except
the first (the entry). crossFile map updated so the analyzer
treats the renamed symbol as declared.
hbrtl_ext/dispatch/dispatch.go
New HB_FUNC FNODE_CALL(cFuncName) that does VM.FindSymbol +
PushSymbol/Function dance and discards the return value. Same
pattern pgserver's callPRG helper uses internally.
app/bridge_server.prg
BridgeDispatch now derives the symbol name from hReq["path"]
( /api/foo[.prg] -> FOO__MAIN ), invokes FNODE_CALL, and
maps "not found" errors to HTTP 404 (other errors -> 500).
Hardcoded /api/hello and /api/echo handlers replaced by the
path-driven model.
Verified end-to-end with app/api/hello.prg and app/api/admin-stats.prg:
GET /api/hello.prg -> 200 + JSON from HELLO__MAIN
GET /api/hello -> 200 (extension optional)
GET /api/admin-stats.prg?from=2026 -> 200 from ADMIN_STATS__MAIN
with query string echoed
GET /api/nope -> 404 "function not found"
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
32 lines
965 B
Plaintext
32 lines
965 B
Plaintext
// app/capi_test.prg — verifies bridge_capi RTL in isolation
|
|
// (single thread, no HTTP). Multi-thread isolation will be exercised
|
|
// once the dispatcher is wired in 1a.3-3.
|
|
FUNCTION Main()
|
|
LOCAL cJson, cOut, cResult
|
|
|
|
? "=== _CTX_SET_JSON / _CTX_GET_JSON ==="
|
|
_CTX_SET_JSON( '{"user":"alice","role":"admin"}' )
|
|
cJson := _CTX_GET_JSON()
|
|
? "ctx json:", cJson
|
|
? "ctx_get user:", ctx_get( "user", "?" )
|
|
? "ctx_get role:", ctx_get( "role", "?" )
|
|
? "ctx_get missing:", ctx_get( "nope", "DEFAULT" )
|
|
|
|
? ""
|
|
? "=== _OUT_APPEND / _OUT_GET / _OUT_CLEAR ==="
|
|
_OUT_APPEND( "Hello, " )
|
|
_OUT_APPEND( "world! " )
|
|
_OUT_APPEND( "Three." )
|
|
cOut := _OUT_GET()
|
|
? "out before clear: [" + cOut + "]"
|
|
_OUT_CLEAR()
|
|
? "out after clear: [" + _OUT_GET() + "]"
|
|
|
|
? ""
|
|
? "=== _BRIDGE_SET_RESULT / _BRIDGE_GET_RESULT ==="
|
|
_BRIDGE_SET_RESULT( "fast-path payload" )
|
|
cResult := _BRIDGE_GET_RESULT()
|
|
? "result:", cResult
|
|
|
|
RETURN NIL
|