calog/libs/calogExport.h
2026-07-04 23:22:22 -05:00

46 lines
2.8 KiB
C

// calogExport.h -- calog export library: publish script functions other scripts can call.
//
// Registers natives so a script can share a function by name across contexts and engines:
// calogExport(name, fn) publish a function value under a global name
// calogUnexport(name) remove it
// calogCall(name, ...args) call an exported function by name -- works in EVERY engine
//
// The natives are calog-prefixed so they never collide with an engine's reserved words
// (plain `export` is a JavaScript keyword; plain `call` is a my-basic keyword).
//
// On engines with a runtime unknown-name hook (Lua, Squirrel, JavaScript, s7), an exported
// name is ALSO reachable by its BARE name, e.g. `luaExample(1, 2)`. Ruby resolves a bare name
// the same way via Kernel#method_missing, but only at TOP LEVEL (self is the main object, so a
// missing method on some other receiver -- obj.foo -- is never hijacked). my-basic likewise
// bare-resolves a name called like a function, but CASE-INSENSITIVELY (it uppercases identifiers
// at parse time), so `luaExample(1, 2)` there matches the export ignoring case. Tcl resolves a bare
// command the same way via its `unknown` handler (`luaExample 1 2`). Wren and Berry resolve names
// statically and use calogCall('luaExample', ...). Resolution is dynamic: a name exported at any
// time becomes callable immediately, and calogUnexport takes effect at once.
//
// An exported function is an ordinary calog function value, so a call runs in the exporter's
// own context/thread (marshalled like any callable), and a call after the exporter is gone
// fails cleanly. The registry is process-wide and reference-counted across runtimes.
//
// NOTE (bare-name shadowing): on the hook engines (and, for a name called like a function, on
// my-basic), an otherwise-undefined name that matches an export resolves to that export -- an
// exported name is visible to every context, so pick export names that will not collide with
// scripts' feature-detection of undefined globals.
#ifndef CALOG_EXPORT_H
#define CALOG_EXPORT_H
#include "calog.h"
// Register the export natives on a runtime. Idempotent across runtimes (shared registry).
int32_t calogExportRegister(CalogT *calog);
// Release every exported function (once the last registered runtime unregisters). Unlike the
// other libraries, call this while the exporting contexts are still ALIVE -- before you close
// them and before calogDestroy -- because an exported function is a live reference into its
// owner's interpreter; releasing it after that context is gone would touch freed memory. The
// static registry bookkeeping itself is intentionally never freed (the natives stay callable
// until calogDestroy), so this is safe to call and re-register across runtimes.
void calogExportShutdown(void);
#endif