Commit graph

1136 commits

Author SHA1 Message Date
c2fc8f78f2 render3d: terrain_height_file - terrain_height's exact bilinear that never pages: a resident tile is read in place, any other from tt_file into four tiles of scratch of its own (in the state's defaults, forgotten when the file closes), so no slot is taken and no recency bumped - a sweep at boot no longer changes which tiles the cache holds, and so what is drawn from it. With the whole copy it is terrain_height. tests/height_file_test: equal to terrain_height over a grid across many tiles, resident and not, at tile corners and past the edge; a whole-map sweep leaves slot_of, tile_in, ref, the heights, the hand and the read counts unchanged
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 02:29:55 +03:00
12553edb26 Merge 7c4e6870
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 02:07:11 +03:00
ea451dfda2 Merge 986fba3586
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 02:07:11 +03:00
7c4e6870b3 render3d: the blades' density window filled apart from its upload - gb_window_fill (the tiles round the camera's, zeros off the map, the corner) and gb_frame sends it; the same bytes, now readable by a test without a GPU
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 02:03:43 +03:00
986fba3586 ludic.i18n: inside a bracket an argument's bytes ride raw - trf escapes a 27 or 31 only outside brackets, and the decoder unescapes only there, so a bracketed line carrying a key with holes (Ada's brief: its legend line's escaped arguments) keeps its own escapes whichever way it was put in (a game's txt_key raw, or trf). 81e1f7d8 unescaped inside the bracket and split the legend's arguments out of the brief. nest_test holds a key whose hole holds a key with two holes: bare, bracketed raw, bracketed through trf, and escaped.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 02:00:20 +03:00
00b45742d1 Merge lang/i18n-data-fill 81e1f7d8: ludic.i18n's L makes bracketed lines (29/30) itself, outermost first
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 01:48:18 +03:00
81e1f7d8e6 ludic.i18n: a line bracketed inside another (bytes 29 .. 30) is made by L itself - each bracket outermost in, a key whole through keyed() so its escaped arguments stay whole, and a split on 31 never inside a bracket (a game's txt_key puts its nested line raw); a stray bracket draws nothing. The game's tx_L did this alone, so L in a test or anywhere else drew the brackets (26.9's move, made now). nest_test holds it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 01:39:44 +03:00
3bf07ce606 Merge lang/builtinnames d4df925b (attrs before export 26b986de + the builtin-name refusal); reseeded, fixpoint 300381
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 01:15:05 +03:00
d4df925b8f checker: a function named like a built-in a call always takes is refused at its declaration - function words(st, k) compiled and every call became words(n) with a pointer for n (invalid IR, far from the cause); the table is selfhost/check/check_builtins.ludic, emit_call's built-ins no find_fn guard lets a declared function take, and ludic-dev syntax --check holds it to emit_call both ways; every other built-in (buffer, floats, double, ...) yields to a declared function in the checker as it already did in codegen. string_temps' keep and cross_heap_test's keep renamed (hand, keep_cell); rejected/builtin_call_name and functions/builtin_yield with their cases (added, not run); reseeded, bootstrap-cfree fixpoint holds
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 01:10:24 +03:00
26b986de5b parser: an attribute before export is kept - @ToClients export event E was a local event (the attributes read in front of export were dropped when the declaration was parsed afresh one call down), as were @Sync / @Owned / @Server / @On / @Public ... before export; and export @ToClients event was refused. Attributes and export now read in either order into one declaration, and a wrapper marks what it added exported (g_at_keep goes); examples/networking/net_export and three schema cases (added, not run); reseeded, bootstrap-cfree fixpoint holds
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 01:03:44 +03:00
64adb052b4 Merge commit 'd703d79feb' into lang/foundations 2026-09-30 00:56:43 +03:00
d703d79feb ludic.i18n: a glued key's name is a-z, 0-9, _ and . only (every key en.po holds), so a word glued on after it is not read as part of it; keys_test: "Not owned. " + a key, and a capital straight after one
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:52:49 +03:00
96c6e27d98 ludic.i18n: a key's text glued into an English line is made where it sits - L decodes each marked name inside a line that is not a key of its own ("A {1}, {2} cm." given a name that is a key, name + "\n" + blurb), in the language in use, then the line takes its old English lookup; kept in the keyed cache. Interim until every such line is a key (26.9). keys_test covers the stop at a sentence's full stop, a key at the head with words after, a mixed argument in a key's hole, and a key whole left alone.
Since the data's text became keys (26.4), a game's English patterns that take a table's name (Notify, txt_pat, a concatenation) drew the raw mark and key.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:50:53 +03:00
a3377215e9 ludic.i18n: tr and key_text lose their @alloc_ok - string(k) of a Key is no allocation to the escape analysis now, and key_text's slice is not one either, so both pass arena strict as they stand (trf / trn keep theirs: they make a line)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:48:29 +03:00
01df9b9d77 runtime (macOS): with a layer asked for, the loader is pinned to our MoltenVK whatever the shell set - the SDK's setup-env.sh exports VK_DRIVER_FILES and VK_ICD_FILENAMES at its own, and the one left set loaded a second MoltenVK; VK_DRIVER_FILES overwritten, VK_ICD_FILENAMES cleared, R3D_VK_ANY_DRIVER=1 to keep the shell's
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:47:07 +03:00
47ba741f6d Merge commit '1ab5ca14' into lang/foundations 2026-09-30 00:43:24 +03:00
c3a37bf76c Merge commit '10a394ae' into lang/foundations (nested and list @Text keys derived, trf's trailing "" padding not counted, string(k) no escape site); reseeded, bootstrap-cfree fixpoint holds
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:43:11 +03:00
c9cf202721 Merge commit '10a394ae' into lang/i18n-data-fill 2026-09-30 00:41:34 +03:00
1ab5ca14fb runtime (macOS): MoltenVK opened first, so a process holds one - the SDK's loader in /usr/local/lib loaded its own MoltenVK beside the linked one and the program drew through it; the loader only when a layer is asked for, pinned to ours (VK_DRIVER_FILES, lib/macos-arm64/MoltenVK_icd.json) unless a driver is named. steady's stream round: a 300-cell warm-up, then the least of three 150-cell windows
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:41:27 +03:00
10a394ae6c compiler: text keys below a row, trf padding and tr's cast (ECS's 26.4 gaps) - a @Text Key in a record nested in a row, or in each item of a list of them, is filled with its derived key <registry>.<row>.<field>.<i>.<field> as a top-level one is, and a @Text []Key a row leaves out takes <...>.0, .1, ... for as many as en.po has (so no .lres spells a key; the manifest and en.po are now read before the parse that fills the rows); field: null is no text; trf / trn's trailing "" literals are padding, not counted against the English's holes; and string(x) of a string or a Key is x itself to the escape analysis, no allocation site, so tr(key) passes arena strict (a template's lone hole still copies); examples/lang/i18n_nested and its feat_case (added, not run); LANGUAGE.md and the changeset; reseeded, bootstrap-cfree fixpoint holds
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:41:05 +03:00
a1419cdd1f Merge commit '603a5bd6' into lang/foundations 2026-09-30 00:40:12 +03:00
2e0a7f0031 Merge commit 'bdda22c' into lang/foundations 2026-09-30 00:39:29 +03:00
da78010281 Merge commit '9a0011c' into lang/foundations (a test program holding a phase handler compiles: rt_init called only when the runtime defines it); reseeded, bootstrap-cfree fixpoint holds
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:39:20 +03:00
603a5bd63f Merge commit 'bdda22c' into lang/i18n-data 2026-09-30 00:35:57 +03:00
9f1273fb32 Merge branch 'lang/foundations' into lang/i18n-data 2026-09-30 00:35:56 +03:00
9a0011c38f compiler: a test program may hold a phase handler - the test runner called @rt_init whenever the program had systems, and a handler alone makes none (LLVM: use of undefined value '@rt_init'); it calls it only when it exists, as an entry program's main does; a ludic test case with a handler (added, not run); reseeded, bootstrap-cfree fixpoint holds
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:34:34 +03:00
bdda22cb2e ludic.i18n: a key with holes inside another key's hole survives - an argument's own 31s and 27s are escaped with 27 and the decoder splits on the unescaped ones (trf(k"a", trf(k"b", x))); keys_test holds it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:32:23 +03:00
86644e6533 packages: the registry text a game fills is keys (Maroon Lake's phase 26.4) - ThingKind.name, GearKind blurb/howto/names, HintCard's words, JobDef title/text/how, NpcLine and NpcChoice text, WeatherKind.name are @Text Key fields (a compiled row that leaves one out takes its derived key, the English is the game's en.po); what a package hands back as text is the key's marked text, "" for none; NpcName.name, NpcChoice.line and SettingDef.text are not text and lose @Text; ludic.i18n's tr/trf/trn/key_text say @alloc_ok (tr is a cast); the packages' tests with key literals (built, not run); changes/text-keys-data.md
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:29:03 +03:00
eaeadc6a52 Merge commit 'f0cf859' into lang/foundations 2026-09-30 00:28:24 +03:00
eb0d3b1846 Merge lang/schemacode (R7, d39a27a) into lang/editortools, so R9 lands after R7 with nothing to resolve: no conflicts (LANGUAGE.md and test.ludic merged), selfhost/ is R7's (its seeds; bootstrap-cfree fixpoint holds)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:27:16 +03:00
50333571d7 Merge lang/foundations (9391695) into lang/editortools: no conflicts, selfhost/ identical to lang/foundations (the seeds unchanged; bootstrap-cfree fixpoint holds at 289532 lines), the help lists R10's --stdin-file, R8's syntax and R9's fmt / remove lines together
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:26:26 +03:00
320ce42626 ludic remove <module> and ludic get --json (R9)
remove is the inverse of add: the require line leaves package.ludic; the lock keeps exactly what the
remaining requires still reach, read from the store's copy of each locked package.ludic (no
network), so a package another still requires stays locked and what only the removed one brought in
leaves with it; each leaving package loses the ludic_modules/ symlink add made, never the shared
store entry. Refused (exit 1) when package.ludic does not require the module; source still
importing a removed package is a warning. With no store copy to read, only the named module leaves.

get --json diffs the lock before and after in memory and prints {added, removed, changed,
unchanged} on stdout (an entry as the lock records it: name, version, hash, kind, provides; a change
as name, from, to, from_hash, to_hash), the resolver's lines on stderr. Cases added to test-pkg,
not run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:24:49 +03:00
047bdf4189 ludic fmt for editors: --lint --json, and a buffer on stdin (R9)
ludic-fmt --lint --json prints the violations --lint reports as one JSON array on stdout,
[{file, line, col, rule, message}] ordered by file, line and column (col where the rule knows it),
the summary on stderr, --lint's exit status, and never rewrites the baseline. ludic-fmt - refuses a
buffer that does not read as Ludic (a string/template/key literal left open, a bracket never closed
or closed by the wrong one) with exit 2 and name:line:col on stderr; - --lint judges a buffer as the
file --stdin-name names (--stdin-rel: that path relative to the project), against its baseline and
lint paths. ludic fmt --lint and ludic fmt - run it from the nearest package.ludic upwards (from
--stdin-name's directory when given). Hooks read nothing and write to stderr under --json or -.
Regression cases added to test-tools and ludic-dev test (fmt_editor_cases), not run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:24:43 +03:00
d39a27a904 Merge lang/foundations (9391695) into lang/schemacode: LANGUAGE.md's command list keeps --stdin-file (R10), the code map in schema (R7) and ludic syntax (R8); selfhost/main.ludic carries all three flags; reseeded from the merged source, bootstrap-cfree fixpoint holds (298653 lines), syntax --check clean, no conflict markers
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:21:47 +03:00
f0cf85943f ludic.i18n: an English value in a key's hole gets the old English lookup (exact, pattern, sentence) while the game still hands English into holes - until its code and data are keys (phase 26.9), where it does nothing; keys_test holds it (exact, a pattern, no line, a number untouched)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:19:46 +03:00
bfd99cdda1 compiler: ludic schema gains a "code" section (R7) - the code map from the compiler, so the studio's scan is only a fallback: modules (package, layer, uses and where, friend, files), states, actions, reducers, every dispatch, events (cancellable, net) with every emit and their @On listeners, ports (members with fn types, defaults, required) and binds (port, member, fn, value, at), handlers (phase, hook and target, @Public, @Server / @Predicted, @Queries with filters as written, scene and layer), models (@Owned, @Sync), prefabs, scenes (start, public, shows, lasts / then, loads, enter / exit, layers) and fn_refs - every fn name in code or a resource file with the slot it fills (registry field and row, port member or default, record field, emit field, call argument, assignment, let). Places are "file:line:col"; sorted by name, sites by place; schema_version stays 1 (additive). The parser records emits, fn refs, handlers and scenes' layers / lasts / loads for it (emit_schema_code.ludic, emit_schema_code_game.ludic); LANGUAGE.md and the changeset say so; schema_case lines added (not run); reseeded, bootstrap-cfree fixpoint holds
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:19:24 +03:00
9391695fce Repair the c804c4b merge (3d65ec6 was committed with conflict markers in selfhost/main.ludic and both seeds): main.ludic keeps both --emit-syntax (R8) and --stdin-file (R10); the seeds regenerated from the merged source, bootstrap-cfree fixpoint holds (289532 lines)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:16:41 +03:00
3d65ec6def Merge commit 'c804c4b' into lang/foundations (R10: --stdin-file checks an unsaved buffer in place of a file the program reads); reseeded, bootstrap-cfree fixpoint holds
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:15:01 +03:00
c804c4b0ee ludicc / ludic build: --stdin-file <path> checks an unsaved buffer in place of its file (R10)
stdin is read once, whole, and read_file serves a copy of it wherever the program opens <path> -
the entry, an import through a barrel, a component's .xml / .lss, an .lres. Paths match after
normalising both ('/' separators, relative under $PWD, . / .. / // folded, case on Windows);
diagnostics keep the file's usual name, with the buffer's lines and columns. A <path> nothing
opens is one warning. On ludic build it implies --check. Reseeded; bootstrap-cfree fixpoint holds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:10:04 +03:00
86146782f7 Merge commit '9f8aec3' into lang/foundations (R8: the syntax vocabulary from the parser, grammars and LSP word lists generated from it, the LSP's outline/hover/definition fixed, 47 docs/language pages); reseeded, bootstrap-cfree fixpoint holds
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:04:52 +03:00
ed19fb5ce4 Merge commit '11447b8' into lang/foundations 2026-09-30 00:02:48 +03:00
9f8aec3bc1 Merge lang/i18nkeys (27024de) into lang/syntax: the vocabulary gains the text keys - the Key type, @TextKey (a registry's), the k"..." and kn"..." literals - and @Text's doc; docs/language pages for Key and @TextKey; ludic-dev syntax rewrote the grammars; reseeded, bootstrap-cfree fixpoint holds
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:02:48 +03:00
4ccbc12b48 Merge commit '27024de' into lang/foundations 2026-09-30 00:00:28 +03:00
86c46c629b changes: syntax-vocabulary (ludic syntax, ludic-dev syntax, the language server's outline and attribute arguments)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 23:59:47 +03:00
e2528c1b10 docs/language: a page for every keyword and attribute the vocabulary has
Keywords: module uses friend export internal numbers unsafe mut port bind action
reducer registry of as from def open alias component prop view (structure),
shows lasts then loads (scenes), system (ecs), dispatch (control), true false
null (operators). Attributes: @Ref @OneOf @Range @Unit @Asset @Color, @Node /
@Clip / @Material, @Tint @Derived, @Text / @Multiline, @Key, @AppendOnly /
@ByKey, @PerMap / @Chunked, @frame @max, @owns / @creates / @releases,
@deterministic @alloc_ok. Each is in tools/docgen/inventory.json; every fence
that is not marked skip parses (ludicc --fmt). annot-clearcolor's token loses its
quotes, which no reader strips.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 23:59:47 +03:00
eb2d6106af ludic-lsp: every declaration by its own kind, every field a child, attribute arguments resolve
documentSymbol named `export property X` and `export registry` a function called
"property" / "registry": `export`, `unsafe` and leading @attributes are now a
lead-in to the declaration after them, which keeps its doc comment and is marked
exported. A record's field default was skipped with padv, which crosses lines, so
a property showed only its first field; a member now ends at a comma, the brace
or its line, past a fn type's parameters and a generic's arguments, and an
attribute's arguments are skipped rather than read as fields.

New symbols: state, event (and cancellable), action and port as records (struct,
event, event, interface) with their members; registry (with its record, for
go-to-type, and its line as detail); enum and its members; component and view
with props, state, fields, functions and events; reducer, named "S on A"; a
module-level let as a constant; def and bind bodies, module / friend / numbers
lines read past. A member of a component is not a name for the whole unit.

Hover and definition on an attribute's argument: @Node(model) / @Clip / @Material
to the field of the record it is written in, @Ref(Kits) to the registry (as any
top-level name), and hover on the attribute shows its docs/language page. A
fn-typed or generic field's type is shown whole. lsp_test (test-lsp) holds all of
it on a module file with each kind of declaration.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 23:59:40 +03:00
2ad6edaae3 ludic syntax, and ludic-dev syntax: every grammar written from the compiler's vocabulary and checked against it
`ludic syntax [--json] [-o FILE]` prints what `ludicc --emit-syntax` does (a line
per entry, or the JSON). `ludic-dev syntax` writes, between "ludic-dev syntax:
begin" / "end" lines, the keyword, type, phase and attribute tables of
ludic_syntax.h, LudicVocabulary's sets (JetBrains), ludic-mode.el's lists and the
language server's word tests (is_keyword_word and the rest; is_contextual_word is
every word the parser does not reserve, and every declaring or modifying one),
and every TextMate pattern marked "comment": "ludic-dev syntax: <group>" (shared
and the VS Code copy). The grammars gain module uses port bind action reducer
dispatch registry def open component prop view alias friend unsafe numbers of as
from mut system; import and extern colour as declarations; the phase clause
knows Overlay; the bitwise pattern matches | and ^ on their own again.

`ludic-dev syntax --check` - and check-vocabulary, whose old parser comparison it
replaces, and the regression suite (syntax_cases, one line per file) - fails when
a written list is behind, when a grammar lacks a keyword, type or phase, when
docs/language has no page for a keyword, type, phase or attribute, or when the
parser (a scan of selfhost/frontend: is_id / text == words, a == / ann ==
attributes) tests a word or reads an attribute vocab.ludic lacks, or the reverse.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 23:59:30 +03:00
73f7d0b7a3 ludicc --emit-syntax: the language's vocabulary as one table beside the parser
selfhost/frontend/vocab.ludic holds every keyword with its role (declaration,
modifier, statement, operator, constant), every declaration's form, the built-in
types and phases, every attribute with what it goes on, its arguments and a
one-line doc, the operators and the literal forms; `ludicc --emit-syntax` prints
it as JSON ("syntax_version": 1) and exits before reading any program. The
parser dispatches on words where it meets them, so the table is held to it from
the emitter's side: a keyword's "reserved" is is_reserved_word's answer, a phase
must pass is_phase_name and a field attribute listed as read must pass
at_field_known, or the emitter refuses to print. Reseeded (both seeds assemble;
bootstrap-cfree: out.ll == seed.ll).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 23:59:02 +03:00
27024de00e ludic-dev test: the deps case expects english_left (26.2) after owned_leaks
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 23:57:56 +03:00
11447b8650 ludic.i18n: tr / trf / trn take the compiler's Key (k"...", kn"..." for trn), built from string(k); keys_test with key literals
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 23:56:05 +03:00