mirror of
https://github.com/fluffos/fluffos
synced 2026-08-12 18:26:06 -04:00
9 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
814c4fa5b9
|
vm: string foreach/ref fixes, buffers as byte arrays (foreach, strict bytes, to_buffer), thorough ref tests; #1196 docs follow-up (#1250)
* docs/tests: fix constructs index regression from #1196; add ref page to sidebar; extend & ref tests - Restore extension-less links and the text_blocks entry in docs/lpc/constructs/index.md (the PR was recreated from a pre-Docusaurus branch and reintroduced .html links, which fail the docs build under onBrokenLinks: 'throw', and dropped text_blocks) - Add lpc/constructs/ref to the hand-authored sidebar in docs/sidebars.ts - Drop the stale VitePress 'layout: doc' frontmatter from ref.md - Extend testsuite/single/tests/operators/ref.lpc: & in parameter declarations, ref keyword in foreach, and bitwise &/&= non-regression Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Skf9CfHwAngWorDNDzPKWp * vm: fix string foreach crash and off-by-one ref reads; support += / -= on string chars Three related defects around the shared string-codepoint lvalue (global_lvalue_codepoint), all reproduced on the unfixed binary: - Nested foreach over strings SEGFAULTED: the iteration cursor lived in the shared global, so the inner loop's F_EXIT_FOREACH reset the iterator out from under the outer loop (null deref in post_index_to_offset). The EGC cursor now lives in each loop's own stack slot (the T_NUMBER slot under the loop variable); the ref case re-arms the shared codepoint lvalue every iteration, and exit only clears the global when it still points at this loop's string slot. - foreach (int ref c in str) read the WRONG characters: the shared index was advanced before the body ran, so every read through the ref was off by one ('abc' summed to 197 instead of 294, and the final iteration read one past the end). The global index now stays on the current character for the whole body. Writes through the ref still go to the loop's by-value stack copy and never reach the iterated variable -- semantics pinned by tests/operators/foreach.lpc. - s[i] += n / s[i] -= n threw "Bad Argument 1 to +=()": F_ADD_EQ and f_sub_eq handled buffer byte lvalues (T_LVALUE_BYTE) but not string codepoint lvalues (T_LVALUE_CODEPOINT), even though ++/--/= worked. Both now route through a new codepoint_lvalue_add() helper and produce the resulting character as the rvalue. Regression tests: nested (plain / ref / multi-byte UTF-8) string foreach and ref-read correctness in tests/operators/foreach.lpc; compound assignment on string chars (incl. reverse index, rvalue result, and non-number rhs error) in tests/operators/string_index.lpc. Verified on the unfixed binary: the nested-foreach test segfaults, the others fail. Full LPC suite passes 2x on clang ASan/UBSan Debug and 2x on RelWithDebInfo. Docs: correct the ref.md note on foreach-over-strings; document the string-char lvalue rules in AGENTS.md (section 8 + audit checklist 9) and the ref/& feature in README. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Skf9CfHwAngWorDNDzPKWp * vm: foreach ref over strings shares the s[i] char-lvalue logic; thorough ref tests Arming a string-char lvalue now goes through one shared helper, aim_lvalue_codepoint(): it validates the target EGC (out-of-bounds and multi-codepoint error cleanly, same messages as s[i]) and points the shared codepoint state at it. Both s[i] lvalues (push_indexed_lvalue) and foreach ref loop variables use it, and every write consumer already funnels into assign_lvalue_codepoint() -- so ref loop chars follow exactly the s[i] rules: - single-codepoint characters (and EGCs up to 4 bytes, which index as their first codepoint) keep working: reads deliver the character, assignments through the loop variable succeed - wider EGCs (flag emoji, ZWJ sequences) now raise the catchable "Indexed character is multi-codepoint" error when the ref loop reaches them, instead of silently reading as -1; the non-ref form still iterates and delivers -1 for such clusters tests/operators/ref.lpc is now a thorough pass-by-reference suite: ref/& parameter declarations and call arguments, by-value contrast, ref forwarding through call chains, call-site refs to array elements / mapping values / string chars (forward and reverse index, write-back), foreach ref over arrays / mapping values / strings (read correctness, multi-byte codepoints, by-value write semantics, assignment error parity, the multi-codepoint error, non-ref contrast), compile-time rejections via generated sources (ref outside an argument list, ref to a range), and bitwise &/&= non-regression -- 39 checks. Full LPC suite passes 2x on RelWithDebInfo and 2x on a clean clang ASan/UBSan Debug build. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Skf9CfHwAngWorDNDzPKWp * tests: cover ref across all LPC types Extend tests/operators/ref.lpc to 58 checks: ref parameters of every value type (int, float, string, array, mapping, object, function, buffer, class, mixed) verifying reassignment propagates; the by-value contrast for reference-typed containers (member writes propagate, reassignment doesn't); call-site refs to buffer bytes (forward and reverse index) and class members (both . and -> spellings); foreach ref over mapping values of mixed types; the compile-time rejection of a ref mapping KEY in foreach; and the clean runtime error for foreach over a non-iterable type (buffer). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Skf9CfHwAngWorDNDzPKWp * buffers behave like byte arrays: foreach, strict 0..255 bytes, string/array promotion, to_buffer() Buffers are now first-class byte containers: - foreach iterates a buffer like an array, delivering each byte as an unsigned int 0..255. A ref loop variable mutates the buffer in place; each ref carries its OWN T_LVALUE_BYTE (in ref->sv), so nested buffer ref loops and b[i] lvalues in the body can't alias each other. T_LVALUE_BYTE consumers now read the lvalue's own pointer/subtype instead of reaching for the shared global_lvalue_byte (which remains only as the scratch instance b[i] arms). - every LPC byte write path (=, ++, --, +=, -=) range-checks the result: a value outside 0..255 raises "Buffer byte value out of range" and leaves the byte unchanged, instead of silently truncating/wrapping. += / -= on bytes also yield the resulting value as their rvalue. - strings and arrays of ints 0..255 PROMOTE to buffers: a new to_buffer() efun (registered like to_int/to_float) is wrapped around the rhs by do_promotions() / rule_expr_assign for 'buffer b = str', 'b += str', initializers, and 'b + str'; range assignment and the runtime + / += paths convert unpromoted (mixed) values through the same svalue_to_buffer_bytes() helper. A string contributes its raw UTF-8 bytes; an array must hold only ints 0..255 (validated before allocation) or the conversion errors with the target unchanged. - fixed a pre-existing ref_t leak: a foreach ref loop variable reused by a re-entered inner loop leaked one ref per outer iteration (flagged by the debug memory checker as 'Found temporary block: make_ref'). tests/operators/buffer_bytes.lpc pins the byte-range semantics, + / += concatenation, all promotion forms, and the error paths (106 checks); foreach.lpc and ref.lpc pin buffer iteration and ref-loop independence; buffer_range_assign.lpc gains range-read pins. New docs for to_buffer (sidebar regenerated) and a rewritten lpc/types/buffer page. Full LPC suite passes 2x on RelWithDebInfo and 2x on a clean clang ASan/UBSan Debug build (no ref-checker warnings); GTest suite 312/312. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Skf9CfHwAngWorDNDzPKWp --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
89060c5a6b
|
docs: fully-expandable generated sidebar + Chinese docs via Docusaurus i18n (#1246)
* docs: fully-expandable generated sidebar, replacing index.md link pages
Rework docs navigation so the sidebar expands to every page of every
reference tree, instead of terminating at generated index.md link lists:
- New docs/gen_sidebar.py (replaces gen_index.py + update_index.sh):
walks efun/, apply/, stdlib/, concepts/, driver/, cli/ and zh-CN/ and
emits sidebars.generated.json — a full Docusaurus category tree per
directory. Category landing pages are now `generated-index` card pages
(title/description/slug), so all generated index.md files are deleted.
--check mode verifies freshness; new .github/workflows/docs-sidebar.yml
runs it in CI.
- New docs/sidebar_meta.json holds curated presentation: category labels,
one-line descriptions (shown on the landing cards), explicit ordering
(driver/cli/concepts read top-down from user-facing to internals) and
per-page label overrides.
- sidebars.ts becomes a hand-authored skeleton (Getting Started, lpc/,
Historical) that splices in the generated trees.
Content reorganization (from a docs-wide review):
- Move misplaced efun pages out of efun/general: terminal/protocol efuns
(act_mxp, send_zmp, request_term_*) to interactive/, debugging efuns
(check_memory, dump_*, clear_debug_level, destructed_objects) to
internals/, shallow_inherit_list to system/.
- Delete stub duplicates superseded by complete pages elsewhere:
general/parse_{add_synonym,dump,my_rules,remove}, contrib/{shuffle,
element_of}.
Modernize key pages with MDX:
- index.mdx: landing page with a card grid linking each doc section.
- build.mdx: per-platform <Tabs> (Ubuntu/macOS/Windows/Alpine+Docker),
admonitions, VitePress [[toc]] leftover removed, stale per-platform CI
workflow links updated to the unified ci.yml.
- ffi-plan.md: GitHub-style [!CAUTION] alert converted to an admonition.
`npm run build` passes clean (onBrokenLinks: throw, no warnings).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0174GM2azvAHBmvyESwxm5om
* docs: serve the Chinese corpus through Docusaurus i18n
Move the zh-CN/ directory out of the default docs tree and into a proper
Docusaurus locale (i18n/zh-CN/docusaurus-plugin-content-docs/current/):
- The flat zh-CN/efun/ directory (333 pages) is re-homed to mirror the
categorized English layout (name-matched 1:1; `hash` maps to strings/
per its own frontmatter). apply/ pages map 1:1; the stray English-text
zh-CN/apply/master/view_errors.md documents a MudOS-era apply that no
longer exists in the driver and is dropped; stdlib/db/database_zh.md
becomes the i18n translation of stdlib/db/database.md; the Chinese
build guide becomes the translation of build.mdx.
- Untranslated pages automatically fall back to English content under
/zh-CN/, so the whole site is navigable in either locale from the new
navbar locale dropdown.
- Both locales share one sidebar. Generated sidebar items now carry
stable `key` fields (the directory/doc path) so translation keys are
unique (both efun/ and stdlib/ have an "Arrays" category, crypto and
strings both document `hash`). Category labels, generated-index
titles/descriptions, navbar and footer are translated in
i18n/zh-CN/...; theme UI strings come from Docusaurus' bundled
zh-Hans translations. Translated landing page at /zh-CN/.
- The "中文文档" sidebar section, the zh-CN tree in gen_sidebar.py /
sidebar_meta.json, and its slice of sidebars.generated.json are gone.
- Relative .md-file links on pages that render in both locales break
the localized build (the file->permalink map points at the localized
copy), so concepts/, the two socket_*_option pages and the config.md
generator now emit extension-less route links instead.
- zh interactive.md/objects.md get explicit slugs like their English
counterparts (a doc named after its parent directory is otherwise a
Docusaurus category-index doc, colliding with the generated-index
route).
`npm run build` builds both locales clean (onBrokenLinks: throw).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0174GM2azvAHBmvyESwxm5om
---------
Co-authored-by: Claude <noreply@anthropic.com>
|
||
|
|
e6f0c377f8
|
wasm: run the full driver in the browser (Emscripten port) (#1231)
The driver cross-compiles to WebAssembly and runs a complete mudlib inside a webpage: compiler, VM, all portable efun packages, and the real telnet protocol layer -- the page is the telnet client, JavaScript is the wire. The LPC testsuite passes inside the wasm driver (browser and node). Architecture (src/wasm/README.md): - Transport interface (src/net/transport.h): each interactive_t owns an abstract byte pipe (write/flush/schedule_command/close). comm.cc and telnet.cc are transport-agnostic and compile unchanged on every target. Implementations select at link time: SocketTransport + WebsocketTransport (net/transport_libevent.cc, native) vs WasmConsoleTransport (src/wasm/comm_wasm.cc). - Inverted event loop: the shared gametick/event core stays in backend.cc; backend_libevent.cc (blocking loop) vs src/wasm/backend_wasm.cc (page-driven fluffos_tick(now_ms), walltime priority queue, capped catch-up). Other per-target singletons (TLS, DNS resolver, crash handler) follow the same link-time pattern -- no #ifdef __EMSCRIPTEN__ in shared logic files. - Mudlib rides in Emscripten's MEMFS via file_packager; driver file I/O needed zero changes. jsbridge package (WASM only): js_eval() (sync), js_call() (async page handlers with LPC callbacks), js_export() (page calls LPC via Module.fluffos.callLPC, Promise-resolved on a later tick) -- fetch, canvas/WebGL, storage, page UIs driving the game. Demo in testsuite/command/jsdemo.lpc + the bundled web terminal. Build/tooling: native-tools + wasm CMake presets (host codegen tools, then cross build); tools/wasm/build-deps.sh (ICU + zlib cross-builds, including the ICU genccode data quirk); tools/wasm/pack-mudlib.sh (any mudlib + driver -> static web bundle, also works standalone from the release zip); src/www/wasm/index.html (self-contained web terminal with a minimal telnet client). On emsdk >= 3.1.57 the build uses native wasm exceptions (-fwasm-exceptions); older toolchains fall back to -sDISABLE_EXCEPTION_CATCHING=0. CI/release: a wasm CI job (latest emsdk, deps cache keyed on resolved emcc version) gates PRs on the LPC testsuite running inside the wasm driver under node; release.yml ships fluffos-<version>-wasm.zip (driver + web terminal + pack-mudlib.sh). Fixed a stale-predefine bug: options.autogen.h now depends on packages.autogen.h + config.h. Docs: docs/build-wasm.md (end-to-end workflow), docs/driver/wasm.md (packer + jsbridge cookbook), docs/efun/jsbridge/*, README + AGENTS updated. Testsuite files for optional packages guard themselves with #ifdef __PACKAGE_*__. Claude-Session: https://claude.ai/code/session_01VVpphH3cgXyziRDCbjUVkb Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
c914f03d66
|
Add local search and documentation guide for docs site (#1221)
* docs: add local full-text search and a contributor README Add @easyops-cn/docusaurus-search-local to the Docusaurus site so the docs get an offline search bar (index built at build time, no external service). English and zh-CN pages are both indexed, and matched terms are highlighted on the target page. Add docs/README.md describing the Docusaurus setup, local dev/build commands, search behavior, directory layout, and gotchas; exclude it from the published site alongside CLAUDE.md. Point the root README's docs/ entry at it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TSzcESzU9947zkGzQ6SMmE * docs: remove dead framework leftovers, fix index generation, complete the nav Delete the VitePress (.vitepress/) and Jekyll (_layouts/, css/) leftovers, the one-shot migration scripts (fix_md_header.py, fix_seealso.py), and the stale keywords.json snapshot; prune the matching .gitignore entries and docusaurus exclude patterns. Rewrite gen_index.py for Docusaurus: it emitted dead .html links and legacy 'layout: doc' frontmatter, choked on non-markdown entries, and dropped nested categories — regenerating an index would have broken it. It now emits the extension-less links the site actually uses, links nested category indexes (restoring apply/* on the zh-CN index), and refuses to run on the docs root. Fix update_index.sh's copy-paste titles (zh-CN efun/build were titled 'APPLY'), stop it clobbering the hand-written lpc/index.md, and cover cli/. Regenerated indexes pick up the missing driver/ffi-plan entry. add_missing_efuns.py now takes the keywords.json path as an argument instead of requiring a stale copy. Move CNAME and the Google site-verification file into static/ so they actually reach the published build output. Complete the sidebar: link the CLI category to cli/index and add the missing portbind/symbol/generate_keywords pages, and expose the previously orphaned stdlib section under Reference. Promote onBrokenLinks to 'throw' now the build is warning-free, and drop the empty Demo section from the landing page. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TSzcESzU9947zkGzQ6SMmE * docs: strip legacy 'layout: doc' frontmatter from all pages Mechanical sweep removing the Jekyll-era 'layout: doc' line from every doc page's frontmatter (Docusaurus ignores it), and the matching line from the templates in docs/CLAUDE.md so new pages don't reintroduce it. No content changes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TSzcESzU9947zkGzQ6SMmE --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
b9e67f1d49 |
docs: add package_ffi design plan (libffi-based LPC FFI + tools/ffi)
Proposal for an OFF-by-default ffi package: dlopen/dlsym + libffi to load native libs and call functions with runtime-described signatures, native memory managed as ref-counted LPC buffers (no new svalue tag), a mandatory valid_ffi master-apply security gate, and a tools/ffi header->LPC bindings generator. Phased v1a/v1b/v2 with GTest + LPC + generator tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
7fe7c5c9a9 |
docs/lpc: source-file resolution, diagnostics, full preprocessor reference
New pages: lpc/source-files (extension rules, extension-blind object identity, registry-before-filesystem, portable-code guidance), lpc/diagnostics (clang-style output, macro expansion notes, include chains, fix-its, show_error_context), preprocessor/conditionals (token-based #if with C precedence, defined()/efun_defined()) and preprocessor/pragma (real pragma table from the driver). Rewrote preprocessor/index (full directive table, immutable predefines), define (function-like macros, stringize/paste, rescan, redefinition-warning semantics) and include (search order, master get_include_path, trailing text, macro file names); constructs/include is now a summary pointing at the reference, and constructs/inherit documents pathname resolution. Dropped the vestigial preprocessor/README; sidebar gains the new pages plus the previously unlisted text_blocks. AGENTS.md now points agents at docs/lpc/ as the authoritative LPC reference. Validated with a clean docusaurus production build. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
2063e95436
|
Fix Docusaurus sidebar, broken links, and gh-pages CI (#1209)
* Reorder sidebar: Driver > CLI > Reference (LPC Language, Apply, EFUN, Concepts) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix Docusaurus build: broken links, duplicate routes, and gh-pages CI - Strip .html from all markdown link targets (51 files) for Docusaurus URL routing - Add slug: frontmatter to 4 files whose names match their parent directory (interactive.md, objects.md, README.md, build.md) to prevent Docusaurus's category-index convention from creating duplicate routes - Fix one missed .html link in zh-CN/build/index.md - Move onBrokenMarkdownLinks to markdown.hooks (Docusaurus v4 deprecation) - Update gh-pages.yml: rename to Docusaurus, use node 22, correct build path (docs/build instead of docs/.vitepress/dist) Build now completes with [SUCCESS] and zero warnings or broken links. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
2f261c5e3f |
Add LPC/Driver sidebar subsections and update docs agent guides
- Expand sidebars.ts: LPC section now has Types, Constructs, Preprocessor subsections; add top-level Driver section with all driver/*.md pages; replace Driver Internal with Concepts (autogenerated) - Add Section 9 to AGENTS.md documenting the Docusaurus 3 setup, config files, markdown compatibility rules, and sidebar format - Update docs/CLAUDE.md to reference AGENTS.md Section 9 and replace stale VitePress references (config path, port 5173) with Docusaurus Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
1ee613bd15 |
Migrate docs from VitePress to Docusaurus 3.10.1
The package.json had dead Docusaurus deps from a previous setup while the
site itself was VitePress. This completes the migration back to Docusaurus
3.10.1 with its latest theme and features:
- Add docusaurus.config.ts with docs plugin (path: '.', routeBasePath: '/')
and markdown.format: 'detect' so .md files use standard markdown
- Add sidebars.ts converted from the VitePress sidebar.ts format
- Replace devDependency-only vitepress with full Docusaurus preset-classic
- Upgrade clsx 1.x → 2.x, prism-react-renderer 2.1 → 2.4, typescript 5.2 → 5.8
- Update index.md to add slug: / for the home page
- Escape {…} in 7 doc files where curly braces appeared in prose text and
were mis-parsed as JSX expressions
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|