Explorar el Código

docs: analyse C FFI and GTK/SQLite/SDL bindings

Eric Streit hace 3 días
padre
commit
9d8bad7062
Se han modificado 2 ficheros con 327 adiciones y 12 borrados
  1. 2 2
      docs/INDEX.md
  2. 325 10
      docs/future-work-2026-10-25.md

+ 2 - 2
docs/INDEX.md

@@ -38,8 +38,8 @@ bisecting *why* a decision was made, not for reading end-to-end).
   ordering, complex types, pragmas (TopSpeed vs portable), UTF-8 string
   libraries, collections and the TopSpeed B-tree Toolkit, communications,
   pyserial, ModBase, network-library design, terminal escape libraries,
-  PIM vs ISO coroutines, external assembly, dynamic-set design and
-  suggested order.
+  C FFI and GTK4/SQLite/SDL bindings, PIM vs ISO coroutines, external
+  assembly, dynamic-set design and suggested order.
 
 ## Designs / running records
 

+ 325 - 10
docs/future-work-2026-10-25.md

@@ -5,8 +5,9 @@ questions do not have to be re-derived later.  It covers `TBITSIZE`,
 address arithmetic, set ordering, complex types, pragmas, UTF-8 string
 libraries, collections, the TopSpeed B-tree Toolkit, communications,
 pyserial, ModBase, network-library design, terminal escape libraries,
-PIM versus ISO coroutines, external assembly, and the dynamic-set
-design.  It is not a commitment to implement everything.
+C FFI and GTK4/SQLite/SDL bindings, PIM versus ISO coroutines, external
+assembly, and the dynamic-set design.  It is not a commitment to
+implement everything.
 
 **State at the time of writing:** suite 310/310, one-shot fixpoint OK
 (3,845,439 bytes), per-object fixpoint OK (11 objects), corpus
@@ -1817,7 +1818,318 @@ No compiler changes are required.
 
 ---
 
-## 14. Suggested order of future work
+## 14. C FFI foundation and GTK4/SQLite/SDL bindings
+
+The planned GTK4, SQLite and SDL bindings are not just three wrapper
+libraries.  They need a C ABI/FFI layer, a binding generator and
+`pkg-config`-aware build/link integration.
+
+### 14.1 Current FFI state
+
+V3 already has:
+
+- `DEFINITION/IMPLEMENTATION MODULE FOR "C"`;
+- `EXPORT UNQUALIFIED`;
+- `EXTERNAL` procedures;
+- a special `FROM libc IMPORT ...` path with known prototypes and
+  permissive varargs for unknown names;
+- raw `ADDRESS`, `POINTER TO` and pointer-sized procedure values;
+- C varargs support for the special `libc` intrinsic path.
+
+What is missing for large C APIs:
+
+- explicit C link-name mapping;
+- C-compatible record/union layout;
+- a true 4-byte `float`;
+- correct `size_t`/`ssize_t` widths;
+- C `bool` vs V3 `BOOLEAN`;
+- C arrays versus V3 descriptors;
+- general foreign varargs;
+- callback/trampoline support;
+- a binding generator;
+- multi-library build/link integration.
+
+### 14.2 Underscores are already allowed
+
+The scanner already accepts underscores:
+
+```text
+ident = ( letter | "_" ) { letter | digit | "_" } .
+```
+
+This was added for `__FILE__` / `__LINE__` compatibility (commit
+`a33fc7c`).  Names such as these already parse:
+
+```modula2
+gtk_application_new
+SDL_CreateWindow
+sqlite3_open_v2
+```
+
+The docs in `docs/features.md` and `docs/language-report.md` still say
+“no underscores” and should be updated.
+
+This reduces binding friction:
+
+- direct C function names;
+- C constants such as `GTK_ALIGN_FILL`;
+- C struct fields such as `SDL_Event.type`;
+- fewer renamed identifiers in generated bindings.
+
+It does **not** solve:
+
+- C struct layout and alignment;
+- C unions and bitfields;
+- C arrays vs V3 descriptors;
+- `char *` and string ownership;
+- true 4-byte `float`;
+- `size_t`/`ssize_t` width;
+- C `bool`;
+- callbacks and closures;
+- varargs;
+- C macros/inline functions;
+- build/link integration.
+
+Policy recommendation:
+
+- keep `_` as a documented V3 extension;
+- gate it behind strict PIM/ISO mode if strict compatibility matters;
+- update the feature matrix and language report;
+- still provide explicit `EXTERNAL "c_name"` for long/decorated names
+  and C wrappers.
+
+`SymTab.Name` is 64 bytes, so names longer than 63 characters can
+truncate; link names need an independent, larger mechanism.
+
+### 14.3 C ABI/type gaps
+
+The binding layer needs a C ABI profile:
+
+```modula2
+TYPE
+  CInt    = INTEGER;      (* C int *)
+  CUInt   = CARDINAL;     (* C unsigned int *)
+  CLong   = LONGINT;      (* C long on LP64 *)
+  CULong  = LONGCARD;
+  CSize   = LONGCARD;     (* size_t, 64-bit on amd64 *)
+  CSSize  = LONGINT;      (* ssize_t *)
+  CFloat  = SHORTREAL;    (* needs a true 4-byte float *)
+  CDouble = REAL;
+  CBool   = INTEGER;      (* C int / gboolean / SDL_bool *)
+  CEnum   = INTEGER;      (* C enum, 32-bit *)
+```
+
+Required changes:
+
+- true `SHORTREAL`/`REAL32` 4-byte float;
+- correct `CSIZE_T`/`CSSIZE_T` widths on amd64;
+- C `bool` (1 byte) separate from `BOOLEAN` (4 bytes);
+- C enums represented as integer aliases, not Modula-2 enums;
+- C `long`/`unsigned long` target-dependent aliases;
+- C string and buffer ownership helpers;
+- C `void *` as `ADDRESS`;
+- C function pointers as compatible procedure values.
+
+### 14.4 Structs, unions and arrays
+
+V3 records are tightly packed, with no alignment/padding.  One-
+dimensional array fields use V3 descriptors; C arrays are inline.
+Variant records are not C unions.
+
+Two strategies:
+
+1. **C accessor/wrapper strategy (recommended first)**
+   - C shims allocate and manipulate C structs.
+   - V3 sees opaque `ADDRESS` handles and gets/sets fields through C
+     functions.
+   - Avoids compiler layout work.
+   - Works for SDL `SDL_Event`, `SDL_AudioSpec`, SQLite structs, GTK
+     `GdkRGBA`/`GValue`.
+
+2. **C-compatible record layout (long term)**
+   - Add `ALIGN`, `PACKED`, `UNION`, inline arrays and bitfields.
+   - Allows direct struct declarations.
+   - Much larger and requires ABI layout tests.
+
+For the first bindings, use wrappers.  Do not start by making every V3
+record C-compatible.
+
+### 14.5 C FFI support library
+
+Add a small C support module, for example `lib/c/C`:
+
+- C scalar aliases;
+- `char *` <-> `ARRAY OF CHAR` conversion;
+- raw buffer with explicit length;
+- allocation/free matching the C allocator;
+- errno/`GetLastError` mapping;
+- optional callback/trampoline helpers;
+- opaque C-struct accessor conventions.
+
+The exact API can evolve, but ownership must be explicit:
+
+- borrowed string;
+- owned string;
+- C-allocated string that must be freed with `free`/`g_free`;
+- pointer valid only for the duration of a call.
+
+### 14.6 Binding generator
+
+Recommended source by target:
+
+| Target | Best source | Strategy |
+| --- | --- | --- |
+| GTK4 | GObject Introspection `.gir` files | Generate types, enums, functions, signals, ownership |
+| GLib/GObject/GIO | `.gir` files | Base bindings |
+| SQLite | `sqlite3.h` | Small hand-written thin binding |
+| SDL3 | `SDL3/SDL.h` | Header parsing plus hand-written struct/callback wrappers |
+
+The generator should emit:
+
+- `.def` declarations with safe Modula-2 names;
+- `EXTERNAL "c_name"` link names;
+- C shims for structs/unions, callbacks, varargs, `GError**`, `GValue`
+  and string ownership;
+- tests for each generated subsystem.
+
+For GTK4, use the installed `.gir` files as the source of truth rather
+than raw headers.  They include type names, transfer/ownership rules,
+nullable annotations, signals and properties.
+
+Do not attempt full GTK4 generation first.  Start with application,
+window, widget basics, buttons, labels, boxes, lists, files and signals.
+
+### 14.7 Build and link integration
+
+`M2make` currently supports one extra C file and links `-lm` only.  It
+needs:
+
+```text
+--cflag ...
+--ldflag ...
+--include ...
+--c-source ...
+--library ...
+--pkg-config gtk4
+--pkg-config sqlite3
+--pkg-config sdl3
+```
+
+Requirements:
+
+- multiple C shim files;
+- multiple include directories;
+- library order;
+- `-pthread` where needed;
+- `pkg-config --cflags --libs`;
+- rpath handling;
+- C shim/library flags in the ABI stamp.
+
+GTK4 needs `glib-2.0`, `gobject-2.0`, `gio-2.0`, `gtk4` and usually
+`-pthread`.  SQLite and SDL3 are much simpler.
+
+### 14.8 Callbacks and event loops
+
+C callbacks need special handling:
+
+- callbacks must be top-level, not nested procedures;
+- no static-link closure can cross into C;
+- Modula-2 exceptions must not escape a C callback;
+- user data should be passed as `ADDRESS` and decoded by a dispatcher;
+- GTK signals, SDL audio/timer callbacks and SQLite callbacks need
+  trampolines or a global callback registry.
+
+GTK4 also brings in GLib/GObject:
+
+- reference counting (`g_object_ref`/`g_object_unref`);
+- floating references;
+- signals (`g_signal_connect_data`);
+- `GError**` out-parameters;
+- `GValue` and properties;
+- `GMainLoop`/`GtkApplication` integration.
+
+A V3 GTK binding must define its main-loop and ownership policy
+explicitly.
+
+### 14.9 Target strategy
+
+**SQLite first**
+
+SQLite is the best first binding:
+
+- opaque `sqlite3` and `sqlite3_stmt`;
+- C strings;
+- `sqlite3_int64`;
+- bind/column operations;
+- callbacks;
+- in-memory databases for tests.
+
+A safe wrapper should hide statement finalization, `sqlite3_free`,
+`SQLITE_TRANSIENT` ownership, error strings and column lifetimes.
+SQLite is an excellent FFI conformance test for ints, int64, doubles,
+blobs, strings, pointers, callbacks and error codes.
+
+**SDL3 second**
+
+SDL3 needs:
+
+- opaque window/renderer/texture pointers;
+- `SDL_Event`, `SDL_Keysym`, `SDL_Rect`, `SDL_Color`, `SDL_AudioSpec`;
+- `SDL_bool`, `Uint32`, `Sint32`, `Uint64`;
+- true `float` or conversion wrappers;
+- audio/timer callbacks;
+- `SDL_Log` varargs;
+- event loop.
+
+Use C helpers to translate `SDL_Event` and `SDL_AudioSpec` to small V3
+records.  Prefer SDL3 unless SDL2 compatibility is required.  Test with
+`SDL_VIDEODRIVER=dummy` and `SDL_AUDIODRIVER=dummy`.
+
+**GTK4 last**
+
+GTK4 is the largest:
+
+- GLib base types and strings;
+- GObject refcount and signals;
+- `GError`;
+- `GValue` and properties;
+- `GList`/`GSList`;
+- `GMainLoop`/`GtkApplication`;
+- many opaque types;
+- ownership/transfer annotations.
+
+GTK4 should come after the C FFI foundation, callbacks, build/link
+integration and GIR generator.  A first binding should be a curated
+subset, not the full API.
+
+### 14.10 Recommended order
+
+1. C FFI foundation:
+   - underscore policy/docs;
+   - `EXTERNAL "c_name"` / `FFIDENT`;
+   - true 4-byte float;
+   - correct `size_t`/`ssize_t`;
+   - C string/buffer/error helpers;
+   - C struct accessor strategy.
+2. `pkg-config`-aware build integration and ABI stamping.
+3. FFI conformance tests.
+4. SQLite binding plus safe wrapper.
+5. SDL3 binding plus event/audio helpers.
+6. GIR-based generator for GLib/GObject.
+7. GTK4 binding subset and headless tests.
+
+Bindings should live outside the core library:
+
+```text
+lib/c/                 C FFI helpers
+bindings/sqlite3/      SQLite binding and wrapper
+bindings/sdl3/         SDL3 binding and wrapper
+bindings/gtk4/         GLib/GObject/GTK4 bindings
+```
+
+---
+
+## 15. Suggested order of future work
 
 1. `TBITSIZE` (small, standard-facing).
 2. `ADDADR`/`SUBADR`/`DIFADR` (small, ISO SYSTEM).
@@ -1832,14 +2144,17 @@ No compiler changes are required.
    `BTreeMap`; persistent `BTreeFile` last.
 8. Terminal emitters: `TermOut`, `VT100`, `VT52`, `Ansi`, optional
    `Regis`; `Tty` and headless tests.
-9. Communications: `Serial`/`Transport` first; protocols and terminal
-   emulation optional.
-10. Network: `Net`/`Transport`, TCP/UDP, `Poll`, then optional TLS/HTTP.
-11. Database: SQLite binding or typed B-tree table layer; dBase III
+9. C FFI foundation and bindings: underscore policy, link names,
+   float32, size_t, C strings/buffers, struct/callback wrappers,
+   pkg-config; SQLite, then SDL3, then GTK4.
+10. Communications: `Serial`/`Transport` first; protocols and terminal
+    emulation optional.
+11. Network: `Net`/`Transport`, TCP/UDP, `Poll`, then optional TLS/HTTP.
+12. Database: SQLite binding or typed B-tree table layer; dBase III
     only if required.
-12. ISO `COROUTINES` subset, then interrupt/protection layer.
-13. Dynamic `SET CONST` and deep composite copies.
-14. Parser error recovery and diagnostics.
+13. ISO `COROUTINES` subset, then interrupt/protection layer.
+14. Dynamic `SET CONST` and deep composite copies.
+15. Parser error recovery and diagnostics.
 
 External assembly needs no compiler work; document it as the supported
 low-level escape hatch.