diff --git a/docs/language/annotations/annot-export.md b/docs/language/annotations/annot-export.md
index 5820f023..ad66fb6c 100644
--- a/docs/language/annotations/annot-export.md
+++ b/docs/language/annotations/annot-export.md
@@ -5,17 +5,17 @@ category: annotations
kind: annotation
tokens: @export
sig: @export fn name(…) -> R
-tip: Expose a function as a C-ABI symbol so a host can call it.
+tip: Expose a function as a native symbol so a host can call it.
order: 3
---
-@export makes a fn visible outside the module as a plain C-ABI symbol, so a host program or another linked object can call it by name. Without it, functions are internal to the compiled unit; with it, the emitted symbol is externally linkable, which is how Ludic hands entry points to a runtime seam or a foreign caller. It is the outbound counterpart to extern fn, which pulls a foreign symbol in. Keep exported signatures to POD scalars and pointers, since they cross a C boundary where Ludic's richer types do not apply.
+@export makes a fn visible outside the module as a plain native symbol, so a host program or another linked object can call it by name. Without it, functions are internal to the compiled unit; with it, the emitted symbol is externally linkable, which is how Ludic hands entry points to a runtime seam or a foreign caller. It is the outbound counterpart to extern fn, which pulls a foreign symbol in. Keep exported signatures to POD scalars and pointers, since they cross a native ABI boundary where Ludic's richer types do not apply.
```ludic
program ScoreModule {
var running_total: int = 0
- @export fn add_points(amount: int) -> int { # callable from a C-ABI host
+ @export fn add_points(amount: int) -> int { # callable from a native host
running_total = running_total + amount
return running_total
}
diff --git a/docs/language/structure/kw-extern.md b/docs/language/structure/kw-extern.md
index eed3427e..1e7bfb2c 100644
--- a/docs/language/structure/kw-extern.md
+++ b/docs/language/structure/kw-extern.md
@@ -5,11 +5,11 @@ category: structure
kind: keyword
tokens: extern
sig: extern fn name(a: T) -> R = "symbol"
-tip: Bind a name to an external C-ABI symbol — the seam for platform and library calls.
+tip: Bind a name to an external native symbol — the seam for platform and library calls.
order: 12
---
-An extern fn declares a function whose body lives outside Ludic and binds it to a C-ABI symbol resolved at link time. It is the seam through which Ludic reaches anything with a C interface — a system library, a math routine, or even another `.ludic` file compiled as a `module`. You write the Ludic signature you want to call and give the real symbol name after `=`; the linker connects them (pass `-L`/`-l` to `ludicc` to point at the library). Types must match the foreign ABI, so map each parameter and the return to the right Ludic type (`int`, `fixed`, `ptr`, …).
+An extern fn declares a function whose body lives outside Ludic and binds it to a native symbol resolved at link time. It is the seam through which Ludic reaches anything with a native interface — a system library, a math routine, or even another `.ludic` file compiled as a `module`. You write the Ludic signature you want to call and give the real symbol name after `=`; the linker connects them (pass `-L`/`-l` to `ludicc` to point at the library). Types must match the foreign ABI, so map each parameter and the return to the right Ludic type (`int`, `fixed`, `ptr`, …).
Parameters:
- `a` — a typed argument passed straight through to the foreign symbol
diff --git a/docs/site/site.json b/docs/site/site.json
index a358652a..852af02c 100644
--- a/docs/site/site.json
+++ b/docs/site/site.json
@@ -14,6 +14,10 @@
{ "label": "Get started", "href": "#start" },
{ "label": "API Reference", "href": "api.html" }
],
+ "ref_nav_links": [
+ { "label": "Home", "href": "index.html" },
+ { "label": "API Reference", "href": "api.html" }
+ ],
"hero": {
"pill": "Opinionated · Batteries-included · No framework",
"title_pre": "Build a game,",
diff --git a/tools/docgen/assets/item.css b/tools/docgen/assets/item.css
index 8da5f9ba..efed1a7e 100644
--- a/tools/docgen/assets/item.css
+++ b/tools/docgen/assets/item.css
@@ -4,7 +4,7 @@
--mint:#7cf5c4; --coral:#ff5d73; --violet:#c792ea; --blue:#82aaff; --amber:#f6c177;
--c-bg:#0b0f20; --c-comment:#5b6788; --c-key:#ff7eb6; --c-type:#7cf5c4;
--c-str:#f6c177; --c-num:#a6b8ff; --c-annot:#c792ea; --c-fn:#82aaff; --c-punc:#9aa6cc; --c-arg:#f6c177;
- --radius:14px; --max:900px; --hdr:60px;
+ --radius:14px; --max:1120px; --hdr:60px;
}
*{box-sizing:border-box}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
@@ -131,13 +131,15 @@
/* ---- hover card (hover-capable devices only; JS also gates it) ---- */
.hovercard{position:fixed;z-index:100;max-width:min(340px,calc(100vw - 24px));background:var(--panel2);
- border:1px solid var(--line2);border-radius:12px;padding:12px 14px;box-shadow:0 20px 50px -18px rgba(0,0,0,.8);pointer-events:none}
+ border:1px solid var(--line2);border-radius:12px;padding:12px 14px;box-shadow:0 20px 50px -18px rgba(0,0,0,.8);
+ pointer-events:auto;cursor:pointer}
+ .hovercard:hover{border-color:var(--mint)}
.hc-top{display:flex;align-items:center;gap:9px;margin-bottom:8px}
.hc-name{font-family:"JetBrains Mono",monospace;color:var(--head);font-weight:700;font-size:14px;overflow-wrap:anywhere}
.hc-sig{display:block;color:var(--c-fn);background:var(--c-bg);border:1px solid var(--line);border-radius:7px;
padding:6px 9px;font-size:12px;margin-bottom:8px;white-space:pre-wrap;overflow-wrap:anywhere}
.hc-tip{color:var(--text);font-size:13.5px;line-height:1.5}
- .hc-foot{color:var(--muted);font-size:11.5px;margin-top:9px;letter-spacing:.3px}
+ .hc-foot{color:var(--mint);font-size:11.5px;margin-top:9px;letter-spacing:.3px}
/* ---- target flash ---- */
@keyframes ludicflash{0%{background:rgba(124,245,196,.28);box-shadow:0 0 0 3px rgba(124,245,196,.28)}
diff --git a/tools/docgen/assets/ludic-highlight.tmpl.js b/tools/docgen/assets/ludic-highlight.tmpl.js
index 6dd57476..a62aa28c 100644
--- a/tools/docgen/assets/ludic-highlight.tmpl.js
+++ b/tools/docgen/assets/ludic-highlight.tmpl.js
@@ -107,13 +107,26 @@
document.querySelectorAll('pre[data-lang="ludic"]').forEach(pre => { pre.innerHTML = highlight(pre.textContent); });
}
- /* ---- hover cards ------------------------------------------------------- */
- let cardEl = null, cardTimer = null;
+ /* ---- tooltip cards: click a token to open; click the card to open the ---
+ ---- page in a new tab; click outside (or Escape) to close ------------- */
+ let cardEl = null, cardAnchor = null;
function ensureCard(){
if (cardEl) return cardEl;
cardEl = document.createElement("div"); cardEl.className = "hovercard"; cardEl.hidden = true;
+ cardEl.addEventListener("click", () => {
+ const h = cardEl.dataset.href; if (h) window.open(h, "_blank", "noopener");
+ });
document.body.appendChild(cardEl); return cardEl;
}
+ function positionCard(a){
+ const el = cardEl, r = a.getBoundingClientRect();
+ const cw = el.offsetWidth, ch = el.offsetHeight;
+ let left = r.left, top = r.bottom + 8;
+ if (left + cw > window.innerWidth - 12) left = window.innerWidth - cw - 12;
+ if (left < 12) left = 12;
+ if (top + ch > window.innerHeight - 12) top = r.top - ch - 8;
+ el.style.left = Math.max(12,left) + "px"; el.style.top = Math.max(12,top) + "px";
+ }
function showCard(a){
const id = a.getAttribute("data-id"); if (!id) return;
const c = CARDS[id]; if (!c) return;
@@ -122,30 +135,25 @@
+ (c.kind||"").replace("namespace-method","method") + ''+esc(c.name||"")+''
+ (c.sig ? ''+esc(c.sig)+'' : "")
+ '